Redeclarable.h revision 651f13cea278ec967336033dd032faef0e9fc2ec
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 21namespace clang { 22 23/// \brief Provides common interface for the Decls that can be redeclared. 24template<typename decl_type> 25class Redeclarable { 26 27protected: 28 class DeclLink { 29 llvm::PointerIntPair<decl_type *, 1, bool> NextAndIsPrevious; 30 public: 31 DeclLink(decl_type *D, bool isLatest) 32 : NextAndIsPrevious(D, isLatest) { } 33 34 bool NextIsPrevious() const { return !NextAndIsPrevious.getInt(); } 35 bool NextIsLatest() const { return NextAndIsPrevious.getInt(); } 36 decl_type *getNext() const { return NextAndIsPrevious.getPointer(); } 37 void setNext(decl_type *D) { NextAndIsPrevious.setPointer(D); } 38 }; 39 40 static DeclLink PreviousDeclLink(decl_type *D) { 41 return DeclLink(D, false); 42 } 43 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 61public: 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. 66 decl_type *getPreviousDecl() { 67 if (RedeclLink.NextIsPrevious()) 68 return RedeclLink.getNext(); 69 return 0; 70 } 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. 78 decl_type *getFirstDecl() { 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. 87 const decl_type *getFirstDecl() 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 True if this is the first declaration in its redeclaration chain. 95 bool isFirstDecl() const { return RedeclLink.NextIsLatest(); } 96 97 /// \brief Returns the most recent (re)declaration of this declaration. 98 decl_type *getMostRecentDecl() { 99 return getFirstDecl()->RedeclLink.getNext(); 100 } 101 102 /// \brief Returns the most recent (re)declaration of this declaration. 103 const decl_type *getMostRecentDecl() const { 104 return getFirstDecl()->RedeclLink.getNext(); 105 } 106 107 /// \brief Set the previous declaration. If PrevDecl is NULL, set this as the 108 /// first and only declaration. 109 void setPreviousDecl(decl_type *PrevDecl); 110 111 /// \brief Iterates through all the redeclarations of the same decl. 112 class redecl_iterator { 113 /// Current - The current declaration. 114 decl_type *Current; 115 decl_type *Starter; 116 bool PassedFirst; 117 118 public: 119 typedef decl_type* value_type; 120 typedef decl_type* reference; 121 typedef decl_type* pointer; 122 typedef std::forward_iterator_tag iterator_category; 123 typedef std::ptrdiff_t difference_type; 124 125 redecl_iterator() : Current(0) { } 126 explicit redecl_iterator(decl_type *C) 127 : Current(C), Starter(C), PassedFirst(false) { } 128 129 reference operator*() const { return Current; } 130 pointer operator->() const { return Current; } 131 132 redecl_iterator& operator++() { 133 assert(Current && "Advancing while iterator has reached end"); 134 // Sanity check to avoid infinite loop on invalid redecl chain. 135 if (Current->isFirstDecl()) { 136 if (PassedFirst) { 137 assert(0 && "Passed first decl twice, invalid redecl chain!"); 138 Current = 0; 139 return *this; 140 } 141 PassedFirst = true; 142 } 143 144 // Get either previous decl or latest decl. 145 decl_type *Next = Current->RedeclLink.getNext(); 146 Current = (Next != Starter ? Next : 0); 147 return *this; 148 } 149 150 redecl_iterator operator++(int) { 151 redecl_iterator tmp(*this); 152 ++(*this); 153 return tmp; 154 } 155 156 friend bool operator==(redecl_iterator x, redecl_iterator y) { 157 return x.Current == y.Current; 158 } 159 friend bool operator!=(redecl_iterator x, redecl_iterator y) { 160 return x.Current != y.Current; 161 } 162 }; 163 164 typedef llvm::iterator_range<redecl_iterator> redecl_range; 165 166 /// \brief Returns an iterator range for all the redeclarations of the same 167 /// decl. It will iterate at least once (when this decl is the only one). 168 redecl_range redecls() const { 169 return redecl_range(redecl_iterator(const_cast<decl_type *>( 170 static_cast<const decl_type *>(this))), 171 redecl_iterator()); 172 } 173 174 redecl_iterator redecls_begin() const { return redecls().begin(); } 175 redecl_iterator redecls_end() const { return redecls().end(); } 176 177 friend class ASTDeclReader; 178 friend class ASTDeclWriter; 179}; 180 181/// \brief Get the primary declaration for a declaration from an AST file. That 182/// will be the first-loaded declaration. 183Decl *getPrimaryMergedDecl(Decl *D); 184 185/// \brief Provides common interface for the Decls that cannot be redeclared, 186/// but can be merged if the same declaration is brought in from multiple 187/// modules. 188template<typename decl_type> 189class Mergeable { 190public: 191 Mergeable() {} 192 193 /// \brief Return the first declaration of this declaration or itself if this 194 /// is the only declaration. 195 decl_type *getFirstDecl() { 196 decl_type *D = static_cast<decl_type*>(this); 197 if (!D->isFromASTFile()) 198 return D; 199 return cast<decl_type>(getPrimaryMergedDecl(const_cast<decl_type*>(D))); 200 } 201 202 /// \brief Return the first declaration of this declaration or itself if this 203 /// is the only declaration. 204 const decl_type *getFirstDecl() const { 205 const decl_type *D = static_cast<const decl_type*>(this); 206 if (!D->isFromASTFile()) 207 return D; 208 return cast<decl_type>(getPrimaryMergedDecl(const_cast<decl_type*>(D))); 209 } 210 211 /// \brief Returns true if this is the first declaration. 212 bool isFirstDecl() const { return getFirstDecl() == this; } 213}; 214 215} 216 217#endif 218