diff options
| author | Richard Smith <richard-llvm@metafoo.co.uk> | 2013-07-13 02:00:19 +0000 | 
|---|---|---|
| committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2013-07-13 02:00:19 +0000 | 
| commit | 95d99308c448cd50596e75ca51286ff1e1f750e2 (patch) | |
| tree | ef7f595ff9b7715326bf529e7b0a3c90135d89fc /clang/lib | |
| parent | 7459be6dc7ee344d5fa9859c50cb892bc4443d16 (diff) | |
| download | bcm5719-llvm-95d99308c448cd50596e75ca51286ff1e1f750e2.tar.gz bcm5719-llvm-95d99308c448cd50596e75ca51286ff1e1f750e2.zip  | |
C++ modules: Don't call DeclContext::lookup when half-way through deserializing
decls. That can reenter deserialization and explode horribly by trying to merge
a declaration that we've not got very far through deserializing yet.
llvm-svn: 186236
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/AST/DeclBase.cpp | 48 | ||||
| -rw-r--r-- | clang/lib/Serialization/ASTReaderDecl.cpp | 28 | 
2 files changed, 58 insertions, 18 deletions
diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp index 7caf698c98d..13bde4ca860 100644 --- a/clang/lib/AST/DeclBase.cpp +++ b/clang/lib/AST/DeclBase.cpp @@ -1170,7 +1170,8 @@ StoredDeclsMap *DeclContext::buildLookup() {    SmallVector<DeclContext *, 2> Contexts;    collectAllContexts(Contexts);    for (unsigned I = 0, N = Contexts.size(); I != N; ++I) -    buildLookupImpl(Contexts[I]); +    buildLookupImpl<&DeclContext::decls_begin, +                    &DeclContext::decls_end>(Contexts[I]);    // We no longer have any lazy decls.    LookupPtr.setInt(false); @@ -1182,8 +1183,10 @@ StoredDeclsMap *DeclContext::buildLookup() {  /// declarations contained within DCtx, which will either be this  /// DeclContext, a DeclContext linked to it, or a transparent context  /// nested within it. +template<DeclContext::decl_iterator (DeclContext::*Begin)() const, +         DeclContext::decl_iterator (DeclContext::*End)() const>  void DeclContext::buildLookupImpl(DeclContext *DCtx) { -  for (decl_iterator I = DCtx->decls_begin(), E = DCtx->decls_end(); +  for (decl_iterator I = (DCtx->*Begin)(), E = (DCtx->*End)();         I != E; ++I) {      Decl *D = *I; @@ -1207,7 +1210,7 @@ void DeclContext::buildLookupImpl(DeclContext *DCtx) {      // context (recursively).      if (DeclContext *InnerCtx = dyn_cast<DeclContext>(D))        if (InnerCtx->isTransparentContext() || InnerCtx->isInlineNamespace()) -        buildLookupImpl(InnerCtx); +        buildLookupImpl<Begin, End>(InnerCtx);    }  } @@ -1264,6 +1267,45 @@ DeclContext::lookup(DeclarationName Name) {    return I->second.getLookupResult();  } +DeclContext::lookup_result +DeclContext::noload_lookup(DeclarationName Name) { +  assert(DeclKind != Decl::LinkageSpec && +         "Should not perform lookups into linkage specs!"); +  if (!hasExternalVisibleStorage()) +    return lookup(Name); + +  DeclContext *PrimaryContext = getPrimaryContext(); +  if (PrimaryContext != this) +    return PrimaryContext->noload_lookup(Name); + +  StoredDeclsMap *Map = LookupPtr.getPointer(); +  if (LookupPtr.getInt()) { +    // Carefully build the lookup map, without deserializing anything. +    SmallVector<DeclContext *, 2> Contexts; +    collectAllContexts(Contexts); +    for (unsigned I = 0, N = Contexts.size(); I != N; ++I) +      buildLookupImpl<&DeclContext::noload_decls_begin, +                      &DeclContext::noload_decls_end>(Contexts[I]); + +    // We no longer have any lazy decls. +    LookupPtr.setInt(false); + +    // There may now be names for which we have local decls but are +    // missing the external decls. +    NeedToReconcileExternalVisibleStorage = true; + +    Map = LookupPtr.getPointer(); +  } + +  if (!Map) +    return lookup_result(lookup_iterator(0), lookup_iterator(0)); + +  StoredDeclsMap::iterator I = Map->find(Name); +  return I != Map->end() +             ? I->second.getLookupResult() +             : lookup_result(lookup_iterator(0), lookup_iterator(0)); +} +  void DeclContext::localUncachedLookup(DeclarationName Name,                                        SmallVectorImpl<NamedDecl *> &Results) {    Results.clear(); diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 84a8b09e4e5..e713b0e382f 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -1914,14 +1914,15 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) {  ASTDeclReader::FindExistingResult::~FindExistingResult() {    if (!AddResult || Existing)      return; -   -  if (New->getDeclContext()->getRedeclContext()->isTranslationUnit() -      && Reader.SemaObj) { + +  DeclContext *DC = New->getDeclContext()->getRedeclContext(); +  if (DC->isTranslationUnit() && Reader.SemaObj) {      Reader.SemaObj->IdResolver.tryAddTopLevelDecl(New, New->getDeclName()); -  } else { -    DeclContext *DC = New->getLexicalDeclContext(); -    if (DC->isNamespace()) -      DC->addDecl(New); +  } else if (NamespaceDecl *NS = dyn_cast<NamespaceDecl>(DC)) { +    // Add the declaration to its redeclaration context so later merging +    // lookups will find it. +    NS->getFirstDeclaration()->makeDeclVisibleInContextImpl(New, +                                                            /*Internal*/true);    }  } @@ -1933,11 +1934,11 @@ ASTDeclReader::FindExistingResult ASTDeclReader::findExisting(NamedDecl *D) {      Result.suppress();      return Result;    } -   +    DeclContext *DC = D->getDeclContext()->getRedeclContext();    if (!DC->isFileContext())      return FindExistingResult(Reader); -   +    if (DC->isTranslationUnit() && Reader.SemaObj) {      IdentifierResolver &IdResolver = Reader.SemaObj->IdResolver; @@ -1970,12 +1971,9 @@ ASTDeclReader::FindExistingResult ASTDeclReader::findExisting(NamedDecl *D) {        if (isSameEntity(*I, D))          return FindExistingResult(Reader, D, *I);      } -  } - -  if (DC->isNamespace()) { -    DeclContext::lookup_result R = DC->lookup(Name); -    for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E;  -         ++I) { +  } else if (NamespaceDecl *NS = dyn_cast<NamespaceDecl>(DC)) { +    DeclContext::lookup_result R = NS->getFirstDeclaration()->noload_lookup(Name); +    for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E; ++I) {        if (isSameEntity(*I, D))          return FindExistingResult(Reader, D, *I);      }  | 

