From 71f3eccbfc2c7c0ad2bbdcb96481d29f568b7a91 Mon Sep 17 00:00:00 2001 From: Frederich Munch Date: Sun, 19 Mar 2017 17:02:49 -0400 Subject: [PATCH] Add Interpreter::verifyDiagnostics and Interpreter::executeInvocation methods. Moves the implementation details outside of cling.cpp. --- include/cling/Interpreter/Interpreter.h | 17 +++++++++ lib/Interpreter/CMakeLists.txt | 1 + lib/Interpreter/Interpreter.cpp | 31 +++++++++++++++ tools/driver/CMakeLists.txt | 2 - tools/driver/cling.cpp | 50 ++++++------------------- tools/libcling/CMakeLists.txt | 1 + 6 files changed, 62 insertions(+), 40 deletions(-) diff --git a/include/cling/Interpreter/Interpreter.h b/include/cling/Interpreter/Interpreter.h index 0c23a90519..84dbd9db59 100644 --- a/include/cling/Interpreter/Interpreter.h +++ b/include/cling/Interpreter/Interpreter.h @@ -768,6 +768,23 @@ namespace cling { /// void addModule(llvm::Module* module, int OptLevel); + ///\brief Execute compiler invocation for output. + /// This should not be called in interactive sessions, rather when cling + /// is used to generate output: cling -E -o + /// Safe to call even if Interpreter::isValid() returns false. + /// + ///\returns Whether execution was successful. + /// + CompilationResult executeInvocation() const; + + ///\brief Run the diagnostics verifier if cling was invoked with the -verify + /// flag. Of particular importance to the test-suite. + /// Safe to call even if Interpreter::isValid() returns false. + /// + ///\returns The number of errors reported or -1 if Interpreter was invalid. + /// + int verifyDiagnostics() const; + void GenerateAutoloadingMap(llvm::StringRef inFile, llvm::StringRef outFile, bool enableMacros = false, bool enableLogs = true); diff --git a/lib/Interpreter/CMakeLists.txt b/lib/Interpreter/CMakeLists.txt index dd243ad919..e0c3a1e5f3 100644 --- a/lib/Interpreter/CMakeLists.txt +++ b/lib/Interpreter/CMakeLists.txt @@ -9,6 +9,7 @@ set(LIBS clangDriver clangFrontend + clangFrontendTool clangParse clangSema clangAST diff --git a/lib/Interpreter/Interpreter.cpp b/lib/Interpreter/Interpreter.cpp index 50965d7156..b89d6ea8b0 100644 --- a/lib/Interpreter/Interpreter.cpp +++ b/lib/Interpreter/Interpreter.cpp @@ -46,6 +46,7 @@ #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/Utils.h" #include "clang/Lex/ExternalPreprocessorSource.h" +#include "clang/FrontendTool/Utils.h" #include "clang/Lex/HeaderSearch.h" #include "clang/Lex/Preprocessor.h" #include "clang/Parse/Parser.h" @@ -1591,6 +1592,36 @@ namespace cling { T.setState(Transaction::kCommitted); } + int Interpreter::verifyDiagnostics() const { + clang::CompilerInstance* CI = getCIOrNull(); + if (!CI) + return -1; + + unsigned Errs = CI->getDiagnostics().getClient()->getNumErrors(); + if (CI->getDiagnosticOpts().VerifyDiagnostics) { + // If there was an error that came from the verifier we must return 1 as + // an exit code for the process. This will make the test fail as expected. + clang::DiagnosticConsumer* Client = CI->getDiagnostics().getClient(); + Client->EndSourceFile(); + Errs = Client->getNumErrors(); + + // The interpreter expects BeginSourceFile/EndSourceFiles to be balanced. + Client->BeginSourceFile(CI->getLangOpts(), &CI->getPreprocessor()); + } + return Errs; + } + + Interpreter::CompilationResult Interpreter::executeInvocation() const { + if (!m_Opts.CompilerOpts.HasOutput) + return kMoreInputExpected; + + if (clang::CompilerInstance* CI = getCIOrNull()) { + if (clang::ExecuteCompilerInvocation(CI)) + return kSuccess; + } + return kFailure; + } + namespace runtime { namespace internal { Value EvaluateDynamicExpression(Interpreter* interp, DynamicExprInfo* DEI, diff --git a/tools/driver/CMakeLists.txt b/tools/driver/CMakeLists.txt index 2a0d700432..719314de32 100644 --- a/tools/driver/CMakeLists.txt +++ b/tools/driver/CMakeLists.txt @@ -12,7 +12,6 @@ set(LLVM_NO_DEAD_STRIP 1) if(BUILD_SHARED_LIBS) set(LIBS LLVMSupport - clangFrontendTool clingInterpreter clingMetaProcessor clingUserInterface @@ -24,7 +23,6 @@ if(BUILD_SHARED_LIBS) else() set(LIBS LLVMSupport - clangFrontendTool clingUserInterface ) add_cling_executable(cling diff --git a/tools/driver/cling.cpp b/tools/driver/cling.cpp index 15089dfea0..760ceff39b 100644 --- a/tools/driver/cling.cpp +++ b/tools/driver/cling.cpp @@ -11,10 +11,6 @@ #include "cling/MetaProcessor/MetaProcessor.h" #include "cling/UserInterface/UserInterface.h" -#include "clang/Basic/LangOptions.h" -#include "clang/Frontend/CompilerInstance.h" -#include "clang/FrontendTool/Utils.h" - #include "llvm/Support/Signals.h" #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/ManagedStatic.h" @@ -28,29 +24,6 @@ #include #endif -// If we are running with -verify a reported has to be returned as unsuccess. -// This is relevant especially for the test suite. -static int checkDiagErrors(clang::CompilerInstance* CI, unsigned* OutErrs = 0) { - - unsigned Errs = CI->getDiagnostics().getClient()->getNumErrors(); - - if (CI->getDiagnosticOpts().VerifyDiagnostics) { - // If there was an error that came from the verifier we must return 1 as - // an exit code for the process. This will make the test fail as expected. - clang::DiagnosticConsumer* Client = CI->getDiagnostics().getClient(); - Client->EndSourceFile(); - Errs = Client->getNumErrors(); - - // The interpreter expects BeginSourceFile/EndSourceFiles to be balanced. - Client->BeginSourceFile(CI->getLangOpts(), &CI->getPreprocessor()); - } - - if (OutErrs) - *OutErrs = Errs; - - return Errs ? EXIT_FAILURE : EXIT_SUCCESS; -} - int main( int argc, char **argv ) { @@ -83,18 +56,19 @@ int main( int argc, char **argv ) { if (Opts.Help || Opts.ShowVersion) return EXIT_SUCCESS; - unsigned ErrsReported = 0; - if (clang::CompilerInstance* CI = Interp.getCIOrNull()) { - // If output requested and execution succeeded let the DiagnosticsEngine - // determine the result code - if (Opts.CompilerOpts.HasOutput && ExecuteCompilerInvocation(CI)) - return checkDiagErrors(CI); + using namespace cling; + const Interpreter::CompilationResult ExecRes = Interp.executeInvocation(); + if (ExecRes != Interpreter::kFailure) { + const int ErrsReported = Interp.verifyDiagnostics(); - checkDiagErrors(CI, &ErrsReported); - } + // If output succeeded and diagnostics verified, we are done. + if (ExecRes == Interpreter::kSuccess && !ErrsReported) + return EXIT_SUCCESS; - // If no errors have been reported, try perror - if (ErrsReported == 0) + // FIXME: This info is barely useful + if (ErrsReported <= 0) + ::fprintf(stderr, "Unknown error"); + } else ::perror("Could not create Interpreter instance"); return EXIT_FAILURE; @@ -138,5 +112,5 @@ int main( int argc, char **argv ) { ::fflush(stdout); ::fflush(stderr); - return checkDiagErrors(Interp.getCI()); + return Interp.verifyDiagnostics() ? EXIT_FAILURE : EXIT_SUCCESS; } diff --git a/tools/libcling/CMakeLists.txt b/tools/libcling/CMakeLists.txt index fc3c1a66a8..2a728fd481 100644 --- a/tools/libcling/CMakeLists.txt +++ b/tools/libcling/CMakeLists.txt @@ -13,6 +13,7 @@ set(SOURCES set(LIBS clangDriver clangFrontend + clangFrontendTool clangParse clangSema clangAST