r211909 - clang-cl: Map /EHs- to -fno-exceptions

Reid Kleckner reid at kleckner.net
Fri Jun 27 10:02:02 PDT 2014


Author: rnk
Date: Fri Jun 27 12:02:02 2014
New Revision: 211909

URL: http://llvm.org/viewvc/llvm-project?rev=211909&view=rev
Log:
clang-cl: Map /EHs- to -fno-exceptions

This isn't 100% compatible with MSVC, but it's close enough.  MSVC's /EH
flag doesn't really control exceptions so much as how to clean up after
an exception is thrown.  The upshot is that cl.exe /EHs- will compile
try, throw, and catch statements with a warning, but clang-cl will
reject such constructs with a hard error.  We can't compile such EH
constructs anyway, but this may matter to consumers of the AST.

Reviewers: hans

Differential Revision: http://reviews.llvm.org/D4317

Added:
    cfe/trunk/test/Driver/cl-eh.cpp
Modified:
    cfe/trunk/include/clang/Driver/CLCompatOptions.td
    cfe/trunk/lib/Driver/Tools.cpp
    cfe/trunk/test/Driver/cl-fallback.c

Modified: cfe/trunk/include/clang/Driver/CLCompatOptions.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/CLCompatOptions.td?rev=211909&r1=211908&r2=211909&view=diff
==============================================================================
--- cfe/trunk/include/clang/Driver/CLCompatOptions.td (original)
+++ cfe/trunk/include/clang/Driver/CLCompatOptions.td Fri Jun 27 12:02:02 2014
@@ -140,6 +140,7 @@ def _SLASH_Zs : CLFlag<"Zs">, HelpText<"
 
 def _SLASH_M_Group : OptionGroup<"</M group>">, Group<cl_compile_Group>;
 
+def _SLASH_EH : CLJoined<"EH">, HelpText<"Exception handling model">;
 def _SLASH_EP : CLFlag<"EP">,
   HelpText<"Disable linemarker output and preprocess to stdout">;
 def _SLASH_FA : CLFlag<"FA">,
@@ -209,7 +210,6 @@ def _SLASH_bigobj : CLFlag<"bigobj">;
 def _SLASH_clr : CLJoined<"clr">;
 def _SLASH_d2Zi_PLUS : CLFlag<"d2Zi+">;
 def _SLASH_doc : CLJoined<"doc">;
-def _SLASH_EH : CLJoined<"EH">;
 def _SLASH_FA_joined : CLJoined<"FA">;
 def _SLASH_favor : CLJoined<"favor">;
 def _SLASH_FC : CLFlag<"FC">;

Modified: cfe/trunk/lib/Driver/Tools.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Tools.cpp?rev=211909&r1=211908&r2=211909&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/Tools.cpp (original)
+++ cfe/trunk/lib/Driver/Tools.cpp Fri Jun 27 12:02:02 2014
@@ -3846,9 +3846,10 @@ void Clang::ConstructJob(Compilation &C,
     }
   }
 
-  // Add exception args.
-  addExceptionArgs(Args, InputType, getToolChain().getTriple(),
-                   KernelOrKext, objcRuntime, CmdArgs);
+  // Handle GCC-style exception args.
+  if (!C.getDriver().IsCLMode())
+    addExceptionArgs(Args, InputType, getToolChain().getTriple(), KernelOrKext,
+                     objcRuntime, CmdArgs);
 
   if (getToolChain().UseSjLjExceptions())
     CmdArgs.push_back("-fsjlj-exceptions");
@@ -4352,6 +4353,45 @@ ObjCRuntime Clang::AddObjCRuntimeArgs(co
   return runtime;
 }
 
+static bool maybeConsumeDash(const std::string &EH, size_t &I) {
+  bool HaveDash = (I + 1 < EH.size() && EH[I + 1] == '-');
+  I += HaveDash;
+  return !HaveDash;
+};
+
+struct EHFlags {
+  EHFlags() : Synch(false), Asynch(false), NoExceptC(false) {}
+  bool Synch;
+  bool Asynch;
+  bool NoExceptC;
+};
+
+/// /EH controls whether to run destructor cleanups when exceptions are
+/// thrown.  There are three modifiers:
+/// - 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.
+/// The default is /EHs-c-, meaning cleanups are disabled.
+static EHFlags parseClangCLEHFlags(const Driver &D, const ArgList &Args) {
+  EHFlags EH;
+  std::vector<std::string> EHArgs = Args.getAllArgValues(options::OPT__SLASH_EH);
+  for (auto EHVal : EHArgs) {
+    for (size_t I = 0, E = EHVal.size(); I != E; ++I) {
+      switch (EHVal[I]) {
+      case 'a': EH.Asynch = maybeConsumeDash(EHVal, I); continue;
+      case 'c': EH.NoExceptC = maybeConsumeDash(EHVal, I); continue;
+      case 's': EH.Synch = maybeConsumeDash(EHVal, I); continue;
+      default: break;
+      }
+      D.Diag(clang::diag::err_drv_invalid_value) << "/EH" << EHVal;
+      break;
+    }
+  }
+  return EH;
+}
+
 void Clang::AddClangCLArgs(const ArgList &Args, ArgStringList &CmdArgs) const {
   unsigned RTOptionID = options::OPT__SLASH_MT;
 
@@ -4404,13 +4444,20 @@ void Clang::AddClangCLArgs(const ArgList
   if (!Args.hasArg(options::OPT_frtti, options::OPT_fno_rtti))
     CmdArgs.push_back("-fno-rtti");
 
+  const Driver &D = getToolChain().getDriver();
+  EHFlags EH = parseClangCLEHFlags(D, Args);
+  // FIXME: Do something with NoExceptC.
+  if (EH.Synch || EH.Asynch) {
+    CmdArgs.push_back("-fexceptions");
+    CmdArgs.push_back("-fcxx-exceptions");
+  }
+
   // /EP should expand to -E -P.
   if (Args.hasArg(options::OPT__SLASH_EP)) {
     CmdArgs.push_back("-E");
     CmdArgs.push_back("-P");
   }
 
-  const Driver &D = getToolChain().getDriver();
   Arg *MostGeneralArg = Args.getLastArg(options::OPT__SLASH_vmg);
   Arg *BestCaseArg = Args.getLastArg(options::OPT__SLASH_vmb);
   if (MostGeneralArg && BestCaseArg)
@@ -7692,6 +7739,7 @@ Command *visualstudio::Compile::GetComma
   // Flags that can simply be passed through.
   Args.AddAllArgs(CmdArgs, options::OPT__SLASH_LD);
   Args.AddAllArgs(CmdArgs, options::OPT__SLASH_LDd);
+  Args.AddAllArgs(CmdArgs, options::OPT__SLASH_EH);
 
   // The order of these flags is relevant, so pick the last one.
   if (Arg *A = Args.getLastArg(options::OPT__SLASH_MD, options::OPT__SLASH_MDd,

Added: cfe/trunk/test/Driver/cl-eh.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/cl-eh.cpp?rev=211909&view=auto
==============================================================================
--- cfe/trunk/test/Driver/cl-eh.cpp (added)
+++ cfe/trunk/test/Driver/cl-eh.cpp Fri Jun 27 12:02:02 2014
@@ -0,0 +1,24 @@
+// Don't attempt slash switches on msys bash.
+// REQUIRES: shell-preserves-root
+
+// Note: %s must be preceded by --, otherwise it may be interpreted as a
+// command-line option, e.g. on Mac where %s is commonly under /Users.
+
+// RUN: %clang_cl /c /EHsc -### -- %s 2>&1 | FileCheck -check-prefix=EHsc %s
+// EHsc: "-fexceptions"
+
+// RUN: %clang_cl /c /EHs-c- -### -- %s 2>&1 | FileCheck -check-prefix=EHs_c_ %s
+// EHs_c_-NOT: "-fexceptions"
+
+// RUN: %clang_cl /c /EHs- /EHc- -### -- %s 2>&1 | FileCheck -check-prefix=EHs_EHc_ %s
+// EHs_EHc_-NOT: "-fexceptions"
+
+// RUN: %clang_cl /c /EHs- /EHs -### -- %s 2>&1 | FileCheck -check-prefix=EHs_EHs %s
+// EHs_EHs: "-fexceptions"
+
+// RUN: %clang_cl /c /EHs- /EHsa -### -- %s 2>&1 | FileCheck -check-prefix=EHs_EHa %s
+// EHs_EHa: "-fexceptions"
+
+// RUN: %clang_cl /c /EHinvalid -### -- %s 2>&1 | FileCheck -check-prefix=EHinvalid %s
+// EHinvalid: error: invalid value 'invalid' in '/EH'
+// EHinvalid-NOT: error:

Modified: cfe/trunk/test/Driver/cl-fallback.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/cl-fallback.c?rev=211909&r1=211908&r2=211909&view=diff
==============================================================================
--- cfe/trunk/test/Driver/cl-fallback.c (original)
+++ cfe/trunk/test/Driver/cl-fallback.c Fri Jun 27 12:02:02 2014
@@ -5,7 +5,7 @@
 // command-line option, e.g. on Mac where %s is commonly under /Users.
 
 // RUN: %clang_cl /fallback /Dfoo=bar /Ubaz /Ifoo /O0 /Ox /GR /GR- /Gy /Gy- \
-// RUN:   /Gw /Gw- /LD /LDd /MD /MDd /MTd /MT /FImyheader.h /Zi \
+// RUN:   /Gw /Gw- /LD /LDd /EHs /EHs- /MD /MDd /MTd /MT /FImyheader.h /Zi \
 // RUN:   -### -- %s 2>&1 \
 // RUN:   | FileCheck %s
 // CHECK: "-fdiagnostics-format" "msvc-fallback"
@@ -25,6 +25,8 @@
 // CHECK: "/FImyheader.h"
 // CHECK: "/LD"
 // CHECK: "/LDd"
+// CHECK: "/EHs"
+// CHECK: "/EHs-"
 // CHECK: "/MT"
 // CHECK: "/Tc" "{{.*cl-fallback.c}}"
 // CHECK: "/Fo{{.*cl-fallback.*.obj}}"





More information about the cfe-commits mailing list