1 //===- IdentifierResolver.h - Lexical Scope Name lookup ---------*- 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 IdentifierResolver class, which is used for lexical 11 // scoped lookup, based on declaration names. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #ifndef LLVM_CLANG_SEMA_IDENTIFIERRESOLVER_H 16 #define LLVM_CLANG_SEMA_IDENTIFIERRESOLVER_H 17 18 #include "clang/Basic/LLVM.h" 19 #include "llvm/ADT/SmallVector.h" 20 #include <cassert> 21 #include <cstddef> 22 #include <cstdint> 23 #include <iterator> 24 25 namespace clang { 26 27 class Decl; 28 class DeclarationName; 29 class DeclContext; 30 class IdentifierInfo; 31 class LangOptions; 32 class NamedDecl; 33 class Preprocessor; 34 class Scope; 35 36 /// IdentifierResolver - Keeps track of shadowed decls on enclosing 37 /// scopes. It manages the shadowing chains of declaration names and 38 /// implements efficient decl lookup based on a declaration name. 39 class IdentifierResolver { 40 /// IdDeclInfo - Keeps track of information about decls associated 41 /// to a particular declaration name. IdDeclInfos are lazily 42 /// constructed and assigned to a declaration name the first time a 43 /// decl with that declaration name is shadowed in some scope. 44 class IdDeclInfo { 45 public: 46 using DeclsTy = SmallVector<NamedDecl *, 2>; 47 decls_begin()48 DeclsTy::iterator decls_begin() { return Decls.begin(); } decls_end()49 DeclsTy::iterator decls_end() { return Decls.end(); } 50 AddDecl(NamedDecl * D)51 void AddDecl(NamedDecl *D) { Decls.push_back(D); } 52 53 /// RemoveDecl - Remove the decl from the scope chain. 54 /// The decl must already be part of the decl chain. 55 void RemoveDecl(NamedDecl *D); 56 57 /// Insert the given declaration at the given position in the list. InsertDecl(DeclsTy::iterator Pos,NamedDecl * D)58 void InsertDecl(DeclsTy::iterator Pos, NamedDecl *D) { 59 Decls.insert(Pos, D); 60 } 61 62 private: 63 DeclsTy Decls; 64 }; 65 66 public: 67 /// iterator - Iterate over the decls of a specified declaration name. 68 /// It will walk or not the parent declaration contexts depending on how 69 /// it was instantiated. 70 class iterator { 71 public: 72 friend class IdentifierResolver; 73 74 using value_type = NamedDecl *; 75 using reference = NamedDecl *; 76 using pointer = NamedDecl *; 77 using iterator_category = std::input_iterator_tag; 78 using difference_type = std::ptrdiff_t; 79 80 /// Ptr - There are 2 forms that 'Ptr' represents: 81 /// 1) A single NamedDecl. (Ptr & 0x1 == 0) 82 /// 2) A IdDeclInfo::DeclsTy::iterator that traverses only the decls of the 83 /// same declaration context. (Ptr & 0x1 == 0x1) 84 uintptr_t Ptr = 0; 85 using BaseIter = IdDeclInfo::DeclsTy::iterator; 86 87 /// A single NamedDecl. (Ptr & 0x1 == 0) iterator(NamedDecl * D)88 iterator(NamedDecl *D) { 89 Ptr = reinterpret_cast<uintptr_t>(D); 90 assert((Ptr & 0x1) == 0 && "Invalid Ptr!"); 91 } 92 93 /// A IdDeclInfo::DeclsTy::iterator that walks or not the parent declaration 94 /// contexts depending on 'LookInParentCtx'. iterator(BaseIter I)95 iterator(BaseIter I) { 96 Ptr = reinterpret_cast<uintptr_t>(I) | 0x1; 97 } 98 isIterator()99 bool isIterator() const { return (Ptr & 0x1); } 100 getIterator()101 BaseIter getIterator() const { 102 assert(isIterator() && "Ptr not an iterator!"); 103 return reinterpret_cast<BaseIter>(Ptr & ~0x1); 104 } 105 106 void incrementSlowCase(); 107 108 public: 109 iterator() = default; 110 111 NamedDecl *operator*() const { 112 if (isIterator()) 113 return *getIterator(); 114 else 115 return reinterpret_cast<NamedDecl*>(Ptr); 116 } 117 118 bool operator==(const iterator &RHS) const { 119 return Ptr == RHS.Ptr; 120 } 121 bool operator!=(const iterator &RHS) const { 122 return Ptr != RHS.Ptr; 123 } 124 125 // Preincrement. 126 iterator& operator++() { 127 if (!isIterator()) // common case. 128 Ptr = 0; 129 else 130 incrementSlowCase(); 131 return *this; 132 } 133 }; 134 135 explicit IdentifierResolver(Preprocessor &PP); 136 ~IdentifierResolver(); 137 138 /// begin - Returns an iterator for decls with the name 'Name'. 139 iterator begin(DeclarationName Name); 140 141 /// end - Returns an iterator that has 'finished'. end()142 iterator end() { 143 return iterator(); 144 } 145 146 /// isDeclInScope - If 'Ctx' is a function/method, isDeclInScope returns true 147 /// if 'D' is in Scope 'S', otherwise 'S' is ignored and isDeclInScope returns 148 /// true if 'D' belongs to the given declaration context. 149 /// 150 /// \param AllowInlineNamespace If \c true, we are checking whether a prior 151 /// declaration is in scope in a declaration that requires a prior 152 /// declaration (because it is either explicitly qualified or is a 153 /// template instantiation or specialization). In this case, a 154 /// declaration is in scope if it's in the inline namespace set of the 155 /// context. 156 bool isDeclInScope(Decl *D, DeclContext *Ctx, Scope *S = nullptr, 157 bool AllowInlineNamespace = false) const; 158 159 /// AddDecl - Link the decl to its shadowed decl chain. 160 void AddDecl(NamedDecl *D); 161 162 /// RemoveDecl - Unlink the decl from its shadowed decl chain. 163 /// The decl must already be part of the decl chain. 164 void RemoveDecl(NamedDecl *D); 165 166 /// Insert the given declaration after the given iterator 167 /// position. 168 void InsertDeclAfter(iterator Pos, NamedDecl *D); 169 170 /// Try to add the given declaration to the top level scope, if it 171 /// (or a redeclaration of it) hasn't already been added. 172 /// 173 /// \param D The externally-produced declaration to add. 174 /// 175 /// \param Name The name of the externally-produced declaration. 176 /// 177 /// \returns true if the declaration was added, false otherwise. 178 bool tryAddTopLevelDecl(NamedDecl *D, DeclarationName Name); 179 180 private: 181 const LangOptions &LangOpt; 182 Preprocessor &PP; 183 184 class IdDeclInfoMap; 185 IdDeclInfoMap *IdDeclInfos; 186 187 void updatingIdentifier(IdentifierInfo &II); 188 void readingIdentifier(IdentifierInfo &II); 189 190 /// FETokenInfo contains a Decl pointer if lower bit == 0. isDeclPtr(void * Ptr)191 static inline bool isDeclPtr(void *Ptr) { 192 return (reinterpret_cast<uintptr_t>(Ptr) & 0x1) == 0; 193 } 194 195 /// FETokenInfo contains a IdDeclInfo pointer if lower bit == 1. toIdDeclInfo(void * Ptr)196 static inline IdDeclInfo *toIdDeclInfo(void *Ptr) { 197 assert((reinterpret_cast<uintptr_t>(Ptr) & 0x1) == 1 198 && "Ptr not a IdDeclInfo* !"); 199 return reinterpret_cast<IdDeclInfo*>( 200 reinterpret_cast<uintptr_t>(Ptr) & ~0x1); 201 } 202 }; 203 204 } // namespace clang 205 206 #endif // LLVM_CLANG_SEMA_IDENTIFIERRESOLVER_H 207