bool DeclCollector::HandleTopLevelDecl(DeclGroupRef DGR) { // if that decl comes from an AST File, i.e. PCH/PCM, no transaction needed // pipe it directly to codegen. if (comesFromASTReader(DGR)) { if (m_CodeGen) { for (DeclGroupRef::iterator I = DGR.begin(), E = DGR.end(); I != E; ++I) { if (NamespaceDecl* ND = dyn_cast<NamespaceDecl>(*I)) { for (NamespaceDecl::decl_iterator IN = ND->decls_begin(), EN = ND->decls_end(); IN != EN; ++IN) // Recurse over decls inside the namespace, like // CodeGenModule::EmitNamespace() does. HandleTopLevelDecl(DeclGroupRef(*IN)); } else { if (!shouldIgnoreDeclFromASTReader(*I)) { m_CodeGen->HandleTopLevelDecl(DeclGroupRef(*I)); } // FIXME: once modules are there this is not needed anymore. // it is used to simulate modules and the ASTDeserializationListener // for sources that are included to describe the library that was // built from the sources (ACLiC). if (!(*I)->isFromASTFile() && m_Interp->getASTDeserializationListener()) m_Interp->getASTDeserializationListener()->DeclRead(0, *I); } } } return true; } Transaction::DelayCallInfo DCI(DGR, Transaction::kCCIHandleTopLevelDecl); m_CurTransaction->append(DCI); return true; }
void DeclCollector::HandleCXXStaticMemberVarInstantiation(VarDecl *D) { assert(m_CurTransaction && "Missing transction"); Transaction::DelayCallInfo DCI(DeclGroupRef(D), Transaction::kCCIHandleCXXStaticMemberVarInstantiation); m_CurTransaction->append(DCI); if (m_Consumer && (!comesFromASTReader(DeclGroupRef(D)) || !shouldIgnore(D))) m_Consumer->HandleCXXStaticMemberVarInstantiation(D); }
void DeclCollector::HandleTagDeclDefinition(TagDecl* TD) { assert(m_CurTransaction && "Missing transction"); Transaction::DelayCallInfo DCI(DeclGroupRef(TD), Transaction::kCCIHandleTagDeclDefinition); m_CurTransaction->append(DCI); if (m_Consumer && (!comesFromASTReader(DeclGroupRef(TD)) || !shouldIgnore(TD))) m_Consumer->HandleTagDeclDefinition(TD); }
void DeclCollector::CompleteTentativeDefinition(VarDecl* VD) { assert(m_CurTransaction && "Missing transction"); // C has tentative definitions which we might need to deal with when running // in C mode. Transaction::DelayCallInfo DCI(DeclGroupRef(VD), Transaction::kCCICompleteTentativeDefinition); m_CurTransaction->append(DCI); if (m_Consumer && (!comesFromASTReader(DeclGroupRef(VD)) || !shouldIgnore(VD))) m_Consumer->CompleteTentativeDefinition(VD); }
void DeclCollector::HandleCXXStaticMemberVarInstantiation(VarDecl *D) { // if that decl comes from an AST File, i.e. PCH/PCM, no transaction needed // pipe it directly to codegen. if (comesFromASTReader(DeclGroupRef(D))) { if (m_CodeGen && !shouldIgnoreDeclFromASTReader(D)) m_CodeGen->HandleCXXStaticMemberVarInstantiation(D); return; } Transaction::DelayCallInfo DCI(DeclGroupRef(D), Transaction::kCCIHandleCXXStaticMemberVarInstantiation); m_CurTransaction->append(DCI); }
void DeclCollector::HandleTagDeclDefinition(TagDecl* TD) { // if that decl comes from an AST File, i.e. PCH/PCM, no transaction needed // pipe it directly to codegen. if (comesFromASTReader(DeclGroupRef(TD))) { if (m_CodeGen) m_CodeGen->HandleTagDeclDefinition(TD); return; } Transaction::DelayCallInfo DCI(DeclGroupRef(TD), Transaction::kCCIHandleTagDeclDefinition); m_CurTransaction->append(DCI); }
void DeclCollector::HandleCXXImplicitFunctionInstantiation(FunctionDecl *D) { // if that decl comes from an AST File, i.e. PCH/PCM, no transaction needed // pipe it directly to codegen. if (comesFromASTReader(DeclGroupRef(D))) { if (m_CodeGen) m_CodeGen->HandleCXXImplicitFunctionInstantiation(D); return; } Transaction::DelayCallInfo DCI(DeclGroupRef(D), Transaction::kCCIHandleCXXImplicitFunctionInstantiation); m_CurTransaction->append(DCI); }
void DeclCollector::CompleteTentativeDefinition(VarDecl* VD) { // C has tentative definitions which we might need to deal with when running // in C mode. Transaction::DelayCallInfo DCI(DeclGroupRef(VD), Transaction::kCCICompleteTentativeDefinition); m_CurTransaction->append(DCI); }
void DeclCollector::HandleVTable(CXXRecordDecl* RD) { assert(m_CurTransaction && "Missing transction"); Transaction::DelayCallInfo DCI(DeclGroupRef(RD), Transaction::kCCIHandleVTable); m_CurTransaction->append(DCI); if (m_Consumer && (!comesFromASTReader(DeclGroupRef(RD)) || !shouldIgnore(RD))) m_Consumer->HandleVTable(RD); // Intentional no-op. It comes through Sema::DefineUsedVTables, which // comes either Sema::ActOnEndOfTranslationUnit or while instantiating a // template. In our case we will do it on transaction commit, without // keeping track of used vtables, because we have cases where we bypass the // clang/AST and directly ask the module so that we have to generate // everything without extra smartness. }
bool DeclCollector::HandleTopLevelDecl(DeclGroupRef DGR) { if (!Transform(DGR)) return false; if (DGR.isNull()) return true; assert(m_CurTransaction && "Missing transction"); Transaction::DelayCallInfo DCI(DGR, Transaction::kCCIHandleTopLevelDecl); m_CurTransaction->append(DCI); if (!m_Consumer || getTransaction()->getIssuedDiags() == Transaction::kErrors) return true; if (comesFromASTReader(DGR)) { for (DeclGroupRef::iterator DI = DGR.begin(), DE = DGR.end(); DI != DE; ++DI) { DeclGroupRef SplitDGR(*DI); // FIXME: The special namespace treatment (not sending itself to // CodeGen, but only its content - if the contained decl should be // emitted) works around issue with the static initialization when // having a PCH and loading a library. We don't want to generate // code for the static that will come through the library. // // This will be fixed with the clang::Modules. Make sure we remember. // assert(!getCI()->getLangOpts().Modules && "Please revisit!"); if (NamespaceDecl* ND = dyn_cast<NamespaceDecl>(*DI)) { for (NamespaceDecl::decl_iterator NDI = ND->decls_begin(), EN = ND->decls_end(); NDI != EN; ++NDI) { // Recurse over decls inside the namespace, like // CodeGenModule::EmitNamespace() does. if (!shouldIgnore(*NDI)) m_Consumer->HandleTopLevelDecl(DeclGroupRef(*NDI)); } } else if (!shouldIgnore(*DI)) { m_Consumer->HandleTopLevelDecl(DeclGroupRef(*DI)); } continue; } } else { m_Consumer->HandleTopLevelDecl(DGR); } return true; }
void DeclCollector::HandleVTable(CXXRecordDecl* RD, bool DefinitionRequired) { Transaction::DelayCallInfo DCI(DeclGroupRef(RD), Transaction::kCCIHandleVTable); m_CurTransaction->append(DCI); // Intentional no-op. It comes through Sema::DefineUsedVTables, which // comes either Sema::ActOnEndOfTranslationUnit or while instantiating a // template. In our case we will do it on transaction commit, without // keeping track of used vtables, because we have cases where we bypass the // clang/AST and directly ask the module so that we have to generate // everything without extra smartness. }
void DeclCollector::HandleVTable(CXXRecordDecl* RD, bool DefinitionRequired) { // if that decl comes from an AST File, i.e. PCH/PCM, no transaction needed // pipe it directly to codegen. if (comesFromASTReader(DeclGroupRef(RD))) { // FIXME: when is the vtable part of the library? if (m_CodeGen) m_CodeGen->HandleVTable(RD, DefinitionRequired); return; } Transaction::DelayCallInfo DCI(DeclGroupRef(RD), Transaction::kCCIHandleVTable); m_CurTransaction->append(DCI); // Intentional no-op. It comes through Sema::DefineUsedVTables, which // comes either Sema::ActOnEndOfTranslationUnit or while instantiating a // template. In our case we will do it on transaction commit, without // keeping track of used vtables, because we have cases where we bypass the // clang/AST and directly ask the module so that we have to generate // everything without extra smartness. }
void DeclCollector::HandleCXXImplicitFunctionInstantiation(FunctionDecl *D) { Transaction::DelayCallInfo DCI(DeclGroupRef(D), Transaction::kCCIHandleCXXImplicitFunctionInstantiation); m_CurTransaction->append(DCI); }
void DeclCollector::HandleTagDeclDefinition(TagDecl* TD) { Transaction::DelayCallInfo DCI(DeclGroupRef(TD), Transaction::kCCIHandleTagDeclDefinition); m_CurTransaction->append(DCI); }
ASTNodeInfo EvaluateTSynthesizer::VisitDeclStmt(DeclStmt* Node) { // Visit all the children, which are the contents of the DeclGroupRef for (Stmt::child_iterator I = Node->child_begin(), E = Node->child_end(); I != E; ++I) { if (*I) { Expr* E = cast_or_null<Expr>(*I); if (!E || !IsArtificiallyDependent(E)) continue; //FIXME: don't assume there is only one decl. assert(Node->isSingleDecl() && "There is more that one decl in stmt"); VarDecl* CuredDecl = cast_or_null<VarDecl>(Node->getSingleDecl()); assert(CuredDecl && "Not a variable declaration!"); QualType CuredDeclTy = CuredDecl->getType(); // check if the case is sometype * somevar = init; // or some_builtin_type somevar = init; if (CuredDecl->hasInit() && (CuredDeclTy->isAnyPointerType() || !CuredDeclTy->isRecordType())) { *I = SubstituteUnknownSymbol(CuredDeclTy, CuredDecl->getInit()); continue; } // 1. Check whether this is the case of MyClass A(dep->symbol()) // 2. Insert the RuntimeUniverse's LifetimeHandler instance // 3. Change the A's initializer to *(MyClass*)instance.getMemory() // 4. Make A reference (&A) // 5. Set the new initializer of A if (CuredDeclTy->isLValueReferenceType()) continue; // Set Sema's Current DeclContext to the one we need DeclContext* OldDC = m_Sema->CurContext; m_Sema->CurContext = CuredDecl->getDeclContext(); ASTNodeInfo NewNode; // 2.1 Get unique name for the LifetimeHandler instance and // initialize it std::string UniqueName; createUniqueName(UniqueName); IdentifierInfo& II = m_Context->Idents.get(UniqueName); // Prepare the initialization Exprs. // We want to call LifetimeHandler(DynamicExprInfo* ExprInfo, // DeclContext DC, // const char* type) // Interpreter* interp) llvm::SmallVector<Expr*, 4> Inits; // Add MyClass in LifetimeHandler unique(DynamicExprInfo* ExprInfo // DC, // "MyClass" // Interpreter* Interp) // Build Arg0 DynamicExprInfo Inits.push_back(BuildDynamicExprInfo(E)); // Build Arg1 DeclContext* DC QualType DCTy = m_Context->getTypeDeclType(m_DeclContextDecl); Inits.push_back(utils::Synthesize::CStyleCastPtrExpr(m_Sema, DCTy, (uint64_t)m_CurDeclContext) ); // Build Arg2 llvm::StringRef // Get the type of the type without specifiers PrintingPolicy Policy(m_Context->getLangOpts()); Policy.SuppressTagKeyword = 1; std::string Res; CuredDeclTy.getAsStringInternal(Res, Policy); Inits.push_back(ConstructConstCharPtrExpr(Res.c_str())); // Build Arg3 cling::Interpreter CXXScopeSpec CXXSS; DeclarationNameInfo NameInfo(m_gCling->getDeclName(), m_gCling->getLocStart()); Expr* gClingDRE = m_Sema->BuildDeclarationNameExpr(CXXSS, NameInfo ,m_gCling).take(); Inits.push_back(gClingDRE); // 2.3 Create a variable from LifetimeHandler. QualType HandlerTy = m_Context->getTypeDeclType(m_LifetimeHandlerDecl); TypeSourceInfo* TSI = m_Context->getTrivialTypeSourceInfo(HandlerTy, m_NoSLoc); VarDecl* HandlerInstance = VarDecl::Create(*m_Context, CuredDecl->getDeclContext(), m_NoSLoc, m_NoSLoc, &II, HandlerTy, TSI, SC_None); // 2.4 Call the best-match constructor. The method does overload // resolution of the constructors and then initializes the new // variable with it ExprResult InitExprResult = m_Sema->ActOnParenListExpr(m_NoSLoc, m_NoELoc, Inits); m_Sema->AddInitializerToDecl(HandlerInstance, InitExprResult.take(), /*DirectInit*/ true, /*TypeMayContainAuto*/ false); // 2.5 Register the instance in the enclosing context CuredDecl->getDeclContext()->addDecl(HandlerInstance); NewNode.addNode(new (m_Context) DeclStmt(DeclGroupRef(HandlerInstance), m_NoSLoc, m_NoELoc) ); // 3.1 Build a DeclRefExpr, which holds the object DeclRefExpr* MemberExprBase = m_Sema->BuildDeclRefExpr(HandlerInstance, HandlerTy, VK_LValue, m_NoSLoc ).takeAs<DeclRefExpr>(); // 3.2 Create a MemberExpr to getMemory from its declaration. CXXScopeSpec SS; LookupResult MemberLookup(*m_Sema, m_LHgetMemoryDecl->getDeclName(), m_NoSLoc, Sema::LookupMemberName); // Add the declaration as if doesn't exist. // TODO: Check whether this is the most appropriate variant MemberLookup.addDecl(m_LHgetMemoryDecl, AS_public); MemberLookup.resolveKind(); Expr* MemberExpr = m_Sema->BuildMemberReferenceExpr(MemberExprBase, HandlerTy, m_NoSLoc, /*IsArrow=*/false, SS, m_NoSLoc, /*FirstQualifierInScope=*/0, MemberLookup, /*TemplateArgs=*/0 ).take(); // 3.3 Build the actual call Scope* S = m_Sema->getScopeForContext(m_Sema->CurContext); Expr* theCall = m_Sema->ActOnCallExpr(S, MemberExpr, m_NoSLoc, MultiExprArg(), m_NoELoc).take(); // Cast to the type LHS type Expr* Result = utils::Synthesize::CStyleCastPtrExpr(m_Sema, CuredDeclTy, theCall); // Cast once more (dereference the cstyle cast) Result = m_Sema->BuildUnaryOp(S, m_NoSLoc, UO_Deref, Result).take(); // 4. CuredDecl->setType(m_Context->getLValueReferenceType(CuredDeclTy)); // 5. CuredDecl->setInit(Result); NewNode.addNode(Node); // Restore Sema's original DeclContext m_Sema->CurContext = OldDC; return NewNode; } } return ASTNodeInfo(Node, 0); }
void Transaction::forceAppend(Decl* D) { forceAppend(DelayCallInfo(DeclGroupRef(D), kCCIHandleTopLevelDecl)); }
void Transaction::append(Decl* D) { append(DeclGroupRef(D)); }
// 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; }
void DeclCollector::HandleCXXStaticMemberVarInstantiation(VarDecl *D) { Transaction::DelayCallInfo DCI(DeclGroupRef(D), Transaction::kCCIHandleCXXStaticMemberVarInstantiation); m_CurTransaction->append(DCI); }
bool DeclExtractor::ExtractDecl(Decl* D) { FunctionDecl* FD = dyn_cast<FunctionDecl>(D); if (FD) { if (FD->getNameAsString().find("__cling_Un1Qu3")) return true; llvm::SmallVector<NamedDecl*, 4> TouchedDecls; CompoundStmt* CS = dyn_cast<CompoundStmt>(FD->getBody()); assert(CS && "Function body not a CompoundStmt?"); DeclContext* DC = FD->getTranslationUnitDecl(); Scope* TUScope = m_Sema->TUScope; assert(TUScope == m_Sema->getScopeForContext(DC) && "TU scope from DC?"); llvm::SmallVector<Stmt*, 4> Stmts; for (CompoundStmt::body_iterator I = CS->body_begin(), EI = CS->body_end(); I != EI; ++I) { DeclStmt* DS = dyn_cast<DeclStmt>(*I); if (!DS) { Stmts.push_back(*I); continue; } for (DeclStmt::decl_iterator J = DS->decl_begin(); J != DS->decl_end(); ++J) { NamedDecl* ND = dyn_cast<NamedDecl>(*J); if (ND) { DeclContext* OldDC = ND->getDeclContext(); // Make sure the decl is not found at its old possition OldDC->removeDecl(ND); if (Scope* S = m_Sema->getScopeForContext(OldDC)) { S->RemoveDecl(ND); m_Sema->IdResolver.RemoveDecl(ND); } if (ND->getDeclContext() == ND->getLexicalDeclContext()) ND->setLexicalDeclContext(DC); else assert("Not implemented: Decl with different lexical context"); ND->setDeclContext(DC); if (VarDecl* VD = dyn_cast<VarDecl>(ND)) { VD->setStorageClass(SC_None); VD->setStorageClassAsWritten(SC_None); // if we want to print the result of the initializer of int i = 5 // or the default initializer int i if (I+1 == EI || !isa<NullStmt>(*(I+1))) { QualType VDTy = VD->getType().getNonReferenceType(); Expr* DRE = m_Sema->BuildDeclRefExpr(VD, VDTy,VK_LValue, SourceLocation() ).take(); Stmts.push_back(DRE); } } // force recalc of the linkage (to external) ND->ClearLinkageCache(); TouchedDecls.push_back(ND); } } } bool hasNoErrors = !CheckForClashingNames(TouchedDecls, DC, TUScope); if (hasNoErrors) { for (size_t i = 0; i < TouchedDecls.size(); ++i) { m_Sema->PushOnScopeChains(TouchedDecls[i], m_Sema->getScopeForContext(DC), /*AddCurContext*/!isa<UsingDirectiveDecl>(TouchedDecls[i])); // The transparent DeclContexts (eg. scopeless enum) doesn't have // scopes. While extracting their contents we need to update the // lookup tables and telling them to pick up the new possitions // in the AST. if (DeclContext* InnerDC = dyn_cast<DeclContext>(TouchedDecls[i])) { if (InnerDC->isTransparentContext()) { // We can't PushDeclContext, because we don't have scope. Sema::ContextRAII pushedDC(*m_Sema, InnerDC); for(DeclContext::decl_iterator DI = InnerDC->decls_begin(), DE = InnerDC->decls_end(); DI != DE ; ++DI) { if (NamedDecl* ND = dyn_cast<NamedDecl>(*DI)) InnerDC->makeDeclVisibleInContext(ND); } } } // Append the new top level decl to the current transaction. getTransaction()->appendUnique(DeclGroupRef(TouchedDecls[i])); } } CS->setStmts(*m_Context, Stmts.data(), Stmts.size()); // Put the wrapper after its declarations. (Nice when AST dumping) DC->removeDecl(FD); DC->addDecl(FD); return hasNoErrors; } return true; }
bool DeclCollector::comesFromASTReader(const Decl* D) const { // The operation is const but clang::DeclGroupRef doesn't allow us to // express it. return comesFromASTReader(DeclGroupRef(const_cast<Decl*>(D))); }
// 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; }
// 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(); const CompilationOptions& CO = m_Consumer->getTransaction()->getCompilationOpts(); assert(!(S.getLangOpts().Modules && CO.CodeGenerationForModule) && "CodeGenerationForModule to be removed once PCMs 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(); smallstream 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 std::unique_ptr<llvm::MemoryBuffer> MB(llvm::MemoryBuffer::getNewUninitMemBuffer(InputSize + 1, source_name.str())); char* MBStart = const_cast<char*>(MB->getBufferStart()); memcpy(MBStart, input.data(), InputSize); MBStart[InputSize] = '\n'; SourceManager& SM = getCI()->getSourceManager(); // Create SourceLocation, which will allow clang to order the overload // candidates for example SourceLocation NewLoc = getLastMemoryBufferEndLoc().getLocWithOffset(1); llvm::MemoryBuffer* MBNonOwn = MB.get(); // Create FileID for the current buffer. FileID FID; // Create FileEntry and FileID for the current buffer. // Enabling the completion point only works on FileEntries. const clang::FileEntry* FE = SM.getFileManager().getVirtualFile(source_name.str(), InputSize, 0 /* mod time*/); SM.overrideFileContents(FE, std::move(MB)); FID = SM.createFileID(FE, NewLoc, SrcMgr::C_User); if (CO.CodeCompletionOffset != -1) { // The completion point is set one a 1-based line/column numbering. // It relies on the implementation to account for the wrapper extra line. PP.SetCodeCompletionPoint(FE, 1/* start point 1-based line*/, CO.CodeCompletionOffset+1/* 1-based column*/); } m_MemoryBuffers.push_back(std::make_pair(MBNonOwn, FID)); // NewLoc only used for diags. PP.EnterSourceFile(FID, /*DirLookup*/0, NewLoc); m_Consumer->getTransaction()->setBufferFID(FID); DiagnosticsEngine& Diags = getCI()->getDiagnostics(); FilteringDiagConsumer::RAAI RAAITmp(*m_DiagConsumer, CO.IgnorePromptDiags); DiagnosticErrorTrap Trap(Diags); Sema::SavePendingInstantiationsRAII SavedPendingInstantiations(S); 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 (Trap.hasErrorOccurred()) m_Consumer->getTransaction()->setIssuedDiags(Transaction::kErrors); if (ADecl) m_Consumer->HandleTopLevelDecl(ADecl.get()); }; // If never entered the while block, there's a chance an error occured if (Trap.hasErrorOccurred()) m_Consumer->getTransaction()->setIssuedDiags(Transaction::kErrors); if (CO.CodeCompletionOffset != -1) { assert((int)SM.getFileOffset(PP.getCodeCompletionLoc()) == CO.CodeCompletionOffset && "Completion point wrongly set!"); assert(PP.isCodeCompletionReached() && "Code completion set but not reached!"); // Let's ignore this transaction: m_Consumer->getTransaction()->setIssuedDiags(Transaction::kErrors); return kSuccess; } #ifdef LLVM_ON_WIN32 // Microsoft-specific: // Late parsed templates can leave unswallowed "macro"-like tokens. // They will seriously confuse the Parser when entering the next // source file. So lex until we are EOF. Token Tok; do { PP.Lex(Tok); } while (Tok.isNot(tok::eof)); #endif #ifndef NDEBUG Token AssertTok; PP.Lex(AssertTok); assert(AssertTok.is(tok::eof) && "Lexer must be EOF when starting incremental parse!"); #endif // 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)); } if (m_Consumer->getTransaction()->getIssuedDiags() == Transaction::kErrors) return kFailed; else if (Diags.getNumWarnings()) return kSuccessWithWarnings; return kSuccess; }