From: Argyrios Kyrtzidis Date: Sat, 18 Jul 2009 08:50:35 +0000 (+0000) Subject: Introduce a redecl_iterator in Decl class, so that we can do a "iterate over all... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=1e4bc099882626059f14d687ed7a1a5518b7f3c2;p=clang 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 --- 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 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 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(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::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(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(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; }