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