DeclContextInternals.h revision 198092
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/DeclBase.h" 18#include "clang/AST/DeclarationName.h" 19#include "llvm/ADT/DenseMap.h" 20#include "llvm/ADT/PointerUnion.h" 21#include "llvm/ADT/SmallVector.h" 22#include <algorithm> 23 24namespace clang { 25 26/// StoredDeclsList - This is an array of decls optimized a common case of only 27/// containing one entry. 28struct StoredDeclsList { 29 /// The kind of data encoded in this list. 30 enum DataKind { 31 /// \brief The data is a NamedDecl*. 32 DK_Decl = 0, 33 /// \brief The data is a declaration ID (an unsigned value), 34 /// shifted left by 2 bits. 35 DK_DeclID = 1, 36 /// \brief The data is a pointer to a vector (of type VectorTy) 37 /// that contains declarations. 38 DK_Decl_Vector = 2, 39 /// \brief The data is a pointer to a vector (of type VectorTy) 40 /// that contains declaration ID. 41 DK_ID_Vector = 3 42 }; 43 44 /// VectorTy - When in vector form, this is what the Data pointer points to. 45 typedef llvm::SmallVector<uintptr_t, 4> VectorTy; 46 47 /// \brief The stored data, which will be either a declaration ID, a 48 /// pointer to a NamedDecl, or a pointer to a vector. 49 uintptr_t Data; 50 51public: 52 StoredDeclsList() : Data(0) {} 53 54 StoredDeclsList(const StoredDeclsList &RHS) : Data(RHS.Data) { 55 if (VectorTy *RHSVec = RHS.getAsVector()) { 56 VectorTy *New = new VectorTy(*RHSVec); 57 Data = reinterpret_cast<uintptr_t>(New) | (Data & 0x03); 58 } 59 } 60 61 ~StoredDeclsList() { 62 // If this is a vector-form, free the vector. 63 if (VectorTy *Vector = getAsVector()) 64 delete Vector; 65 } 66 67 StoredDeclsList &operator=(const StoredDeclsList &RHS) { 68 if (VectorTy *Vector = getAsVector()) 69 delete Vector; 70 Data = RHS.Data; 71 if (VectorTy *RHSVec = RHS.getAsVector()) { 72 VectorTy *New = new VectorTy(*RHSVec); 73 Data = reinterpret_cast<uintptr_t>(New) | (Data & 0x03); 74 } 75 return *this; 76 } 77 78 bool isNull() const { return (Data & ~0x03) == 0; } 79 80 NamedDecl *getAsDecl() const { 81 if ((Data & 0x03) != DK_Decl) 82 return 0; 83 84 return reinterpret_cast<NamedDecl *>(Data & ~0x03); 85 } 86 87 VectorTy *getAsVector() const { 88 if ((Data & 0x03) != DK_ID_Vector && (Data & 0x03) != DK_Decl_Vector) 89 return 0; 90 91 return reinterpret_cast<VectorTy *>(Data & ~0x03); 92 } 93 94 void setOnlyValue(NamedDecl *ND) { 95 assert(!getAsVector() && "Not inline"); 96 Data = reinterpret_cast<uintptr_t>(ND); 97 } 98 99 void setFromDeclIDs(const llvm::SmallVectorImpl<unsigned> &Vec) { 100 if (Vec.size() > 1) { 101 VectorTy *Vector = getAsVector(); 102 if (!Vector) { 103 Vector = new VectorTy; 104 Data = reinterpret_cast<uintptr_t>(Vector) | DK_ID_Vector; 105 } 106 107 Vector->resize(Vec.size()); 108 std::copy(Vec.begin(), Vec.end(), Vector->begin()); 109 return; 110 } 111 112 if (VectorTy *Vector = getAsVector()) 113 delete Vector; 114 115 if (Vec.empty()) 116 Data = 0; 117 else 118 Data = (Vec[0] << 2) | DK_DeclID; 119 } 120 121 /// \brief Force the stored declarations list to contain actual 122 /// declarations. 123 /// 124 /// This routine will resolve any declaration IDs for declarations 125 /// that may not yet have been loaded from external storage. 126 void materializeDecls(ASTContext &Context); 127 128 bool hasDeclarationIDs() const { 129 DataKind DK = (DataKind)(Data & 0x03); 130 return DK == DK_DeclID || DK == DK_ID_Vector; 131 } 132 133 /// getLookupResult - Return an array of all the decls that this list 134 /// represents. 135 DeclContext::lookup_result getLookupResult(ASTContext &Context) { 136 if (isNull()) 137 return DeclContext::lookup_result(0, 0); 138 139 if (hasDeclarationIDs()) 140 materializeDecls(Context); 141 142 // If we have a single NamedDecl, return it. 143 if (getAsDecl()) { 144 assert(!isNull() && "Empty list isn't allowed"); 145 146 // Data is a raw pointer to a NamedDecl*, return it. 147 void *Ptr = &Data; 148 return DeclContext::lookup_result((NamedDecl**)Ptr, (NamedDecl**)Ptr+1); 149 } 150 151 assert(getAsVector() && "Must have a vector at this point"); 152 VectorTy &Vector = *getAsVector(); 153 154 // Otherwise, we have a range result. 155 return DeclContext::lookup_result((NamedDecl **)&Vector[0], 156 (NamedDecl **)&Vector[0]+Vector.size()); 157 } 158 159 /// HandleRedeclaration - If this is a redeclaration of an existing decl, 160 /// replace the old one with D and return true. Otherwise return false. 161 bool HandleRedeclaration(ASTContext &Context, NamedDecl *D) { 162 if (hasDeclarationIDs()) 163 materializeDecls(Context); 164 165 // Most decls only have one entry in their list, special case it. 166 if (NamedDecl *OldD = getAsDecl()) { 167 if (!D->declarationReplaces(OldD)) 168 return false; 169 setOnlyValue(D); 170 return true; 171 } 172 173 // Determine if this declaration is actually a redeclaration. 174 VectorTy &Vec = *getAsVector(); 175 for (VectorTy::iterator OD = Vec.begin(), ODEnd = Vec.end(); 176 OD != ODEnd; ++OD) { 177 NamedDecl *OldD = reinterpret_cast<NamedDecl *>(*OD); 178 if (D->declarationReplaces(OldD)) { 179 *OD = reinterpret_cast<uintptr_t>(D); 180 return true; 181 } 182 } 183 184 return false; 185 } 186 187 /// AddSubsequentDecl - This is called on the second and later decl when it is 188 /// not a redeclaration to merge it into the appropriate place in our list. 189 /// 190 void AddSubsequentDecl(NamedDecl *D) { 191 assert(!hasDeclarationIDs() && "Must materialize before adding decls"); 192 193 // If this is the second decl added to the list, convert this to vector 194 // form. 195 if (NamedDecl *OldD = getAsDecl()) { 196 VectorTy *VT = new VectorTy(); 197 VT->push_back(reinterpret_cast<uintptr_t>(OldD)); 198 Data = reinterpret_cast<uintptr_t>(VT) | DK_Decl_Vector; 199 } 200 201 VectorTy &Vec = *getAsVector(); 202 if (isa<UsingDirectiveDecl>(D) || 203 D->getIdentifierNamespace() == Decl::IDNS_Tag) 204 Vec.push_back(reinterpret_cast<uintptr_t>(D)); 205 else if (reinterpret_cast<NamedDecl *>(Vec.back()) 206 ->getIdentifierNamespace() == Decl::IDNS_Tag) { 207 uintptr_t TagD = Vec.back(); 208 Vec.back() = reinterpret_cast<uintptr_t>(D); 209 Vec.push_back(TagD); 210 } else 211 Vec.push_back(reinterpret_cast<uintptr_t>(D)); 212 } 213}; 214 215typedef llvm::DenseMap<DeclarationName, StoredDeclsList> StoredDeclsMap; 216 217 218} // end namespace clang 219 220#endif 221