-Implement proper name lookup for namespaces.

-identifierResolver exposes an iterator interface to get all decls through the scope chain.
-The semantic staff (checking IdentifierNamespace and Doug's checking for shadowed tags were moved out of IdentifierResolver and back into Sema. IdentifierResolver just gives an iterator for all reachable decls of an identifier.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@50923 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Argyrios Kyrtzidis 2008-05-09 23:39:43 +00:00
Родитель 0951052064
Коммит 00bc645d15
6 изменённых файлов: 495 добавлений и 177 удалений

Просмотреть файл

@ -1251,7 +1251,7 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D) {
// 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) {
@ -1526,3 +1526,4 @@ void Parser::ParseTypeofSpecifier(DeclSpec &DS) {
}
}

Просмотреть файл

@ -13,67 +13,16 @@
//===----------------------------------------------------------------------===//
#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.
@ -88,17 +37,14 @@ public:
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>();
@ -111,56 +57,40 @@ void IdentifierResolver::AddDecl(NamedDecl *D, Scope *S) {
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.
@ -178,71 +108,72 @@ void IdentifierResolver::RemoveDecl(NamedDecl *D) {
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");
void *Ptr = II->getFETokenInfo<void>();
/// 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");
if (!Ptr) return NULL;
void *Ptr = II->getFETokenInfo<void>();
if (!Ptr) return end(II);
LookupContext LC(Ctx);
if (isDeclPtr(Ptr)) {
NamedDecl *D = static_cast<NamedDecl*>(Ptr);
return (D->getIdentifierNamespace() & NS) ? D : NULL;
}
if (LC.isEqOrContainedBy(LookupContext(D)))
return iterator(D);
else
return end(II);
}
IdDeclInfo *IDI = toIdDeclInfo(Ptr);
// 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;
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!");
/// 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);
// common case
if (D == ShadowedDecls.back()) {
ShadowedDecls.pop_back();
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();
for (ShadowedIter SI = ShadowedDecls.end()-1;
SI != ShadowedDecls.begin(); --SI) {
if (*(SI-1) == D) {
ShadowedDecls.erase(SI-1);
return;
}
}
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'

Просмотреть файл

@ -15,37 +15,354 @@
#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
/// if 'D' is in Scope 'S', otherwise 'S' is ignored and isDeclInScope returns
/// true if 'D' belongs to the given declaration context.
static bool isDeclInScope(Decl *D, DeclContext *Ctx, Scope *S = 0) {
if (Ctx->isFunctionOrMethod())
return S->isDeclScope(D);
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

Просмотреть файл

@ -59,13 +59,40 @@ void Sema::PopDeclContext() {
/// 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) {
@ -115,8 +142,10 @@ Decl *Sema::LookupDecl(const IdentifierInfo *II, unsigned NSI,
// 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
@ -184,11 +213,7 @@ ScopedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid,
// 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;
}
@ -797,12 +822,12 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) {
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()) {
@ -873,7 +898,9 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) {
// 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;
@ -914,7 +941,7 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) {
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) {
@ -942,7 +969,7 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) {
}
// 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;
}
@ -1221,12 +1248,14 @@ Sema::DeclTy *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Declarator &D) {
// 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));
@ -1375,7 +1404,8 @@ Sema::DeclTy *Sema::ActOnTag(Scope *S, unsigned TagType, TagKind TK,
// 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) {
@ -1733,7 +1763,7 @@ Sema::DeclTy *Sema::ActOnEnumConstant(Scope *S, DeclTy *theEnumDecl,
// 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

Просмотреть файл

@ -335,7 +335,8 @@ Sema::DeclTy *Sema::ActOnStartNamespaceDef(Scope *NamespcScope,
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

Просмотреть файл

@ -8,8 +8,46 @@ void f() { A = 0; } // expected-error {{error: unexpected namespace name 'A': ex
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;
}
}
}
}