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