From: David Majnemer Date: Sat, 20 Feb 2016 09:23:47 +0000 (+0000) Subject: [MSVC Compat] Implement -EHc semantics X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=73b50332f53eb7902d75ee32149804d126a400cd;p=clang [MSVC Compat] Implement -EHc semantics The -EHc flag implicitly adds a nothrow attribute to any extern "C" function when exceptions are enabled. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@261425 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/LangOptions.def b/include/clang/Basic/LangOptions.def index a3ee84291f..623e896bbd 100644 --- a/include/clang/Basic/LangOptions.def +++ b/include/clang/Basic/LangOptions.def @@ -110,6 +110,7 @@ LANGOPT(Exceptions , 1, 0, "exception handling") LANGOPT(ObjCExceptions , 1, 0, "Objective-C exceptions") LANGOPT(CXXExceptions , 1, 0, "C++ exceptions") LANGOPT(SjLjExceptions , 1, 0, "setjmp-longjump exception handling") +LANGOPT(ExternCNoUnwind , 1, 0, "Assume extern C functions don't unwind") LANGOPT(TraditionalCPP , 1, 0, "traditional CPP emulation") LANGOPT(RTTI , 1, 1, "run-time type information") LANGOPT(RTTIData , 1, 1, "emit run-time type information data") diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index 721c30f1b1..b725b5f6af 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -511,6 +511,8 @@ def main_file_name : Separate<["-"], "main-file-name">, def fblocks_runtime_optional : Flag<["-"], "fblocks-runtime-optional">, HelpText<"Weakly link in the blocks runtime">; +def fexternc_nounwind : Flag<["-"], "fexternc-nounwind">, + HelpText<"Assume all functions with C linkage do not unwind">; def fsjlj_exceptions : Flag<["-"], "fsjlj-exceptions">, HelpText<"Use SjLj style exceptions">; def split_dwarf_file : Separate<["-"], "split-dwarf-file">, diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp index 9c64da58c2..fd647a484e 100644 --- a/lib/Driver/Tools.cpp +++ b/lib/Driver/Tools.cpp @@ -5786,8 +5786,7 @@ struct EHFlags { /// - s: Cleanup after "synchronous" exceptions, aka C++ exceptions. /// - a: Cleanup after "asynchronous" exceptions, aka structured exceptions. /// The 'a' modifier is unimplemented and fundamentally hard in LLVM IR. -/// - c: Assume that extern "C" functions are implicitly noexcept. This -/// modifier is an optimization, so we ignore it for now. +/// - c: Assume that extern "C" functions are implicitly nounwind. /// The default is /EHs-c-, meaning cleanups are disabled. static EHFlags parseClangCLEHFlags(const Driver &D, const ArgList &Args) { EHFlags EH; @@ -5897,10 +5896,11 @@ void Clang::AddClangCLArgs(const ArgList &Args, ArgStringList &CmdArgs, const Driver &D = getToolChain().getDriver(); EHFlags EH = parseClangCLEHFlags(D, Args); - // FIXME: Do something with NoExceptC. if (EH.Synch || EH.Asynch) { CmdArgs.push_back("-fcxx-exceptions"); CmdArgs.push_back("-fexceptions"); + if (EH.NoUnwindC) + CmdArgs.push_back("-fexternc-nounwind"); } // /EP should expand to -E -P. diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 2e0822794e..cf4b5cf20a 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -1688,6 +1688,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, Opts.ObjCExceptions = Args.hasArg(OPT_fobjc_exceptions); Opts.CXXExceptions = Args.hasArg(OPT_fcxx_exceptions); Opts.SjLjExceptions = Args.hasArg(OPT_fsjlj_exceptions); + Opts.ExternCNoUnwind = Args.hasArg(OPT_fexternc_nounwind); Opts.TraditionalCPP = Args.hasArg(OPT_traditional_cpp); Opts.RTTI = Opts.CPlusPlus && !Args.hasArg(OPT_fno_rtti); diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 62cd5c8e3d..a775be9ea2 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -11582,6 +11582,13 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) { } } + // If C++ exceptions are enabled but we are told extern "C" functions cannot + // throw, add an implicit nothrow attribute to any extern "C" function we come + // across. + if (getLangOpts().CXXExceptions && getLangOpts().ExternCNoUnwind && + FD->isExternC() && !FD->hasAttr()) + FD->addAttr(NoThrowAttr::CreateImplicit(Context, FD->getLocation())); + IdentifierInfo *Name = FD->getIdentifier(); if (!Name) return;