Introduce a redecl_iterator in Decl class, so that we can do a "iterate over all declarations of the same decl" without knowing the exact type.

llvm-svn: 76298
This commit is contained in:
Argyrios Kyrtzidis 2009-07-18 08:50:35 +00:00
parent fad334ce5b
commit 05898da9cb
4 changed files with 83 additions and 11 deletions

View File

@ -259,7 +259,19 @@ protected:
DeclaredInCondition(false), TypeSpecStartLoc(TSSL) {
SClass = SC;
}
typedef Redeclarable<VarDecl> redeclarable_base;
virtual VarDecl *getNextRedeclaration() { return RedeclLink.getNext(); }
public:
typedef redeclarable_base::redecl_iterator redecl_iterator;
redecl_iterator redecls_begin() const {
return redeclarable_base::redecls_begin();
}
redecl_iterator redecls_end() const {
return redeclarable_base::redecls_end();
}
static VarDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id,
QualType T, StorageClass S,
@ -683,7 +695,18 @@ protected:
virtual ~FunctionDecl() {}
virtual void Destroy(ASTContext& C);
typedef Redeclarable<FunctionDecl> redeclarable_base;
virtual FunctionDecl *getNextRedeclaration() { return RedeclLink.getNext(); }
public:
typedef redeclarable_base::redecl_iterator redecl_iterator;
redecl_iterator redecls_begin() const {
return redeclarable_base::redecls_begin();
}
redecl_iterator redecls_end() const {
return redeclarable_base::redecls_end();
}
static FunctionDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L,
DeclarationName N, QualType T,
StorageClass S = None, bool isInline = false,

View File

@ -320,6 +320,62 @@ public:
/// \brief Whether this particular Decl is a primary one.
bool isCanonicalDecl() const { return getCanonicalDecl() == this; }
protected:
/// \brief Returns the next redeclaration or itself if this is the only decl.
///
/// Decl subclasses that can be redeclared should override this method so that
/// Decl::redecl_iterator can iterate over them.
virtual Decl *getNextRedeclaration() { return this; }
public:
/// \brief Iterates through all the redeclarations of the same decl.
class redecl_iterator {
/// Current - The current declaration.
Decl *Current;
Decl *Starter;
public:
typedef Decl* value_type;
typedef Decl* reference;
typedef Decl* pointer;
typedef std::forward_iterator_tag iterator_category;
typedef std::ptrdiff_t difference_type;
redecl_iterator() : Current(0) { }
explicit redecl_iterator(Decl *C) : Current(C), Starter(C) { }
reference operator*() const { return Current; }
pointer operator->() const { return Current; }
redecl_iterator& operator++() {
assert(Current && "Advancing while iterator has reached end");
// Get either previous decl or latest decl.
Decl *Next = Current->getNextRedeclaration();
Current = (Next != Starter ? Next : 0);
return *this;
}
redecl_iterator operator++(int) {
redecl_iterator tmp(*this);
++(*this);
return tmp;
}
friend bool operator==(redecl_iterator x, redecl_iterator y) {
return x.Current == y.Current;
}
friend bool operator!=(redecl_iterator x, redecl_iterator y) {
return x.Current != y.Current;
}
};
/// \brief Returns iterator for all the redeclarations of the same decl.
/// It will iterate at least once (when this decl is the only one).
redecl_iterator redecls_begin() const {
return redecl_iterator(const_cast<Decl*>(this));
}
redecl_iterator redecls_end() const { return redecl_iterator(); }
/// getBody - If this Decl represents a declaration for a body of code,
/// such as a function or method definition, this method returns the

View File

@ -565,7 +565,7 @@ bool FunctionDecl::isExternGNUInline(ASTContext &Context) const {
void
FunctionDecl::setPreviousDeclaration(FunctionDecl *PrevDecl) {
Redeclarable<FunctionDecl>::setPreviousDeclaration(PrevDecl);
redeclarable_base::setPreviousDeclaration(PrevDecl);
if (FunctionTemplateDecl *FunTmpl = getDescribedFunctionTemplate()) {
FunctionTemplateDecl *PrevFunTmpl

View File

@ -133,16 +133,9 @@ static void ProcessDecl(Decl *D) {
}
case PrintDecls :
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
for (FunctionDecl::redecl_iterator I = FD->redecls_begin(),
E = FD->redecls_end(); I != E; ++I)
ASTLocation(*I).print(OS);
} else if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
for (VarDecl::redecl_iterator I = VD->redecls_begin(),
E = VD->redecls_end(); I != E; ++I)
ASTLocation(*I).print(OS);
} else
ASTLocation(D).print(OS);
for (Decl::redecl_iterator I = D->redecls_begin(),
E = D->redecls_end(); I != E; ++I)
ASTLocation(*I).print(OS);
break;
}