diff --git a/clang/include/clang/Sema/IdentifierResolver.h b/clang/include/clang/Sema/IdentifierResolver.h index 770f146e6a14..33486c2ffeb7 100644 --- a/clang/include/clang/Sema/IdentifierResolver.h +++ b/clang/include/clang/Sema/IdentifierResolver.h @@ -53,6 +53,11 @@ class IdentifierResolver { /// declaration was not found, returns false. bool ReplaceDecl(NamedDecl *Old, NamedDecl *New); + /// \brief Insert the given declaration at the given position in the list. + void InsertDecl(DeclsTy::iterator Pos, NamedDecl *D) { + Decls.insert(Pos, D); + } + private: DeclsTy Decls; }; @@ -166,6 +171,10 @@ public: /// (and, therefore, replaced). bool ReplaceDecl(NamedDecl *Old, NamedDecl *New); + /// \brief Insert the given declaration prior to the given iterator + /// position + void InsertDecl(iterator Pos, NamedDecl *D); + /// \brief Link the declaration into the chain of declarations for /// the given identifier. /// diff --git a/clang/lib/Sema/IdentifierResolver.cpp b/clang/lib/Sema/IdentifierResolver.cpp index 10856225ad0f..fcfc05380b4e 100644 --- a/clang/lib/Sema/IdentifierResolver.cpp +++ b/clang/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(); + + 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(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/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 7c3f726a99b5..19d96f2ec061 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/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(D) && !cast(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, diff --git a/clang/test/SemaCXX/goto.cpp b/clang/test/SemaCXX/goto.cpp new file mode 100644 index 000000000000..2db9d97fd8b0 --- /dev/null +++ b/clang/test/SemaCXX/goto.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// PR9463 +double *end; +void f() { + { + int end = 0; + goto end; + end = 1; + } + + end: + return; +} + +void g() { + end = 1; // expected-error{{assigning to 'double *' from incompatible type 'int'}} +}