1193326Sed//===-- DeclContextInternals.h - DeclContext Representation -----*- C++ -*-===// 2193326Sed// 3193326Sed// The LLVM Compiler Infrastructure 4193326Sed// 5193326Sed// This file is distributed under the University of Illinois Open Source 6193326Sed// License. See LICENSE.TXT for details. 7193326Sed// 8193326Sed//===----------------------------------------------------------------------===// 9193326Sed// 10193326Sed// This file defines the data structures used in the implementation 11193326Sed// of DeclContext. 12193326Sed// 13193326Sed//===----------------------------------------------------------------------===// 14193326Sed#ifndef LLVM_CLANG_AST_DECLCONTEXTINTERNALS_H 15193326Sed#define LLVM_CLANG_AST_DECLCONTEXTINTERNALS_H 16193326Sed 17199482Srdivacky#include "clang/AST/Decl.h" 18252723Sdim#include "clang/AST/DeclCXX.h" 19193326Sed#include "clang/AST/DeclarationName.h" 20252723Sdim#include "llvm/ADT/DenseMap.h" 21263509Sdim#include "llvm/ADT/PointerIntPair.h" 22245431Sdim#include "llvm/ADT/PointerUnion.h" 23193326Sed#include "llvm/ADT/SmallVector.h" 24193326Sed#include <algorithm> 25193326Sed 26193326Sednamespace clang { 27193326Sed 28206084Srdivackyclass DependentDiagnostic; 29206084Srdivacky 30263509Sdim/// \brief An array of decls optimized for the common case of only containing 31263509Sdim/// one entry. 32193326Sedstruct StoredDeclsList { 33193326Sed 34263509Sdim /// \brief When in vector form, this is what the Data pointer points to. 35226890Sdim typedef SmallVector<NamedDecl *, 4> DeclsTy; 36193326Sed 37263509Sdim /// \brief A collection of declarations, with a flag to indicate if we have 38263509Sdim /// further external declarations. 39263509Sdim typedef llvm::PointerIntPair<DeclsTy *, 1, bool> DeclsAndHasExternalTy; 40263509Sdim 41212904Sdim /// \brief The stored data, which will be either a pointer to a NamedDecl, 42263509Sdim /// or a pointer to a vector with a flag to indicate if there are further 43263509Sdim /// external declarations. 44263509Sdim llvm::PointerUnion<NamedDecl*, DeclsAndHasExternalTy> Data; 45193326Sed 46193326Sedpublic: 47212904Sdim StoredDeclsList() {} 48193326Sed 49193326Sed StoredDeclsList(const StoredDeclsList &RHS) : Data(RHS.Data) { 50212904Sdim if (DeclsTy *RHSVec = RHS.getAsVector()) 51263509Sdim Data = DeclsAndHasExternalTy(new DeclsTy(*RHSVec), 52263509Sdim RHS.hasExternalDecls()); 53193326Sed } 54198092Srdivacky 55193326Sed ~StoredDeclsList() { 56193326Sed // If this is a vector-form, free the vector. 57212904Sdim if (DeclsTy *Vector = getAsVector()) 58193326Sed delete Vector; 59193326Sed } 60198092Srdivacky 61193326Sed StoredDeclsList &operator=(const StoredDeclsList &RHS) { 62212904Sdim if (DeclsTy *Vector = getAsVector()) 63193326Sed delete Vector; 64193326Sed Data = RHS.Data; 65212904Sdim if (DeclsTy *RHSVec = RHS.getAsVector()) 66263509Sdim Data = DeclsAndHasExternalTy(new DeclsTy(*RHSVec), hasExternalDecls()); 67193326Sed return *this; 68193326Sed } 69198092Srdivacky 70212904Sdim bool isNull() const { return Data.isNull(); } 71198092Srdivacky 72193326Sed NamedDecl *getAsDecl() const { 73212904Sdim return Data.dyn_cast<NamedDecl *>(); 74193326Sed } 75193326Sed 76263509Sdim DeclsAndHasExternalTy getAsVectorAndHasExternal() const { 77263509Sdim return Data.dyn_cast<DeclsAndHasExternalTy>(); 78263509Sdim } 79263509Sdim 80212904Sdim DeclsTy *getAsVector() const { 81263509Sdim return getAsVectorAndHasExternal().getPointer(); 82193326Sed } 83193326Sed 84263509Sdim bool hasExternalDecls() const { 85263509Sdim return getAsVectorAndHasExternal().getInt(); 86263509Sdim } 87263509Sdim 88263509Sdim void setHasExternalDecls() { 89263509Sdim if (DeclsTy *Vec = getAsVector()) 90263509Sdim Data = DeclsAndHasExternalTy(Vec, true); 91263509Sdim else { 92263509Sdim DeclsTy *VT = new DeclsTy(); 93263509Sdim if (NamedDecl *OldD = getAsDecl()) 94263509Sdim VT->push_back(OldD); 95263509Sdim Data = DeclsAndHasExternalTy(VT, true); 96263509Sdim } 97263509Sdim } 98263509Sdim 99193326Sed void setOnlyValue(NamedDecl *ND) { 100193326Sed assert(!getAsVector() && "Not inline"); 101212904Sdim Data = ND; 102212904Sdim // Make sure that Data is a plain NamedDecl* so we can use its address 103212904Sdim // at getLookupResult. 104212904Sdim assert(*(NamedDecl **)&Data == ND && 105212904Sdim "PointerUnion mangles the NamedDecl pointer!"); 106193326Sed } 107193326Sed 108200583Srdivacky void remove(NamedDecl *D) { 109200583Srdivacky assert(!isNull() && "removing from empty list"); 110200583Srdivacky if (NamedDecl *Singleton = getAsDecl()) { 111200583Srdivacky assert(Singleton == D && "list is different singleton"); 112200583Srdivacky (void)Singleton; 113212904Sdim Data = (NamedDecl *)0; 114200583Srdivacky return; 115200583Srdivacky } 116200583Srdivacky 117212904Sdim DeclsTy &Vec = *getAsVector(); 118212904Sdim DeclsTy::iterator I = std::find(Vec.begin(), Vec.end(), D); 119200583Srdivacky assert(I != Vec.end() && "list does not contain decl"); 120200583Srdivacky Vec.erase(I); 121200583Srdivacky 122212904Sdim assert(std::find(Vec.begin(), Vec.end(), D) 123200583Srdivacky == Vec.end() && "list still contains decl"); 124200583Srdivacky } 125200583Srdivacky 126252723Sdim /// \brief Remove any declarations which were imported from an external 127252723Sdim /// AST source. 128252723Sdim void removeExternalDecls() { 129252723Sdim if (isNull()) { 130252723Sdim // Nothing to do. 131252723Sdim } else if (NamedDecl *Singleton = getAsDecl()) { 132252723Sdim if (Singleton->isFromASTFile()) 133252723Sdim *this = StoredDeclsList(); 134252723Sdim } else { 135252723Sdim DeclsTy &Vec = *getAsVector(); 136252723Sdim Vec.erase(std::remove_if(Vec.begin(), Vec.end(), 137252723Sdim std::mem_fun(&Decl::isFromASTFile)), 138252723Sdim Vec.end()); 139263509Sdim // Don't have any external decls any more. 140263509Sdim Data = DeclsAndHasExternalTy(&Vec, false); 141252723Sdim } 142252723Sdim } 143252723Sdim 144193326Sed /// getLookupResult - Return an array of all the decls that this list 145193326Sed /// represents. 146212904Sdim DeclContext::lookup_result getLookupResult() { 147193326Sed if (isNull()) 148208600Srdivacky return DeclContext::lookup_result(DeclContext::lookup_iterator(0), 149208600Srdivacky DeclContext::lookup_iterator(0)); 150198092Srdivacky 151193326Sed // If we have a single NamedDecl, return it. 152193326Sed if (getAsDecl()) { 153193326Sed assert(!isNull() && "Empty list isn't allowed"); 154198092Srdivacky 155193326Sed // Data is a raw pointer to a NamedDecl*, return it. 156193326Sed void *Ptr = &Data; 157193326Sed return DeclContext::lookup_result((NamedDecl**)Ptr, (NamedDecl**)Ptr+1); 158193326Sed } 159198092Srdivacky 160193326Sed assert(getAsVector() && "Must have a vector at this point"); 161212904Sdim DeclsTy &Vector = *getAsVector(); 162198092Srdivacky 163193326Sed // Otherwise, we have a range result. 164252723Sdim return DeclContext::lookup_result(Vector.begin(), Vector.end()); 165193326Sed } 166198092Srdivacky 167193326Sed /// HandleRedeclaration - If this is a redeclaration of an existing decl, 168193326Sed /// replace the old one with D and return true. Otherwise return false. 169212904Sdim bool HandleRedeclaration(NamedDecl *D) { 170193326Sed // Most decls only have one entry in their list, special case it. 171193326Sed if (NamedDecl *OldD = getAsDecl()) { 172193326Sed if (!D->declarationReplaces(OldD)) 173193326Sed return false; 174193326Sed setOnlyValue(D); 175193326Sed return true; 176193326Sed } 177198092Srdivacky 178193326Sed // Determine if this declaration is actually a redeclaration. 179212904Sdim DeclsTy &Vec = *getAsVector(); 180212904Sdim for (DeclsTy::iterator OD = Vec.begin(), ODEnd = Vec.end(); 181193326Sed OD != ODEnd; ++OD) { 182212904Sdim NamedDecl *OldD = *OD; 183193326Sed if (D->declarationReplaces(OldD)) { 184212904Sdim *OD = D; 185193326Sed return true; 186193326Sed } 187193326Sed } 188193326Sed 189193326Sed return false; 190193326Sed } 191198092Srdivacky 192193326Sed /// AddSubsequentDecl - This is called on the second and later decl when it is 193193326Sed /// not a redeclaration to merge it into the appropriate place in our list. 194198092Srdivacky /// 195193326Sed void AddSubsequentDecl(NamedDecl *D) { 196263509Sdim assert(!isNull() && "don't AddSubsequentDecl when we have no decls"); 197263509Sdim 198193326Sed // If this is the second decl added to the list, convert this to vector 199193326Sed // form. 200193326Sed if (NamedDecl *OldD = getAsDecl()) { 201212904Sdim DeclsTy *VT = new DeclsTy(); 202212904Sdim VT->push_back(OldD); 203263509Sdim Data = DeclsAndHasExternalTy(VT, false); 204193326Sed } 205198092Srdivacky 206212904Sdim DeclsTy &Vec = *getAsVector(); 207200583Srdivacky 208200583Srdivacky // Using directives end up in a special entry which contains only 209200583Srdivacky // other using directives, so all this logic is wasted for them. 210200583Srdivacky // But avoiding the logic wastes time in the far-more-common case 211200583Srdivacky // that we're *not* adding a new using directive. 212200583Srdivacky 213200583Srdivacky // Tag declarations always go at the end of the list so that an 214200583Srdivacky // iterator which points at the first tag will start a span of 215200583Srdivacky // decls that only contains tags. 216207619Srdivacky if (D->hasTagIdentifierNamespace()) 217212904Sdim Vec.push_back(D); 218200583Srdivacky 219200583Srdivacky // Resolved using declarations go at the front of the list so that 220200583Srdivacky // they won't show up in other lookup results. Unresolved using 221200583Srdivacky // declarations (which are always in IDNS_Using | IDNS_Ordinary) 222200583Srdivacky // follow that so that the using declarations will be contiguous. 223200583Srdivacky else if (D->getIdentifierNamespace() & Decl::IDNS_Using) { 224212904Sdim DeclsTy::iterator I = Vec.begin(); 225200583Srdivacky if (D->getIdentifierNamespace() != Decl::IDNS_Using) { 226200583Srdivacky while (I != Vec.end() && 227212904Sdim (*I)->getIdentifierNamespace() == Decl::IDNS_Using) 228200583Srdivacky ++I; 229200583Srdivacky } 230212904Sdim Vec.insert(I, D); 231200583Srdivacky 232200583Srdivacky // All other declarations go at the end of the list, but before any 233200583Srdivacky // tag declarations. But we can be clever about tag declarations 234200583Srdivacky // because there can only ever be one in a scope. 235252723Sdim } else if (!Vec.empty() && Vec.back()->hasTagIdentifierNamespace()) { 236212904Sdim NamedDecl *TagD = Vec.back(); 237212904Sdim Vec.back() = D; 238193326Sed Vec.push_back(TagD); 239193326Sed } else 240212904Sdim Vec.push_back(D); 241193326Sed } 242193326Sed}; 243193326Sed 244206084Srdivackyclass StoredDeclsMap 245245431Sdim : public llvm::SmallDenseMap<DeclarationName, StoredDeclsList, 4> { 246193326Sed 247206084Srdivackypublic: 248206084Srdivacky static void DestroyAll(StoredDeclsMap *Map, bool Dependent); 249193326Sed 250206084Srdivackyprivate: 251206084Srdivacky friend class ASTContext; // walks the chain deleting these 252206084Srdivacky friend class DeclContext; 253206084Srdivacky llvm::PointerIntPair<StoredDeclsMap*, 1> Previous; 254206084Srdivacky}; 255206084Srdivacky 256206084Srdivackyclass DependentStoredDeclsMap : public StoredDeclsMap { 257206084Srdivackypublic: 258206084Srdivacky DependentStoredDeclsMap() : FirstDiagnostic(0) {} 259206084Srdivacky 260206084Srdivackyprivate: 261206084Srdivacky friend class DependentDiagnostic; 262206084Srdivacky friend class DeclContext; // iterates over diagnostics 263206084Srdivacky 264206084Srdivacky DependentDiagnostic *FirstDiagnostic; 265206084Srdivacky}; 266206084Srdivacky 267193326Sed} // end namespace clang 268193326Sed 269198092Srdivacky#endif 270