IncrementalParser::EParseResult IncrementalParser::Compile(llvm::StringRef input) { // Just in case when Parse is called, we want to complete the transaction // coming from parse and then start new one. m_Consumer->HandleTranslationUnit(getCI()->getASTContext()); // Reset the module builder to clean up global initializers, c'tors, d'tors: if (GetCodeGenerator()) { GetCodeGenerator()->Initialize(getCI()->getASTContext()); } EParseResult Result = Parse(input); // Check for errors coming from our custom consumers. DiagnosticConsumer& DClient = m_CI->getDiagnosticClient(); DClient.BeginSourceFile(getCI()->getLangOpts(), &getCI()->getPreprocessor()); m_Consumer->HandleTranslationUnit(getCI()->getASTContext()); DClient.EndSourceFile(); m_CI->getDiagnostics().Reset(); if (!m_SyntaxOnly) { m_Interpreter->runStaticInitializersOnce(); } return Result; }
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(), CG ? CG->GetModule() : 0, CG, name); m_StoredStates.push_back(state); }
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<HeaderSearchOptions::Entry>::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()); }
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(); }
void IncrementalParser::codeGenTransaction(Transaction* T) { // codegen the transaction assert(T->getCompilationOpts().CodeGeneration && "CodeGen turned off"); assert(T->getState() == Transaction::kCompleted && "Must be completed"); assert(hasCodeGenerator() && "No CodeGen"); // Could trigger derserialization of decls. Transaction* deserT = beginTransaction(CompilationOptions()); // Commit this transaction first - T might need symbols from it, so // trigger emission of weak symbols by providing use. ParseResultTransaction PRT = endTransaction(deserT); commitTransaction(PRT); deserT = PRT.getPointer(); // This llvm::Module is done; finalize it and pass it to the execution // engine. if (!T->isNestedTransaction() && hasCodeGenerator()) { // The initializers are emitted to the symbol "_GLOBAL__sub_I_" + filename. // Make that unique! deserT = beginTransaction(CompilationOptions()); // Reset the module builder to clean up global initializers, c'tors, d'tors getCodeGenerator()->HandleTranslationUnit(getCI()->getASTContext()); auto PRT = endTransaction(deserT); commitTransaction(PRT); deserT = PRT.getPointer(); std::unique_ptr<llvm::Module> M(getCodeGenerator()->ReleaseModule()); if (M) { m_Interpreter->addModule(M.get(), T->getCompilationOpts().OptLevel); T->setModule(std::move(M)); } if (T->getIssuedDiags() != Transaction::kNone) { // Module has been released from Codegen, reset the Diags now. DiagnosticsEngine& Diags = getCI()->getSema().getDiagnostics(); Diags.Reset(/*soft=*/true); Diags.getClient()->clear(); } // Create a new module. StartModule(); } }
llvm::StringRef Interpreter::createUniqueWrapper() { const size_t size = sizeof(utils::Synthesize::UniquePrefix) + sizeof(m_UniqueCounter); llvm::SmallString<size> out(utils::Synthesize::UniquePrefix); llvm::raw_svector_ostream(out) << m_UniqueCounter++; return (getCI()->getASTContext().Idents.getOwn(out)).getName(); }
void IncrementalParser::rollbackTransaction(Transaction* T) const { ASTNodeEraser NodeEraser(&getCI()->getSema()); if (NodeEraser.RevertTransaction(T)) T->setState(Transaction::kRolledBack); else T->setState(Transaction::kRolledBackWithErrors); }
// Each input line is contained in separate memory buffer. The SourceManager // assigns sort-of invalid FileID for each buffer, i.e there is no FileEntry // for the MemoryBuffer's FileID. That in turn is problem because invalid // SourceLocations are given to the diagnostics. Thus the diagnostics cannot // order the overloads, for example // // Our work-around is creating a virtual file, which doesn't exist on the disk // with enormous size (no allocation is done). That file has valid FileEntry // and so on... We use it for generating valid SourceLocations with valid // offsets so that it doesn't cause any troubles to the diagnostics. // // +---------------------+ // | Main memory buffer | // +---------------------+ // | Virtual file SLoc | // | address space |<-----------------+ // | ... |<------------+ | // | ... | | | // | ... |<----+ | | // | ... | | | | // +~~~~~~~~~~~~~~~~~~~~~+ | | | // | input_line_1 | ....+.......+..--+ // +---------------------+ | | // | input_line_2 | ....+.....--+ // +---------------------+ | // | ... | | // +---------------------+ | // | input_line_N | ..--+ // +---------------------+ // void IncrementalParser::CreateSLocOffsetGenerator() { SourceManager& SM = getCI()->getSourceManager(); FileManager& FM = SM.getFileManager(); const FileEntry* FE = FM.getVirtualFile("Interactrive/InputLineIncluder", 1U << 15U, time(0)); m_VirtualFileID = SM.createFileID(FE, SourceLocation(), SrcMgr::C_User); assert(!m_VirtualFileID.isInvalid() && "No VirtualFileID created?"); }
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* LookupFrom = 0; const DirectoryLookup* CurDir = 0; ModuleMap::KnownHeader suggestedModule; // PP::LookupFile uses it to issue 'nice' diagnostic SourceLocation fileNameLoc; PP.LookupFile(fileNameLoc, headerFile, isAngled, LookupFrom, CurDir, /*SearchPath*/0, /*RelativePath*/ 0, &suggestedModule, /*SkipCache*/false, /*OpenFile*/ false, /*CacheFail*/ false); if (!suggestedModule) return Interpreter::kFailure; // Copied from PPDirectives.cpp SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 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; }
void Correlation::computeCI(double ci) { if(isSort==No) sortParameters(); if(ci==-1) { ci=defaultCI; } for(int i=0;i<nbparameter;i++) { getCI(sortparameters[i],nbsample,ci,&CIbuffer[i][0],&CIbuffer[i][1]); } }
void Interpreter::GenerateAutoloadingMap(llvm::StringRef inFile, llvm::StringRef outFile, bool enableMacros, bool enableLogs) { const char *const dummy="cling"; // Create an interpreter without any runtime, producing the fwd decls. cling::Interpreter fwdGen(1, &dummy, nullptr, 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() + "\""; cling::Transaction* T = fwdGen.m_IncrParser->Parse(includeFile , CO); // If this was already #included we will get a T == 0. if (!T) return; std::string err; llvm::raw_fd_ostream out(outFile.data(), err, llvm::sys::fs::OpenFlags::F_None); if (enableLogs){ llvm::raw_fd_ostream log(llvm::Twine(outFile).concat(llvm::Twine(".skipped")).str().c_str(), err, llvm::sys::fs::OpenFlags::F_None); log << "Generated for :" << inFile << "\n"; ForwardDeclPrinter visitor(out, log, fwdGen.getSema().getSourceManager(), *T); visitor.printStats(); } else { llvm::raw_null_ostream sink; ForwardDeclPrinter visitor(out, sink, fwdGen.getSema().getSourceManager(), *T); } // Avoid assertion in the ~IncrementalParser. T->setState(Transaction::kCommitted); // unload(1); return; }
IncrementalParser::ParseResultTransaction IncrementalParser::endTransaction(Transaction* T) { assert(T && "Null transaction!?"); assert(T->getState() == Transaction::kCollecting); #ifndef NDEBUG if (T->hasNestedTransactions()) { for(Transaction::const_nested_iterator I = T->nested_begin(), E = T->nested_end(); I != E; ++I) assert((*I)->isCompleted() && "Nested transaction not completed!?"); } #endif T->setState(Transaction::kCompleted); DiagnosticsEngine& Diag = getCI()->getSema().getDiagnostics(); //TODO: Make the enum orable. EParseResult ParseResult = kSuccess; assert((Diag.hasFatalErrorOccurred() ? Diag.hasErrorOccurred() : true) && "Diag.hasFatalErrorOccurred without Diag.hasErrorOccurred !"); if (Diag.hasErrorOccurred() || T->getIssuedDiags() == Transaction::kErrors) { T->setIssuedDiags(Transaction::kErrors); ParseResult = kFailed; } else if (Diag.getNumWarnings() > 0) { T->setIssuedDiags(Transaction::kWarnings); ParseResult = kSuccessWithWarnings; } // Empty transaction, send it back to the pool. if (T->empty()) { assert((!m_Consumer->getTransaction() || (m_Consumer->getTransaction() == T)) && "Cannot release different T"); // If a nested transaction the active one should be its parent // from now on. FIXME: Merge conditional with commitTransaction if (T->isNestedTransaction()) m_Consumer->setTransaction(T->getParent()); else m_Consumer->setTransaction((Transaction*)0); m_TransactionPool->releaseTransaction(T); return ParseResultTransaction(nullptr, ParseResult); } addTransaction(T); return ParseResultTransaction(T, ParseResult); }
void IncrementalParser::unloadTransaction(Transaction* T) { if (!T) T = getLastTransaction(); assert(T->getState() == Transaction::kCommitted && "Unloading not commited transaction?"); assert(T->getModule() && "Trying to uncodegen transaction taken in syntax only mode. "); ASTNodeEraser NodeEraser(&getCI()->getSema()); NodeEraser.RevertTransaction(T); InterpreterCallbacks* callbacks = m_Interpreter->getCallbacks(); if (callbacks) callbacks->TransactionUnloaded(*T); }
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->executeFunction(mangledNameIfNeeded.c_str(), res); return ConvertExecutionResult(ExeRes); }
void IncrementalParser::codeGenTransaction(Transaction* T) { // codegen the transaction assert(T->getCompilationOpts().CodeGeneration && "CodeGen turned off"); assert(hasCodeGenerator() && "No CodeGen"); T->setModule(getCodeGenerator()->GetModule()); for (size_t Idx = 0; Idx < T->size() /*can change in the loop!*/; ++Idx) { // Copy DCI; it might get relocated below. Transaction::DelayCallInfo I = (*T)[Idx]; if (I.m_Call == Transaction::kCCIHandleTopLevelDecl) getCodeGenerator()->HandleTopLevelDecl(I.m_DGR); else if (I.m_Call == Transaction::kCCIHandleInterestingDecl) { // Usually through BackendConsumer which doesn't implement // HandleInterestingDecl() and thus calls // ASTConsumer::HandleInterestingDecl() getCodeGenerator()->HandleTopLevelDecl(I.m_DGR); } else if(I.m_Call == Transaction::kCCIHandleTagDeclDefinition) { TagDecl* TD = cast<TagDecl>(I.m_DGR.getSingleDecl()); getCodeGenerator()->HandleTagDeclDefinition(TD); } else if (I.m_Call == Transaction::kCCIHandleVTable) { CXXRecordDecl* CXXRD = cast<CXXRecordDecl>(I.m_DGR.getSingleDecl()); getCodeGenerator()->HandleVTable(CXXRD, /*isRequired*/true); } else if (I.m_Call == Transaction::kCCIHandleCXXImplicitFunctionInstantiation) { FunctionDecl* FD = cast<FunctionDecl>(I.m_DGR.getSingleDecl()); getCodeGenerator()->HandleCXXImplicitFunctionInstantiation(FD); } else if (I.m_Call == Transaction::kCCIHandleCXXStaticMemberVarInstantiation) { VarDecl* VD = cast<VarDecl>(I.m_DGR.getSingleDecl()); getCodeGenerator()->HandleCXXStaticMemberVarInstantiation(VD); } else if (I.m_Call == Transaction::kCCINone) ; // We use that internally as delimiter in the Transaction. else llvm_unreachable("We shouldn't have decl without call info."); } getCodeGenerator()->HandleTranslationUnit(getCI()->getASTContext()); }
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()); return DeclareInternal(input, CO); }
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 IncrementalParser::Initialize() { if (hasCodeGenerator()) getCodeGenerator()->Initialize(getCI()->getASTContext()); CompilationOptions CO; CO.DeclarationExtraction = 0; CO.ValuePrinting = CompilationOptions::VPDisabled; CO.CodeGeneration = hasCodeGenerator(); // pull in PCHs const std::string& PCHFileName = m_CI->getInvocation ().getPreprocessorOpts().ImplicitPCHInclude; if (!PCHFileName.empty()) { Transaction* CurT = beginTransaction(CO); m_CI->createPCHExternalASTSource(PCHFileName, true /*DisablePCHValidation*/, true /*AllowPCHWithCompilerErrors*/, 0 /*DeserializationListener*/); Transaction* EndedT = endTransaction(CurT); commitTransaction(EndedT); } Transaction* CurT = beginTransaction(CO); Sema* TheSema = &m_CI->getSema(); m_Parser.reset(new Parser(m_CI->getPreprocessor(), *TheSema, false /*skipFuncBodies*/)); m_CI->getPreprocessor().EnterMainSourceFile(); // Initialize the parser after we have entered the main source file. m_Parser->Initialize(); // Perform initialization that occurs after the parser has been initialized // but before it parses anything. Initializes the consumers too. TheSema->Initialize(); ExternalASTSource *External = TheSema->getASTContext().getExternalSource(); if (External) External->StartTranslationUnit(m_Consumer); Transaction* EndedT = endTransaction(CurT); commitTransaction(EndedT); }
Transaction* IncrementalParser::endTransaction() const { Transaction* CurT = m_Consumer->getTransaction(); assert(CurT->getState() == Transaction::kCollecting); CurT->setState(Transaction::kCompleted); const DiagnosticsEngine& Diags = getCI()->getSema().getDiagnostics(); //TODO: Make the enum orable. if (Diags.getNumWarnings() > 0) CurT->setIssuedDiags(Transaction::kWarnings); if (Diags.hasErrorOccurred() || Diags.hasFatalErrorOccurred()) CurT->setIssuedDiags(Transaction::kErrors); if (CurT->hasNestedTransactions()) { for(Transaction::const_nested_iterator I = CurT->nested_begin(), E = CurT->nested_end(); I != E; ++I) assert((*I)->isCompleted() && "Nested transaction not completed!?"); } return CurT; }
Interpreter::ExecutionResult Interpreter::runStaticInitializersOnce(const Transaction& T) const { assert(!isInSyntaxOnlyMode() && "Running on what?"); assert(T.getState() == Transaction::kCommitted && "Must be committed"); // Forward to IncrementalExecutor; should not be called by // anyone except for IncrementalParser. llvm::Module* module = m_IncrParser->getCodeGenerator()->GetModule(); IncrementalExecutor::ExecutionResult ExeRes = m_Executor->runStaticInitializersOnce(module); // Avoid eternal additions to llvm.ident; see // CodeGenModule::EmitVersionIdentMetadata(). llvm::NamedMDNode *IdentMetadata = module->getNamedMetadata("llvm.ident"); if (IdentMetadata) module->eraseNamedMetadata(IdentMetadata); // Reset the module builder to clean up global initializers, c'tors, d'tors ASTContext& C = getCI()->getASTContext(); m_IncrParser->getCodeGenerator()->HandleTranslationUnit(C); return ConvertExecutionResult(ExeRes); }
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* LookupFrom = 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, LookupFrom, CurDir, /*SearchPath*/0, /*RelativePath*/ 0, /*suggestedModule*/0, /*SkipCache*/false, /*OpenFile*/ false, /*CacheFail*/ false); if (FE) return FE->getName(); return getDynamicLibraryManager()->lookupLibrary(canonicalFile); }
// Each input line is contained in separate memory buffer. The SourceManager // assigns sort-of invalid FileID for each buffer, i.e there is no FileEntry // for the MemoryBuffer's FileID. That in turn is problem because invalid // SourceLocations are given to the diagnostics. Thus the diagnostics cannot // order the overloads, for example // // Our work-around is creating a virtual file, which doesn't exist on the disk // with enormous size (no allocation is done). That file has valid FileEntry // and so on... We use it for generating valid SourceLocations with valid // offsets so that it doesn't cause any troubles to the diagnostics. // // +---------------------+ // | Main memory buffer | // +---------------------+ // | Virtual file SLoc | // | address space |<-----------------+ // | ... |<------------+ | // | ... | | | // | ... |<----+ | | // | ... | | | | // +~~~~~~~~~~~~~~~~~~~~~+ | | | // | input_line_1 | ....+.......+..--+ // +---------------------+ | | // | input_line_2 | ....+.....--+ // +---------------------+ | // | ... | | // +---------------------+ | // | input_line_N | ..--+ // +---------------------+ // void IncrementalParser::CreateSLocOffsetGenerator() { SourceManager& SM = getCI()->getSourceManager(); m_VirtualFileID = SM.getMainFileID(); assert(!m_VirtualFileID.isInvalid() && "No VirtualFileID created?"); }
void IncrementalParser::commitTransaction(Transaction* T) { //Transaction* CurT = m_Consumer->getTransaction(); assert(T->isCompleted() && "Transaction not ended!?"); assert(T->getState() != Transaction::kCommitted && "Committing an already committed transaction."); // Check for errors... if (T->getIssuedDiags() == Transaction::kErrors) { rollbackTransaction(T); return; } if (T->hasNestedTransactions()) { for(Transaction::const_nested_iterator I = T->nested_begin(), E = T->nested_end(); I != E; ++I) if ((*I)->getState() != Transaction::kCommitted) commitTransaction(*I); } // We are sure it's safe to pipe it through the transformers bool success = true; for (size_t i = 0; i < m_TTransformers.size(); ++i) { success = m_TTransformers[i]->TransformTransaction(*T); if (!success) { break; } } m_CI->getDiagnostics().Reset(); // FIXME: Should be in rollback transaction. if (!success) { // Roll back on error in a transformer rollbackTransaction(T); return; } // Pull all template instantiations in that came from the consumers. getCI()->getSema().PerformPendingInstantiations(); m_Consumer->HandleTranslationUnit(getCI()->getASTContext()); if (T->getCompilationOpts().CodeGeneration && hasCodeGenerator()) { // codegen the transaction for (size_t Idx = 0; Idx < T->size() /*can change in the loop!*/; ++Idx) { // Copy DCI; it might get relocated below. Transaction::DelayCallInfo I = (*T)[Idx]; if (I.m_Call == Transaction::kCCIHandleTopLevelDecl) getCodeGenerator()->HandleTopLevelDecl(I.m_DGR); else if (I.m_Call == Transaction::kCCIHandleInterestingDecl) { // Usually through BackendConsumer which doesn't implement // HandleInterestingDecl() and thus calls // ASTConsumer::HandleInterestingDecl() getCodeGenerator()->HandleTopLevelDecl(I.m_DGR); } else if(I.m_Call == Transaction::kCCIHandleTagDeclDefinition) { TagDecl* TD = cast<TagDecl>(I.m_DGR.getSingleDecl()); getCodeGenerator()->HandleTagDeclDefinition(TD); } else if (I.m_Call == Transaction::kCCIHandleVTable) { CXXRecordDecl* CXXRD = cast<CXXRecordDecl>(I.m_DGR.getSingleDecl()); getCodeGenerator()->HandleVTable(CXXRD, /*isRequired*/true); } else if (I.m_Call == Transaction::kCCIHandleCXXImplicitFunctionInstantiation) { FunctionDecl* FD = cast<FunctionDecl>(I.m_DGR.getSingleDecl()); getCodeGenerator()->HandleCXXImplicitFunctionInstantiation(FD); } else if (I.m_Call == Transaction::kCCIHandleCXXStaticMemberVarInstantiation) { VarDecl* VD = cast<VarDecl>(I.m_DGR.getSingleDecl()); getCodeGenerator()->HandleCXXStaticMemberVarInstantiation(VD); } else if (I.m_Call == Transaction::kCCINone) ; // We use that internally as delimiter in the Transaction. else llvm_unreachable("We shouldn't have decl without call info."); } getCodeGenerator()->HandleTranslationUnit(getCI()->getASTContext()); T->setModule(getCodeGenerator()->GetModule()); // The static initializers might run anything and can thus cause more // decls that need to end up in a transaction. But this one is done // with CodeGen... T->setState(Transaction::kCommitting); // run the static initializers that came from codegenning if (m_Interpreter->runStaticInitializersOnce() >= Interpreter::kExeFirstError) { // Roll back on error in a transformer rollbackTransaction(T); return; } } else T->setState(Transaction::kCommitting); InterpreterCallbacks* callbacks = m_Interpreter->getCallbacks(); if (callbacks) { callbacks->TransactionCommitted(*T); } if (T->hasNestedTransactions()) { Transaction* SubTransactionWhileCommitting = *T->rnested_begin(); if (SubTransactionWhileCommitting->getState() == Transaction::kCollecting) { // A nested transaction was created while committing this // transaction; commit it now. SubTransactionWhileCommitting->setState(Transaction::kCompleted); commitTransaction(SubTransactionWhileCommitting); } } T->setState(Transaction::kCommitted); // If the transaction is empty do nothing. // Except it was nested transaction and we want to reuse it later on. if (T->empty() && T->isNestedTransaction()) { // We need to remove the marker from its parent. Transaction* ParentT = T->getParent(); for (size_t i = 0; i < ParentT->size(); ++i) if ((*ParentT)[i].m_DGR.isNull()) ParentT->erase(i); } if (T->isNestedTransaction()) { // TODO: Add proper logic in the case where there are multiple nested // transaction. This now won't handle the case where there are more than // one level 1 nested transactions. m_Consumer->setTransaction(T->getParent()); } }
// Add the input to the memory buffer, parse it, and add it to the AST. IncrementalParser::EParseResult IncrementalParser::Parse(llvm::StringRef input) { Preprocessor& PP = m_CI->getPreprocessor(); DiagnosticConsumer& DClient = m_CI->getDiagnosticClient(); PP.enableIncrementalProcessing(); DClient.BeginSourceFile(m_CI->getLangOpts(), &PP); // Reset the transaction information getLastTransaction().setBeforeFirstDecl(getCI()->getSema().CurContext); if (input.size()) { std::ostringstream source_name; source_name << "input_line_" << (m_MemoryBuffer.size() + 1); llvm::MemoryBuffer* MB = llvm::MemoryBuffer::getMemBufferCopy(input, source_name.str()); m_MemoryBuffer.push_back(MB); SourceManager& SM = getCI()->getSourceManager(); // Create SourceLocation, which will allow clang to order the overload // candidates for example SourceLocation NewLoc = SM.getLocForStartOfFile(m_VirtualFileID); NewLoc = NewLoc.getLocWithOffset(m_MemoryBuffer.size() + 1); // Create FileID for the current buffer FileID FID = SM.createFileIDForMemBuffer(m_MemoryBuffer.back(), /*LoadedID*/0, /*LoadedOffset*/0, NewLoc); PP.EnterSourceFile(FID, 0, NewLoc); } Parser::DeclGroupPtrTy ADecl; while (!m_Parser->ParseTopLevelDecl(ADecl)) { // Not end of file. // If we got a null return and something *was* parsed, ignore it. This // is due to a top-level semicolon, an action override, or a parse error // skipping something. if (ADecl) { DeclGroupRef DGR = ADecl.getAsVal<DeclGroupRef>(); for (DeclGroupRef::iterator i=DGR.begin(); i< DGR.end(); ++i) { if (!m_FirstTopLevelDecl) m_FirstTopLevelDecl = *((*i)->getDeclContext()->decls_begin()); m_LastTopLevelDecl = *i; } m_Consumer->HandleTopLevelDecl(DGR); } // ADecl }; // Process any TopLevelDecls generated by #pragma weak. for (llvm::SmallVector<Decl*,2>::iterator I = getCI()->getSema().WeakTopLevelDecls().begin(), E = getCI()->getSema().WeakTopLevelDecls().end(); I != E; ++I) { m_Consumer->HandleTopLevelDecl(DeclGroupRef(*I)); } getCI()->getSema().PerformPendingInstantiations(); DClient.EndSourceFile(); PP.enableIncrementalProcessing(false); DiagnosticsEngine& Diag = getCI()->getSema().getDiagnostics(); if (Diag.hasErrorOccurred()) return IncrementalParser::kFailed; else if (Diag.getNumWarnings()) return IncrementalParser::kSuccessWithWarnings; return IncrementalParser::kSuccess; }
Interpreter::CompilationResult Interpreter::EvaluateInternal(const std::string& input, const CompilationOptions& CO, Value* V, /* = 0 */ Transaction** T /* = 0 */) { StateDebuggerRAII stateDebugger(this); // Wrap the expression std::string WrapperName; std::string Wrapper = input; WrapInput(Wrapper, WrapperName); // Disable warnings which doesn't make sense when using the prompt // This gets reset with the clang::Diagnostics().Reset(/*soft*/=false) // using clang's API we simulate: // #pragma warning push // #pragma warning ignore ... // #pragma warning ignore ... // #pragma warning pop SourceLocation Loc = getNextAvailableLoc(); DiagnosticsEngine& Diags = getCI()->getDiagnostics(); Diags.pushMappings(Loc); // The source locations of #pragma warning ignore must be greater than // the ones from #pragma push Diags.setSeverity(clang::diag::warn_unused_expr, clang::diag::Severity::Ignored, SourceLocation()); Diags.setSeverity(clang::diag::warn_unused_call, clang::diag::Severity::Ignored, SourceLocation()); Diags.setSeverity(clang::diag::warn_unused_comparison, clang::diag::Severity::Ignored, SourceLocation()); Diags.setSeverity(clang::diag::ext_return_has_expr, clang::diag::Severity::Ignored, SourceLocation()); if (Transaction* lastT = m_IncrParser->Compile(Wrapper, CO)) { Loc = m_IncrParser->getLastMemoryBufferEndLoc().getLocWithOffset(1); // if the location was the same we are in recursive calls and to avoid an // assert in clang we should increment by a value. if (SourceLocation::getFromRawEncoding(m_LastCustomPragmaDiagPopPoint) == Loc) // Nested #pragma pop-s must be on different source locations. Loc = Loc.getLocWithOffset(1); m_LastCustomPragmaDiagPopPoint = Loc.getRawEncoding(); Diags.popMappings(Loc); assert((lastT->getState() == Transaction::kCommitted || lastT->getState() == Transaction::kRolledBack) && "Not committed?"); if (lastT->getIssuedDiags() != Transaction::kErrors) { 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; } } if (V) *V = Value(); return Interpreter::kFailure; } Diags.popMappings(Loc.getLocWithOffset(1)); return Interpreter::kSuccess; }
const Sema& Interpreter::getSema() const { return getCI()->getSema(); }
Sema& Interpreter::getSema() { return getCI()->getSema(); }
// Add the input to the memory buffer, parse it, and add it to the AST. IncrementalParser::EParseResult IncrementalParser::ParseInternal(llvm::StringRef input) { if (input.empty()) return IncrementalParser::kSuccess; Sema& S = getCI()->getSema(); assert(!(S.getLangOpts().Modules && m_Consumer->getTransaction()->getCompilationOpts() .CodeGenerationForModule) && "CodeGenerationForModule should be removed once modules are available!"); // Recover resources if we crash before exiting this method. llvm::CrashRecoveryContextCleanupRegistrar<Sema> CleanupSema(&S); Preprocessor& PP = m_CI->getPreprocessor(); if (!PP.getCurrentLexer()) { PP.EnterSourceFile(m_CI->getSourceManager().getMainFileID(), 0, SourceLocation()); } assert(PP.isIncrementalProcessingEnabled() && "Not in incremental mode!?"); PP.enableIncrementalProcessing(); std::ostringstream source_name; source_name << "input_line_" << (m_MemoryBuffers.size() + 1); // Create an uninitialized memory buffer, copy code in and append "\n" size_t InputSize = input.size(); // don't include trailing 0 // MemBuffer size should *not* include terminating zero llvm::MemoryBuffer* MB = llvm::MemoryBuffer::getNewUninitMemBuffer(InputSize + 1, source_name.str()); char* MBStart = const_cast<char*>(MB->getBufferStart()); memcpy(MBStart, input.data(), InputSize); memcpy(MBStart + InputSize, "\n", 2); m_MemoryBuffers.push_back(MB); SourceManager& SM = getCI()->getSourceManager(); // Create SourceLocation, which will allow clang to order the overload // candidates for example SourceLocation NewLoc = SM.getLocForStartOfFile(m_VirtualFileID); NewLoc = NewLoc.getLocWithOffset(m_MemoryBuffers.size() + 1); // Create FileID for the current buffer FileID FID = SM.createFileIDForMemBuffer(m_MemoryBuffers.back(), SrcMgr::C_User, /*LoadedID*/0, /*LoadedOffset*/0, NewLoc); PP.EnterSourceFile(FID, /*DirLookup*/0, NewLoc); Parser::DeclGroupPtrTy ADecl; while (!m_Parser->ParseTopLevelDecl(ADecl)) { // If we got a null return and something *was* parsed, ignore it. This // is due to a top-level semicolon, an action override, or a parse error // skipping something. if (ADecl) m_Consumer->HandleTopLevelDecl(ADecl.getAsVal<DeclGroupRef>()); }; // Process any TopLevelDecls generated by #pragma weak. for (llvm::SmallVector<Decl*,2>::iterator I = S.WeakTopLevelDecls().begin(), E = S.WeakTopLevelDecls().end(); I != E; ++I) { m_Consumer->HandleTopLevelDecl(DeclGroupRef(*I)); } DiagnosticsEngine& Diag = S.getDiagnostics(); if (Diag.hasErrorOccurred()) return IncrementalParser::kFailed; else if (Diag.getNumWarnings()) return IncrementalParser::kSuccessWithWarnings; return IncrementalParser::kSuccess; }
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>(*(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.</p> // 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 <set> using namespace std; extern "C" int printf(const char*,...); struct S { template <typename T> 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<int>; (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<LangOptions&>(getCI()->getLangOpts()); bool savedAccessControl = LO.AccessControl; LO.AccessControl = withAccessControl; cling::Transaction* T = 0; cling::Interpreter::CompilationResult CR = declare(code, &T); LO.AccessControl = savedAccessControl; 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<LinkageSpecDecl>(*I->m_DGR.begin())) { DeclContext::decl_iterator DeclBegin = LSD->decls_begin(); if (DeclBegin == LSD->decls_end()) continue; if (const FunctionDecl* D = dyn_cast<FunctionDecl>(*DeclBegin)) { const IdentifierInfo* II = D->getDeclName().getAsIdentifierInfo(); if (II && II->getName() == name) return D; } } } return 0; }
void IncrementalParser::commitTransaction(Transaction* T) { //Transaction* CurT = m_Consumer->getTransaction(); assert(T->isCompleted() && "Transaction not ended!?"); assert(T->getState() != Transaction::kCommitted && "Committing an already committed transaction."); // If committing a nested transaction the active one should be its parent // from now on. if (T->isNestedTransaction()) m_Consumer->setTransaction(T->getParent()); // Check for errors... if (T->getIssuedDiags() == Transaction::kErrors) { rollbackTransaction(T); return; } if (T->hasNestedTransactions()) { for(Transaction::const_nested_iterator I = T->nested_begin(), E = T->nested_end(); I != E; ++I) if ((*I)->getState() != Transaction::kCommitted) commitTransaction(*I); } if (!transformTransactionAST(T)) return; // Here we expect a template instantiation. We need to open the transaction // that we are currently work with. Transaction::State oldState = T->getState(); T->setState(Transaction::kCollecting); // Pull all template instantiations in that came from the consumers. getCI()->getSema().PerformPendingInstantiations(); T->setState(oldState); m_Consumer->HandleTranslationUnit(getCI()->getASTContext()); if (T->getCompilationOpts().CodeGeneration && hasCodeGenerator()) { codeGenTransaction(T); transformTransactionIR(T); } // The static initializers might run anything and can thus cause more // decls that need to end up in a transaction. But this one is done // with CodeGen... T->setState(Transaction::kCommitted); if (T->getCompilationOpts().CodeGeneration && hasCodeGenerator()) { runStaticInitOnTransaction(T); } InterpreterCallbacks* callbacks = m_Interpreter->getCallbacks(); if (callbacks) callbacks->TransactionCommitted(*T); // If the transaction is empty do nothing. // Except it was nested transaction and we want to reuse it later on. if (T->empty() && T->isNestedTransaction()) { // We need to remove the marker from its parent. Transaction* ParentT = T->getParent(); for (size_t i = 0; i < ParentT->size(); ++i) if ((*ParentT)[i].m_DGR.isNull()) ParentT->erase(i); } }