From: Anders Carlsson Date: Mon, 28 Feb 2011 02:27:16 +0000 (+0000) Subject: Add a -fcxx-exceptions flag to the frontend, which can be used to enable X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=15348aeb81285c75b2e92b5bf8d2db3445d147c2;p=clang Add a -fcxx-exceptions flag to the frontend, which can be used to enable C++ exceptions, even when exceptions have been turned off using -fno-exceptions. Make the -fobjc-exceptions flag do the same thing, but for Objective-C exceptions. C++ and Objective-C exceptions can also be disabled using -fno-cxx-excptions and -fno-objc-exceptions. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@126630 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index 288c10f523..1b9d279f57 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -264,6 +264,7 @@ def fcompile_resource_EQ : Joined<"-fcompile-resource=">, Group; def fconstant_cfstrings : Flag<"-fconstant-cfstrings">, Group; def fconstant_string_class_EQ : Joined<"-fconstant-string-class=">, Group; def fcreate_profile : Flag<"-fcreate-profile">, Group; +def fcxx_exceptions: Flag<"-fcxx-exceptions">, Group; def fdebug_pass_arguments : Flag<"-fdebug-pass-arguments">, Group; def fdebug_pass_structure : Flag<"-fdebug-pass-structure">, Group; def fdiagnostics_fixit_info : Flag<"-fdiagnostics-fixit-info">, Group; @@ -325,6 +326,7 @@ def fno_caret_diagnostics : Flag<"-fno-caret-diagnostics">, Group; def fno_color_diagnostics : Flag<"-fno-color-diagnostics">, Group; def fno_common : Flag<"-fno-common">, Group; def fno_constant_cfstrings : Flag<"-fno-constant-cfstrings">, Group; +def fno_cxx_exceptions: Flag<"-fno-cxx-exceptions">, Group; def fno_diagnostics_fixit_info : Flag<"-fno-diagnostics-fixit-info">, Group; def fno_diagnostics_show_option : Flag<"-fno-diagnostics-show-option">, Group; def fno_dollars_in_identifiers : Flag<"-fno-dollars-in-identifiers">, Group; diff --git a/lib/CodeGen/CGException.cpp b/lib/CodeGen/CGException.cpp index eb907e1fff..0b248bd783 100644 --- a/lib/CodeGen/CGException.cpp +++ b/lib/CodeGen/CGException.cpp @@ -439,7 +439,7 @@ void CodeGenFunction::EmitCXXThrowExpr(const CXXThrowExpr *E) { } void CodeGenFunction::EmitStartEHSpec(const Decl *D) { - if (!CGM.getLangOptions().Exceptions) + if (!CGM.getLangOptions().CXXExceptions) return; const FunctionDecl* FD = dyn_cast_or_null(D); @@ -467,7 +467,7 @@ void CodeGenFunction::EmitStartEHSpec(const Decl *D) { } void CodeGenFunction::EmitEndEHSpec(const Decl *D) { - if (!CGM.getLangOptions().Exceptions) + if (!CGM.getLangOptions().CXXExceptions) return; const FunctionDecl* FD = dyn_cast_or_null(D); diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp index 43ff90da07..475b904b06 100644 --- a/lib/Driver/Tools.cpp +++ b/lib/Driver/Tools.cpp @@ -780,25 +780,84 @@ shouldUseExceptionTablesForObjCExceptions(const ArgList &Args, Triple.getArch() == llvm::Triple::arm)); } -static bool needsExceptions(const ArgList &Args, types::ID InputType, - const llvm::Triple &Triple) { - // Handle -fno-exceptions. +/// addExceptionArgs - Adds exception related arguments to the driver command +/// arguments. There's a master flag, -fexceptions and also language specific +/// flags to enable/disable C++ and Objective-C exceptions. +/// This makes it possible to for example disable C++ exceptions but enable +/// Objective-C exceptions. +static void addExceptionArgs(const ArgList &Args, types::ID InputType, + const llvm::Triple &Triple, + bool KernelOrKext, bool IsRewriter, + ArgStringList &CmdArgs) { + if (KernelOrKext) + return; + + // Exceptions are enabled by default. + bool ExceptionsEnabled = true; + + // This keeps track of whether exceptions were explicitly turned on or off. + bool DidHaveExplicitExceptionFlag = false; + if (Arg *A = Args.getLastArg(options::OPT_fexceptions, options::OPT_fno_exceptions)) { if (A->getOption().matches(options::OPT_fexceptions)) - return true; - else - return false; + ExceptionsEnabled = true; + else + ExceptionsEnabled = false; + + DidHaveExplicitExceptionFlag = true; } - // Otherwise, C++ inputs use exceptions. - if (types::isCXX(InputType)) - return true; + bool ShouldUseExceptionTables = false; + + // Exception tables and cleanups can be enabled with -fexceptions even if the + // language itself doesn't support exceptions. + if (ExceptionsEnabled && DidHaveExplicitExceptionFlag) + ShouldUseExceptionTables = true; - if (types::isObjC(InputType)) - return shouldUseExceptionTablesForObjCExceptions(Args, Triple); + if (types::isObjC(InputType)) { + bool ObjCExceptionsEnabled = ExceptionsEnabled; + + if (Arg *A = Args.getLastArg(options::OPT_fobjc_exceptions, + options::OPT_fno_objc_exceptions, + options::OPT_fexceptions, + options::OPT_fno_exceptions)) { + if (A->getOption().matches(options::OPT_fobjc_exceptions)) + ObjCExceptionsEnabled = true; + else if (A->getOption().matches(options::OPT_fno_objc_exceptions)) + ObjCExceptionsEnabled = false; + } - return false; + if (ObjCExceptionsEnabled) { + CmdArgs.push_back("-fobjc-exceptions"); + + ShouldUseExceptionTables |= + shouldUseExceptionTablesForObjCExceptions(Args, Triple); + } + } + + if (types::isCXX(InputType)) { + bool CXXExceptionsEnabled = ExceptionsEnabled; + + if (Arg *A = Args.getLastArg(options::OPT_fcxx_exceptions, + options::OPT_fno_cxx_exceptions, + options::OPT_fexceptions, + options::OPT_fno_exceptions)) { + if (A->getOption().matches(options::OPT_fcxx_exceptions)) + CXXExceptionsEnabled = true; + else + CXXExceptionsEnabled = false; + } + + if (CXXExceptionsEnabled) { + CmdArgs.push_back("-fcxx-exceptions"); + + ShouldUseExceptionTables = true; + } + } + + if (ShouldUseExceptionTables) + CmdArgs.push_back("-fexceptions"); } void Clang::ConstructJob(Compilation &C, const JobAction &JA, @@ -1416,10 +1475,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, false)) CmdArgs.push_back("-fno-elide-constructors"); - // -fexceptions=0 is default. - if (!KernelOrKext && - needsExceptions(Args, InputType, getToolChain().getTriple())) - CmdArgs.push_back("-fexceptions"); + // Add exception args. + addExceptionArgs(Args, InputType, getToolChain().getTriple(), + KernelOrKext, IsRewriter, CmdArgs); if (getToolChain().UseSjLjExceptions()) CmdArgs.push_back("-fsjlj-exceptions"); @@ -1556,11 +1614,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, getToolChain().IsObjCDefaultSynthPropertiesDefault())) { CmdArgs.push_back("-fobjc-default-synthesize-properties"); } - - // -fno-objc-exceptions is default. - if (IsRewriter || Args.hasFlag(options::OPT_fobjc_exceptions, - options::OPT_fno_objc_exceptions)) - CmdArgs.push_back("-fobjc-exceptions"); } if (!Args.hasFlag(options::OPT_fassume_sane_operator_new, diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 6dd7aabaa1..bdbb90839a 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -477,7 +477,7 @@ Sema::ActOnCXXNullPtrLiteral(SourceLocation Loc) { ExprResult Sema::ActOnCXXThrow(SourceLocation OpLoc, Expr *Ex) { // Don't report an error if 'throw' is used in system headers. - if (!getLangOptions().Exceptions && + if (!getLangOptions().CXXExceptions && !getSourceManager().isInSystemHeader(OpLoc)) Diag(OpLoc, diag::err_exceptions_disabled) << "throw"; diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index 89957e60de..a45fa3b7d1 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -1766,7 +1766,7 @@ StmtResult Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock, MultiStmtArg RawHandlers) { // Don't report an error if 'try' is used in system headers. - if (!getLangOptions().Exceptions && + if (!getLangOptions().CXXExceptions && !getSourceManager().isInSystemHeader(TryLoc)) Diag(TryLoc, diag::err_exceptions_disabled) << "try";