DeclContextInternals.h revision 252723
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" 21245431Sdim#include "llvm/ADT/PointerUnion.h" 22193326Sed#include "llvm/ADT/SmallVector.h" 23193326Sed#include <algorithm> 24193326Sed 25193326Sednamespace clang { 26193326Sed 27206084Srdivackyclass DependentDiagnostic; 28206084Srdivacky 29193326Sed/// StoredDeclsList - This is an array of decls optimized a common case of only 30193326Sed/// containing one entry. 31193326Sedstruct StoredDeclsList { 32193326Sed 33212904Sdim /// DeclsTy - When in vector form, this is what the Data pointer points to. 34226890Sdim typedef SmallVector<NamedDecl *, 4> DeclsTy; 35193326Sed 36212904Sdim /// \brief The stored data, which will be either a pointer to a NamedDecl, 37212904Sdim /// or a pointer to a vector. 38212904Sdim llvm::PointerUnion<NamedDecl *, DeclsTy *> Data; 39193326Sed 40193326Sedpublic: 41212904Sdim StoredDeclsList() {} 42193326Sed 43193326Sed StoredDeclsList(const StoredDeclsList &RHS) : Data(RHS.Data) { 44212904Sdim if (DeclsTy *RHSVec = RHS.getAsVector()) 45212904Sdim Data = new DeclsTy(*RHSVec); 46193326Sed } 47198092Srdivacky 48193326Sed ~StoredDeclsList() { 49193326Sed // If this is a vector-form, free the vector. 50212904Sdim if (DeclsTy *Vector = getAsVector()) 51193326Sed delete Vector; 52193326Sed } 53198092Srdivacky 54193326Sed StoredDeclsList &operator=(const StoredDeclsList &RHS) { 55212904Sdim if (DeclsTy *Vector = getAsVector()) 56193326Sed delete Vector; 57193326Sed Data = RHS.Data; 58212904Sdim if (DeclsTy *RHSVec = RHS.getAsVector()) 59212904Sdim Data = new DeclsTy(*RHSVec); 60193326Sed return *this; 61193326Sed } 62198092Srdivacky 63212904Sdim bool isNull() const { return Data.isNull(); } 64198092Srdivacky 65193326Sed NamedDecl *getAsDecl() const { 66212904Sdim return Data.dyn_cast<NamedDecl *>(); 67193326Sed } 68193326Sed 69212904Sdim DeclsTy *getAsVector() const { 70212904Sdim return Data.dyn_cast<DeclsTy *>(); 71193326Sed } 72193326Sed 73193326Sed void setOnlyValue(NamedDecl *ND) { 74193326Sed assert(!getAsVector() && "Not inline"); 75212904Sdim Data = ND; 76212904Sdim // Make sure that Data is a plain NamedDecl* so we can use its address 77212904Sdim // at getLookupResult. 78212904Sdim assert(*(NamedDecl **)&Data == ND && 79212904Sdim "PointerUnion mangles the NamedDecl pointer!"); 80193326Sed } 81193326Sed 82200583Srdivacky void remove(NamedDecl *D) { 83200583Srdivacky assert(!isNull() && "removing from empty list"); 84200583Srdivacky if (NamedDecl *Singleton = getAsDecl()) { 85200583Srdivacky assert(Singleton == D && "list is different singleton"); 86200583Srdivacky (void)Singleton; 87212904Sdim Data = (NamedDecl *)0; 88200583Srdivacky return; 89200583Srdivacky } 90200583Srdivacky 91212904Sdim DeclsTy &Vec = *getAsVector(); 92212904Sdim DeclsTy::iterator I = std::find(Vec.begin(), Vec.end(), D); 93200583Srdivacky assert(I != Vec.end() && "list does not contain decl"); 94200583Srdivacky Vec.erase(I); 95200583Srdivacky 96212904Sdim assert(std::find(Vec.begin(), Vec.end(), D) 97200583Srdivacky == Vec.end() && "list still contains decl"); 98200583Srdivacky } 99200583Srdivacky 100252723Sdim /// \brief Remove any declarations which were imported from an external 101252723Sdim /// AST source. 102252723Sdim void removeExternalDecls() { 103252723Sdim if (isNull()) { 104252723Sdim // Nothing to do. 105252723Sdim } else if (NamedDecl *Singleton = getAsDecl()) { 106252723Sdim if (Singleton->isFromASTFile()) 107252723Sdim *this = StoredDeclsList(); 108252723Sdim } else { 109252723Sdim DeclsTy &Vec = *getAsVector(); 110252723Sdim Vec.erase(std::remove_if(Vec.begin(), Vec.end(), 111252723Sdim std::mem_fun(&Decl::isFromASTFile)), 112252723Sdim Vec.end()); 113252723Sdim } 114252723Sdim } 115252723Sdim 116193326Sed /// getLookupResult - Return an array of all the decls that this list 117193326Sed /// represents. 118212904Sdim DeclContext::lookup_result getLookupResult() { 119193326Sed if (isNull()) 120208600Srdivacky return DeclContext::lookup_result(DeclContext::lookup_iterator(0), 121208600Srdivacky DeclContext::lookup_iterator(0)); 122198092Srdivacky 123193326Sed // If we have a single NamedDecl, return it. 124193326Sed if (getAsDecl()) { 125193326Sed assert(!isNull() && "Empty list isn't allowed"); 126198092Srdivacky 127193326Sed // Data is a raw pointer to a NamedDecl*, return it. 128193326Sed void *Ptr = &Data; 129193326Sed return DeclContext::lookup_result((NamedDecl**)Ptr, (NamedDecl**)Ptr+1); 130193326Sed } 131198092Srdivacky 132193326Sed assert(getAsVector() && "Must have a vector at this point"); 133212904Sdim DeclsTy &Vector = *getAsVector(); 134198092Srdivacky 135193326Sed // Otherwise, we have a range result. 136252723Sdim return DeclContext::lookup_result(Vector.begin(), Vector.end()); 137193326Sed } 138198092Srdivacky 139193326Sed /// HandleRedeclaration - If this is a redeclaration of an existing decl, 140193326Sed /// replace the old one with D and return true. Otherwise return false. 141212904Sdim bool HandleRedeclaration(NamedDecl *D) { 142193326Sed // Most decls only have one entry in their list, special case it. 143193326Sed if (NamedDecl *OldD = getAsDecl()) { 144193326Sed if (!D->declarationReplaces(OldD)) 145193326Sed return false; 146193326Sed setOnlyValue(D); 147193326Sed return true; 148193326Sed } 149198092Srdivacky 150193326Sed // Determine if this declaration is actually a redeclaration. 151212904Sdim DeclsTy &Vec = *getAsVector(); 152212904Sdim for (DeclsTy::iterator OD = Vec.begin(), ODEnd = Vec.end(); 153193326Sed OD != ODEnd; ++OD) { 154212904Sdim NamedDecl *OldD = *OD; 155193326Sed if (D->declarationReplaces(OldD)) { 156212904Sdim *OD = D; 157193326Sed return true; 158193326Sed } 159193326Sed } 160193326Sed 161193326Sed return false; 162193326Sed } 163198092Srdivacky 164193326Sed /// AddSubsequentDecl - This is called on the second and later decl when it is 165193326Sed /// not a redeclaration to merge it into the appropriate place in our list. 166198092Srdivacky /// 167193326Sed void AddSubsequentDecl(NamedDecl *D) { 168193326Sed // If this is the second decl added to the list, convert this to vector 169193326Sed // form. 170193326Sed if (NamedDecl *OldD = getAsDecl()) { 171212904Sdim DeclsTy *VT = new DeclsTy(); 172212904Sdim VT->push_back(OldD); 173212904Sdim Data = VT; 174193326Sed } 175198092Srdivacky 176212904Sdim DeclsTy &Vec = *getAsVector(); 177200583Srdivacky 178200583Srdivacky // Using directives end up in a special entry which contains only 179200583Srdivacky // other using directives, so all this logic is wasted for them. 180200583Srdivacky // But avoiding the logic wastes time in the far-more-common case 181200583Srdivacky // that we're *not* adding a new using directive. 182200583Srdivacky 183200583Srdivacky // Tag declarations always go at the end of the list so that an 184200583Srdivacky // iterator which points at the first tag will start a span of 185200583Srdivacky // decls that only contains tags. 186207619Srdivacky if (D->hasTagIdentifierNamespace()) 187212904Sdim Vec.push_back(D); 188200583Srdivacky 189200583Srdivacky // Resolved using declarations go at the front of the list so that 190200583Srdivacky // they won't show up in other lookup results. Unresolved using 191200583Srdivacky // declarations (which are always in IDNS_Using | IDNS_Ordinary) 192200583Srdivacky // follow that so that the using declarations will be contiguous. 193200583Srdivacky else if (D->getIdentifierNamespace() & Decl::IDNS_Using) { 194212904Sdim DeclsTy::iterator I = Vec.begin(); 195200583Srdivacky if (D->getIdentifierNamespace() != Decl::IDNS_Using) { 196200583Srdivacky while (I != Vec.end() && 197212904Sdim (*I)->getIdentifierNamespace() == Decl::IDNS_Using) 198200583Srdivacky ++I; 199200583Srdivacky } 200212904Sdim Vec.insert(I, D); 201200583Srdivacky 202200583Srdivacky // All other declarations go at the end of the list, but before any 203200583Srdivacky // tag declarations. But we can be clever about tag declarations 204200583Srdivacky // because there can only ever be one in a scope. 205252723Sdim } else if (!Vec.empty() && Vec.back()->hasTagIdentifierNamespace()) { 206212904Sdim NamedDecl *TagD = Vec.back(); 207212904Sdim Vec.back() = D; 208193326Sed Vec.push_back(TagD); 209193326Sed } else 210212904Sdim Vec.push_back(D); 211193326Sed } 212193326Sed}; 213193326Sed 214206084Srdivackyclass StoredDeclsMap 215245431Sdim : public llvm::SmallDenseMap<DeclarationName, StoredDeclsList, 4> { 216193326Sed 217206084Srdivackypublic: 218206084Srdivacky static void DestroyAll(StoredDeclsMap *Map, bool Dependent); 219193326Sed 220206084Srdivackyprivate: 221206084Srdivacky friend class ASTContext; // walks the chain deleting these 222206084Srdivacky friend class DeclContext; 223206084Srdivacky llvm::PointerIntPair<StoredDeclsMap*, 1> Previous; 224206084Srdivacky}; 225206084Srdivacky 226206084Srdivackyclass DependentStoredDeclsMap : public StoredDeclsMap { 227206084Srdivackypublic: 228206084Srdivacky DependentStoredDeclsMap() : FirstDiagnostic(0) {} 229206084Srdivacky 230206084Srdivackyprivate: 231206084Srdivacky friend class DependentDiagnostic; 232206084Srdivacky friend class DeclContext; // iterates over diagnostics 233206084Srdivacky 234206084Srdivacky DependentDiagnostic *FirstDiagnostic; 235206084Srdivacky}; 236206084Srdivacky 237193326Sed} // end namespace clang 238193326Sed 239198092Srdivacky#endif 240