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