aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>2009-07-18 08:50:35 +0000
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>2009-07-18 08:50:35 +0000
commit1e4bc099882626059f14d687ed7a1a5518b7f3c2 (patch)
tree8f7309284f4789d87f4712e354c5aed9cbb8188e
parentf23e839e9ddea324c743d26da43fb767f90ca223 (diff)
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.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@76298 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/AST/Decl.h23
-rw-r--r--include/clang/AST/DeclBase.h56
-rw-r--r--lib/AST/Decl.cpp2
-rw-r--r--tools/index-test/index-test.cpp13
4 files changed, 83 insertions, 11 deletions
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index a6feec9179..55f141c0b6 100644
--- a/include/clang/AST/Decl.h
+++ b/include/clang/AST/Decl.h
@@ -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,
diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h
index 5350706ae0..4c190f134a 100644
--- a/include/clang/AST/DeclBase.h
+++ b/include/clang/AST/DeclBase.h
@@ -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
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index e59d632f90..6b1f830c40 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -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
diff --git a/tools/index-test/index-test.cpp b/tools/index-test/index-test.cpp
index a188cd103e..10449ed0ba 100644
--- a/tools/index-test/index-test.cpp
+++ b/tools/index-test/index-test.cpp
@@ -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;
}