clang  9.0.0svn
DeclContextInternals.h
Go to the documentation of this file.
1 //===- DeclContextInternals.h - DeclContext Representation ------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines the data structures used in the implementation
10 // of DeclContext.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_CLANG_AST_DECLCONTEXTINTERNALS_H
15 #define LLVM_CLANG_AST_DECLCONTEXTINTERNALS_H
16 
17 #include "clang/AST/Decl.h"
18 #include "clang/AST/DeclBase.h"
19 #include "clang/AST/DeclCXX.h"
21 #include "llvm/ADT/DenseMap.h"
22 #include "llvm/ADT/PointerIntPair.h"
23 #include "llvm/ADT/PointerUnion.h"
24 #include "llvm/ADT/SmallVector.h"
25 #include <algorithm>
26 #include <cassert>
27 
28 namespace clang {
29 
30 class DependentDiagnostic;
31 
32 /// An array of decls optimized for the common case of only containing
33 /// one entry.
35  /// When in vector form, this is what the Data pointer points to.
37 
38  /// A collection of declarations, with a flag to indicate if we have
39  /// further external declarations.
40  using DeclsAndHasExternalTy = llvm::PointerIntPair<DeclsTy *, 1, bool>;
41 
42  /// The stored data, which will be either a pointer to a NamedDecl,
43  /// or a pointer to a vector with a flag to indicate if there are further
44  /// external declarations.
45  llvm::PointerUnion<NamedDecl *, DeclsAndHasExternalTy> Data;
46 
47 public:
48  StoredDeclsList() = default;
49 
50  StoredDeclsList(StoredDeclsList &&RHS) : Data(RHS.Data) {
51  RHS.Data = (NamedDecl *)nullptr;
52  }
53 
55  // If this is a vector-form, free the vector.
56  if (DeclsTy *Vector = getAsVector())
57  delete Vector;
58  }
59 
61  if (DeclsTy *Vector = getAsVector())
62  delete Vector;
63  Data = RHS.Data;
64  RHS.Data = (NamedDecl *)nullptr;
65  return *this;
66  }
67 
68  bool isNull() const { return Data.isNull(); }
69 
70  NamedDecl *getAsDecl() const {
71  return Data.dyn_cast<NamedDecl *>();
72  }
73 
75  return Data.dyn_cast<DeclsAndHasExternalTy>();
76  }
77 
78  DeclsTy *getAsVector() const {
79  return getAsVectorAndHasExternal().getPointer();
80  }
81 
82  bool hasExternalDecls() const {
83  return getAsVectorAndHasExternal().getInt();
84  }
85 
87  if (DeclsTy *Vec = getAsVector())
88  Data = DeclsAndHasExternalTy(Vec, true);
89  else {
90  DeclsTy *VT = new DeclsTy();
91  if (NamedDecl *OldD = getAsDecl())
92  VT->push_back(OldD);
93  Data = DeclsAndHasExternalTy(VT, true);
94  }
95  }
96 
97  void setOnlyValue(NamedDecl *ND) {
98  assert(!getAsVector() && "Not inline");
99  Data = ND;
100  // Make sure that Data is a plain NamedDecl* so we can use its address
101  // at getLookupResult.
102  assert(*(NamedDecl **)&Data == ND &&
103  "PointerUnion mangles the NamedDecl pointer!");
104  }
105 
106  void remove(NamedDecl *D) {
107  assert(!isNull() && "removing from empty list");
108  if (NamedDecl *Singleton = getAsDecl()) {
109  assert(Singleton == D && "list is different singleton");
110  (void)Singleton;
111  Data = (NamedDecl *)nullptr;
112  return;
113  }
114 
115  DeclsTy &Vec = *getAsVector();
116  DeclsTy::iterator I = std::find(Vec.begin(), Vec.end(), D);
117  assert(I != Vec.end() && "list does not contain decl");
118  Vec.erase(I);
119 
120  assert(std::find(Vec.begin(), Vec.end(), D)
121  == Vec.end() && "list still contains decl");
122  }
123 
124  /// Remove any declarations which were imported from an external
125  /// AST source.
127  if (isNull()) {
128  // Nothing to do.
129  } else if (NamedDecl *Singleton = getAsDecl()) {
130  if (Singleton->isFromASTFile())
131  *this = StoredDeclsList();
132  } else {
133  DeclsTy &Vec = *getAsVector();
134  Vec.erase(std::remove_if(Vec.begin(), Vec.end(),
135  [](Decl *D) { return D->isFromASTFile(); }),
136  Vec.end());
137  // Don't have any external decls any more.
138  Data = DeclsAndHasExternalTy(&Vec, false);
139  }
140  }
141 
142  /// getLookupResult - Return an array of all the decls that this list
143  /// represents.
145  if (isNull())
147 
148  // If we have a single NamedDecl, return it.
149  if (NamedDecl *ND = getAsDecl()) {
150  assert(!isNull() && "Empty list isn't allowed");
151 
152  // Data is a raw pointer to a NamedDecl*, return it.
153  return DeclContext::lookup_result(ND);
154  }
155 
156  assert(getAsVector() && "Must have a vector at this point");
157  DeclsTy &Vector = *getAsVector();
158 
159  // Otherwise, we have a range result.
160  return DeclContext::lookup_result(Vector);
161  }
162 
163  /// HandleRedeclaration - If this is a redeclaration of an existing decl,
164  /// replace the old one with D and return true. Otherwise return false.
165  bool HandleRedeclaration(NamedDecl *D, bool IsKnownNewer) {
166  // Most decls only have one entry in their list, special case it.
167  if (NamedDecl *OldD = getAsDecl()) {
168  if (!D->declarationReplaces(OldD, IsKnownNewer))
169  return false;
170  setOnlyValue(D);
171  return true;
172  }
173 
174  // Determine if this declaration is actually a redeclaration.
175  DeclsTy &Vec = *getAsVector();
176  for (DeclsTy::iterator OD = Vec.begin(), ODEnd = Vec.end();
177  OD != ODEnd; ++OD) {
178  NamedDecl *OldD = *OD;
179  if (D->declarationReplaces(OldD, IsKnownNewer)) {
180  *OD = D;
181  return true;
182  }
183  }
184 
185  return false;
186  }
187 
188  /// AddSubsequentDecl - This is called on the second and later decl when it is
189  /// not a redeclaration to merge it into the appropriate place in our list.
191  assert(!isNull() && "don't AddSubsequentDecl when we have no 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  DeclsTy *VT = new DeclsTy();
197  VT->push_back(OldD);
198  Data = DeclsAndHasExternalTy(VT, false);
199  }
200 
201  DeclsTy &Vec = *getAsVector();
202 
203  // Using directives end up in a special entry which contains only
204  // other using directives, so all this logic is wasted for them.
205  // But avoiding the logic wastes time in the far-more-common case
206  // that we're *not* adding a new using directive.
207 
208  // Tag declarations always go at the end of the list so that an
209  // iterator which points at the first tag will start a span of
210  // decls that only contains tags.
211  if (D->hasTagIdentifierNamespace())
212  Vec.push_back(D);
213 
214  // Resolved using declarations go at the front of the list so that
215  // they won't show up in other lookup results. Unresolved using
216  // declarations (which are always in IDNS_Using | IDNS_Ordinary)
217  // follow that so that the using declarations will be contiguous.
218  else if (D->getIdentifierNamespace() & Decl::IDNS_Using) {
219  DeclsTy::iterator I = Vec.begin();
221  while (I != Vec.end() &&
222  (*I)->getIdentifierNamespace() == Decl::IDNS_Using)
223  ++I;
224  }
225  Vec.insert(I, D);
226 
227  // All other declarations go at the end of the list, but before any
228  // tag declarations. But we can be clever about tag declarations
229  // because there can only ever be one in a scope.
230  } else if (!Vec.empty() && Vec.back()->hasTagIdentifierNamespace()) {
231  NamedDecl *TagD = Vec.back();
232  Vec.back() = D;
233  Vec.push_back(TagD);
234  } else
235  Vec.push_back(D);
236  }
237 };
238 
240  : public llvm::SmallDenseMap<DeclarationName, StoredDeclsList, 4> {
241 public:
242  static void DestroyAll(StoredDeclsMap *Map, bool Dependent);
243 
244 private:
245  friend class ASTContext; // walks the chain deleting these
246  friend class DeclContext;
247 
248  llvm::PointerIntPair<StoredDeclsMap*, 1> Previous;
249 };
250 
252 public:
253  DependentStoredDeclsMap() = default;
254 
255 private:
256  friend class DeclContext; // iterates over diagnostics
257  friend class DependentDiagnostic;
258 
259  DependentDiagnostic *FirstDiagnostic = nullptr;
260 };
261 
262 } // namespace clang
263 
264 #endif // LLVM_CLANG_AST_DECLCONTEXTINTERNALS_H
void AddSubsequentDecl(NamedDecl *D)
AddSubsequentDecl - This is called on the second and later decl when it is not a redeclaration to mer...
llvm::PointerUnion< NamedDecl *, DeclsAndHasExternalTy > Data
The stored data, which will be either a pointer to a NamedDecl, or a pointer to a vector with a flag ...
llvm::PointerIntPair< DeclsTy *, 1, bool > DeclsAndHasExternalTy
A collection of declarations, with a flag to indicate if we have further external declarations...
SmallVector< NamedDecl *, 4 > DeclsTy
When in vector form, this is what the Data pointer points to.
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
unsigned getIdentifierNamespace() const
Definition: DeclBase.h:791
bool HandleRedeclaration(NamedDecl *D, bool IsKnownNewer)
HandleRedeclaration - If this is a redeclaration of an existing decl, replace the old one with D and ...
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:154
The results of name lookup within a DeclContext.
Definition: DeclBase.h:1186
bool hasTagIdentifierNamespace() const
Definition: DeclBase.h:801
DeclsAndHasExternalTy getAsVectorAndHasExternal() const
StoredDeclsList & operator=(StoredDeclsList &&RHS)
DeclsTy * getAsVector() const
void removeExternalDecls()
Remove any declarations which were imported from an external AST source.
StateNode * Previous
DeclContext::lookup_result getLookupResult()
getLookupResult - Return an array of all the decls that this list represents.
bool declarationReplaces(NamedDecl *OldD, bool IsKnownNewer=true) const
Determine whether this declaration, if known to be well-formed within its context, will replace the declaration OldD if introduced into scope.
Definition: Decl.cpp:1643
NamedDecl * getAsDecl() const
An array of decls optimized for the common case of only containing one entry.
Dataflow Directional Tag Classes.
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition: DeclBase.h:1261
A dependently-generated diagnostic.
void setOnlyValue(NamedDecl *ND)
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate.h) and friends (in DeclFriend.h).
StoredDeclsList(StoredDeclsList &&RHS)
DeclContextLookupResult lookup_result
Definition: DeclBase.h:2200
This represents a decl that may have a name.
Definition: Decl.h:248
This declaration is a using declaration.
Definition: DeclBase.h:163