// Enter function-declaration scope, limiting any declarators to the
// function prototype scope, including parameter declarators.
- EnterScope(Scope::DeclScope);
+ EnterScope(Scope::FnScope|Scope::DeclScope);
bool IsVariadic = false;
while (1) {
}
}
+
//===----------------------------------------------------------------------===//
#include "IdentifierResolver.h"
-#include "clang/Basic/IdentifierTable.h"
-#include "clang/AST/Decl.h"
-#include "clang/Parse/Scope.h"
#include <list>
#include <vector>
using namespace clang;
-namespace {
-
-class IdDeclInfo;
-
-/// Identifier's FETokenInfo contains a Decl pointer if lower bit == 0.
-static inline bool isDeclPtr(void *Ptr) {
- return (reinterpret_cast<uintptr_t>(Ptr) & 0x1) == 0;
-}
-
-/// Identifier's FETokenInfo contains a IdDeclInfo pointer if lower bit == 1.
-static inline IdDeclInfo *toIdDeclInfo(void *Ptr) {
- return reinterpret_cast<IdDeclInfo*>(
- reinterpret_cast<uintptr_t>(Ptr) & ~0x1
- );
-}
-
-
-/// IdDeclInfo - Keeps track of information about decls associated to a
-/// particular identifier. IdDeclInfos are lazily constructed and assigned
-/// to an identifier the first time a decl with that identifier is shadowed
-/// in some scope.
-class IdDeclInfo {
- typedef llvm::SmallVector<NamedDecl *, 2> ShadowedTy;
- ShadowedTy ShadowedDecls;
-
-public:
- typedef ShadowedTy::iterator ShadowedIter;
-
- inline ShadowedIter shadowed_begin() { return ShadowedDecls.begin(); }
- inline ShadowedIter shadowed_end() { return ShadowedDecls.end(); }
-
- /// Add a decl in the scope chain.
- void PushShadowed(NamedDecl *D) {
- assert(D && "Decl null");
- ShadowedDecls.push_back(D);
- }
-
- /// Add the decl at the top of scope chain.
- void PushGlobalShadowed(NamedDecl *D) {
- assert(D && "Decl null");
- ShadowedDecls.insert(ShadowedDecls.begin(), D);
- }
-
- /// RemoveShadowed - Remove the decl from the scope chain.
- /// The decl must already be part of the decl chain.
- void RemoveShadowed(NamedDecl *D);
-};
-
/// IdDeclInfoMap - Associates IdDeclInfos with Identifiers.
/// Allocates 'pools' (vectors of IdDeclInfos) to avoid allocating each
/// individual IdDeclInfo to heap.
-class IdDeclInfoMap {
+class IdentifierResolver::IdDeclInfoMap {
static const unsigned int VECTOR_SIZE = 512;
// Holds vectors of IdDeclInfos that serve as 'pools'.
// New vectors are added when the current one is full.
IdDeclInfo &operator[](IdentifierInfo *II);
};
-} // end anonymous namespace
-
IdentifierResolver::IdentifierResolver() : IdDeclInfos(new IdDeclInfoMap) {}
IdentifierResolver::~IdentifierResolver() {
- delete static_cast<IdDeclInfoMap*>(IdDeclInfos);
+ delete IdDeclInfos;
}
/// AddDecl - Link the decl to its shadowed decl chain.
-void IdentifierResolver::AddDecl(NamedDecl *D, Scope *S) {
- assert(D && S && "null param passed");
+void IdentifierResolver::AddDecl(NamedDecl *D) {
IdentifierInfo *II = D->getIdentifier();
void *Ptr = II->getFETokenInfo<void>();
if (isDeclPtr(Ptr)) {
II->setFETokenInfo(NULL);
- IdDeclInfoMap &Map = *static_cast<IdDeclInfoMap*>(IdDeclInfos);
- IDI = &Map[II];
- IDI->PushShadowed(static_cast<NamedDecl*>(Ptr));
+ IDI = &(*IdDeclInfos)[II];
+ NamedDecl *PrevD = static_cast<NamedDecl*>(Ptr);
+ IDI->AddDecl(PrevD);
} else
IDI = toIdDeclInfo(Ptr);
- // C++ [basic.scope]p4:
- // -- exactly one declaration shall declare a class name or
- // enumeration name that is not a typedef name and the other
- // declarations shall all refer to the same object or
- // enumerator, or all refer to functions and function templates;
- // in this case the class name or enumeration name is hidden.
- if (isa<TagDecl>(D) && IDI->shadowed_end() != IDI->shadowed_begin()) {
- // We are pushing the name of a tag (enum or class).
- IdDeclInfo::ShadowedIter TopIter = IDI->shadowed_end() - 1;
- if (S->isDeclScope(*TopIter)) {
- // There is already a declaration with the same name in the same
- // scope. It must be found before we find the new declaration,
- // so swap the order on the shadowed declaration stack.
- NamedDecl *Temp = *TopIter;
- *TopIter = D;
- D = Temp;
- }
- }
-
- IDI->PushShadowed(D);
+ IDI->AddDecl(D);
}
-/// AddGlobalDecl - Link the decl at the top of the shadowed decl chain.
-void IdentifierResolver::AddGlobalDecl(NamedDecl *D) {
- assert(D && "null param passed");
+/// AddShadowedDecl - Link the decl to its shadowed decl chain putting it
+/// after the decl that the iterator points to, thus the 'CIT' decl will be
+/// encountered before the 'D' decl.
+void IdentifierResolver::AddShadowedDecl(NamedDecl *D, NamedDecl *Shadow) {
+ assert(D->getIdentifier() == Shadow->getIdentifier() && "Different ids!");
+ assert(LookupContext(D) == LookupContext(Shadow) && "Different context!");
+
IdentifierInfo *II = D->getIdentifier();
void *Ptr = II->getFETokenInfo<void>();
-
- if (!Ptr) {
- II->setFETokenInfo(D);
- return;
- }
+ assert(Ptr && "No decl from Ptr ?");
IdDeclInfo *IDI;
if (isDeclPtr(Ptr)) {
II->setFETokenInfo(NULL);
- IdDeclInfoMap &Map = *static_cast<IdDeclInfoMap*>(IdDeclInfos);
- IDI = &Map[II];
- IDI->PushShadowed(static_cast<NamedDecl*>(Ptr));
- } else
- IDI = toIdDeclInfo(Ptr);
+ IDI = &(*IdDeclInfos)[II];
+ NamedDecl *PrevD = static_cast<NamedDecl*>(Ptr);
+ assert(PrevD == Shadow && "Invalid shadow decl ?");
+ IDI->AddDecl(D);
+ IDI->AddDecl(PrevD);
+ return;
+ }
- IDI->PushGlobalShadowed(D);
+ IDI = toIdDeclInfo(Ptr);
+ IDI->AddShadowed(D, Shadow);
}
/// RemoveDecl - Unlink the decl from its shadowed decl chain.
return;
}
- return toIdDeclInfo(Ptr)->RemoveShadowed(D);
+ return toIdDeclInfo(Ptr)->RemoveDecl(D);
}
-/// Lookup - Find the non-shadowed decl that belongs to a particular
-/// Decl::IdentifierNamespace.
-NamedDecl *IdentifierResolver::Lookup(const IdentifierInfo *II, unsigned NS) {
- assert(II && "null param passed");
+/// begin - Returns an iterator for all decls, starting at the given
+/// declaration context.
+IdentifierResolver::iterator
+IdentifierResolver::begin(const IdentifierInfo *II, DeclContext *Ctx) {
+ assert(Ctx && "null param passed");
+
void *Ptr = II->getFETokenInfo<void>();
+ if (!Ptr) return end(II);
- if (!Ptr) return NULL;
+ LookupContext LC(Ctx);
if (isDeclPtr(Ptr)) {
NamedDecl *D = static_cast<NamedDecl*>(Ptr);
- return (D->getIdentifierNamespace() & NS) ? D : NULL;
- }
- IdDeclInfo *IDI = toIdDeclInfo(Ptr);
+ if (LC.isEqOrContainedBy(LookupContext(D)))
+ return iterator(D);
+ else
+ return end(II);
- // ShadowedDecls are ordered from most shadowed to less shadowed.
- // So we do a reverse iteration from end to begin.
- for (IdDeclInfo::ShadowedIter SI = IDI->shadowed_end();
- SI != IDI->shadowed_begin(); --SI) {
- NamedDecl *D = *(SI-1);
- if (D->getIdentifierNamespace() & NS)
- return D;
}
-
- // we didn't find the decl.
- return NULL;
+
+ IdDeclInfo *IDI = toIdDeclInfo(Ptr);
+ return iterator(IDI->FindContext(LC));
}
-/// RemoveShadowed - Remove the decl from the scope chain.
-/// The decl must already be part of the decl chain.
-void IdDeclInfo::RemoveShadowed(NamedDecl *D) {
- assert(D && "null decl passed");
- assert(!ShadowedDecls.empty() &&
- "Didn't find this decl on its identifier's chain!");
-
- // common case
- if (D == ShadowedDecls.back()) {
- ShadowedDecls.pop_back();
- return;
- }
+/// ctx_begin - Returns an iterator for only decls that belong to the given
+/// declaration context.
+IdentifierResolver::ctx_iterator
+IdentifierResolver::ctx_begin(const IdentifierInfo *II, DeclContext *Ctx) {
+ assert(Ctx && "null param passed");
+
+ void *Ptr = II->getFETokenInfo<void>();
+ if (!Ptr) return ctx_end(II);
+
+ LookupContext LC(Ctx);
+
+ if (isDeclPtr(Ptr)) {
+ NamedDecl *D = static_cast<NamedDecl*>(Ptr);
+
+ if (LC == LookupContext(D))
+ return ctx_iterator(D);
+ else
+ return ctx_end(II);
- for (ShadowedIter SI = ShadowedDecls.end()-1;
- SI != ShadowedDecls.begin(); --SI) {
- if (*(SI-1) == D) {
- ShadowedDecls.erase(SI-1);
- return;
- }
}
+
+ IdDeclInfo *IDI = toIdDeclInfo(Ptr);
+ IdDeclInfo::DeclsTy::iterator I = IDI->FindContext(LookupContext(Ctx));
+ if (I != IDI->decls_begin() && LC != LookupContext(*(I-1)))
+ I = IDI->decls_begin();
- assert(false && "Didn't find this decl on its identifier's chain!");
+ return ctx_iterator(I);
}
+
/// Returns the IdDeclInfo associated to the IdentifierInfo.
/// It creates a new IdDeclInfo if one was not created before for this id.
-IdDeclInfo &IdDeclInfoMap::operator[](IdentifierInfo *II) {
+IdentifierResolver::IdDeclInfo &
+IdentifierResolver::IdDeclInfoMap::operator[](IdentifierInfo *II) {
assert (II && "null IdentifierInfo passed");
void *Ptr = II->getFETokenInfo<void>();
- if (Ptr) {
- assert(!isDeclPtr(Ptr) && "didn't clear decl for FEToken");
- return *toIdDeclInfo(Ptr);
- }
+ if (Ptr) return *toIdDeclInfo(Ptr);
if (CurIndex == VECTOR_SIZE) {
// Add a IdDeclInfo vector 'pool'
#ifndef LLVM_CLANG_AST_SEMA_IDENTIFIERRESOLVER_H
#define LLVM_CLANG_AST_SEMA_IDENTIFIERRESOLVER_H
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Parse/Scope.h"
+#include "clang/AST/Decl.h"
+
namespace clang {
- class IdentifierInfo;
- class NamedDecl;
- class Scope;
/// IdentifierResolver - Keeps track of shadowed decls on enclosing scopes.
/// It manages the shadowing chains of identifiers and implements efficent decl
/// lookup based on an identifier.
class IdentifierResolver {
+
+ /// LookupContext - A wrapper for DeclContext. DeclContext is only part of
+ /// ScopedDecls, LookupContext can be used with all decls (assumes
+ /// translation unit context for non ScopedDecls).
+ class LookupContext {
+ DeclContext *Ctx;
+
+ /// TUCtx - Provides a common value for translation unit context for all
+ /// decls.
+ /// FIXME: When (if ?) all decls can point to their translation unit context
+ /// remove this hack.
+ static inline DeclContext *TUCtx() {
+ return reinterpret_cast<DeclContext*>(-1);
+ }
+
+ /// getContext - Returns translation unit context for non ScopedDecls and
+ /// for EnumConstantDecls returns the parent context of their EnumDecl.
+ static DeclContext *getContext(Decl *D) {
+ DeclContext *Ctx;
+
+ if (EnumConstantDecl *EnumD = dyn_cast<EnumConstantDecl>(D)) {
+ Ctx = EnumD->getDeclContext()->getParent();
+ } else if (ScopedDecl *SD = dyn_cast<ScopedDecl>(D))
+ Ctx = SD->getDeclContext();
+ else
+ return TUCtx();
+
+ if (isa<TranslationUnitDecl>(Ctx))
+ return TUCtx();
+
+ return Ctx;
+ }
+
+ public:
+ LookupContext(Decl *D) {
+ Ctx = getContext(D);
+ }
+ LookupContext(DeclContext *DC) {
+ if (!DC || isa<TranslationUnitDecl>(DC))
+ Ctx = TUCtx();
+ else
+ Ctx = DC;
+ }
+
+ bool isTU() const {
+ return (Ctx == TUCtx());
+ }
+
+ /// getParent - Returns the parent context. This should not be called for
+ /// a translation unit context.
+ LookupContext getParent() const {
+ assert(!isTU() && "TU has no parent!");
+ return LookupContext(Ctx->getParent());
+ }
+
+ /// isEqOrContainedBy - Returns true of the given context is the same or a
+ /// parent of this one.
+ bool isEqOrContainedBy(const LookupContext &PC) const {
+ if (PC.isTU()) return true;
+
+ for (LookupContext Next = *this; !Next.isTU(); Next = Next.getParent())
+ if (Next.Ctx == PC.Ctx) return true;
+
+ return false;
+ }
+
+ bool operator==(const LookupContext &RHS) const {
+ return Ctx == RHS.Ctx;
+ }
+ bool operator!=(const LookupContext &RHS) const {
+ return Ctx != RHS.Ctx;
+ }
+ };
+
+ /// IdDeclInfo - Keeps track of information about decls associated to a
+ /// particular identifier. IdDeclInfos are lazily constructed and assigned
+ /// to an identifier the first time a decl with that identifier is shadowed
+ /// in some scope.
+ class IdDeclInfo {
+ public:
+ typedef llvm::SmallVector<NamedDecl*, 2> DeclsTy;
+
+ inline DeclsTy::iterator decls_begin() { return Decls.begin(); }
+ inline DeclsTy::iterator decls_end() { return Decls.end(); }
+
+ /// FindContext - Returns an iterator pointing just after the decl that is
+ /// in the given context or in a parent of it. The search is in reverse
+ /// order, from end to begin.
+ DeclsTy::iterator FindContext(const LookupContext &Ctx) {
+ return FindContext(Ctx, Decls.end());
+ }
+
+ /// FindContext - Returns an iterator pointing just after the decl that is
+ /// in the given context or in a parent of it. The search is in reverse
+ /// order, from end to begin.
+ DeclsTy::iterator FindContext(const LookupContext &Ctx,
+ const DeclsTy::iterator &Start) {
+ for (DeclsTy::iterator I = Start; I != Decls.begin(); --I) {
+ if (Ctx.isEqOrContainedBy(LookupContext(*(I-1))))
+ return I;
+ }
+
+ return Decls.begin();
+ }
+
+ /// iterator - Iterate over the decls by walking their parent contexts too.
+ class iterator {
+ public:
+ typedef DeclsTy::iterator BaseIter;
+
+ iterator(const BaseIter &DeclIt) : DI(DeclIt) {}
+ const BaseIter &getBase() { return DI; }
+
+ NamedDecl *&operator*() const {
+ return *(DI-1);
+ }
+
+ bool operator==(const iterator &RHS) const {
+ return DI == RHS.DI;
+ }
+ bool operator!=(const iterator &RHS) const {
+ return DI != RHS.DI;
+ }
+
+ // Preincrement.
+ iterator& operator++() {
+ NamedDecl *D = **this;
+ void *Ptr = D->getIdentifier()->getFETokenInfo<void>();
+ assert(!isDeclPtr(Ptr) && "Decl with wrong id ?");
+ DI = toIdDeclInfo(Ptr)->FindContext(LookupContext(D), DI-1);
+ return *this;
+ }
+
+ private:
+ BaseIter DI;
+ };
+
+ /// ctx_iterator - Iterator over the decls of a specific context only.
+ class ctx_iterator {
+ public:
+ typedef DeclsTy::iterator BaseIter;
+
+ ctx_iterator(const BaseIter &DeclIt) : DI(DeclIt) {}
+ const BaseIter &getBase() { return DI; }
+
+ NamedDecl *&operator*() const {
+ return *(DI-1);
+ }
+
+ bool operator==(const ctx_iterator &RHS) const {
+ return DI == RHS.DI;
+ }
+ bool operator!=(const ctx_iterator &RHS) const {
+ return DI != RHS.DI;
+ }
+
+ // Preincrement.
+ ctx_iterator& operator++() {
+ NamedDecl *D = **this;
+ void *Ptr = D->getIdentifier()->getFETokenInfo<void>();
+ assert(!isDeclPtr(Ptr) && "Decl with wrong id ?");
+ IdDeclInfo *Info = toIdDeclInfo(Ptr);
+
+ --DI;
+ if (DI != Info->Decls.begin() &&
+ LookupContext(D) != LookupContext(**this))
+ DI = Info->Decls.begin();
+ return *this;
+ }
+
+ private:
+ BaseIter DI;
+ };
+
+ void AddDecl(NamedDecl *D) {
+ Decls.insert(FindContext(LookupContext(D)), D);
+ }
+
+ /// AddShadowed - Add a decl by putting it directly above the 'Shadow' decl.
+ /// Later lookups will find the 'Shadow' decl first. The 'Shadow' decl must
+ /// be already added to the scope chain and must be in the same context as
+ /// the decl that we want to add.
+ void AddShadowed(NamedDecl *D, NamedDecl *Shadow) {
+ assert(LookupContext(D) == LookupContext(Shadow) &&
+ "Decl and Shadow not in same context!");
+
+ for (DeclsTy::iterator I = Decls.end(); I != Decls.begin(); --I) {
+ if (Shadow == *(I-1)) {
+ Decls.insert(I-1, D);
+ return;
+ }
+ }
+
+ assert(0 && "Shadow wasn't in scope chain!");
+ }
+
+ /// RemoveDecl - Remove the decl from the scope chain.
+ /// The decl must already be part of the decl chain.
+ void RemoveDecl(NamedDecl *D) {
+ for (DeclsTy::iterator I = Decls.end(); I != Decls.begin(); --I) {
+ if (D == *(I-1)) {
+ Decls.erase(I-1);
+ return;
+ }
+ }
+
+ assert(0 && "Didn't find this decl on its identifier's chain!");
+ }
+
+ private:
+ DeclsTy Decls;
+ };
+
+ /// SwizzledIterator - Can be instantiated either with a single NamedDecl*
+ /// (the common case where only one decl is associated with an identifier) or
+ /// with an 'Iter' iterator, when there are more than one decls to lookup.
+ template<typename Iter>
+ class SwizzledIterator {
+ uintptr_t Ptr;
+
+ SwizzledIterator() : Ptr(0) {}
+ SwizzledIterator(NamedDecl *D) {
+ Ptr = reinterpret_cast<uintptr_t>(D);
+ }
+ SwizzledIterator(Iter I) {
+ Ptr = reinterpret_cast<uintptr_t>(I.getBase()) | 0x1;
+ }
+
+ bool isIterator() const { return (Ptr & 0x1); }
+
+ Iter getIterator() const {
+ assert(isIterator() && "Ptr not an iterator.");
+ return reinterpret_cast<typename Iter::BaseIter>(Ptr & ~0x1);
+ }
+
+ friend class IdentifierResolver;
+ public:
+ NamedDecl *operator*() const {
+ if (isIterator())
+ return *getIterator();
+ else
+ return reinterpret_cast<NamedDecl*>(Ptr);
+ }
+
+ bool operator==(const SwizzledIterator &RHS) const {
+ return Ptr == RHS.Ptr;
+ }
+ bool operator!=(const SwizzledIterator &RHS) const {
+ return Ptr != RHS.Ptr;
+ }
+
+ // Preincrement.
+ SwizzledIterator& operator++() {
+ if (isIterator()) {
+ Iter I = getIterator();
+ ++I;
+ Ptr = reinterpret_cast<uintptr_t>(I.getBase()) | 0x1;
+ }
+ else // This is a single NamedDecl*.
+ Ptr = 0;
+
+ return *this;
+ }
+ };
+
public:
- IdentifierResolver();
- ~IdentifierResolver();
+
+ typedef SwizzledIterator<IdDeclInfo::iterator> iterator;
+ typedef SwizzledIterator<IdDeclInfo::ctx_iterator> ctx_iterator;
+
+ /// begin - Returns an iterator for all decls, starting at the given
+ /// declaration context.
+ static iterator begin(const IdentifierInfo *II, DeclContext *Ctx);
+
+ static iterator end(const IdentifierInfo *II) {
+ void *Ptr = II->getFETokenInfo<void>();
+ if (!Ptr || isDeclPtr(Ptr))
+ return iterator();
+
+ IdDeclInfo *IDI = toIdDeclInfo(Ptr);
+ return iterator(IDI->decls_begin());
+ }
+
+ /// ctx_begin - Returns an iterator for only decls that belong to the given
+ /// declaration context.
+ static ctx_iterator ctx_begin(const IdentifierInfo *II, DeclContext *Ctx);
+
+ static ctx_iterator ctx_end(const IdentifierInfo *II) {
+ void *Ptr = II->getFETokenInfo<void>();
+ if (!Ptr || isDeclPtr(Ptr))
+ return ctx_iterator();
+
+ IdDeclInfo *IDI = toIdDeclInfo(Ptr);
+ return ctx_iterator(IDI->decls_begin());
+ }
+
+ /// isDeclInScope - If 'Ctx' is a function/method, isDeclInScope returns true\r
+ /// if 'D' is in Scope 'S', otherwise 'S' is ignored and isDeclInScope returns\r
+ /// true if 'D' belongs to the given declaration context.\r
+ static bool isDeclInScope(Decl *D, DeclContext *Ctx, Scope *S = 0) {
+ if (Ctx->isFunctionOrMethod())\r
+ return S->isDeclScope(D);\r
+\r
+ return LookupContext(D) == LookupContext(Ctx);
+ }
/// AddDecl - Link the decl to its shadowed decl chain.
- void AddDecl(NamedDecl *D, Scope *S);
+ void AddDecl(NamedDecl *D);
- /// AddGlobalDecl - Link the decl at the top of the shadowed decl chain.
- void AddGlobalDecl(NamedDecl *D);
+ /// AddShadowedDecl - Link the decl to its shadowed decl chain putting it
+ /// after the decl that the iterator points to, thus the 'CIT' decl will be
+ /// encountered before the 'D' decl.
+ void AddShadowedDecl(NamedDecl *D, NamedDecl *Shadow);
/// RemoveDecl - Unlink the decl from its shadowed decl chain.
/// The decl must already be part of the decl chain.
void RemoveDecl(NamedDecl *D);
- /// Lookup - Find the non-shadowed decl that belongs to one or more
- /// of the specified Decl::IdentifierNamespaces.
- NamedDecl *Lookup(const IdentifierInfo *II, unsigned NSI);
+ IdentifierResolver();
+ ~IdentifierResolver();
private:
- // An instance of IdDeclInfoMap class, that's hidden away in the
- // implementation file.
- void *IdDeclInfos;
+ class IdDeclInfoMap;
+ IdDeclInfoMap *IdDeclInfos;
+
+ /// Identifier's FETokenInfo contains a Decl pointer if lower bit == 0.
+ static inline bool isDeclPtr(void *Ptr) {
+ return (reinterpret_cast<uintptr_t>(Ptr) & 0x1) == 0;
+ }
+
+ /// Identifier's FETokenInfo contains a IdDeclInfo pointer if lower bit == 1.
+ static inline IdDeclInfo *toIdDeclInfo(void *Ptr) {
+ assert((reinterpret_cast<uintptr_t>(Ptr) & 0x1) == 1
+ && "Ptr not a IdDeclInfo* !");
+ return reinterpret_cast<IdDeclInfo*>(
+ reinterpret_cast<uintptr_t>(Ptr) & ~0x1
+ );
+ }
};
} // end namespace clang
/// Add this decl to the scope shadowed decl chains.
void Sema::PushOnScopeChains(NamedDecl *D, Scope *S) {
- IdResolver.AddDecl(D, S);
S->AddDecl(D);
+
+ // C++ [basic.scope]p4:
+ // -- exactly one declaration shall declare a class name or
+ // enumeration name that is not a typedef name and the other
+ // declarations shall all refer to the same object or
+ // enumerator, or all refer to functions and function templates;
+ // in this case the class name or enumeration name is hidden.
+ if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
+ // We are pushing the name of a tag (enum or class).
+ IdentifierResolver::ctx_iterator
+ CIT = IdResolver.ctx_begin(TD->getIdentifier(), TD->getDeclContext());
+ if (CIT != IdResolver.ctx_end(TD->getIdentifier()) &&
+ IdResolver.isDeclInScope(*CIT, TD->getDeclContext(), S)) {
+ // There is already a declaration with the same name in the same
+ // scope. It must be found before we find the new declaration,
+ // so swap the order on the shadowed declaration chain.
+
+ IdResolver.AddShadowedDecl(TD, *CIT);
+ return;
+ }
+ }
+
+ IdResolver.AddDecl(D);
}
void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) {
if (S->decl_empty()) return;
assert((S->getFlags() & Scope::DeclScope) &&"Scope shouldn't contain decls!");
+
+ // We only want to remove the decls from the identifier decl chains for local
+ // scopes, when inside a function/method.
+ if (S->getFnParent() == 0)
+ return;
for (Scope::decl_iterator I = S->decl_begin(), E = S->decl_end();
I != E; ++I) {
// Scan up the scope chain looking for a decl that matches this identifier
// that is in the appropriate namespace. This search should not take long, as
// shadowing of names is uncommon, and deep shadowing is extremely uncommon.
- NamedDecl *ND = IdResolver.Lookup(II, NS);
- if (ND) return ND;
+ for (IdentifierResolver::iterator
+ I = IdResolver.begin(II, CurContext), E = IdResolver.end(II); I != E; ++I)
+ if ((*I)->getIdentifierNamespace() & NS)
+ return *I;
// If we didn't find a use of this identifier, and if the identifier
// corresponds to a compiler builtin, create the decl object for the builtin
// TUScope is the translation-unit scope to insert this function into.
- TUScope->AddDecl(New);
-
- // Add this decl to the end of the identifier info.
- IdResolver.AddGlobalDecl(New);
-
+ PushOnScopeChains(New, TUScope);
return New;
}
D.getAttributes());
// Merge the decl with the existing one if appropriate. If the decl is
// in an outer scope, it isn't the same thing.
- if (PrevDecl && S->isDeclScope(PrevDecl)) {
+ if (PrevDecl && IdResolver.isDeclInScope(PrevDecl, CurContext, S)) {
NewTD = MergeTypeDefDecl(NewTD, PrevDecl);
if (NewTD == 0) return 0;
}
New = NewTD;
- if (S->getParent() == 0) {
+ if (S->getFnParent() == 0) {
// C99 6.7.7p2: If a typedef name specifies a variably modified type
// then it shall have block scope.
if (NewTD->getUnderlyingType()->isVariablyModifiedType()) {
// Merge the decl with the existing one if appropriate. Since C functions
// are in a flat namespace, make sure we consider decls in outer scopes.
- if (PrevDecl) {
+ if (PrevDecl &&
+ (!getLangOptions().CPlusPlus ||
+ IdResolver.isDeclInScope(PrevDecl, CurContext, S)) ) {
bool Redeclaration = false;
NewFD = MergeFunctionDecl(NewFD, PrevDecl, Redeclaration);
if (NewFD == 0) return 0;
case DeclSpec::SCS_register: SC = VarDecl::Register; break;
case DeclSpec::SCS_private_extern: SC = VarDecl::PrivateExtern; break;
}
- if (S->getParent() == 0) {
+ if (S->getFnParent() == 0) {
// C99 6.9p2: The storage-class specifiers auto and register shall not
// appear in the declaration specifiers in an external declaration.
if (SC == VarDecl::Auto || SC == VarDecl::Register) {
}
// Merge the decl with the existing one if appropriate. If the decl is
// in an outer scope, it isn't the same thing.
- if (PrevDecl && S->isDeclScope(PrevDecl)) {
+ if (PrevDecl && IdResolver.isDeclInScope(PrevDecl, CurContext, S)) {
NewVD = MergeVarDecl(NewVD, PrevDecl);
if (NewVD == 0) return 0;
}
// See if this is a redefinition.
Decl *PrevDcl = LookupDecl(D.getIdentifier(), Decl::IDNS_Ordinary,
GlobalScope);
- if (FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(PrevDcl)) {
- const FunctionDecl *Definition;
- if (FD->getBody(Definition)) {
- Diag(D.getIdentifierLoc(), diag::err_redefinition,
- D.getIdentifier()->getName());
- Diag(Definition->getLocation(), diag::err_previous_definition);
+ if (PrevDcl && IdResolver.isDeclInScope(PrevDcl, CurContext)) {
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(PrevDcl)) {
+ const FunctionDecl *Definition;
+ if (FD->getBody(Definition)) {
+ Diag(D.getIdentifierLoc(), diag::err_redefinition,
+ D.getIdentifier()->getName());
+ Diag(Definition->getLocation(), diag::err_previous_definition);
+ }
}
}
Decl *decl = static_cast<Decl*>(ActOnDeclarator(GlobalScope, D, 0));
// If this is a use of a previous tag, or if the tag is already declared in
// the same scope (so that the definition/declaration completes or
// rementions the tag), reuse the decl.
- if (TK == TK_Reference || S->isDeclScope(PrevDecl)) {
+ if (TK == TK_Reference ||
+ IdResolver.isDeclInScope(PrevDecl, CurContext, S)) {
// Make sure that this wasn't declared as an enum and now used as a struct
// or something similar.
if (PrevDecl->getKind() != Kind) {
// Verify that there isn't already something declared with this name in this
// scope.
if (Decl *PrevDecl = LookupDecl(Id, Decl::IDNS_Ordinary, S)) {
- if (S->isDeclScope(PrevDecl)) {
+ if (IdResolver.isDeclInScope(PrevDecl, CurContext, S)) {
if (isa<EnumConstantDecl>(PrevDecl))
Diag(IdLoc, diag::err_redefinition_of_enumerator, Id->getName());
else
LookupDecl(II, Decl::IDNS_Tag | Decl::IDNS_Ordinary, DeclRegionScope,
/*enableLazyBuiltinCreation=*/false);
- if (PrevDecl && DeclRegionScope->isDeclScope(PrevDecl)) {
+ if (PrevDecl &&
+ IdResolver.isDeclInScope(PrevDecl, CurContext, DeclRegionScope)) {
if (NamespaceDecl *OrigNS = dyn_cast<NamespaceDecl>(PrevDecl)) {
// This is an extended namespace definition.
// Attach this namespace decl to the chain of extended namespace
int A; // expected-error {{error: redefinition of 'A' as different kind of symbol}}
class A; // expected-error {{error: redefinition of 'A' as different kind of symbol}}
-class B; // expected-error {{error: previous definition is here}}
+class B {}; // expected-error {{error: previous definition is here}}
namespace B {} // expected-error {{error: redefinition of 'B' as different kind of symbol}}
void C(); // expected-error {{error: previous definition is here}}
namespace C {} // expected-error {{error: redefinition of 'C' as different kind of symbol}}
+
+namespace S1 {
+ int x;
+
+ namespace S2 {
+
+ namespace S3 {
+ B x;
+ }
+ }
+}
+
+namespace S1 {
+ void f() {
+ x = 0;
+ }
+
+ namespace S2 {
+
+ namespace S3 {
+ void f() {
+ x = 0; // expected-error {{error: incompatible type assigning 'int', expected 'class B'}}
+ }
+ }
+
+ int y;
+ }
+}
+
+namespace S1 {
+ namespace S2 {
+ namespace S3 {
+ void f3() {
+ y = 0;
+ }
+ }
+ }
+}