summaryrefslogtreecommitdiffstats
path: root/clang/lib/AST
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2013-02-07 03:37:08 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2013-02-07 03:37:08 +0000
commit645d755d3e40bfb57f19ab7c474b832b71f3b095 (patch)
tree31de144326a7759ce327c929fc73bc40c836bf80 /clang/lib/AST
parent9ce12e36abf44b6373b88610f3c73fbbbdee9b36 (diff)
downloadbcm5719-llvm-645d755d3e40bfb57f19ab7c474b832b71f3b095.tar.gz
bcm5719-llvm-645d755d3e40bfb57f19ab7c474b832b71f3b095.zip
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. llvm-svn: 174577
Diffstat (limited to 'clang/lib/AST')
-rw-r--r--clang/lib/AST/DeclBase.cpp47
1 files changed, 37 insertions, 10 deletions
diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp
index 52ecdeb3183..3039c954626 100644
--- a/clang/lib/AST/DeclBase.cpp
+++ b/clang/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()) {
OpenPOWER on IntegriCloud