diff options
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/IdentifierResolver.cpp | 33 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 15 |
2 files changed, 47 insertions, 1 deletions
diff --git a/lib/Sema/IdentifierResolver.cpp b/lib/Sema/IdentifierResolver.cpp index 10856225ad..fcfc05380b 100644 --- a/lib/Sema/IdentifierResolver.cpp +++ b/lib/Sema/IdentifierResolver.cpp @@ -168,6 +168,39 @@ void IdentifierResolver::AddDecl(NamedDecl *D) { IDI->AddDecl(D); } +void IdentifierResolver::InsertDecl(iterator Pos, NamedDecl *D) { + if (Pos == iterator()) { + // Simple case: insert at the beginning of the list (which is the + // end of the stored vector). + AddDecl(D); + return; + } + + DeclarationName Name = D->getDeclName(); + void *Ptr = Name.getFETokenInfo<void>(); + + if (isDeclPtr(Ptr)) { + // There's only one element, and we want to insert before it in the list. + // Just create the storage for these identifiers and insert them in the + // opposite order we normally would. + assert(isDeclPtr(Ptr) && "Not a single declaration!"); + Name.setFETokenInfo(NULL); + IdDeclInfo *IDI = &(*IdDeclInfos)[Name]; + NamedDecl *PrevD = static_cast<NamedDecl*>(Ptr); + IDI->AddDecl(D); + IDI->AddDecl(PrevD); + return; + } + + // General case: insert the declaration at the appropriate point in the + // list, which already has at least two elements. + IdDeclInfo *IDI = toIdDeclInfo(Ptr); + if (Pos.isIterator()) + IDI->InsertDecl(Pos.getIterator(), D); + else + IDI->InsertDecl(IDI->decls_begin(), D); +} + /// RemoveDecl - Unlink the decl from its shadowed decl chain. /// The decl must already be part of the decl chain. void IdentifierResolver::RemoveDecl(NamedDecl *D) { diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 7c3f726a99..19d96f2ec0 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -494,7 +494,20 @@ void Sema::PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext) { } S->AddDecl(D); - IdResolver.AddDecl(D); + + if (isa<LabelDecl>(D) && !cast<LabelDecl>(D)->isGnuLocal()) { + // Implicitly-generated labels may end up getting generated in an order that + // isn't strictly lexical, which breaks name lookup. Be careful to insert + // the label at the appropriate place in the identifier chain. + for (I = IdResolver.begin(D->getDeclName()); I != IEnd; ++I) { + if ((*I)->getLexicalDeclContext()->Encloses(CurContext)) + break; + } + + IdResolver.InsertDecl(I, D); + } else { + IdResolver.AddDecl(D); + } } bool Sema::isDeclInScope(NamedDecl *&D, DeclContext *Ctx, Scope *S, |