Unify ctx_iterator/ctx_begin()/ctx_end() and iterator/begin()/end() so that a single iterator type is used for both traversing decls of the same declaration context *and* of the parent declaration contexts, depending on the value of the bool parameter 'LookInParentCtx' that is passed to IdentifierResolver::begin().

llvm-svn: 53724
This commit is contained in:
Argyrios Kyrtzidis 2008-07-17 17:49:50 +00:00
parent 7e5edf1a1f
commit ef34aed1f9
3 changed files with 103 additions and 160 deletions

View File

@ -111,58 +111,70 @@ void IdentifierResolver::RemoveDecl(NamedDecl *D) {
return toIdDeclInfo(Ptr)->RemoveDecl(D);
}
/// begin - Returns an iterator for all decls, starting at the given
/// declaration context.
/// begin - Returns an iterator for decls of identifier 'II', starting at
/// declaration context 'Ctx'. If 'LookInParentCtx' is true, it will walk the
/// decls of parent declaration contexts too.
IdentifierResolver::iterator
IdentifierResolver::begin(const IdentifierInfo *II, DeclContext *Ctx) {
IdentifierResolver::begin(const IdentifierInfo *II, DeclContext *Ctx,
bool LookInParentCtx) {
assert(Ctx && "null param passed");
void *Ptr = II->getFETokenInfo<void>();
if (!Ptr) return end(II);
if (!Ptr) return end();
LookupContext LC(Ctx);
if (isDeclPtr(Ptr)) {
NamedDecl *D = static_cast<NamedDecl*>(Ptr);
LookupContext DC(D);
if (LC.isEqOrContainedBy(LookupContext(D)))
if (( LookInParentCtx && LC.isEqOrContainedBy(DC)) ||
(!LookInParentCtx && LC == DC))
return iterator(D);
else
return end(II);
return end();
}
IdDeclInfo *IDI = toIdDeclInfo(Ptr);
return iterator(IDI->FindContext(LC));
IdDeclInfo::DeclsTy::iterator I;
if (LookInParentCtx)
I = IDI->FindContext(LC);
else {
for (I = IDI->decls_end(); I != IDI->decls_begin(); --I)
if (LookupContext(*(I-1)) == LC)
break;
}
if (I != IDI->decls_begin())
return iterator(I-1, LookInParentCtx);
else // No decls found.
return end();
}
/// 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);
/// PreIncIter - Do a preincrement when 'Ptr' is a BaseIter.
void IdentifierResolver::iterator::PreIncIter() {
NamedDecl *D = **this;
LookupContext Ctx(D);
void *InfoPtr = D->getIdentifier()->getFETokenInfo<void>();
assert(!isDeclPtr(InfoPtr) && "Decl with wrong id ?");
IdDeclInfo *Info = toIdDeclInfo(InfoPtr);
BaseIter I = getIterator();
if (LookInParentCtx())
I = Info->FindContext(Ctx, I);
else {
if (I != Info->decls_begin() && LookupContext(*(I-1)) != Ctx) {
// The next decl is in different declaration context.
// Skip remaining decls and set the iterator to the end.
I = Info->decls_begin();
}
}
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();
return ctx_iterator(I);
if (I != Info->decls_begin())
*this = iterator(I-1, LookInParentCtx());
else // No more decls.
*this = end();
}

View File

@ -134,75 +134,6 @@ class IdentifierResolver {
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);
}
@ -242,28 +173,47 @@ class IdentifierResolver {
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;
public:
SwizzledIterator() : Ptr(0) {}
SwizzledIterator(NamedDecl *D) {
/// iterator - Iterate over the decls of a specified identifier.
/// It will walk or not the parent declaration contexts depending on how
/// it was instantiated.
class iterator {
/// Ptr - There are 3 forms that 'Ptr' represents:
/// 1) A single NamedDecl. (Ptr & 0x1 == 0)
/// 2) A IdDeclInfo::DeclsTy::iterator that traverses only the decls of the
/// same declaration context. (Ptr & 0x3 == 0x1)
/// 3) A IdDeclInfo::DeclsTy::iterator that traverses the decls of parent
/// declaration contexts too. (Ptr & 0x3 == 0x3)
uintptr_t Ptr;
typedef IdDeclInfo::DeclsTy::iterator BaseIter;
iterator() : Ptr(0) {}
/// A single NamedDecl. (Ptr & 0x1 == 0)
iterator(NamedDecl *D) {
Ptr = reinterpret_cast<uintptr_t>(D);
assert((Ptr & 0x1) == 0 && "Invalid Ptr!");
}
SwizzledIterator(Iter I) {
Ptr = reinterpret_cast<uintptr_t>(I.getBase()) | 0x1;
/// A IdDeclInfo::DeclsTy::iterator that walks or not the parent declaration
/// contexts depending on 'LookInParentCtx'.
iterator(BaseIter I, bool LookInParentCtx) {
Ptr = reinterpret_cast<uintptr_t>(I) | 0x1;
assert((Ptr & 0x2) == 0 && "Invalid Ptr!");
if (LookInParentCtx) Ptr |= 0x2;
}
bool isIterator() const { return (Ptr & 0x1); }
Iter getIterator() const {
assert(isIterator() && "Ptr not an iterator.");
return reinterpret_cast<typename Iter::BaseIter>(Ptr & ~0x1);
bool LookInParentCtx() const {
assert(isIterator() && "Ptr not an iterator!");
return (Ptr & 0x2) != 0;
}
BaseIter getIterator() const {
assert(isIterator() && "Ptr not an iterator!");
return reinterpret_cast<BaseIter>(Ptr & ~0x3);
}
friend class IdentifierResolver;
public:
NamedDecl *operator*() const {
@ -273,56 +223,36 @@ class IdentifierResolver {
return reinterpret_cast<NamedDecl*>(Ptr);
}
bool operator==(const SwizzledIterator &RHS) const {
bool operator==(const iterator &RHS) const {
return Ptr == RHS.Ptr;
}
bool operator!=(const SwizzledIterator &RHS) const {
bool operator!=(const iterator &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*.
iterator& operator++() {
if (!isIterator()) // common case.
Ptr = 0;
else
PreIncIter();
return *this;
}
private:
void PreIncIter();
};
public:
/// begin - Returns an iterator for decls of identifier 'II', starting at
/// declaration context 'Ctx'. If 'LookInParentCtx' is true, it will walk the
/// decls of parent declaration contexts too.
/// Default for 'LookInParentCtx is true.
static iterator begin(const IdentifierInfo *II, DeclContext *Ctx,
bool LookInParentCtx = true);
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());
/// end - Returns an iterator that has 'finished'.
static iterator end() {
return iterator();
}
/// isDeclInScope - If 'Ctx' is a function/method, isDeclInScope returns true

View File

@ -91,15 +91,16 @@ void Sema::PushOnScopeChains(NamedDecl *D, Scope *S) {
// 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)) {
IdentifierResolver::iterator
I = IdResolver.begin(TD->getIdentifier(),
TD->getDeclContext(), false/*LookInParentCtx*/);
if (I != IdResolver.end() &&
IdResolver.isDeclInScope(*I, 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);
IdResolver.AddShadowedDecl(TD, *I);
return;
}
}
@ -158,7 +159,7 @@ Decl *Sema::LookupDecl(const IdentifierInfo *II, unsigned NSI,
// that is in the appropriate namespace. This search should not take long, as
// shadowing of names is uncommon, and deep shadowing is extremely uncommon.
for (IdentifierResolver::iterator
I = IdResolver.begin(II, CurContext), E = IdResolver.end(II); I != E; ++I)
I = IdResolver.begin(II, CurContext), E = IdResolver.end(); I != E; ++I)
if ((*I)->getIdentifierNamespace() & NS)
return *I;