//------------------------------------------------------------------------------ // CLING - the C++ LLVM-based InterpreterG :) // author: Lukasz Janyst // // 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. //------------------------------------------------------------------------------ #include "cling/Interpreter/Interpreter.h" #include "ClingUtils.h" #include "cling-compiledata.h" #include "DynamicLookup.h" #include "ForwardDeclPrinter.h" #include "IncrementalExecutor.h" #include "IncrementalParser.h" #include "MultiplexInterpreterCallbacks.h" #include "cling/Interpreter/CIFactory.h" #include "cling/Interpreter/ClangInternalState.h" #include "cling/Interpreter/CompilationOptions.h" #include "cling/Interpreter/DynamicLibraryManager.h" #include "cling/Interpreter/LookupHelper.h" #include "cling/Interpreter/Transaction.h" #include "cling/Interpreter/Value.h" #include "cling/Utils/AST.h" #include "cling/Interpreter/AutoloadCallback.h" #include "clang/AST/ASTContext.h" #include "clang/AST/GlobalDecl.h" #include "clang/Basic/TargetInfo.h" #include "clang/Basic/SourceManager.h" #include "clang/CodeGen/ModuleBuilder.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/Utils.h" #include "clang/Lex/Preprocessor.h" #include "clang/Parse/Parser.h" #include "clang/Sema/Sema.h" #include "clang/Sema/SemaDiagnostic.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" #include #include #include using namespace clang; namespace { static cling::Interpreter::ExecutionResult ConvertExecutionResult(cling::IncrementalExecutor::ExecutionResult ExeRes) { switch (ExeRes) { case cling::IncrementalExecutor::kExeSuccess: return cling::Interpreter::kExeSuccess; case cling::IncrementalExecutor::kExeFunctionNotCompiled: return cling::Interpreter::kExeFunctionNotCompiled; case cling::IncrementalExecutor::kExeUnresolvedSymbols: return cling::Interpreter::kExeUnresolvedSymbols; default: break; } return cling::Interpreter::kExeSuccess; } static bool isPracticallyEmptyModule(const llvm::Module* M) { return M->empty() && M->global_empty() && M->alias_empty(); } } // unnamed namespace namespace cling { Interpreter::PushTransactionRAII::PushTransactionRAII(const Interpreter* i) : m_Interpreter(i) { CompilationOptions CO; CO.DeclarationExtraction = 0; CO.ValuePrinting = 0; CO.ResultEvaluation = 0; CO.DynamicScoping = 0; CO.Debug = 0; CO.CodeGeneration = 1; CO.CodeGenerationForModule = 0; m_Transaction = m_Interpreter->m_IncrParser->beginTransaction(CO); } Interpreter::PushTransactionRAII::~PushTransactionRAII() { pop(); } void Interpreter::PushTransactionRAII::pop() const { IncrementalParser::ParseResultTransaction PRT = m_Interpreter->m_IncrParser->endTransaction(m_Transaction); if (PRT.getPointer()) { assert(PRT.getPointer()==m_Transaction && "Ended different transaction?"); m_Interpreter->m_IncrParser->commitTransaction(PRT); } } Interpreter::StateDebuggerRAII::StateDebuggerRAII(const Interpreter* i) : m_Interpreter(i) { if (!i->isPrintingDebug()) return; const CompilerInstance& CI = *m_Interpreter->getCI(); CodeGenerator* CG = i->m_IncrParser->getCodeGenerator(); // The ClangInternalState constructor can provoke deserialization, // we need a transaction. PushTransactionRAII pushedT(i); m_State.reset(new ClangInternalState(CI.getASTContext(), CI.getPreprocessor(), CG ? CG->GetModule() : 0, CG, "aName")); } Interpreter::StateDebuggerRAII::~StateDebuggerRAII() { // The ClangInternalState destructor can provoke deserialization, // we need a transaction. PushTransactionRAII pushedT(m_Interpreter); pop(); } void Interpreter::StateDebuggerRAII::pop() const { if (!m_Interpreter->isPrintingDebug()) return; m_State->compare("aName"); } // This function isn't referenced outside its translation unit, but it // can't use the "static" keyword because its address is used for // GetMainExecutable (since some platforms don't support taking the // address of main, and some platforms can't implement GetMainExecutable // without being given the address of a function in the main executable). std::string GetExecutablePath(const char *Argv0) { // This just needs to be some symbol in the binary; C++ doesn't // allow taking the address of ::main however. void *MainAddr = (void*) (intptr_t) GetExecutablePath; return llvm::sys::fs::getMainExecutable(Argv0, MainAddr); } const Parser& Interpreter::getParser() const { return *m_IncrParser->getParser(); } Parser& Interpreter::getParser() { return *m_IncrParser->getParser(); } clang::SourceLocation Interpreter::getNextAvailableLoc() const { return m_IncrParser->getLastMemoryBufferEndLoc().getLocWithOffset(1); } bool Interpreter::isInSyntaxOnlyMode() const { return getCI()->getFrontendOpts().ProgramAction == clang::frontend::ParseSyntaxOnly; } Interpreter::Interpreter(int argc, const char* const *argv, const char* llvmdir /*= 0*/, bool noRuntime) : m_UniqueCounter(0), m_PrintDebug(false), m_DynamicLookupDeclared(false), m_DynamicLookupEnabled(false), m_RawInputEnabled(false) { m_LLVMContext.reset(new llvm::LLVMContext); std::vector LeftoverArgsIdx; m_Opts = InvocationOptions::CreateFromArgs(argc, argv, LeftoverArgsIdx); std::vector LeftoverArgs; for (size_t I = 0, N = LeftoverArgsIdx.size(); I < N; ++I) { LeftoverArgs.push_back(argv[LeftoverArgsIdx[I]]); } m_DyLibManager.reset(new DynamicLibraryManager(getOptions())); m_IncrParser.reset(new IncrementalParser(this, LeftoverArgs.size(), &LeftoverArgs[0], llvmdir)); Sema& SemaRef = getSema(); Preprocessor& PP = SemaRef.getPreprocessor(); // Enable incremental processing, which prevents the preprocessor destroying // the lexer on EOF token. PP.enableIncrementalProcessing(); m_LookupHelper.reset(new LookupHelper(new Parser(PP, SemaRef, /*SkipFunctionBodies*/false, /*isTemp*/true), this)); if (!isInSyntaxOnlyMode()) m_Executor.reset(new IncrementalExecutor(SemaRef.Diags, getCI()->getCodeGenOpts())); // Tell the diagnostic client that we are entering file parsing mode. DiagnosticConsumer& DClient = getCI()->getDiagnosticClient(); DClient.BeginSourceFile(getCI()->getLangOpts(), &PP); llvm::SmallVector IncrParserTransactions; m_IncrParser->Initialize(IncrParserTransactions); handleFrontendOptions(); AddRuntimeIncludePaths(argv[0]); if (!noRuntime) { if (getCI()->getLangOpts().CPlusPlus) IncludeCXXRuntime(); else IncludeCRuntime(); } // Commit the transactions, now that gCling is set up. It is needed for // static initialization in these transactions through local_cxa_atexit(). for (auto&& I: IncrParserTransactions) m_IncrParser->commitTransaction(I); // Disable suggestions for ROOT bool showSuggestions = !llvm::StringRef(ClingStringify(CLING_VERSION)).startswith("ROOT"); std::unique_ptr AutoLoadCB(new AutoloadCallback(this, showSuggestions)); setCallbacks(std::move(AutoLoadCB)); } Interpreter::~Interpreter() { if (m_Executor) m_Executor->shuttingDown(); for (size_t i = 0, e = m_StoredStates.size(); i != e; ++i) delete m_StoredStates[i]; getCI()->getDiagnostics().getClient()->EndSourceFile(); // We want to keep the callback alive during the shutdown of Sema, CodeGen // and the ASTContext. For that to happen we shut down the IncrementalParser // explicitly, before the implicit destruction (through the unique_ptr) of // the callbacks. m_IncrParser.reset(0); } const char* Interpreter::getVersion() const { return ClingStringify(CLING_VERSION); } void Interpreter::handleFrontendOptions() { if (m_Opts.ShowVersion) { llvm::errs() << getVersion() << '\n'; } if (m_Opts.Help) { m_Opts.PrintHelp(); } } void Interpreter::AddRuntimeIncludePaths(const char* argv0) { // Add configuration paths to interpreter's include files. #ifdef CLING_INCLUDE_PATHS llvm::StringRef InclPaths(CLING_INCLUDE_PATHS); for (std::pair Split = InclPaths.split(':'); !Split.second.empty(); Split = InclPaths.split(':')) { if (llvm::sys::fs::is_directory(Split.first)) AddIncludePath(Split.first); InclPaths = Split.second; } // Add remaining part AddIncludePath(InclPaths); #endif llvm::SmallString<512> P(GetExecutablePath(argv0)); if (!P.empty()) { // Remove /cling from foo/bin/clang llvm::StringRef ExeIncl = llvm::sys::path::parent_path(P); // Remove /bin from foo/bin ExeIncl = llvm::sys::path::parent_path(ExeIncl); P.resize(ExeIncl.size()); // Get foo/include llvm::sys::path::append(P, "include"); if (llvm::sys::fs::is_directory(P.str())) AddIncludePath(P.str()); } } void Interpreter::IncludeCXXRuntime() { // Set up common declarations which are going to be available // only at runtime // Make sure that the universe won't be included to compile time by using // -D __CLING__ as CompilerInstance's arguments std::stringstream initializer; #ifdef _WIN32 // We have to use the #defined __CLING__ on windows first. //FIXME: Find proper fix. initializer << "#ifdef __CLING__ \n#endif\n"; #endif initializer << "#include \"cling/Interpreter/RuntimeUniverse.h\"\n"; if (!isInSyntaxOnlyMode()) { // Set up the gCling variable if it can be used initializer << "namespace cling {namespace runtime { " "cling::Interpreter *gCling=(cling::Interpreter*)" << (uintptr_t)this << ";} }"; } declare(initializer.str()); } void Interpreter::IncludeCRuntime() { // Set up the gCling variable if it can be used std::stringstream initializer; initializer << "void* gCling=(void*)" << (uintptr_t)this << ';'; declare(initializer.str()); // declare("void setValueNoAlloc(void* vpI, void* vpSVR, void* vpQT);"); // declare("void setValueNoAlloc(void* vpI, void* vpV, void* vpQT, float value);"); // declare("void setValueNoAlloc(void* vpI, void* vpV, void* vpQT, double value);"); // declare("void setValueNoAlloc(void* vpI, void* vpV, void* vpQT, long double value);"); // declare("void setValueNoAlloc(void* vpI, void* vpV, void* vpQT, unsigned long long value);"); // declare("void setValueNoAlloc(void* vpI, void* vpV, void* vpQT, const void* value);"); // declare("void* setValueWithAlloc(void* vpI, void* vpV, void* vpQT);"); declare("#include \"cling/Interpreter/CValuePrinter.h\""); } void Interpreter::AddIncludePath(llvm::StringRef incpath) { // Add the given path to the list of directories in which the interpreter // looks for include files. Only one path item can be specified at a // time, i.e. "path1:path2" is not supported. CompilerInstance* CI = getCI(); HeaderSearchOptions& headerOpts = CI->getHeaderSearchOpts(); const bool IsFramework = false; const bool IsSysRootRelative = true; // Avoid duplicates; just return early if incpath is already in UserEntries. for (std::vector::const_iterator I = headerOpts.UserEntries.begin(), E = headerOpts.UserEntries.end(); I != E; ++I) if (I->Path == incpath) return; headerOpts.AddPath(incpath, frontend::Angled, IsFramework, IsSysRootRelative); Preprocessor& PP = CI->getPreprocessor(); clang::ApplyHeaderSearchOptions(PP.getHeaderSearchInfo(), headerOpts, PP.getLangOpts(), PP.getTargetInfo().getTriple()); } void Interpreter::DumpIncludePath() { llvm::SmallVector IncPaths; GetIncludePaths(IncPaths, true /*withSystem*/, true /*withFlags*/); // print'em all for (unsigned i = 0; i < IncPaths.size(); ++i) { llvm::errs() << IncPaths[i] <<"\n"; } } void Interpreter::storeInterpreterState(const std::string& name) const { // This may induce deserialization PushTransactionRAII RAII(this); CodeGenerator* CG = m_IncrParser->getCodeGenerator(); ClangInternalState* state = new ClangInternalState(getCI()->getASTContext(), getCI()->getPreprocessor(), getLastTransaction()->getModule(), CG, name); m_StoredStates.push_back(state); } void Interpreter::compareInterpreterState(const std::string& name) const { short foundAtPos = -1; for (short i = 0, e = m_StoredStates.size(); i != e; ++i) { if (m_StoredStates[i]->getName() == name) { foundAtPos = i; break; } } if (foundAtPos < 0) { llvm::errs() << "The store point name " << name << " does not exist." "Unbalanced store / compare\n"; return; } // This may induce deserialization PushTransactionRAII RAII(this); m_StoredStates[foundAtPos]->compare(name); } void Interpreter::printIncludedFiles(llvm::raw_ostream& Out) const { ClangInternalState::printIncludedFiles(Out, getCI()->getSourceManager()); } // Adapted from clang/lib/Frontend/CompilerInvocation.cpp void Interpreter::GetIncludePaths(llvm::SmallVectorImpl& incpaths, bool withSystem, bool withFlags) { const HeaderSearchOptions Opts(getCI()->getHeaderSearchOpts()); if (withFlags && Opts.Sysroot != "/") { incpaths.push_back("-isysroot"); incpaths.push_back(Opts.Sysroot); } /// User specified include entries. for (unsigned i = 0, e = Opts.UserEntries.size(); i != e; ++i) { const HeaderSearchOptions::Entry &E = Opts.UserEntries[i]; if (E.IsFramework && E.Group != frontend::Angled) llvm::report_fatal_error("Invalid option set!"); switch (E.Group) { case frontend::After: if (withFlags) incpaths.push_back("-idirafter"); break; case frontend::Quoted: if (withFlags) incpaths.push_back("-iquote"); break; case frontend::System: if (!withSystem) continue; if (withFlags) incpaths.push_back("-isystem"); break; case frontend::IndexHeaderMap: if (!withSystem) continue; if (withFlags) incpaths.push_back("-index-header-map"); if (withFlags) incpaths.push_back(E.IsFramework? "-F" : "-I"); break; case frontend::CSystem: if (!withSystem) continue; if (withFlags) incpaths.push_back("-c-isystem"); break; case frontend::ExternCSystem: if (!withSystem) continue; if (withFlags) incpaths.push_back("-extern-c-isystem"); break; case frontend::CXXSystem: if (!withSystem) continue; if (withFlags) incpaths.push_back("-cxx-isystem"); break; case frontend::ObjCSystem: if (!withSystem) continue; if (withFlags) incpaths.push_back("-objc-isystem"); break; case frontend::ObjCXXSystem: if (!withSystem) continue; if (withFlags) incpaths.push_back("-objcxx-isystem"); break; case frontend::Angled: if (withFlags) incpaths.push_back(E.IsFramework ? "-F" : "-I"); break; } incpaths.push_back(E.Path); } if (withSystem && !Opts.ResourceDir.empty()) { if (withFlags) incpaths.push_back("-resource-dir"); incpaths.push_back(Opts.ResourceDir); } if (withSystem && withFlags && !Opts.ModuleCachePath.empty()) { incpaths.push_back("-fmodule-cache-path"); incpaths.push_back(Opts.ModuleCachePath); } if (withSystem && withFlags && !Opts.UseStandardSystemIncludes) incpaths.push_back("-nostdinc"); if (withSystem && withFlags && !Opts.UseStandardCXXIncludes) incpaths.push_back("-nostdinc++"); if (withSystem && withFlags && Opts.UseLibcxx) incpaths.push_back("-stdlib=libc++"); if (withSystem && withFlags && Opts.Verbose) incpaths.push_back("-v"); } CompilerInstance* Interpreter::getCI() const { return m_IncrParser->getCI(); } Sema& Interpreter::getSema() const { return getCI()->getSema(); } ///\brief Maybe transform the input line to implement cint command line /// semantics (declarations are global) and compile to produce a module. /// Interpreter::CompilationResult Interpreter::process(const std::string& input, Value* V /* = 0 */, Transaction** T /* = 0 */) { if (isRawInputEnabled() || !ShouldWrapInput(input)) return declare(input, T); CompilationOptions CO; CO.DeclarationExtraction = 1; CO.ValuePrinting = CompilationOptions::VPAuto; CO.ResultEvaluation = (bool)V; CO.DynamicScoping = isDynamicLookupEnabled(); CO.Debug = isPrintingDebug(); if (EvaluateInternal(input, CO, V, T) == Interpreter::kFailure) { return Interpreter::kFailure; } return Interpreter::kSuccess; } Interpreter::CompilationResult Interpreter::parse(const std::string& input, Transaction** T /*=0*/) const { CompilationOptions CO; CO.CodeGeneration = 0; CO.DeclarationExtraction = 0; CO.ValuePrinting = 0; CO.ResultEvaluation = 0; CO.DynamicScoping = isDynamicLookupEnabled(); CO.Debug = isPrintingDebug(); return DeclareInternal(input, CO, T); } Interpreter::CompilationResult Interpreter::loadModuleForHeader(const std::string& headerFile) { Preprocessor& PP = getCI()->getPreprocessor(); //Copied from clang's PPDirectives.cpp bool isAngled = false; // Clang doc says: // "LookupFrom is set when this is a \#include_next directive, it specifies // the file to start searching from." const DirectoryLookup* FromDir = 0; const FileEntry* FromFile = 0; const DirectoryLookup* CurDir = 0; ModuleMap::KnownHeader suggestedModule; // PP::LookupFile uses it to issue 'nice' diagnostic SourceLocation fileNameLoc; PP.LookupFile(fileNameLoc, headerFile, isAngled, FromDir, FromFile, CurDir, /*SearchPath*/0, /*RelativePath*/ 0, &suggestedModule, /*SkipCache*/false, /*OpenFile*/ false, /*CacheFail*/ false); if (!suggestedModule) return Interpreter::kFailure; // Copied from PPDirectives.cpp SmallVector, 2> path; for (Module *mod = suggestedModule.getModule(); mod; mod = mod->Parent) { IdentifierInfo* II = &getSema().getPreprocessor().getIdentifierTable().get(mod->Name); path.push_back(std::make_pair(II, fileNameLoc)); } std::reverse(path.begin(), path.end()); // Pretend that the module came from an inclusion directive, so that clang // will create an implicit import declaration to capture it in the AST. bool isInclude = true; SourceLocation includeLoc; if (getCI()->loadModule(includeLoc, path, Module::AllVisible, isInclude)) { // After module load we need to "force" Sema to generate the code for // things like dynamic classes. getSema().ActOnEndOfTranslationUnit(); return Interpreter::kSuccess; } return Interpreter::kFailure; } Interpreter::CompilationResult Interpreter::parseForModule(const std::string& input) { CompilationOptions CO; CO.CodeGeneration = 1; CO.CodeGenerationForModule = 1; CO.DeclarationExtraction = 0; CO.ValuePrinting = 0; CO.ResultEvaluation = 0; CO.DynamicScoping = isDynamicLookupEnabled(); CO.Debug = isPrintingDebug(); // When doing parseForModule avoid warning about the user code // being loaded ... we probably might as well extend this to // ALL warnings ... but this will suffice for now (working // around a real bug in QT :(). DiagnosticsEngine& Diag = getCI()->getDiagnostics(); Diag.setSeverity(clang::diag::warn_field_is_uninit, clang::diag::Severity::Ignored, SourceLocation()); CompilationResult Result = DeclareInternal(input, CO); Diag.setSeverity(clang::diag::warn_field_is_uninit, clang::diag::Severity::Warning, SourceLocation()); return Result; } Interpreter::CompilationResult Interpreter::declare(const std::string& input, Transaction** T/*=0 */) { CompilationOptions CO; CO.DeclarationExtraction = 0; CO.ValuePrinting = 0; CO.ResultEvaluation = 0; CO.DynamicScoping = isDynamicLookupEnabled(); CO.Debug = isPrintingDebug(); return DeclareInternal(input, CO, T); } Interpreter::CompilationResult Interpreter::evaluate(const std::string& input, Value& V) { // Here we might want to enforce further restrictions like: Only one // ExprStmt can be evaluated and etc. Such enforcement cannot happen in the // worker, because it is used from various places, where there is no such // rule CompilationOptions CO; CO.DeclarationExtraction = 0; CO.ValuePrinting = 0; CO.ResultEvaluation = 1; return EvaluateInternal(input, CO, &V); } Interpreter::CompilationResult Interpreter::echo(const std::string& input, Value* V /* = 0 */) { CompilationOptions CO; CO.DeclarationExtraction = 0; CO.ValuePrinting = CompilationOptions::VPEnabled; CO.ResultEvaluation = (bool)V; return EvaluateInternal(input, CO, V); } Interpreter::CompilationResult Interpreter::execute(const std::string& input) { CompilationOptions CO; CO.DeclarationExtraction = 0; CO.ValuePrinting = 0; CO.ResultEvaluation = 0; CO.DynamicScoping = 0; CO.Debug = isPrintingDebug(); return EvaluateInternal(input, CO); } Interpreter::CompilationResult Interpreter::emitAllDecls(Transaction* T) { assert(!isInSyntaxOnlyMode() && "No CodeGenerator?"); m_IncrParser->emitTransaction(T); m_IncrParser->addTransaction(T); m_IncrParser->markWholeTransactionAsUsed(T); T->setState(Transaction::kCollecting); m_IncrParser->commitTransaction(m_IncrParser->endTransaction(T)); if (executeTransaction(*T)) return Interpreter::kSuccess; return Interpreter::kFailure; } bool Interpreter::ShouldWrapInput(const std::string& input) { // TODO: For future reference. // Parser* P = const_cast(m_IncrParser->getParser()); // Parser::TentativeParsingAction TA(P); // TPResult result = P->isCXXDeclarationSpecifier(); // TA.Revert(); // return result == TPResult::True(); // FIXME: can't skipToEndOfLine because we don't want to PragmaLex // because we don't want to pollute the preprocessor. Without PragmaLex // there is no "end of line" / eod token. So skip the #line before lexing. size_t posStart = 0; size_t lenInput = input.length(); while (lenInput > posStart && isspace(input[posStart])) ++posStart; // Don't wrap empty input if (posStart == lenInput) return false; if (input[posStart] == '#') { size_t posDirective = posStart + 1; while (lenInput > posDirective && isspace(input[posDirective])) ++posDirective; // A single '#'? Weird... better don't wrap. if (posDirective == lenInput) return false; if (!strncmp(&input[posDirective], "line ", 5)) { // There is a line directive. It does affect the determination whether // this input should be wrapped; skip the line. size_t posEOD = input.find('\n', posDirective + 5); if (posEOD != std::string::npos) posStart = posEOD + 1; } } //llvm::OwningPtr buf; //buf.reset(llvm::MemoryBuffer::getMemBuffer(&input[posStart], // "Cling Preparse Buf")); Lexer WrapLexer(SourceLocation(), getSema().getLangOpts(), input.c_str() + posStart, input.c_str() + posStart, input.c_str() + input.size()); Token Tok; WrapLexer.LexFromRawLexer(Tok); const tok::TokenKind kind = Tok.getKind(); if (kind == tok::raw_identifier && !Tok.needsCleaning()) { StringRef keyword(Tok.getRawIdentifier()); if (keyword.equals("using")) { // FIXME: Using definitions and declarations should be decl extracted. // Until we have that, don't wrap them if they are the only input. const char* cursor = keyword.data(); cursor = strchr(cursor, ';'); // advance to end of using decl / def. if (!cursor) { // Using decl / def without trailing ';' means input consists of only // that using decl /def: should not wrap. return false; } // Skip whitespace after ';' do ++cursor; while (*cursor && isspace(*cursor)); if (!*cursor) return false; // There is "more" - let's assume this input consists of a using // declaration or definition plus some code that should be wrapped. return true; } if (keyword.equals("extern")) return false; if (keyword.equals("namespace")) return false; if (keyword.equals("template")) return false; } else if (kind == tok::hash) { WrapLexer.LexFromRawLexer(Tok); if (Tok.is(tok::raw_identifier) && !Tok.needsCleaning()) { StringRef keyword(Tok.getRawIdentifier()); if (keyword.equals("include")) return false; } } return true; } void Interpreter::WrapInput(std::string& input, std::string& fname) { fname = createUniqueWrapper(); input.insert(0, "void " + fname + "(void* vpClingValue) {\n "); input.append("\n;\n}"); } Interpreter::ExecutionResult Interpreter::RunFunction(const FunctionDecl* FD, Value* res /*=0*/) { if (getCI()->getDiagnostics().hasErrorOccurred()) return kExeCompilationError; if (isInSyntaxOnlyMode()) { return kExeNoCodeGen; } if (!FD) return kExeUnkownFunction; std::string mangledNameIfNeeded; utils::Analyze::maybeMangleDeclName(FD, mangledNameIfNeeded); IncrementalExecutor::ExecutionResult ExeRes = m_Executor->executeWrapper(mangledNameIfNeeded.c_str(), res); return ConvertExecutionResult(ExeRes); } const FunctionDecl* Interpreter::DeclareCFunction(StringRef name, StringRef code, bool withAccessControl) { /* In CallFunc we currently always (intentionally and somewhat necessarily) always fully specify member function template, however this can lead to an ambiguity with a class template. For example in roottest/cling/functionTemplate we get: input_line_171:3:15: warning: lookup of 'set' in member access expression is ambiguous; using member of 't' ((t*)obj)->set(*(int*)args[0]); ^ roottest/cling/functionTemplate/t.h:19:9: note: lookup in the object type 't' refers here void set(T targ) { ^ /usr/include/c++/4.4.5/bits/stl_set.h:87:11: note: lookup from the current scope refers here class set ^ This is an intention warning implemented in clang, see http://llvm.org/viewvc/llvm-project?view=revision&revision=105518 which 'should have been' an error: C++ [basic.lookup.classref] requires this to be an error, but, because it's hard to work around, Clang downgrades it to a warning as an extension.

// C++98 [basic.lookup.classref]p1: // In a class member access expression (5.2.5), if the . or -> token is // immediately followed by an identifier followed by a <, the identifier // must be looked up to determine whether the < is the beginning of a // template argument list (14.2) or a less-than operator. The identifier // is first looked up in the class of the object expression. If the // identifier is not found, it is then looked up in the context of the // entire postfix-expression and shall name a class or function template. If // the lookup in the class of the object expression finds a template, the // name is also looked up in the context of the entire postfix-expression // and // -- if the name is not found, the name found in the class of the // object expression is used, otherwise // -- if the name is found in the context of the entire postfix-expression // and does not name a class template, the name found in the class of the // object expression is used, otherwise // -- if the name found is a class template, it must refer to the same // entity as the one found in the class of the object expression, // otherwise the program is ill-formed. See -Wambiguous-member-template An alternative to disabling the diagnostics is to use a pointer to member function: #include using namespace std; extern "C" int printf(const char*,...); struct S { template void set(T) {}; virtual void virtua() { printf("S\n"); } }; struct T: public S { void virtua() { printf("T\n"); } }; int main() { S *s = new T(); typedef void (S::*Func_p)(int); Func_p p = &S::set; (s->*p)(12); typedef void (S::*Vunc_p)(void); Vunc_p q = &S::virtua; (s->*q)(); // prints "T" return 0; } */ DiagnosticsEngine& Diag = getCI()->getDiagnostics(); Diag.setSeverity(clang::diag::ext_nested_name_member_ref_lookup_ambiguous, clang::diag::Severity::Ignored, SourceLocation()); LangOptions& LO = const_cast(getCI()->getLangOpts()); bool savedAccessControl = LO.AccessControl; LO.AccessControl = withAccessControl; cling::Transaction* T = 0; cling::Interpreter::CompilationResult CR = declare(code, &T); LO.AccessControl = savedAccessControl; Diag.setSeverity(clang::diag::ext_nested_name_member_ref_lookup_ambiguous, clang::diag::Severity::Warning, SourceLocation()); if (CR != cling::Interpreter::kSuccess) return 0; for (cling::Transaction::const_iterator I = T->decls_begin(), E = T->decls_end(); I != E; ++I) { if (I->m_Call != cling::Transaction::kCCIHandleTopLevelDecl) continue; if (const LinkageSpecDecl* LSD = dyn_cast(*I->m_DGR.begin())) { DeclContext::decl_iterator DeclBegin = LSD->decls_begin(); if (DeclBegin == LSD->decls_end()) continue; if (const FunctionDecl* D = dyn_cast(*DeclBegin)) { const IdentifierInfo* II = D->getDeclName().getAsIdentifierInfo(); if (II && II->getName() == name) return D; } } } return 0; } void* Interpreter::compileFunction(llvm::StringRef name, llvm::StringRef code, bool ifUnique, bool withAccessControl) { // // Compile the wrapper code. // if (isInSyntaxOnlyMode()) return 0; if (ifUnique) { if (void* Addr = (void*)getAddressOfGlobal(name)) { return Addr; } } const FunctionDecl* FD = DeclareCFunction(name, code, withAccessControl); if (!FD) return 0; // // Get the wrapper function pointer // from the ExecutionEngine (the JIT). // if (const llvm::GlobalValue* GV = getLastTransaction()->getModule()->getNamedValue(name)) return m_Executor->getPointerToGlobalFromJIT(*GV); return 0; } void* Interpreter::compileDtorCallFor(const clang::RecordDecl* RD) { void* &addr = m_DtorWrappers[RD]; if (addr) return addr; std::string funcname; { llvm::raw_string_ostream namestr(funcname); namestr << "__cling_Destruct_" << RD; } std::string code = "extern \"C\" void "; clang::QualType RDQT(RD->getTypeForDecl(), 0); std::string typeName = utils::TypeName::GetFullyQualifiedName(RDQT, RD->getASTContext()); std::string dtorName = RD->getNameAsString(); code += funcname + "(void* obj){((" + typeName + "*)obj)->~" + dtorName + "();}"; // ifUniq = false: we know it's unique, no need to check. addr = compileFunction(funcname, code, false /*ifUniq*/, false /*withAccessControl*/); return addr; } void Interpreter::createUniqueName(std::string& out) { out += utils::Synthesize::UniquePrefix; llvm::raw_string_ostream(out) << m_UniqueCounter++; } bool Interpreter::isUniqueName(llvm::StringRef name) { return name.startswith(utils::Synthesize::UniquePrefix); } llvm::StringRef Interpreter::createUniqueWrapper() { const size_t size = sizeof(utils::Synthesize::UniquePrefix) + sizeof(m_UniqueCounter); llvm::SmallString out(utils::Synthesize::UniquePrefix); llvm::raw_svector_ostream(out) << m_UniqueCounter++; return (getCI()->getASTContext().Idents.getOwn(out)).getName(); } bool Interpreter::isUniqueWrapper(llvm::StringRef name) { return name.startswith(utils::Synthesize::UniquePrefix); } Interpreter::CompilationResult Interpreter::DeclareInternal(const std::string& input, const CompilationOptions& CO, Transaction** T /* = 0 */) const { StateDebuggerRAII stateDebugger(this); IncrementalParser::ParseResultTransaction PRT = m_IncrParser->Compile(input, CO); if (PRT.getInt() == IncrementalParser::kFailed) return Interpreter::kFailure; if (T) *T = PRT.getPointer(); return Interpreter::kSuccess; } Interpreter::CompilationResult Interpreter::EvaluateInternal(const std::string& input, CompilationOptions CO, Value* V, /* = 0 */ Transaction** T /* = 0 */) { StateDebuggerRAII stateDebugger(this); // Wrap the expression std::string WrapperName; std::string Wrapper = input; WrapInput(Wrapper, WrapperName); // We have wrapped and need to disable warnings that are caused by // non-default C++ at the prompt: CO.IgnorePromptDiags = 1; IncrementalParser::ParseResultTransaction PRT = m_IncrParser->Compile(Wrapper, CO); Transaction* lastT = PRT.getPointer(); if (lastT && lastT->getState() != Transaction::kCommitted) { assert((lastT->getState() == Transaction::kCommitted || lastT->getState() == Transaction::kRolledBack || lastT->getState() == Transaction::kRolledBackWithErrors) && "Not committed?"); if (V) *V = Value(); return kFailure; } // Might not have a Transaction if (PRT.getInt() == IncrementalParser::kFailed) { if (V) *V = Value(); return kFailure; } if (!lastT) { // Empty transactions are good, too! if (V) *V = Value(); return kSuccess; } Value resultV; if (!V) V = &resultV; if (!lastT->getWrapperFD()) // no wrapper to run return Interpreter::kSuccess; else if (RunFunction(lastT->getWrapperFD(), V) < kExeFirstError){ if (lastT->getCompilationOpts().ValuePrinting != CompilationOptions::VPDisabled && V->isValid() // the !V->needsManagedAllocation() case is handled by // dumpIfNoStorage. && V->needsManagedAllocation()) V->dump(); return Interpreter::kSuccess; } return Interpreter::kSuccess; } std::string Interpreter::lookupFileOrLibrary(llvm::StringRef file) { std::string canonicalFile = DynamicLibraryManager::normalizePath(file); if (canonicalFile.empty()) canonicalFile = file; const FileEntry* FE = 0; //Copied from clang's PPDirectives.cpp bool isAngled = false; // Clang doc says: // "LookupFrom is set when this is a \#include_next directive, it // specifies the file to start searching from." const DirectoryLookup* FromDir = 0; const FileEntry* FromFile = 0; const DirectoryLookup* CurDir = 0; Preprocessor& PP = getCI()->getPreprocessor(); // PP::LookupFile uses it to issue 'nice' diagnostic SourceLocation fileNameLoc; FE = PP.LookupFile(fileNameLoc, canonicalFile, isAngled, FromDir, FromFile, CurDir, /*SearchPath*/0, /*RelativePath*/ 0, /*suggestedModule*/0, /*SkipCache*/false, /*OpenFile*/ false, /*CacheFail*/ false); if (FE) return FE->getName(); return getDynamicLibraryManager()->lookupLibrary(canonicalFile); } Interpreter::CompilationResult Interpreter::loadFile(const std::string& filename, bool allowSharedLib /*=true*/, Transaction** T /*= 0*/) { DynamicLibraryManager* DLM = getDynamicLibraryManager(); std::string canonicalLib = DLM->lookupLibrary(filename); if (allowSharedLib && !canonicalLib.empty()) { switch (DLM->loadLibrary(filename, /*permanent*/false)) { case DynamicLibraryManager::kLoadLibSuccess: // Intentional fall through case DynamicLibraryManager::kLoadLibAlreadyLoaded: return kSuccess; case DynamicLibraryManager::kLoadLibNotFound: assert(0 && "Cannot find library with existing canonical name!"); return kFailure; default: // Not a source file (canonical name is non-empty) but can't load. return kFailure; } } std::string code; code += "#include \"" + filename + "\""; CompilationResult res = declare(code, T); return res; } void Interpreter::unload(unsigned numberOfTransactions) { while(true) { cling::Transaction* T = m_IncrParser->getLastTransaction(); if (!T) { llvm::errs() << "cling: invalid last transaction; unload failed!\n"; return; } if (InterpreterCallbacks* callbacks = getCallbacks()) callbacks->TransactionUnloaded(*T); if (m_Executor) // we also might be in fsyntax-only mode. m_Executor->runAndRemoveStaticDestructors(T); m_IncrParser->rollbackTransaction(T); if (!--numberOfTransactions) break; } } static void runAndRemoveStaticDestructorsImpl(IncrementalExecutor &executor, std::vector &transactions, unsigned int begin, unsigned int end) { for(auto i = begin; i != end; --i) { if (transactions[i-1] != nullptr) executor.runAndRemoveStaticDestructors(const_cast(transactions[i-1])); } } void Interpreter::runAndRemoveStaticDestructors(unsigned numberOfTransactions) { if (!m_Executor) return; auto transactions( m_IncrParser->getAllTransactions() ); unsigned int min = 0; if (transactions.size() > numberOfTransactions) { min = transactions.size() - numberOfTransactions; } runAndRemoveStaticDestructorsImpl(*m_Executor, transactions, transactions.size(), min); } void Interpreter::runAndRemoveStaticDestructors() { if (!m_Executor) return; auto transactions( m_IncrParser->getAllTransactions() ); runAndRemoveStaticDestructorsImpl(*m_Executor, transactions, transactions.size(), 0); } void Interpreter::installLazyFunctionCreator(void* (*fp)(const std::string&)) { m_Executor->installLazyFunctionCreator(fp); } Value Interpreter::Evaluate(const char* expr, DeclContext* DC, bool ValuePrinterReq) { Sema& TheSema = getCI()->getSema(); // The evaluation should happen on the global scope, because of the wrapper // that is created. // // We can't PushDeclContext, because we don't have scope. Sema::ContextRAII pushDC(TheSema, TheSema.getASTContext().getTranslationUnitDecl()); Value Result; getCallbacks()->SetIsRuntime(true); if (ValuePrinterReq) echo(expr, &Result); else evaluate(expr, Result); getCallbacks()->SetIsRuntime(false); return Result; } void Interpreter::setCallbacks(std::unique_ptr C) { // We need it to enable LookupObject callback. if (!m_Callbacks) { m_Callbacks.reset(new MultiplexInterpreterCallbacks(this)); // FIXME: Move to the InterpreterCallbacks.cpp; if (DynamicLibraryManager* DLM = getDynamicLibraryManager()) DLM->setCallbacks(m_Callbacks.get()); } static_cast(m_Callbacks.get()) ->addCallback(std::move(C)); } const Transaction* Interpreter::getFirstTransaction() const { return m_IncrParser->getFirstTransaction(); } const Transaction* Interpreter::getLastTransaction() const { return m_IncrParser->getLastTransaction(); } const Transaction* Interpreter::getCurrentTransaction() const { return m_IncrParser->getCurrentTransaction(); } void Interpreter::enableDynamicLookup(bool value /*=true*/) { if (!m_DynamicLookupDeclared && value) { // No dynlookup for the dynlookup header! m_DynamicLookupEnabled = false; if (loadModuleForHeader("cling/Interpreter/DynamicLookupRuntimeUniverse.h") != kSuccess) declare("#include \"cling/Interpreter/DynamicLookupRuntimeUniverse.h\""); } m_DynamicLookupDeclared = true; // Enable it *after* parsing the headers. m_DynamicLookupEnabled = value; } Interpreter::ExecutionResult Interpreter::executeTransaction(Transaction& T) { assert(!isInSyntaxOnlyMode() && "Running on what?"); assert(T.getState() == Transaction::kCommitted && "Must be committed"); IncrementalExecutor::ExecutionResult ExeRes = IncrementalExecutor::kExeSuccess; if (!isPracticallyEmptyModule(T.getModule())) { T.setExeUnloadHandle(m_Executor.get(), m_Executor->emitToJIT()); // Forward to IncrementalExecutor; should not be called by // anyone except for IncrementalParser. ExeRes = m_Executor->runStaticInitializersOnce(T); } return ConvertExecutionResult(ExeRes); } bool Interpreter::addSymbol(const char* symbolName, void* symbolAddress) { // Forward to IncrementalExecutor; if (!symbolName || !symbolAddress ) return false; return m_Executor->addSymbol(symbolName, symbolAddress); } void Interpreter::addModule(llvm::Module* module) { m_Executor->addModule(module); } void* Interpreter::getAddressOfGlobal(const GlobalDecl& GD, bool* fromJIT /*=0*/) const { // Return a symbol's address, and whether it was jitted. std::string mangledName; utils::Analyze::maybeMangleDeclName(GD, mangledName); return getAddressOfGlobal(mangledName.c_str(), fromJIT); } void* Interpreter::getAddressOfGlobal(llvm::StringRef SymName, bool* fromJIT /*=0*/) const { // Return a symbol's address, and whether it was jitted. if (isInSyntaxOnlyMode()) return 0; return m_Executor->getAddressOfGlobal(SymName, fromJIT); } void Interpreter::AddAtExitFunc(void (*Func) (void*), void* Arg) { m_Executor->AddAtExitFunc(Func, Arg); } void Interpreter::GenerateAutoloadingMap(llvm::StringRef inFile, llvm::StringRef outFile, bool enableMacros, bool enableLogs) { const char *const dummy="cling_fwd_declarator"; // Create an interpreter without any runtime, producing the fwd decls. // FIXME: CIFactory appends extra 3 folders to the llvmdir. std::string llvmdir = getCI()->getHeaderSearchOpts().ResourceDir + "/../../../"; cling::Interpreter fwdGen(1, &dummy, llvmdir.c_str(), true); // Copy the same header search options to the new instance. Preprocessor& fwdGenPP = fwdGen.getCI()->getPreprocessor(); HeaderSearchOptions headerOpts = getCI()->getHeaderSearchOpts(); clang::ApplyHeaderSearchOptions(fwdGenPP.getHeaderSearchInfo(), headerOpts, fwdGenPP.getLangOpts(), fwdGenPP.getTargetInfo().getTriple()); CompilationOptions CO; CO.DeclarationExtraction = 0; CO.ValuePrinting = 0; CO.ResultEvaluation = 0; CO.DynamicScoping = 0; CO.Debug = isPrintingDebug(); std::string includeFile = std::string("#include \"") + inFile.str() + "\""; IncrementalParser::ParseResultTransaction PRT = fwdGen.m_IncrParser->Parse(includeFile, CO); cling::Transaction* T = PRT.getPointer(); // If this was already #included we will get a T == 0. if (PRT.getInt() == IncrementalParser::kFailed || !T) return; std::error_code EC; llvm::raw_fd_ostream out(outFile.data(), EC, llvm::sys::fs::OpenFlags::F_None); llvm::raw_fd_ostream log((outFile + ".skipped").str().c_str(), EC, llvm::sys::fs::OpenFlags::F_None); log << "Generated for :" << inFile << "\n"; forwardDeclare(*T, fwdGen.getCI()->getSema(), out, enableMacros, &log); } void Interpreter::forwardDeclare(Transaction& T, Sema& S, llvm::raw_ostream& out, bool enableMacros /*=false*/, llvm::raw_ostream* logs /*=0*/) const { llvm::raw_null_ostream null; if (!logs) logs = &null; ForwardDeclPrinter visitor(out, *logs, S, T); visitor.printStats(); // Avoid assertion in the ~IncrementalParser. T.setState(Transaction::kCommitted); } } //end namespace cling