[cfe-commits] r75604 - in /cfe/trunk: include/clang/AST/Decl.h lib/AST/Decl.cpp

Douglas Gregor dgregor at apple.com
Tue Jul 14 00:11:12 PDT 2009


On Jul 14, 2009, at 5:20 AM, Argiris Kirtzidis wrote:

> Author: akirtzidis
> Date: Mon Jul 13 22:20:21 2009
> New Revision: 75604
>
> URL: http://llvm.org/viewvc/llvm-project?rev=75604&view=rev
> Log:
> Introduce redecl_iterator, used for iterating over the  
> redeclarations of a FunctionDecl or VarDecl.
>
> It iterates over all the redeclarations, regardless of the starting  
> point. For example:
>
> 1) int f();
> 2) int f();
> 3) int f();
>
> if you have the (2) FunctionDecl and call redecls_begin/redecls_end  
> to iterate, you'll get this sequence:
> (2)
> (1)
> (3)
>
> The motivation to introduce this was that, previously, if (3) was a  
> function definition,
> and you called getBody() at (2), it would not return it, since  
> getBody() iterated over the previous declarations only,
> so it would only check (2) and (1).

Excellent! Solving this problem has been on my TODO list for several  
months :)

(Some comments below)

> Modified:
>    cfe/trunk/include/clang/AST/Decl.h
>    cfe/trunk/lib/AST/Decl.cpp
>
> Modified: cfe/trunk/include/clang/AST/Decl.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=75604&r1=75603&r2=75604&view=diff
>
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- cfe/trunk/include/clang/AST/Decl.h (original)
> +++ cfe/trunk/include/clang/AST/Decl.h Mon Jul 13 22:20:21 2009
> @@ -439,6 +439,54 @@
>
>   virtual Decl *getPrimaryDecl() const;
>
> +  /// \brief Iterates through all the redeclarations of the same  
> var decl.
> +  class redecl_iterator {
> +    /// Current - The current declaration.
> +    VarDecl *Current;
> +    VarDecl *Starter;
> +
> +  public:
> +    typedef VarDecl*             value_type;
> +    typedef VarDecl*             reference;
> +    typedef VarDecl*             pointer;
> +    typedef std::forward_iterator_tag iterator_category;
> +    typedef std::ptrdiff_t            difference_type;
> +
> +    redecl_iterator() : Current(0) { }
> +    explicit redecl_iterator(VarDecl *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.
> +      VarDecl *Next = Current->PreviousDeclaration.getPointer();
> +      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 variable.
> +  /// It will iterate at least once (when this decl is the only one).
> +  redecl_iterator redecls_begin() const {
> +    return redecl_iterator(const_cast<VarDecl*>(this));
> +  }
> +  redecl_iterator redecls_end() const { return redecl_iterator(); }
> +
>   /// hasLocalStorage - Returns true if a variable with function scope
>   ///  is a non-static local variable.
>   bool hasLocalStorage() const {
> @@ -862,6 +910,54 @@
>
>   virtual Decl *getPrimaryDecl() const;
>
> +  /// \brief Iterates through all the redeclarations of the same  
> function decl.
> +  class redecl_iterator {
> +    /// Current - The current declaration.
> +    FunctionDecl *Current;
> +    FunctionDecl *Starter;
> +
> +  public:
> +    typedef FunctionDecl*             value_type;
> +    typedef FunctionDecl*             reference;
> +    typedef FunctionDecl*             pointer;
> +    typedef std::forward_iterator_tag iterator_category;
> +    typedef std::ptrdiff_t            difference_type;
> +
> +    redecl_iterator() : Current(0) { }
> +    explicit redecl_iterator(FunctionDecl *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.
> +      FunctionDecl *Next = Current->PreviousDeclaration.getPointer();
> +      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;
> +    }
> +  };

This is mostly copy-paste-and-modify from VarDecl's redecl_iterator.  
Can we extract the common functionality into a template? We'll also  
need the same behavior for other kinds of entities that can be  
redeclared---tag types and templates, for example.

	- Doug



More information about the cfe-commits mailing list