DeclContext::lookup_result DeclContext::lookup(DeclarationName Name) { DeclContext *PrimaryContext = getPrimaryContext(); if (PrimaryContext != this) return PrimaryContext->lookup(Name); if (hasExternalVisibleStorage()) { // Check to see if we've already cached the lookup results. if (LookupPtr) { StoredDeclsMap::iterator I = LookupPtr->find(Name); if (I != LookupPtr->end()) return I->second.getLookupResult(getParentASTContext()); } ExternalASTSource *Source = getParentASTContext().getExternalSource(); return Source->FindExternalVisibleDeclsByName(this, Name); } /// If there is no lookup data structure, build one now by walking /// all of the linked DeclContexts (in declaration order!) and /// inserting their values. if (!LookupPtr) { buildLookup(this); if (!LookupPtr) return lookup_result(lookup_iterator(0), lookup_iterator(0)); } StoredDeclsMap::iterator Pos = LookupPtr->find(Name); if (Pos == LookupPtr->end()) return lookup_result(lookup_iterator(0), lookup_iterator(0)); return Pos->second.getLookupResult(getParentASTContext()); }
/// \brief Load the declarations within this lexical storage from an /// external source. void DeclContext::LoadLexicalDeclsFromExternalStorage() const { ExternalASTSource *Source = getParentASTContext().getExternalSource(); assert(hasExternalLexicalStorage() && Source && "No external storage?"); // Notify that we have a DeclContext that is initializing. ExternalASTSource::Deserializing ADeclContext(Source); llvm::SmallVector<Decl*, 64> Decls; if (Source->FindExternalLexicalDecls(this, Decls)) return; // There is no longer any lexical storage in this context ExternalLexicalStorage = false; if (Decls.empty()) return; // We may have already loaded just the fields of this record, in which case // don't add the decls, just replace the FirstDecl/LastDecl chain. if (const RecordDecl *RD = dyn_cast<RecordDecl>(this)) if (RD->LoadedFieldsFromExternalStorage) { llvm::tie(FirstDecl, LastDecl) = BuildDeclChain(Decls); return; } // Splice the newly-read declarations into the beginning of the list // of declarations. Decl *ExternalFirst, *ExternalLast; llvm::tie(ExternalFirst, ExternalLast) = BuildDeclChain(Decls); ExternalLast->NextDeclInContext = FirstDecl; FirstDecl = ExternalFirst; if (!LastDecl) LastDecl = ExternalLast; }
void DefnContext::MaterializeVisibleDefnsFromExternalStorage() { ExternalASTSource *Source = getParentASTContext().getExternalSource(); assert(hasExternalVisibleStorage() && Source && "No external storage?"); if (!LookupPtr) CreateStoredDefnsMap(getParentASTContext()); Source->MaterializeVisibleDefns(this); }
/// \brief We have just acquired external visible storage, and we already have /// built a lookup map. For every name in the map, pull in the new names from /// the external storage. void DeclContext::reconcileExternalVisibleStorage() { assert(NeedToReconcileExternalVisibleStorage && LookupPtr.getPointer()); NeedToReconcileExternalVisibleStorage = false; StoredDeclsMap &Map = *LookupPtr.getPointer(); ExternalASTSource *Source = getParentASTContext().getExternalSource(); for (StoredDeclsMap::iterator I = Map.begin(); I != Map.end(); ++I) { I->second.removeExternalDecls(); Source->FindExternalVisibleDeclsByName(this, I->first); } }
DeclContext::lookup_result DeclContext::lookup(DeclarationName Name) { assert(DeclKind != Decl::LinkageSpec && "Should not perform lookups into linkage specs!"); DeclContext *PrimaryContext = getPrimaryContext(); if (PrimaryContext != this) return PrimaryContext->lookup(Name); if (hasExternalVisibleStorage()) { StoredDeclsMap *Map = LookupPtr.getPointer(); if (LookupPtr.getInt()) Map = buildLookup(); else if (NeedToReconcileExternalVisibleStorage) reconcileExternalVisibleStorage(); if (!Map) Map = CreateStoredDeclsMap(getParentASTContext()); // If a PCH/module has a result for this name, and we have a local // declaration, we will have imported the PCH/module result when adding the // local declaration or when reconciling the module. std::pair<StoredDeclsMap::iterator, bool> R = Map->insert(std::make_pair(Name, StoredDeclsList())); if (!R.second) return R.first->second.getLookupResult(); ExternalASTSource *Source = getParentASTContext().getExternalSource(); if (Source->FindExternalVisibleDeclsByName(this, Name)) { if (StoredDeclsMap *Map = LookupPtr.getPointer()) { StoredDeclsMap::iterator I = Map->find(Name); if (I != Map->end()) return I->second.getLookupResult(); } } return lookup_result(lookup_iterator(0), lookup_iterator(0)); } StoredDeclsMap *Map = LookupPtr.getPointer(); if (LookupPtr.getInt()) Map = buildLookup(); if (!Map) return lookup_result(lookup_iterator(0), lookup_iterator(0)); StoredDeclsMap::iterator I = Map->find(Name); if (I == Map->end()) return lookup_result(lookup_iterator(0), lookup_iterator(0)); return I->second.getLookupResult(); }
DefnContext::lookup_result DefnContext::lookup(DefinitionName Name) { if (hasExternalVisibleStorage()) { // Check to see if we've already cached the lookup results. if (LookupPtr) { StoredDefnsMap::iterator I = LookupPtr->find(Name); if (I != LookupPtr->end()) return I->second.getLookupResult(); } ExternalASTSource *Source = getParentASTContext().getExternalSource(); return Source->FindExternalVisibleDefnsByName(this, Name); } StoredDefnsMap::iterator Pos = LookupPtr->find(Name); if (Pos == LookupPtr->end()) return lookup_result(lookup_iterator(0), lookup_iterator(0)); return Pos->second.getLookupResult(); }
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); }
/// \brief Load the declarations within this lexical storage from an /// external source. void DeclContext::LoadLexicalDeclsFromExternalStorage() const { ExternalASTSource *Source = getParentASTContext().getExternalSource(); assert(hasExternalLexicalStorage() && Source && "No external storage?"); // Notify that we have a DeclContext that is initializing. ExternalASTSource::Deserializing ADeclContext(Source); llvm::SmallVector<Decl*, 64> Decls; if (Source->FindExternalLexicalDecls(this, Decls)) return; // There is no longer any lexical storage in this context ExternalLexicalStorage = false; if (Decls.empty()) return; // Resolve all of the declaration IDs into declarations, building up // a chain of declarations via the Decl::NextDeclInContext field. Decl *FirstNewDecl = 0; Decl *PrevDecl = 0; for (unsigned I = 0, N = Decls.size(); I != N; ++I) { Decl *D = Decls[I]; if (PrevDecl) PrevDecl->NextDeclInContext = D; else FirstNewDecl = D; PrevDecl = D; } // Splice the newly-read declarations into the beginning of the list // of declarations. PrevDecl->NextDeclInContext = FirstDecl; FirstDecl = FirstNewDecl; if (!LastDecl) LastDecl = PrevDecl; }
void DeclContext::LoadVisibleDeclsFromExternalStorage() const { DeclContext *This = const_cast<DeclContext *>(this); ExternalASTSource *Source = getParentASTContext().getExternalSource(); assert(hasExternalVisibleStorage() && Source && "No external storage?"); llvm::SmallVector<VisibleDeclaration, 64> Decls; if (Source->ReadDeclsVisibleInContext(This, Decls)) return; // There is no longer any visible storage in this context ExternalVisibleStorage = false; // Load the declaration IDs for all of the names visible in this // context. assert(!LookupPtr && "Have a lookup map before de-serialization?"); StoredDeclsMap *Map = new StoredDeclsMap; LookupPtr = Map; for (unsigned I = 0, N = Decls.size(); I != N; ++I) { (*Map)[Decls[I].Name].setFromDeclIDs(Decls[I].Declarations); } }
/// \brief Load the declarations within this lexical storage from an /// external source. void DeclContext::LoadLexicalDeclsFromExternalStorage() const { ExternalASTSource *Source = getParentASTContext().getExternalSource(); assert(hasExternalLexicalStorage() && Source && "No external storage?"); // Notify that we have a DeclContext that is initializing. ExternalASTSource::Deserializing ADeclContext(Source); // Load the external declarations, if any. SmallVector<Decl*, 64> Decls; ExternalLexicalStorage = false; switch (Source->FindExternalLexicalDecls(this, Decls)) { case ELR_Success: break; case ELR_Failure: case ELR_AlreadyLoaded: return; } if (Decls.empty()) return; // We may have already loaded just the fields of this record, in which case // we need to ignore them. bool FieldsAlreadyLoaded = false; if (const RecordDecl *RD = dyn_cast<RecordDecl>(this)) FieldsAlreadyLoaded = RD->LoadedFieldsFromExternalStorage; // Splice the newly-read declarations into the beginning of the list // of declarations. Decl *ExternalFirst, *ExternalLast; llvm::tie(ExternalFirst, ExternalLast) = BuildDeclChain(Decls, FieldsAlreadyLoaded); ExternalLast->NextInContextAndBits.setPointer(FirstDecl); FirstDecl = ExternalFirst; if (!LastDecl) LastDecl = ExternalLast; }
DeclContext::lookup_result DeclContext::lookup(DeclarationName Name) { assert(DeclKind != Decl::LinkageSpec && "Should not perform lookups into linkage specs!"); DeclContext *PrimaryContext = getPrimaryContext(); if (PrimaryContext != this) return PrimaryContext->lookup(Name); if (hasExternalVisibleStorage()) { // If a PCH has a result for this name, and we have a local declaration, we // will have imported the PCH result when adding the local declaration. // FIXME: For modules, we could have had more declarations added by module // imoprts since we saw the declaration of the local name. if (StoredDeclsMap *Map = LookupPtr.getPointer()) { StoredDeclsMap::iterator I = Map->find(Name); if (I != Map->end()) return I->second.getLookupResult(); } ExternalASTSource *Source = getParentASTContext().getExternalSource(); return Source->FindExternalVisibleDeclsByName(this, Name); } StoredDeclsMap *Map = LookupPtr.getPointer(); if (LookupPtr.getInt()) Map = buildLookup(); if (!Map) return lookup_result(lookup_iterator(0), lookup_iterator(0)); StoredDeclsMap::iterator I = Map->find(Name); if (I == Map->end()) return lookup_result(lookup_iterator(0), lookup_iterator(0)); return I->second.getLookupResult(); }
DeclContext::lookup_result DeclContext::lookup(IdentifierInfo &Name) { DeclContext *PrimaryContext = getPrimaryContext(); if (PrimaryContext != this) // FIXME: not needed? return PrimaryContext->lookup(Name); #if 0 // FIXME: modules. eventually. resync this part from clang. if (hasExternalVisibleStorage()) { // If a PCH has a result for this name, and we have a local declaration, we // will have imported the PCH result when adding the local declaration. // FIXME: For modules, we could have had more declarations added by module // imoprts since we saw the declaration of the local name. if (StoredDeclsMap *Map = LookupPtr.getPointer()) { StoredDeclsMap::iterator I = Map->find(&Name); if (I != Map->end()) return I->second.getLookupResult(); } ExternalASTSource *Source = getParentASTContext().getExternalSource(); return Source->FindExternalVisibleDeclsByName(this, Name); } #endif StoredDeclsMap *Map = LookupPtr.getPointer(); if (LookupPtr.getInt()) Map = buildLookup(); if (!Map) return lookup_result(lookup_iterator(0), lookup_iterator(0)); StoredDeclsMap::iterator I = Map->find(&Name); if (I == Map->end()) return lookup_result(lookup_iterator(0), lookup_iterator(0)); return I->second.getLookupResult(); }
void StoredDeclsList::materializeDecls(ASTContext &Context) { if (isNull()) return; switch ((DataKind)(Data & 0x03)) { case DK_Decl: case DK_Decl_Vector: break; case DK_DeclID: { // Resolve this declaration ID to an actual declaration by // querying the external AST source. unsigned DeclID = Data >> 2; ExternalASTSource *Source = Context.getExternalSource(); assert(Source && "No external AST source available!"); Data = reinterpret_cast<uintptr_t>(Source->GetDecl(DeclID)); break; } case DK_ID_Vector: { // We have a vector of declaration IDs. Resolve all of them to // actual declarations. VectorTy &Vector = *getAsVector(); ExternalASTSource *Source = Context.getExternalSource(); assert(Source && "No external AST source available!"); for (unsigned I = 0, N = Vector.size(); I != N; ++I) Vector[I] = reinterpret_cast<uintptr_t>(Source->GetDecl(Vector[I])); Data = (Data & ~0x03) | DK_Decl_Vector; break; } } }
bool IncrementalParser::Initialize(llvm::SmallVectorImpl<ParseResultTransaction>& result, bool isChildInterpreter) { m_TransactionPool.reset(new TransactionPool); if (hasCodeGenerator()) getCodeGenerator()->Initialize(getCI()->getASTContext()); CompilationOptions CO = m_Interpreter->makeDefaultCompilationOpts(); Transaction* CurT = beginTransaction(CO); Preprocessor& PP = m_CI->getPreprocessor(); DiagnosticsEngine& Diags = m_CI->getSema().getDiagnostics(); // Pull in PCH. const std::string& PCHFileName = m_CI->getInvocation().getPreprocessorOpts().ImplicitPCHInclude; if (!PCHFileName.empty()) { Transaction* PchT = beginTransaction(CO); DiagnosticErrorTrap Trap(Diags); m_CI->createPCHExternalASTSource(PCHFileName, true /*DisablePCHValidation*/, true /*AllowPCHWithCompilerErrors*/, 0 /*DeserializationListener*/, true /*OwnsDeserializationListener*/); result.push_back(endTransaction(PchT)); if (Trap.hasErrorOccurred()) { result.push_back(endTransaction(CurT)); return false; } } addClingPragmas(*m_Interpreter); // Must happen after attaching the PCH, else PCH elements will end up // being lexed. PP.EnterMainSourceFile(); Sema* TheSema = &m_CI->getSema(); m_Parser.reset(new Parser(PP, *TheSema, false /*skipFuncBodies*/)); // Initialize the parser after PP has entered the main source file. m_Parser->Initialize(); ExternalASTSource *External = TheSema->getASTContext().getExternalSource(); if (External) External->StartTranslationUnit(m_Consumer); // Start parsing the "main file" to warm up lexing (enter caching lex mode // for ParseInternal()'s call EnterSourceFile() to make sense. while (!m_Parser->ParseTopLevelDecl()) {} // If I belong to the parent Interpreter, am using C++, and -noruntime // wasn't given on command line, then #include <new> and check ABI if (!isChildInterpreter && m_CI->getLangOpts().CPlusPlus && !m_Interpreter->getOptions().NoRuntime) { // <new> is needed by the ValuePrinter so it's a good thing to include it. // We need to include it to determine the version number of the standard // library implementation. ParseInternal("#include <new>"); // That's really C++ ABI compatibility. C has other problems ;-) CheckABICompatibility(*m_Interpreter); } // DO NOT commit the transactions here: static initialization in these // transactions requires gCling through local_cxa_atexit(), but that has not // been defined yet! ParseResultTransaction PRT = endTransaction(CurT); result.push_back(PRT); return true; }
DeclContext::lookup_result DeclContext::lookup(DeclarationName Name) { assert(DeclKind != Decl::LinkageSpec && "Should not perform lookups into linkage specs!"); DeclContext *PrimaryContext = getPrimaryContext(); if (PrimaryContext != this) return PrimaryContext->lookup(Name); #if AXEL_LOOKUP_CHANGES StoredDeclsMap *Map = LookupPtr.getPointer(); if (LookupPtr.getInt()) Map = buildLookup(); #endif if (hasExternalVisibleStorage()) { // If a PCH has a result for this name, and we have a local declaration, we // will have imported the PCH result when adding the local declaration. // FIXME: For modules, we could have had more declarations added by module // imoprts since we saw the declaration of the local name. #if AXEL_LOOKUP_CHANGES if (Map) { #else if (StoredDeclsMap *Map = LookupPtr.getPointer()) { #endif StoredDeclsMap::iterator I = Map->find(Name); if (I != Map->end()) return I->second.getLookupResult(); } ExternalASTSource *Source = getParentASTContext().getExternalSource(); return Source->FindExternalVisibleDeclsByName(this, Name); } #ifndef AXEL_LOOKUP_CHANGES StoredDeclsMap *Map = LookupPtr.getPointer(); if (LookupPtr.getInt()) Map = buildLookup(); #endif if (!Map) return lookup_result(lookup_iterator(0), lookup_iterator(0)); StoredDeclsMap::iterator I = Map->find(Name); if (I == Map->end()) return lookup_result(lookup_iterator(0), lookup_iterator(0)); return I->second.getLookupResult(); } void DeclContext::localUncachedLookup(DeclarationName Name, llvm::SmallVectorImpl<NamedDecl *> &Results) { Results.clear(); // If there's no external storage, just perform a normal lookup and copy // the results. if (!hasExternalVisibleStorage() && !hasExternalLexicalStorage() && Name) { lookup_result LookupResults = lookup(Name); Results.insert(Results.end(), LookupResults.first, LookupResults.second); return; } // If we have a lookup table, check there first. Maybe we'll get lucky. if (Name) { if (StoredDeclsMap *Map = LookupPtr.getPointer()) { StoredDeclsMap::iterator Pos = Map->find(Name); if (Pos != Map->end()) { Results.insert(Results.end(), Pos->second.getLookupResult().first, Pos->second.getLookupResult().second); return; } } } // Slow case: grovel through the declarations in our chain looking for // matches. for (Decl *D = FirstDecl; D; D = D->getNextDeclInContext()) { if (NamedDecl *ND = dyn_cast<NamedDecl>(D)) if (ND->getDeclName() == Name) Results.push_back(ND); } }
void clang::ParseAST(Sema &S, bool PrintStats, bool SkipFunctionBodies) { // Collect global stats on Decls/Stmts (until we have a module streamer). if (PrintStats) { Decl::EnableStatistics(); Stmt::EnableStatistics(); } // Also turn on collection of stats inside of the Sema object. bool OldCollectStats = PrintStats; std::swap(OldCollectStats, S.CollectStats); // Initialize the template instantiation observer chain. // FIXME: See note on "finalize" below. initialize(S.TemplateInstCallbacks, S); ASTConsumer *Consumer = &S.getASTConsumer(); std::unique_ptr<Parser> ParseOP( new Parser(S.getPreprocessor(), S, SkipFunctionBodies)); Parser &P = *ParseOP.get(); llvm::CrashRecoveryContextCleanupRegistrar<const void, ResetStackCleanup> CleanupPrettyStack(llvm::SavePrettyStackState()); PrettyStackTraceParserEntry CrashInfo(P); // Recover resources if we crash before exiting this method. llvm::CrashRecoveryContextCleanupRegistrar<Parser> CleanupParser(ParseOP.get()); S.getPreprocessor().EnterMainSourceFile(); P.Initialize(); Parser::DeclGroupPtrTy ADecl; ExternalASTSource *External = S.getASTContext().getExternalSource(); if (External) External->StartTranslationUnit(Consumer); for (bool AtEOF = P.ParseFirstTopLevelDecl(ADecl); !AtEOF; AtEOF = P.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 && !Consumer->HandleTopLevelDecl(ADecl.get())) return; } // Process any TopLevelDecls generated by #pragma weak. for (Decl *D : S.WeakTopLevelDecls()) Consumer->HandleTopLevelDecl(DeclGroupRef(D)); Consumer->HandleTranslationUnit(S.getASTContext()); // Finalize the template instantiation observer chain. // FIXME: This (and init.) should be done in the Sema class, but because // Sema does not have a reliable "Finalize" function (it has a // destructor, but it is not guaranteed to be called ("-disable-free")). // So, do the initialization above and do the finalization here: finalize(S.TemplateInstCallbacks, S); std::swap(OldCollectStats, S.CollectStats); if (PrintStats) { llvm::errs() << "\nSTATISTICS:\n"; P.getActions().PrintStats(); S.getASTContext().PrintStats(); Decl::PrintStats(); Stmt::PrintStats(); Consumer->PrintStats(); } }
void clang::ParseAST(Sema &S, bool PrintStats, bool SkipFunctionBodies) { // Collect global stats on Decls/Stmts (until we have a module streamer). if (PrintStats) { Decl::EnableStatistics(); Stmt::EnableStatistics(); } // Also turn on collection of stats inside of the Sema object. bool OldCollectStats = PrintStats; std::swap(OldCollectStats, S.CollectStats); ASTConsumer *Consumer = &S.getASTConsumer(); OwningPtr<Parser> ParseOP(new Parser(S.getPreprocessor(), S, SkipFunctionBodies)); Parser &P = *ParseOP.get(); PrettyStackTraceParserEntry CrashInfo(P); // Recover resources if we crash before exiting this method. llvm::CrashRecoveryContextCleanupRegistrar<Parser> CleanupParser(ParseOP.get()); S.getPreprocessor().EnterMainSourceFile(); P.Initialize(); S.Initialize(); // C11 6.9p1 says translation units must have at least one top-level // declaration. C++ doesn't have this restriction. We also don't want to // complain if we have a precompiled header, although technically if the PCH // is empty we should still emit the (pedantic) diagnostic. Parser::DeclGroupPtrTy ADecl; ExternalASTSource *External = S.getASTContext().getExternalSource(); if (External) External->StartTranslationUnit(Consumer); if (P.ParseTopLevelDecl(ADecl)) { if (!External && !S.getLangOpts().CPlusPlus) P.Diag(diag::ext_empty_translation_unit); } else { do { // 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 && !Consumer->HandleTopLevelDecl(ADecl.get())) return; } while (!P.ParseTopLevelDecl(ADecl)); } // Process any TopLevelDecls generated by #pragma weak. for (SmallVector<Decl*,2>::iterator I = S.WeakTopLevelDecls().begin(), E = S.WeakTopLevelDecls().end(); I != E; ++I) Consumer->HandleTopLevelDecl(DeclGroupRef(*I)); Consumer->HandleTranslationUnit(S.getASTContext()); std::swap(OldCollectStats, S.CollectStats); if (PrintStats) { llvm::errs() << "\nSTATISTICS:\n"; P.getActions().PrintStats(); S.getASTContext().PrintStats(); Decl::PrintStats(); Stmt::PrintStats(); Consumer->PrintStats(); } }