From 960813e1643ec788707bf18b0cdce4bb142d560a Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Sat, 20 Feb 2016 09:23:47 +0000 Subject: [PATCH] [MSVC Compat] Implement -EHc semantics The -EHc flag implicitly adds a nothrow attribute to any extern "C" function when exceptions are enabled. llvm-svn: 261425 --- clang/include/clang/Basic/LangOptions.def | 1 + clang/include/clang/Driver/CC1Options.td | 2 ++ clang/lib/Driver/Tools.cpp | 6 +++--- clang/lib/Frontend/CompilerInvocation.cpp | 1 + clang/lib/Sema/SemaDecl.cpp | 7 +++++++ 5 files changed, 14 insertions(+), 3 deletions(-) diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def index a3ee842..623e896 100644 --- a/clang/include/clang/Basic/LangOptions.def +++ b/clang/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/clang/include/clang/Driver/CC1Options.td b/clang/include/clang/Driver/CC1Options.td index 721c30f..b725b5f 100644 --- a/clang/include/clang/Driver/CC1Options.td +++ b/clang/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/clang/lib/Driver/Tools.cpp b/clang/lib/Driver/Tools.cpp index 9c64da5..fd647a4 100644 --- a/clang/lib/Driver/Tools.cpp +++ b/clang/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/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 2e08227..cf4b5cf 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/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/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 62cd5c8..a775be9 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/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; -- 2.7.4