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 #include "llvm/Support/Casting.h" 19 #include <iterator> 20 21 namespace clang { 22 23 /// \brief Provides common interface for the Decls that can be redeclared. 24 template<typename decl_type> 25 class Redeclarable { 26 27 protected: 28 // FIXME: PointerIntPair is a value class that should not be inherited from. 29 // This should change to using containment. 30 struct DeclLink : public llvm::PointerIntPair<decl_type *, 1, bool> { DeclLinkDeclLink31 DeclLink(decl_type *D, bool isLatest) 32 : llvm::PointerIntPair<decl_type *, 1, bool>(D, isLatest) { } 33 34 typedef llvm::PointerIntPair<decl_type *, 1, bool> base_type; 35 NextIsPreviousDeclLink36 bool NextIsPrevious() const { return base_type::getInt() == false; } NextIsLatestDeclLink37 bool NextIsLatest() const { return base_type::getInt() == true; } getNextDeclLink38 decl_type *getNext() const { return base_type::getPointer(); } 39 }; 40 41 struct PreviousDeclLink : public DeclLink { PreviousDeclLinkPreviousDeclLink42 PreviousDeclLink(decl_type *D) : DeclLink(D, false) { } 43 }; 44 45 struct LatestDeclLink : public DeclLink { LatestDeclLinkLatestDeclLink46 LatestDeclLink(decl_type *D) : DeclLink(D, true) { } 47 }; 48 49 /// \brief Points to the next redeclaration in the chain. 50 /// 51 /// If NextIsPrevious() is true, this is a link to the previous declaration 52 /// of this same Decl. If NextIsLatest() is true, this is the first 53 /// declaration and Link points to the latest declaration. For example: 54 /// 55 /// #1 int f(int x, int y = 1); // <pointer to #3, true> 56 /// #2 int f(int x = 0, int y); // <pointer to #1, false> 57 /// #3 int f(int x, int y) { return x + y; } // <pointer to #2, false> 58 /// 59 /// If there is only one declaration, it is <pointer to self, true> 60 DeclLink RedeclLink; 61 62 public: Redeclarable()63 Redeclarable() : RedeclLink(LatestDeclLink(static_cast<decl_type*>(this))) { } 64 65 /// \brief Return the previous declaration of this declaration or NULL if this 66 /// is the first declaration. getPreviousDecl()67 decl_type *getPreviousDecl() { 68 if (RedeclLink.NextIsPrevious()) 69 return RedeclLink.getNext(); 70 return 0; 71 } getPreviousDecl()72 const decl_type *getPreviousDecl() const { 73 return const_cast<decl_type *>( 74 static_cast<const decl_type*>(this))->getPreviousDecl(); 75 } 76 77 /// \brief Return the first declaration of this declaration or itself if this 78 /// is the only declaration. getFirstDeclaration()79 decl_type *getFirstDeclaration() { 80 decl_type *D = static_cast<decl_type*>(this); 81 while (D->getPreviousDecl()) 82 D = D->getPreviousDecl(); 83 return D; 84 } 85 86 /// \brief Return the first declaration of this declaration or itself if this 87 /// is the only declaration. getFirstDeclaration()88 const decl_type *getFirstDeclaration() const { 89 const decl_type *D = static_cast<const decl_type*>(this); 90 while (D->getPreviousDecl()) 91 D = D->getPreviousDecl(); 92 return D; 93 } 94 95 /// \brief Returns true if this is the first declaration. isFirstDeclaration()96 bool isFirstDeclaration() const { 97 return RedeclLink.NextIsLatest(); 98 } 99 100 /// \brief Returns the most recent (re)declaration of this declaration. getMostRecentDecl()101 decl_type *getMostRecentDecl() { 102 return getFirstDeclaration()->RedeclLink.getNext(); 103 } 104 105 /// \brief Returns the most recent (re)declaration of this declaration. getMostRecentDecl()106 const decl_type *getMostRecentDecl() const { 107 return getFirstDeclaration()->RedeclLink.getNext(); 108 } 109 110 /// \brief Set the previous declaration. If PrevDecl is NULL, set this as the 111 /// first and only declaration. 112 void setPreviousDeclaration(decl_type *PrevDecl); 113 114 /// \brief Iterates through all the redeclarations of the same decl. 115 class redecl_iterator { 116 /// Current - The current declaration. 117 decl_type *Current; 118 decl_type *Starter; 119 bool PassedFirst; 120 121 public: 122 typedef decl_type* value_type; 123 typedef decl_type* reference; 124 typedef decl_type* pointer; 125 typedef std::forward_iterator_tag iterator_category; 126 typedef std::ptrdiff_t difference_type; 127 redecl_iterator()128 redecl_iterator() : Current(0) { } redecl_iterator(decl_type * C)129 explicit redecl_iterator(decl_type *C) 130 : Current(C), Starter(C), PassedFirst(false) { } 131 132 reference operator*() const { return Current; } 133 pointer operator->() const { return Current; } 134 135 redecl_iterator& operator++() { 136 assert(Current && "Advancing while iterator has reached end"); 137 // Sanity check to avoid infinite loop on invalid redecl chain. 138 if (Current->isFirstDeclaration()) { 139 if (PassedFirst) { 140 assert(0 && "Passed first decl twice, invalid redecl chain!"); 141 Current = 0; 142 return *this; 143 } 144 PassedFirst = true; 145 } 146 147 // Get either previous decl or latest decl. 148 decl_type *Next = Current->RedeclLink.getNext(); 149 Current = (Next != Starter ? Next : 0); 150 return *this; 151 } 152 153 redecl_iterator operator++(int) { 154 redecl_iterator tmp(*this); 155 ++(*this); 156 return tmp; 157 } 158 159 friend bool operator==(redecl_iterator x, redecl_iterator y) { 160 return x.Current == y.Current; 161 } 162 friend bool operator!=(redecl_iterator x, redecl_iterator y) { 163 return x.Current != y.Current; 164 } 165 }; 166 167 /// \brief Returns iterator for all the redeclarations of the same decl. 168 /// It will iterate at least once (when this decl is the only one). redecls_begin()169 redecl_iterator redecls_begin() const { 170 return redecl_iterator(const_cast<decl_type*>( 171 static_cast<const decl_type*>(this))); 172 } redecls_end()173 redecl_iterator redecls_end() const { return redecl_iterator(); } 174 175 friend class ASTDeclReader; 176 friend class ASTDeclWriter; 177 }; 178 179 } 180 181 #endif 182