diff --git a/docs/ReleaseNotes.md b/docs/ReleaseNotes.md index 9830fddf..2f78acc7 100644 --- a/docs/ReleaseNotes.md +++ b/docs/ReleaseNotes.md @@ -40,6 +40,8 @@ Experimental Features * Dynamic Scopes: * Precompiled Headers: cling now has the ability to generate precompiled headers cling -x c++-header InputHeader.h -o Output.pch +* Preprocessed Output: cling now has the ability to generate preprocessed output +cling -E -dM will show all preprocessor definitions Fixed Bugs diff --git a/lib/Interpreter/CIFactory.cpp b/lib/Interpreter/CIFactory.cpp index ca75f40d..34c5f3c2 100644 --- a/lib/Interpreter/CIFactory.cpp +++ b/lib/Interpreter/CIFactory.cpp @@ -27,7 +27,6 @@ #include "clang/Frontend/FrontendDiagnostic.h" #include "clang/Frontend/TextDiagnosticPrinter.h" #include "clang/Frontend/VerifyDiagnosticConsumer.h" -#include "clang/FrontendTool/Utils.h" #include "clang/Serialization/SerializationDiagnostic.h" #include "clang/Lex/Preprocessor.h" #include "clang/Sema/Sema.h" @@ -639,11 +638,12 @@ static void stringifyPreprocSetting(PreprocessorOptions& PPOpts, class ActionScan { std::set m_Visited; - const clang::driver::Action::ActionClass m_Kind; + llvm::SmallVector m_Kinds; bool find (const clang::driver::Action* A) { if (A && !m_Visited.count(A)) { - if (A->getKind() == m_Kind) + if (std::find(m_Kinds.begin(), m_Kinds.end(), A->getKind()) != + m_Kinds.end()) return true; m_Visited.insert(A); @@ -653,7 +653,11 @@ static void stringifyPreprocSetting(PreprocessorOptions& PPOpts, } public: - ActionScan(clang::driver::Action::ActionClass k) : m_Kind(k) {} + ActionScan(clang::driver::Action::ActionClass a, int b = -1) { + m_Kinds.push_back(a); + if (b != -1) + m_Kinds.push_back(clang::driver::Action::ActionClass(b)); + } bool find (clang::driver::Compilation* C) { for (clang::driver::Action* A : C->getActions()) { @@ -667,7 +671,7 @@ static void stringifyPreprocSetting(PreprocessorOptions& PPOpts, static CompilerInstance* createCIImpl(std::unique_ptr Buffer, const CompilerOptions& COpts, const char* LLVMDir, - bool OnlyLex) { + bool OnlyLex, bool HasInput = false) { // Follow clang -v convention of printing version on first line if (COpts.Verbose) cling::log() << "cling version " << ClingStringify(CLING_VERSION) << '\n'; @@ -712,8 +716,7 @@ static void stringifyPreprocSetting(PreprocessorOptions& PPOpts, } #endif - const bool genOutput = COpts.HasOutput && !OnlyLex; - if (!genOutput) { + if (!COpts.HasOutput || !HasInput) { argvCompile.push_back("-c"); argvCompile.push_back("-"); } @@ -762,17 +765,18 @@ static void stringifyPreprocSetting(PreprocessorOptions& PPOpts, InvocationPtr.release(); CI->setDiagnostics(Diags.get()); // Diags is ref-counted - if (genOutput) { - ActionScan scan(clang::driver::Action::PrecompileJobClass); + if (COpts.HasOutput && !OnlyLex) { + ActionScan scan(clang::driver::Action::PrecompileJobClass, + clang::driver::Action::PreprocessJobClass); if (!scan.find(Compilation.get())) { - cling::errs() << "Only output to precompiled header is supported.\n"; + cling::errs() << "Only precompiled header or preprocessor " + "output is supported.\n"; return nullptr; } if (!SetupCompiler(CI.get(), true)) return nullptr; ProcessWarningOptions(*Diags, DiagOpts); - ExecuteCompilerInvocation(CI.get()); return CI.release(); } @@ -941,7 +945,8 @@ CompilerInstance* CIFactory::createCI(llvm::StringRef Code, const InvocationOptions& Opts, const char* LLVMDir) { return createCIImpl(llvm::MemoryBuffer::getMemBuffer(Code), - Opts.CompilerOpts, LLVMDir, false /*OnlyLex*/); + Opts.CompilerOpts, LLVMDir, false /*OnlyLex*/, + Opts.Inputs.size() > 0); } CompilerInstance* CIFactory::createCI(MemBufPtr_t Buffer, int argc, diff --git a/lib/Interpreter/CMakeLists.txt b/lib/Interpreter/CMakeLists.txt index a24c8502..8e577028 100644 --- a/lib/Interpreter/CMakeLists.txt +++ b/lib/Interpreter/CMakeLists.txt @@ -9,7 +9,6 @@ set(LIBS clangDriver clangFrontend - clangFrontendTool clangParse clangSema clangAST diff --git a/lib/Interpreter/InvocationOptions.cpp b/lib/Interpreter/InvocationOptions.cpp index d0941412..2b2c8738 100644 --- a/lib/Interpreter/InvocationOptions.cpp +++ b/lib/Interpreter/InvocationOptions.cpp @@ -114,7 +114,7 @@ void CompilerOptions::Parse(int argc, const char* const argv[], for (const Arg* arg : Args) { switch (arg->getOption().getID()) { // case options::OPT_d_Flag: - // case options::OPT_E: + case options::OPT_E: case options::OPT_o: HasOutput = true; break; case options::OPT_x: Language = true; break; case options::OPT_resource_dir: ResourceDir = true; break; diff --git a/test/Driver/E.C b/test/Driver/E.C new file mode 100644 index 00000000..782dd236 --- /dev/null +++ b/test/Driver/E.C @@ -0,0 +1,15 @@ +//------------------------------------------------------------------------------ +// CLING - the C++ LLVM-based InterpreterG :) +// +// This file is dual-licensed: you can choose to license it under the University +// of Illinois Open Source License or the GNU Lesser General Public License. See +// LICENSE.TXT for details. +//------------------------------------------------------------------------------ + +// RUN: %cling -dM -E -xc++ /dev/null | grep CLING | FileCheck %s + +// CHECK: #define __CLING__ 1 +// CHECK: #define __CLING__CXX11 1 +// CHECK: #define __CLING__{{GNUC|clang}} + +.q diff --git a/tools/driver/CMakeLists.txt b/tools/driver/CMakeLists.txt index fe2f2b5e..fec00b6c 100644 --- a/tools/driver/CMakeLists.txt +++ b/tools/driver/CMakeLists.txt @@ -12,6 +12,7 @@ set(LLVM_NO_DEAD_STRIP 1) if(BUILD_SHARED_LIBS) set(LIBS LLVMSupport + clangFrontendTool clingInterpreter clingMetaProcessor clingUserInterface @@ -23,6 +24,7 @@ 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 7846d5af..89ae3938 100644 --- a/tools/driver/cling.cpp +++ b/tools/driver/cling.cpp @@ -13,6 +13,7 @@ #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" @@ -50,6 +51,7 @@ static int checkDiagErrors(clang::CompilerInstance* CI, unsigned* OutErrs = 0) { return Errs ? EXIT_FAILURE : EXIT_SUCCESS; } + int main( int argc, char **argv ) { llvm::llvm_shutdown_obj shutdownTrigger; @@ -79,8 +81,10 @@ int main( int argc, char **argv ) { if (!interp.isValid()) { unsigned ErrsReported = 0; if (clang::CompilerInstance* CI = interp.getCIOrNull()) { - // If output requested let the DiagnosticsEngine determine the result code - if (interp.getOptions().CompilerOpts.HasOutput) + // If output requested and execution succeeded let the DiagnosticsEngine + // determine the result code + if (interp.getOptions().CompilerOpts.HasOutput && + ExecuteCompilerInvocation(CI)) return checkDiagErrors(CI); checkDiagErrors(CI, &ErrsReported); @@ -92,9 +96,11 @@ int main( int argc, char **argv ) { return EXIT_FAILURE; } + if (interp.getOptions().Help || interp.getOptions().ShowVersion) return EXIT_SUCCESS; + interp.AddIncludePath("."); for (size_t I = 0, N = interp.getOptions().LibsToLoad.size(); I < N; ++I) { diff --git a/tools/libcling/CMakeLists.txt b/tools/libcling/CMakeLists.txt index 6a8204e4..828ac5cc 100644 --- a/tools/libcling/CMakeLists.txt +++ b/tools/libcling/CMakeLists.txt @@ -13,7 +13,6 @@ set(SOURCES set(LIBS clangDriver clangFrontend - clangFrontendTool clangParse clangSema clangAST