Redeclarable.h revision f23e839e9ddea324c743d26da43fb767f90ca223
1//===-- Redeclarable.h - Base for Decls that can be redeclared -*- C++ -*-====//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10//  This file defines the Redeclarable interface.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_CLANG_AST_REDECLARABLE_H
15#define LLVM_CLANG_AST_REDECLARABLE_H
16
17#include "llvm/ADT/PointerIntPair.h"
18
19namespace clang {
20
21/// \brief Provides common interface for the Decls that can be redeclared.
22template<typename decl_type>
23class Redeclarable {
24
25protected:
26  struct DeclLink : public llvm::PointerIntPair<decl_type *, 1, bool> {
27    DeclLink(decl_type *D, bool isLatest)
28      : llvm::PointerIntPair<decl_type *, 1, bool>(D, isLatest) { }
29
30    typedef llvm::PointerIntPair<decl_type *, 1, bool> base_type;
31
32    bool NextIsPrevious() const { return base_type::getInt() == false; }
33    bool NextIsLatest() const { return base_type::getInt() == true; }
34    decl_type *getNext() const { return base_type::getPointer(); }
35  };
36
37  struct PreviousDeclLink : public DeclLink {
38    PreviousDeclLink(decl_type *D) : DeclLink(D, false) { }
39  };
40
41  struct LatestDeclLink : public DeclLink {
42    LatestDeclLink(decl_type *D) : DeclLink(D, true) { }
43  };
44
45  /// \brief Points to the next redeclaration in the chain.
46  ///
47  /// If NextIsPrevious() is true, this is a link to the previous declaration
48  /// of this same Decl. If NextIsLatest() is true, this is the first
49  /// declaration and Link points to the latest declaration. For example:
50  ///
51  ///  #1 int f(int x, int y = 1); // <pointer to #3, true>
52  ///  #2 int f(int x = 0, int y); // <pointer to #1, false>
53  ///  #3 int f(int x, int y) { return x + y; } // <pointer to #2, false>
54  ///
55  /// If there is only one declaration, it is <pointer to self, true>
56  DeclLink RedeclLink;
57
58public:
59  Redeclarable() : RedeclLink(LatestDeclLink(static_cast<decl_type*>(this))) { }
60
61  /// \brief Return the previous declaration of this declaration or NULL if this
62  /// is the first declaration.
63  decl_type *getPreviousDeclaration() {
64    if (RedeclLink.NextIsPrevious())
65      return RedeclLink.getNext();
66    return 0;
67  }
68  const decl_type *getPreviousDeclaration() const {
69    return const_cast<decl_type *>(
70                 static_cast<const decl_type*>(this))->getPreviousDeclaration();
71  }
72
73  /// \brief Return the first declaration of this declaration or itself if this
74  /// is the only declaration.
75  decl_type *getFirstDeclaration() {
76    decl_type *D = static_cast<decl_type*>(this);
77    while (D->getPreviousDeclaration())
78      D = D->getPreviousDeclaration();
79    return D;
80  }
81
82  /// \brief Set the previous declaration. If PrevDecl is NULL, set this as the
83  /// first and only declaration.
84  void setPreviousDeclaration(decl_type *PrevDecl) {
85    decl_type *First;
86
87    if (PrevDecl) {
88      // Point to previous.
89      RedeclLink = PreviousDeclLink(PrevDecl);
90      First = PrevDecl->getFirstDeclaration();
91      assert(First->RedeclLink.NextIsLatest() && "Expected first");
92    } else {
93      // Make this first.
94      First = static_cast<decl_type*>(this);
95    }
96
97    // First one will point to this one as latest.
98    First->RedeclLink = LatestDeclLink(static_cast<decl_type*>(this));
99  }
100
101  /// \brief Iterates through all the redeclarations of the same decl.
102  class redecl_iterator {
103    /// Current - The current declaration.
104    decl_type *Current;
105    decl_type *Starter;
106
107  public:
108    typedef decl_type*                value_type;
109    typedef decl_type*                reference;
110    typedef decl_type*                pointer;
111    typedef std::forward_iterator_tag iterator_category;
112    typedef std::ptrdiff_t            difference_type;
113
114    redecl_iterator() : Current(0) { }
115    explicit redecl_iterator(decl_type *C) : Current(C), Starter(C) { }
116
117    reference operator*() const { return Current; }
118    pointer operator->() const { return Current; }
119
120    redecl_iterator& operator++() {
121      assert(Current && "Advancing while iterator has reached end");
122      // Get either previous decl or latest decl.
123      decl_type *Next = Current->RedeclLink.getNext();
124      Current = (Next != Starter ? Next : 0);
125      return *this;
126    }
127
128    redecl_iterator operator++(int) {
129      redecl_iterator tmp(*this);
130      ++(*this);
131      return tmp;
132    }
133
134    friend bool operator==(redecl_iterator x, redecl_iterator y) {
135      return x.Current == y.Current;
136    }
137    friend bool operator!=(redecl_iterator x, redecl_iterator y) {
138      return x.Current != y.Current;
139    }
140  };
141
142  /// \brief Returns iterator for all the redeclarations of the same decl.
143  /// It will iterate at least once (when this decl is the only one).
144  redecl_iterator redecls_begin() const {
145    return redecl_iterator(const_cast<decl_type*>(
146                                          static_cast<const decl_type*>(this)));
147  }
148  redecl_iterator redecls_end() const { return redecl_iterator(); }
149};
150
151}
152
153#endif
154