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