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