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