Hi hans,
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.
http://reviews.llvm.org/D4317
Files:
include/clang/Driver/CLCompatOptions.td
lib/Driver/Tools.cpp
test/Driver/cl-eh.cpp
Index: include/clang/Driver/CLCompatOptions.td
===================================================================
--- include/clang/Driver/CLCompatOptions.td
+++ include/clang/Driver/CLCompatOptions.td
@@ -140,6 +140,7 @@
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_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">;
Index: lib/Driver/Tools.cpp
===================================================================
--- lib/Driver/Tools.cpp
+++ lib/Driver/Tools.cpp
@@ -3844,9 +3844,10 @@
}
}
- // 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,8 @@
}
void Clang::AddClangCLArgs(const ArgList &Args, ArgStringList &CmdArgs) const {
+ const Driver &D = getToolChain().getDriver();
+
unsigned RTOptionID = options::OPT__SLASH_MT;
if (Args.hasArg(options::OPT__SLASH_LDd))
@@ -4403,13 +4406,47 @@
if (!Args.hasArg(options::OPT_frtti, options::OPT_fno_rtti))
CmdArgs.push_back("-fno-rtti");
+ // /EH controls the 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.
+ bool SynchEH = false;
+ bool AsynchEH = false;
+ bool NoExceptC = false;
+ std::vector<std::string> EHArgs = Args.getAllArgValues(options::OPT__SLASH_EH);
+ auto maybeConsumeDash = [](const std::string &EH, size_t &I) {
+ bool HaveDash = (I + 1 < EH.size() && EH[I + 1] == '-');
+ I += HaveDash;
+ return !HaveDash;
+ };
+ for (auto EH : EHArgs) {
+ for (size_t I = 0, E = EH.size(); I != E; ++I) {
+ switch (EH[I]) {
+ case 'a': AsynchEH = maybeConsumeDash(EH, I); continue;
+ case 'c': NoExceptC = maybeConsumeDash(EH, I); continue;
+ case 's': SynchEH = maybeConsumeDash(EH, I); continue;
+ default: break;
+ }
+ D.Diag(clang::diag::err_drv_invalid_value) << "/EH" << EH;
+ break;
+ }
+ }
+ (void)NoExceptC; // FIXME: Do something with the 'c' modifier.
+ if (SynchEH || AsynchEH) {
+ 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)
Index: test/Driver/cl-eh.cpp
===================================================================
--- /dev/null
+++ test/Driver/cl-eh.cpp
@@ -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:
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits