1 //===- DeclContextInternals.h - DeclContext Representation ------*- 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 data structures used in the implementation 11 // of DeclContext. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #ifndef LLVM_CLANG_AST_DECLCONTEXTINTERNALS_H 16 #define LLVM_CLANG_AST_DECLCONTEXTINTERNALS_H 17 18 #include "clang/AST/Decl.h" 19 #include "clang/AST/DeclBase.h" 20 #include "clang/AST/DeclCXX.h" 21 #include "clang/AST/DeclarationName.h" 22 #include "llvm/ADT/DenseMap.h" 23 #include "llvm/ADT/PointerIntPair.h" 24 #include "llvm/ADT/PointerUnion.h" 25 #include "llvm/ADT/SmallVector.h" 26 #include <algorithm> 27 #include <cassert> 28 29 namespace clang { 30 31 class DependentDiagnostic; 32 33 /// An array of decls optimized for the common case of only containing 34 /// one entry. 35 struct StoredDeclsList { 36 /// When in vector form, this is what the Data pointer points to. 37 using DeclsTy = SmallVector<NamedDecl *, 4>; 38 39 /// A collection of declarations, with a flag to indicate if we have 40 /// further external declarations. 41 using DeclsAndHasExternalTy = llvm::PointerIntPair<DeclsTy *, 1, bool>; 42 43 /// The stored data, which will be either a pointer to a NamedDecl, 44 /// or a pointer to a vector with a flag to indicate if there are further 45 /// external declarations. 46 llvm::PointerUnion<NamedDecl *, DeclsAndHasExternalTy> Data; 47 48 public: 49 StoredDeclsList() = default; 50 StoredDeclsListStoredDeclsList51 StoredDeclsList(StoredDeclsList &&RHS) : Data(RHS.Data) { 52 RHS.Data = (NamedDecl *)nullptr; 53 } 54 ~StoredDeclsListStoredDeclsList55 ~StoredDeclsList() { 56 // If this is a vector-form, free the vector. 57 if (DeclsTy *Vector = getAsVector()) 58 delete Vector; 59 } 60 61 StoredDeclsList &operator=(StoredDeclsList &&RHS) { 62 if (DeclsTy *Vector = getAsVector()) 63 delete Vector; 64 Data = RHS.Data; 65 RHS.Data = (NamedDecl *)nullptr; 66 return *this; 67 } 68 isNullStoredDeclsList69 bool isNull() const { return Data.isNull(); } 70 getAsDeclStoredDeclsList71 NamedDecl *getAsDecl() const { 72 return Data.dyn_cast<NamedDecl *>(); 73 } 74 getAsVectorAndHasExternalStoredDeclsList75 DeclsAndHasExternalTy getAsVectorAndHasExternal() const { 76 return Data.dyn_cast<DeclsAndHasExternalTy>(); 77 } 78 getAsVectorStoredDeclsList79 DeclsTy *getAsVector() const { 80 return getAsVectorAndHasExternal().getPointer(); 81 } 82 hasExternalDeclsStoredDeclsList83 bool hasExternalDecls() const { 84 return getAsVectorAndHasExternal().getInt(); 85 } 86 setHasExternalDeclsStoredDeclsList87 void setHasExternalDecls() { 88 if (DeclsTy *Vec = getAsVector()) 89 Data = DeclsAndHasExternalTy(Vec, true); 90 else { 91 DeclsTy *VT = new DeclsTy(); 92 if (NamedDecl *OldD = getAsDecl()) 93 VT->push_back(OldD); 94 Data = DeclsAndHasExternalTy(VT, true); 95 } 96 } 97 setOnlyValueStoredDeclsList98 void setOnlyValue(NamedDecl *ND) { 99 assert(!getAsVector() && "Not inline"); 100 Data = ND; 101 // Make sure that Data is a plain NamedDecl* so we can use its address 102 // at getLookupResult. 103 assert(*(NamedDecl **)&Data == ND && 104 "PointerUnion mangles the NamedDecl pointer!"); 105 } 106 removeStoredDeclsList107 void remove(NamedDecl *D) { 108 assert(!isNull() && "removing from empty list"); 109 if (NamedDecl *Singleton = getAsDecl()) { 110 assert(Singleton == D && "list is different singleton"); 111 (void)Singleton; 112 Data = (NamedDecl *)nullptr; 113 return; 114 } 115 116 DeclsTy &Vec = *getAsVector(); 117 DeclsTy::iterator I = std::find(Vec.begin(), Vec.end(), D); 118 assert(I != Vec.end() && "list does not contain decl"); 119 Vec.erase(I); 120 121 assert(std::find(Vec.begin(), Vec.end(), D) 122 == Vec.end() && "list still contains decl"); 123 } 124 125 /// Remove any declarations which were imported from an external 126 /// AST source. removeExternalDeclsStoredDeclsList127 void removeExternalDecls() { 128 if (isNull()) { 129 // Nothing to do. 130 } else if (NamedDecl *Singleton = getAsDecl()) { 131 if (Singleton->isFromASTFile()) 132 *this = StoredDeclsList(); 133 } else { 134 DeclsTy &Vec = *getAsVector(); 135 Vec.erase(std::remove_if(Vec.begin(), Vec.end(), 136 [](Decl *D) { return D->isFromASTFile(); }), 137 Vec.end()); 138 // Don't have any external decls any more. 139 Data = DeclsAndHasExternalTy(&Vec, false); 140 } 141 } 142 143 /// getLookupResult - Return an array of all the decls that this list 144 /// represents. getLookupResultStoredDeclsList145 DeclContext::lookup_result getLookupResult() { 146 if (isNull()) 147 return DeclContext::lookup_result(); 148 149 // If we have a single NamedDecl, return it. 150 if (NamedDecl *ND = getAsDecl()) { 151 assert(!isNull() && "Empty list isn't allowed"); 152 153 // Data is a raw pointer to a NamedDecl*, return it. 154 return DeclContext::lookup_result(ND); 155 } 156 157 assert(getAsVector() && "Must have a vector at this point"); 158 DeclsTy &Vector = *getAsVector(); 159 160 // Otherwise, we have a range result. 161 return DeclContext::lookup_result(Vector); 162 } 163 164 /// HandleRedeclaration - If this is a redeclaration of an existing decl, 165 /// replace the old one with D and return true. Otherwise return false. HandleRedeclarationStoredDeclsList166 bool HandleRedeclaration(NamedDecl *D, bool IsKnownNewer) { 167 // Most decls only have one entry in their list, special case it. 168 if (NamedDecl *OldD = getAsDecl()) { 169 if (!D->declarationReplaces(OldD, IsKnownNewer)) 170 return false; 171 setOnlyValue(D); 172 return true; 173 } 174 175 // Determine if this declaration is actually a redeclaration. 176 DeclsTy &Vec = *getAsVector(); 177 for (DeclsTy::iterator OD = Vec.begin(), ODEnd = Vec.end(); 178 OD != ODEnd; ++OD) { 179 NamedDecl *OldD = *OD; 180 if (D->declarationReplaces(OldD, IsKnownNewer)) { 181 *OD = D; 182 return true; 183 } 184 } 185 186 return false; 187 } 188 189 /// AddSubsequentDecl - This is called on the second and later decl when it is 190 /// not a redeclaration to merge it into the appropriate place in our list. AddSubsequentDeclStoredDeclsList191 void AddSubsequentDecl(NamedDecl *D) { 192 assert(!isNull() && "don't AddSubsequentDecl when we have no decls"); 193 194 // If this is the second decl added to the list, convert this to vector 195 // form. 196 if (NamedDecl *OldD = getAsDecl()) { 197 DeclsTy *VT = new DeclsTy(); 198 VT->push_back(OldD); 199 Data = DeclsAndHasExternalTy(VT, false); 200 } 201 202 DeclsTy &Vec = *getAsVector(); 203 204 // Using directives end up in a special entry which contains only 205 // other using directives, so all this logic is wasted for them. 206 // But avoiding the logic wastes time in the far-more-common case 207 // that we're *not* adding a new using directive. 208 209 // Tag declarations always go at the end of the list so that an 210 // iterator which points at the first tag will start a span of 211 // decls that only contains tags. 212 if (D->hasTagIdentifierNamespace()) 213 Vec.push_back(D); 214 215 // Resolved using declarations go at the front of the list so that 216 // they won't show up in other lookup results. Unresolved using 217 // declarations (which are always in IDNS_Using | IDNS_Ordinary) 218 // follow that so that the using declarations will be contiguous. 219 else if (D->getIdentifierNamespace() & Decl::IDNS_Using) { 220 DeclsTy::iterator I = Vec.begin(); 221 if (D->getIdentifierNamespace() != Decl::IDNS_Using) { 222 while (I != Vec.end() && 223 (*I)->getIdentifierNamespace() == Decl::IDNS_Using) 224 ++I; 225 } 226 Vec.insert(I, D); 227 228 // All other declarations go at the end of the list, but before any 229 // tag declarations. But we can be clever about tag declarations 230 // because there can only ever be one in a scope. 231 } else if (!Vec.empty() && Vec.back()->hasTagIdentifierNamespace()) { 232 NamedDecl *TagD = Vec.back(); 233 Vec.back() = D; 234 Vec.push_back(TagD); 235 } else 236 Vec.push_back(D); 237 } 238 }; 239 240 class StoredDeclsMap 241 : public llvm::SmallDenseMap<DeclarationName, StoredDeclsList, 4> { 242 public: 243 static void DestroyAll(StoredDeclsMap *Map, bool Dependent); 244 245 private: 246 friend class ASTContext; // walks the chain deleting these 247 friend class DeclContext; 248 249 llvm::PointerIntPair<StoredDeclsMap*, 1> Previous; 250 }; 251 252 class DependentStoredDeclsMap : public StoredDeclsMap { 253 public: 254 DependentStoredDeclsMap() = default; 255 256 private: 257 friend class DeclContext; // iterates over diagnostics 258 friend class DependentDiagnostic; 259 260 DependentDiagnostic *FirstDiagnostic = nullptr; 261 }; 262 263 } // namespace clang 264 265 #endif // LLVM_CLANG_AST_DECLCONTEXTINTERNALS_H 266