Index: clang/tools/clang-repl/ClangRepl.cpp =================================================================== --- clang/tools/clang-repl/ClangRepl.cpp +++ clang/tools/clang-repl/ClangRepl.cpp @@ -28,6 +28,8 @@ llvm::cl::CommaSeparated); static llvm::cl::opt OptHostSupportsJit("host-supports-jit", llvm::cl::Hidden); +static llvm::cl::opt OptHostSupportsException("host-supports-exception", + llvm::cl::Hidden); static llvm::cl::list OptInputs(llvm::cl::Positional, llvm::cl::desc("[code to run]")); @@ -65,6 +67,35 @@ return Errs ? EXIT_FAILURE : EXIT_SUCCESS; } +// Check if the host environment supports c++ exception handling +// by querying the existence of symbol __cxa_throw. +static bool checkExceptionSupport() { + auto J = llvm::orc::LLJITBuilder().create(); + if (!J) { + llvm::consumeError(J.takeError()); + return false; + } + + auto Interp = clang::Interpreter::create(std::move(CI)); + if (!Interp) { + llvm::consumeError(Interp.takeError()); + return false; + } + + if (auto Err = Interp->ParseAndExecute("")) { + llvm::consumeError(std::move(Err)); + return false; + } + + auto Sym = Interp->getSymbolAddress("__cxa_throw"); + if (!Sym) { + llvm::consumeError(Sym.takeError()); + return false; + } + + return true; +} + llvm::ExitOnError ExitOnErr; int main(int argc, const char **argv) { ExitOnErr.setBanner("clang-repl: "); @@ -87,6 +118,14 @@ return 0; } + if (OptHostSupportsException) { + if (checkExceptionSupport()) + llvm::outs() << "true\n"; + else + llvm::outs() << "false\n"; + return 0; + } + // FIXME: Investigate if we could use runToolOnCodeWithArgs from tooling. It // can replace the boilerplate code for creation of the compiler instance. auto CI = ExitOnErr(clang::IncrementalCompilerBuilder::create(ClangArgv));