diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2013-02-07 03:37:08 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2013-02-07 03:37:08 +0000 |
commit | bbcd0f3ba215d5a8857b224e32b0330586a00dc6 (patch) | |
tree | 2308609a03b6cb5ad435da2773727698496a0777 /lib | |
parent | 3646c68676c3c46a026b23d52188ef6e0d856178 (diff) |
Fix handling of module imports adding names to a DeclContext after qualified
name lookup has been performed in that context (this probably only happens in
C++).
1) Whenever we add names to a context, set a flag on it, and if we perform
lookup and discover that the context has had a lookup table built but has the
flag set, update all entries in the lookup table with additional names from
the external source.
2) When marking a DeclContext as having external visible decls, mark the
context in which lookup is performed, not the one we are adding. These won't
be the same if we're adding another copy of a pre-existing namespace.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@174577 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AST/DeclBase.cpp | 47 | ||||
-rw-r--r-- | lib/Serialization/ASTReaderDecl.cpp | 15 |
2 files changed, 48 insertions, 14 deletions
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp index 52ecdeb318..3039c95462 100644 --- a/lib/AST/DeclBase.cpp +++ b/lib/AST/DeclBase.cpp @@ -913,6 +913,24 @@ DeclContext::BuildDeclChain(ArrayRef<Decl*> Decls, return std::make_pair(FirstNewDecl, PrevDecl); } +/// \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); + if (!LookupPtr.getPointer()) + return; + + 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); + } +} + /// \brief Load the declarations within this lexical storage from an /// external source. void @@ -963,9 +981,8 @@ ExternalASTSource::SetNoExternalVisibleDeclsForName(const DeclContext *DC, if (!(Map = DC->LookupPtr.getPointer())) Map = DC->CreateStoredDeclsMap(Context); - StoredDeclsList &List = (*Map)[Name]; - assert(List.isNull()); - (void) List; + // Add an entry to the map for this name, if it's not already present. + (*Map)[Name]; return DeclContext::lookup_result(); } @@ -975,7 +992,6 @@ ExternalASTSource::SetExternalVisibleDeclsForName(const DeclContext *DC, DeclarationName Name, ArrayRef<NamedDecl*> Decls) { ASTContext &Context = DC->getParentASTContext(); - StoredDeclsMap *Map; if (!(Map = DC->LookupPtr.getPointer())) Map = DC->CreateStoredDeclsMap(Context); @@ -986,6 +1002,7 @@ ExternalASTSource::SetExternalVisibleDeclsForName(const DeclContext *DC, if (List.isNull()) List.setOnlyValue(*I); else + // FIXME: Need declarationReplaces handling for redeclarations in modules. List.AddSubsequentDecl(*I); } @@ -1145,6 +1162,10 @@ StoredDeclsMap *DeclContext::buildLookup() { /// DeclContext, a DeclContext linked to it, or a transparent context /// nested within it. void DeclContext::buildLookupImpl(DeclContext *DCtx) { + // FIXME: If buildLookup is supposed to return a complete map, we should not + // bail out in buildLookup if hasExternalVisibleStorage. If it is not required + // to include names from PCH and modules, we should use the noload_ iterators + // here. for (decl_iterator I = DCtx->decls_begin(), E = DCtx->decls_end(); I != E; ++I) { Decl *D = *I; @@ -1175,11 +1196,17 @@ DeclContext::lookup(DeclarationName Name) { 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()) { + if (NeedToReconcileExternalVisibleStorage) + reconcileExternalVisibleStorage(); + + StoredDeclsMap *Map = LookupPtr.getPointer(); + if (LookupPtr.getInt()) + Map = buildLookup(); + + // 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. + if (Map) { StoredDeclsMap::iterator I = Map->find(Name); if (I != Map->end()) return I->second.getLookupResult(); @@ -1224,7 +1251,7 @@ void DeclContext::localUncachedLookup(DeclarationName Name, } // If we have a lookup table, check there first. Maybe we'll get lucky. - if (Name) { + if (Name && !LookupPtr.getInt()) { if (StoredDeclsMap *Map = LookupPtr.getPointer()) { StoredDeclsMap::iterator Pos = Map->find(Name); if (Pos != Map->end()) { diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index 469b3938ee..c2ace30782 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -2122,12 +2122,18 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) { // If this declaration is also a declaration context, get the // offsets for its tables of lexical and visible declarations. if (DeclContext *DC = dyn_cast<DeclContext>(D)) { + // FIXME: This should really be + // DeclContext *LookupDC = DC->getPrimaryContext(); + // but that can walk the redeclaration chain, which might not work yet. + DeclContext *LookupDC = DC; + if (isa<NamespaceDecl>(DC)) + LookupDC = DC->getPrimaryContext(); std::pair<uint64_t, uint64_t> Offsets = Reader.VisitDeclContext(DC); if (Offsets.first || Offsets.second) { if (Offsets.first != 0) DC->setHasExternalLexicalStorage(true); if (Offsets.second != 0) - DC->setHasExternalVisibleStorage(true); + LookupDC->setHasExternalVisibleStorage(true); if (ReadDeclContextStorage(*Loc.F, DeclsCursor, Offsets, Loc.F->DeclContextInfos[DC])) return 0; @@ -2139,7 +2145,7 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) { if (I != PendingVisibleUpdates.end()) { // There are updates. This means the context has external visible // storage, even if the original stored version didn't. - DC->setHasExternalVisibleStorage(true); + LookupDC->setHasExternalVisibleStorage(true); DeclContextVisibleUpdates &U = I->second; for (DeclContextVisibleUpdates::iterator UI = U.begin(), UE = U.end(); UI != UE; ++UI) { @@ -2150,8 +2156,9 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) { PendingVisibleUpdates.erase(I); } - if (!DC->hasExternalVisibleStorage() && DC->hasExternalLexicalStorage()) - DC->setMustBuildLookupTable(); + if (!LookupDC->hasExternalVisibleStorage() && + DC->hasExternalLexicalStorage()) + LookupDC->setMustBuildLookupTable(); } assert(Idx == Record.size()); |