]> granicus.if.org Git - clang/commitdiff
Introduce a redecl_iterator in Decl class, so that we can do a "iterate over all...
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>
Sat, 18 Jul 2009 08:50:35 +0000 (08:50 +0000)
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>
Sat, 18 Jul 2009 08:50:35 +0000 (08:50 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@76298 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/Decl.h
include/clang/AST/DeclBase.h
lib/AST/Decl.cpp
tools/index-test/index-test.cpp

index a6feec917965097d19a9fc918f9023f43cb2fc73..55f141c0b645b8f895be7c35c8909e7cfc519f0b 100644 (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,
index 5350706ae0c44fcd89ee93d7301d36254e3721b7..4c190f134aeb0731bcbb24572644cc2e4244a5c5 100644 (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
index e59d632f90e94e0ee13f05367727fac037ac263a..6b1f830c404469dd44390dbc6315913f117639f7 100644 (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 
index a188cd103ed8bc951dffcdde07cef8493531af1d..10449ed0baa0e28c067624b5becfd27330d5a0c2 100644 (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;
     
   }