Redeclarable.h revision a865005c74019184e04f7fcdd4d61c31c095a4ff
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 // 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> { 31 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 36 bool NextIsPrevious() const { return base_type::getInt() == false; } 37 bool NextIsLatest() const { return base_type::getInt() == true; } 38 decl_type *getNext() const { return base_type::getPointer(); } 39 }; 40 41 struct PreviousDeclLink : public DeclLink { 42 PreviousDeclLink(decl_type *D) : DeclLink(D, false) { } 43 }; 44 45 struct LatestDeclLink : public DeclLink { 46 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 62public: 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. 67 decl_type *getPreviousDeclaration() { 68 if (RedeclLink.NextIsPrevious()) 69 return RedeclLink.getNext(); 70 return 0; 71 } 72 const decl_type *getPreviousDeclaration() const { 73 return const_cast<decl_type *>( 74 static_cast<const decl_type*>(this))->getPreviousDeclaration(); 75 } 76 77 /// \brief Return the first declaration of this declaration or itself if this 78 /// is the only declaration. 79 decl_type *getFirstDeclaration() { 80 decl_type *D = static_cast<decl_type*>(this); 81 while (D->getPreviousDeclaration()) 82 D = D->getPreviousDeclaration(); 83 return D; 84 } 85 86 /// \brief Return the first declaration of this declaration or itself if this 87 /// is the only declaration. 88 const decl_type *getFirstDeclaration() const { 89 const decl_type *D = static_cast<const decl_type*>(this); 90 while (D->getPreviousDeclaration()) 91 D = D->getPreviousDeclaration(); 92 return D; 93 } 94 95 /// \brief Returns true if this is the first declaration. 96 bool isFirstDeclaration() const { 97 return RedeclLink.NextIsLatest(); 98 } 99 100 /// \brief Returns the most recent (re)declaration of this declaration. 101 decl_type *getMostRecentDeclaration() { 102 return getFirstDeclaration()->RedeclLink.getNext(); 103 } 104 105 /// \brief Returns the most recent (re)declaration of this declaration. 106 const decl_type *getMostRecentDeclaration() 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 decl_type *First; 114 115 if (PrevDecl) { 116 // Point to previous. Make sure that this is actually the most recent 117 // redeclaration, or we can build invalid chains. If the most recent 118 // redeclaration is invalid, it won't be PrevDecl, but we want it anyway. 119 RedeclLink = PreviousDeclLink(llvm::cast<decl_type>( 120 PrevDecl->getMostRecentDeclaration())); 121 First = PrevDecl->getFirstDeclaration(); 122 assert(First->RedeclLink.NextIsLatest() && "Expected first"); 123 } else { 124 // Make this first. 125 First = static_cast<decl_type*>(this); 126 } 127 128 // First one will point to this one as latest. 129 First->RedeclLink = LatestDeclLink(static_cast<decl_type*>(this)); 130 } 131 132 /// \brief Iterates through all the redeclarations of the same decl. 133 class redecl_iterator { 134 /// Current - The current declaration. 135 decl_type *Current; 136 decl_type *Starter; 137 138 public: 139 typedef decl_type* value_type; 140 typedef decl_type* reference; 141 typedef decl_type* pointer; 142 typedef std::forward_iterator_tag iterator_category; 143 typedef std::ptrdiff_t difference_type; 144 145 redecl_iterator() : Current(0) { } 146 explicit redecl_iterator(decl_type *C) : Current(C), Starter(C) { } 147 148 reference operator*() const { return Current; } 149 pointer operator->() const { return Current; } 150 151 redecl_iterator& operator++() { 152 assert(Current && "Advancing while iterator has reached end"); 153 // Get either previous decl or latest decl. 154 decl_type *Next = Current->RedeclLink.getNext(); 155 Current = (Next != Starter ? Next : 0); 156 return *this; 157 } 158 159 redecl_iterator operator++(int) { 160 redecl_iterator tmp(*this); 161 ++(*this); 162 return tmp; 163 } 164 165 friend bool operator==(redecl_iterator x, redecl_iterator y) { 166 return x.Current == y.Current; 167 } 168 friend bool operator!=(redecl_iterator x, redecl_iterator y) { 169 return x.Current != y.Current; 170 } 171 }; 172 173 /// \brief Returns iterator for all the redeclarations of the same decl. 174 /// It will iterate at least once (when this decl is the only one). 175 redecl_iterator redecls_begin() const { 176 return redecl_iterator(const_cast<decl_type*>( 177 static_cast<const decl_type*>(this))); 178 } 179 redecl_iterator redecls_end() const { return redecl_iterator(); } 180 181 friend class PCHDeclReader; 182 friend class PCHDeclWriter; 183}; 184 185} 186 187#endif 188