clang 24.0.0git
IdentifierResolver.cpp
Go to the documentation of this file.
1//===- IdentifierResolver.cpp - Lexical Scope Name lookup -----------------===//
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 implements the IdentifierResolver class, which is used for lexical
10// scoped lookup, based on declaration names.
11//
12//===----------------------------------------------------------------------===//
13
15#include "clang/AST/Decl.h"
16#include "clang/AST/DeclBase.h"
22#include "clang/Sema/Scope.h"
23#include "llvm/Support/ErrorHandling.h"
24#include <cassert>
25#include <cstdint>
26
27using namespace clang;
28
29//===----------------------------------------------------------------------===//
30// IdDeclInfoMap class
31//===----------------------------------------------------------------------===//
32
33/// IdDeclInfoMap - Associates IdDeclInfos with declaration names.
34/// Allocates 'pools' (vectors of IdDeclInfos) to avoid allocating each
35/// individual IdDeclInfo to heap.
37 static const unsigned int POOL_SIZE = 512;
38
39 /// We use our own linked-list implementation because it is sadly
40 /// impossible to add something to a pre-C++0x STL container without
41 /// a completely unnecessary copy.
42 struct IdDeclInfoPool {
43 IdDeclInfoPool *Next;
44 IdDeclInfo Pool[POOL_SIZE];
45
46 IdDeclInfoPool(IdDeclInfoPool *Next) : Next(Next) {}
47 };
48
49 IdDeclInfoPool *CurPool = nullptr;
50 unsigned int CurIndex = POOL_SIZE;
51
52public:
53 IdDeclInfoMap() = default;
54
56 IdDeclInfoPool *Cur = CurPool;
57 while (IdDeclInfoPool *P = Cur) {
58 Cur = Cur->Next;
59 delete P;
60 }
61 }
62
63 IdDeclInfoMap(const IdDeclInfoMap &) = delete;
65
66 /// Returns the IdDeclInfo associated to the DeclarationName.
67 /// It creates a new IdDeclInfo if one was not created before for this id.
68 IdDeclInfo &operator[](DeclarationName Name);
69};
70
71//===----------------------------------------------------------------------===//
72// IdDeclInfo Implementation
73//===----------------------------------------------------------------------===//
74
75/// RemoveDecl - Remove the decl from the scope chain.
76/// The decl must already be part of the decl chain.
77void IdentifierResolver::IdDeclInfo::RemoveDecl(NamedDecl *D) {
78 for (DeclsTy::iterator I = Decls.end(); I != Decls.begin(); --I) {
79 if (D == *(I-1)) {
80 Decls.erase(I-1);
81 return;
82 }
83 }
84
85 llvm_unreachable("Didn't find this decl on its identifier's chain!");
86}
87
88//===----------------------------------------------------------------------===//
89// IdentifierResolver Implementation
90//===----------------------------------------------------------------------===//
91
93 : LangOpt(PP.getLangOpts()), PP(PP), IdDeclInfos(new IdDeclInfoMap) {}
94
96 delete IdDeclInfos;
97}
98
99/// isDeclInScope - If 'Ctx' is a function/method, isDeclInScope returns true
100/// if 'D' is in Scope 'S', otherwise 'S' is ignored and isDeclInScope returns
101/// true if 'D' belongs to the given declaration context.
102///
103/// If 'Ctx' is an expansion statement, we use its enclosing function instead.
105 bool AllowInlineNamespace) const {
106 Ctx = Ctx->getRedeclContext();
107 // The names for HLSL cbuffer/tbuffers only used by the CPU-side
108 // reflection API which supports querying bindings. It will not have name
109 // conflict with other Decls.
110 if (LangOpt.HLSL && isa<HLSLBufferDecl>(D))
111 return false;
114 ->isFunctionOrMethod() ||
115 (S && S->isFunctionPrototypeScope())) {
116 // Ignore the scopes associated within transparent declaration contexts.
117 while (S->getEntity() &&
119 (!LangOpt.CPlusPlus && isa<RecordDecl>(S->getEntity()))))
120 S = S->getParent();
121
122 if (S->isDeclScope(D))
123 return true;
124 if (LangOpt.CPlusPlus) {
125 // C++ 3.3.2p3:
126 // The name declared in a catch exception-declaration is local to the
127 // handler and shall not be redeclared in the outermost block of the
128 // handler.
129 // C++ 3.3.2p4:
130 // Names declared in the for-init-statement, and in the condition of if,
131 // while, for, and switch statements are local to the if, while, for, or
132 // switch statement (including the controlled statement), and shall not be
133 // redeclared in a subsequent condition of that statement nor in the
134 // outermost block (or, for the if statement, any of the outermost blocks)
135 // of the controlled statement.
136 //
137 assert(S->getParent() && "No TUScope?");
138 // If the current decl is in a lambda, we shouldn't consider this is a
139 // redefinition as lambda has its own scope.
140 if (S->getParent()->isControlScope() && !S->isFunctionScope()) {
141 S = S->getParent();
142 if (S->isDeclScope(D))
143 return true;
144 }
145 if (S->isFnTryCatchScope())
146 return S->getParent()->isDeclScope(D);
147 }
148 return false;
149 }
150
151 // FIXME: If D is a local extern declaration, this check doesn't make sense;
152 // we should be checking its lexical context instead in that case, because
153 // that is its scope.
155 return AllowInlineNamespace ? Ctx->InEnclosingNamespaceSetOf(DCtx)
156 : Ctx->Equals(DCtx);
157}
158
159/// AddDecl - Link the decl to its shadowed decl chain.
161 DeclarationName Name = D->getDeclName();
162 if (IdentifierInfo *II = Name.getAsIdentifierInfo())
163 updatingIdentifier(*II);
164
165 void *Ptr = Name.getFETokenInfo();
166
167 if (!Ptr) {
168 Name.setFETokenInfo(D);
169 return;
170 }
171
172 IdDeclInfo *IDI;
173
174 if (isDeclPtr(Ptr)) {
175 Name.setFETokenInfo(nullptr);
176 IDI = &(*IdDeclInfos)[Name];
177 NamedDecl *PrevD = static_cast<NamedDecl*>(Ptr);
178 IDI->AddDecl(PrevD);
179 } else
180 IDI = toIdDeclInfo(Ptr);
181
182 IDI->AddDecl(D);
183}
184
186 DeclarationName Name = D->getDeclName();
187 if (IdentifierInfo *II = Name.getAsIdentifierInfo())
188 updatingIdentifier(*II);
189
190 void *Ptr = Name.getFETokenInfo();
191
192 if (!Ptr) {
193 AddDecl(D);
194 return;
195 }
196
197 if (isDeclPtr(Ptr)) {
198 // We only have a single declaration: insert before or after it,
199 // as appropriate.
200 if (Pos == iterator()) {
201 // Add the new declaration before the existing declaration.
202 NamedDecl *PrevD = static_cast<NamedDecl*>(Ptr);
203 RemoveDecl(PrevD);
204 AddDecl(D);
205 AddDecl(PrevD);
206 } else {
207 // Add new declaration after the existing declaration.
208 AddDecl(D);
209 }
210
211 return;
212 }
213
214 // General case: insert the declaration at the appropriate point in the
215 // list, which already has at least two elements.
216 IdDeclInfo *IDI = toIdDeclInfo(Ptr);
217 if (Pos.isIterator()) {
218 IDI->InsertDecl(Pos.getIterator() + 1, D);
219 } else
220 IDI->InsertDecl(IDI->decls_begin(), D);
221}
222
223/// RemoveDecl - Unlink the decl from its shadowed decl chain.
224/// The decl must already be part of the decl chain.
226 assert(D && "null param passed");
227 DeclarationName Name = D->getDeclName();
228 if (IdentifierInfo *II = Name.getAsIdentifierInfo())
229 updatingIdentifier(*II);
230
231 void *Ptr = Name.getFETokenInfo();
232
233 assert(Ptr && "Didn't find this decl on its identifier's chain!");
234
235 if (isDeclPtr(Ptr)) {
236 assert(D == Ptr && "Didn't find this decl on its identifier's chain!");
237 Name.setFETokenInfo(nullptr);
238 return;
239 }
240
241 return toIdDeclInfo(Ptr)->RemoveDecl(D);
242}
243
244llvm::iterator_range<IdentifierResolver::iterator>
246 return {begin(Name), end()};
247}
248
250 if (IdentifierInfo *II = Name.getAsIdentifierInfo())
251 readingIdentifier(*II);
252
253 void *Ptr = Name.getFETokenInfo();
254 if (!Ptr) return end();
255
256 if (isDeclPtr(Ptr))
257 return iterator(static_cast<NamedDecl*>(Ptr));
258
259 IdDeclInfo *IDI = toIdDeclInfo(Ptr);
260
261 IdDeclInfo::DeclsTy::iterator I = IDI->decls_end();
262 if (I != IDI->decls_begin())
263 return iterator(I-1);
264 // No decls found.
265 return end();
266}
267
268namespace {
269
270enum DeclMatchKind {
271 DMK_Different,
272 DMK_Replace,
273 DMK_Ignore
274};
275
276} // namespace
277
278/// Compare two declarations to see whether they are different or,
279/// if they are the same, whether the new declaration should replace the
280/// existing declaration.
281static DeclMatchKind compareDeclarations(NamedDecl *Existing, NamedDecl *New) {
282 // If the declarations are identical, ignore the new one.
283 if (Existing == New)
284 return DMK_Ignore;
285
286 // If the declarations have different kinds, they're obviously different.
287 if (Existing->getKind() != New->getKind())
288 return DMK_Different;
289
290 // If the declarations are redeclarations of each other, keep the newest one.
291 if (Existing->getCanonicalDecl() == New->getCanonicalDecl()) {
292 // If we're adding an imported declaration, don't replace another imported
293 // declaration.
294 if (Existing->isFromASTFile() && New->isFromASTFile())
295 return DMK_Different;
296
297 // If either of these is the most recent declaration, use it.
298 Decl *MostRecent = Existing->getMostRecentDecl();
299 if (Existing == MostRecent)
300 return DMK_Ignore;
301
302 if (New == MostRecent)
303 return DMK_Replace;
304
305 // If the existing declaration is somewhere in the previous declaration
306 // chain of the new declaration, then prefer the new declaration.
307 for (auto *RD : New->redecls()) {
308 if (RD == Existing)
309 return DMK_Replace;
310
311 if (RD->isCanonicalDecl())
312 break;
313 }
314
315 return DMK_Ignore;
316 }
317
318 return DMK_Different;
319}
320
322 if (IdentifierInfo *II = Name.getAsIdentifierInfo())
323 readingIdentifier(*II);
324
325 void *Ptr = Name.getFETokenInfo();
326
327 if (!Ptr) {
328 Name.setFETokenInfo(D);
329 return true;
330 }
331
332 IdDeclInfo *IDI;
333
334 if (isDeclPtr(Ptr)) {
335 NamedDecl *PrevD = static_cast<NamedDecl*>(Ptr);
336
337 switch (compareDeclarations(PrevD, D)) {
338 case DMK_Different:
339 break;
340
341 case DMK_Ignore:
342 return false;
343
344 case DMK_Replace:
345 Name.setFETokenInfo(D);
346 return true;
347 }
348
349 Name.setFETokenInfo(nullptr);
350 IDI = &(*IdDeclInfos)[Name];
351
352 // If the existing declaration is not visible in translation unit scope,
353 // then add the new top-level declaration first.
355 IDI->AddDecl(D);
356 IDI->AddDecl(PrevD);
357 } else {
358 IDI->AddDecl(PrevD);
359 IDI->AddDecl(D);
360 }
361 return true;
362 }
363
364 IDI = toIdDeclInfo(Ptr);
365
366 // See whether this declaration is identical to any existing declarations.
367 // If not, find the right place to insert it.
368 for (IdDeclInfo::DeclsTy::iterator I = IDI->decls_begin(),
369 IEnd = IDI->decls_end();
370 I != IEnd; ++I) {
371
372 switch (compareDeclarations(*I, D)) {
373 case DMK_Different:
374 break;
375
376 case DMK_Ignore:
377 return false;
378
379 case DMK_Replace:
380 *I = D;
381 return true;
382 }
383
384 if (!(*I)->getDeclContext()->getRedeclContext()->isTranslationUnit()) {
385 // We've found a declaration that is not visible from the translation
386 // unit (it's in an inner scope). Insert our declaration here.
387 IDI->InsertDecl(I, D);
388 return true;
389 }
390 }
391
392 // Add the declaration to the end.
393 IDI->AddDecl(D);
394 return true;
395}
396
397void IdentifierResolver::readingIdentifier(IdentifierInfo &II) {
398 if (II.isOutOfDate())
400}
401
402void IdentifierResolver::updatingIdentifier(IdentifierInfo &II) {
403 if (II.isOutOfDate())
405
406 if (II.isFromAST())
408}
409
410//===----------------------------------------------------------------------===//
411// IdDeclInfoMap Implementation
412//===----------------------------------------------------------------------===//
413
414/// Returns the IdDeclInfo associated to the DeclarationName.
415/// It creates a new IdDeclInfo if one was not created before for this id.
416IdentifierResolver::IdDeclInfo &
418 void *Ptr = Name.getFETokenInfo();
419
420 if (Ptr) return *toIdDeclInfo(Ptr);
421
422 if (CurIndex == POOL_SIZE) {
423 CurPool = new IdDeclInfoPool(CurPool);
424 CurIndex = 0;
425 }
426 IdDeclInfo *IDI = &CurPool->Pool[CurIndex];
427 Name.setFETokenInfo(reinterpret_cast<void*>(
428 reinterpret_cast<uintptr_t>(IDI) | 0x1)
429 );
430 ++CurIndex;
431 return *IDI;
432}
433
435 NamedDecl *D = **this;
436 void *InfoPtr = D->getDeclName().getFETokenInfo();
437 assert(!isDeclPtr(InfoPtr) && "Decl with wrong id ?");
438 IdDeclInfo *Info = toIdDeclInfo(InfoPtr);
439
440 BaseIter I = getIterator();
441 if (I != Info->decls_begin())
442 *this = iterator(I-1);
443 else // No more decls.
444 *this = iterator();
445}
FormatToken * Next
The next token in the unwrapped line.
static DeclMatchKind compareDeclarations(NamedDecl *Existing, NamedDecl *New)
Compare two declarations to see whether they are different or, if they are the same,...
Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.
Defines the clang::LangOptions interface.
Defines the clang::Preprocessor interface.
IdDeclInfoMap - Associates IdDeclInfos with declaration names.
IdDeclInfoMap(const IdDeclInfoMap &)=delete
IdDeclInfoMap & operator=(const IdDeclInfoMap &)=delete
IdDeclInfo & operator[](DeclarationName Name)
Returns the IdDeclInfo associated to the DeclarationName.
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition DeclBase.h:1466
bool Equals(const DeclContext *DC) const
Determine whether this declaration context is equivalent to the declaration context DC.
Definition DeclBase.h:2259
bool isTransparentContext() const
isTransparentContext - Determines whether this context is a "transparent" context,...
bool InEnclosingNamespaceSetOf(const DeclContext *NS) const
Test if this context is part of the enclosing namespace set of the context NS, as defined in C++0x [n...
bool isTranslationUnit() const
Definition DeclBase.h:2202
DeclContext * getRedeclContext()
getRedeclContext - Retrieve the context in which an entity conflicts with other entities of the same ...
bool isFunctionOrMethod() const
Definition DeclBase.h:2178
DeclContext * getEnclosingNonExpansionStatementContext()
Retrieve the innermost enclosing context that doesn't belong to an expansion statement.
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
bool isFromASTFile() const
Determine whether this declaration came from an AST file (such as a precompiled header or module) rat...
Definition DeclBase.h:805
DeclContext * getDeclContext()
Definition DeclBase.h:456
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
Definition DeclBase.h:995
Kind getKind() const
Definition DeclBase.h:450
The name of a declaration.
IdentifierInfo * getAsIdentifierInfo() const
Retrieve the IdentifierInfo * stored in this declaration name, or null if this declaration name isn't...
void * getFETokenInfo() const
Get and set FETokenInfo.
virtual void updateOutOfDateIdentifier(const IdentifierInfo &II)=0
Update an out-of-date identifier.
One of these records is kept for each identifier that is lexed.
bool isFromAST() const
Return true if the identifier in its current state was loaded from an AST file.
void setFETokenInfoChangedSinceDeserialization()
Note that the frontend token information for this identifier has changed since it was loaded from an ...
bool isOutOfDate() const
Determine whether the information for this identifier is out of date with respect to the external sou...
iterator - Iterate over the decls of a specified declaration name.
IdDeclInfo::DeclsTy::iterator BaseIter
iterator(NamedDecl *D)
A single NamedDecl. (Ptr & 0x1 == 0)
iterator begin(DeclarationName Name)
Returns an iterator over decls with the name 'Name'.
void RemoveDecl(NamedDecl *D)
RemoveDecl - Unlink the decl from its shadowed decl chain.
IdentifierResolver(Preprocessor &PP)
void InsertDeclAfter(iterator Pos, NamedDecl *D)
Insert the given declaration after the given iterator position.
bool tryAddTopLevelDecl(NamedDecl *D, DeclarationName Name)
Try to add the given declaration to the top level scope, if it (or a redeclaration of it) hasn't alre...
iterator end()
Returns the end iterator.
void AddDecl(NamedDecl *D)
AddDecl - Link the decl to its shadowed decl chain.
llvm::iterator_range< iterator > decls(DeclarationName Name)
Returns a range of decls with the name 'Name'.
bool isDeclInScope(Decl *D, DeclContext *Ctx, Scope *S=nullptr, bool AllowInlineNamespace=false) const
isDeclInScope - If 'Ctx' is a function/method, isDeclInScope returns true if 'D' is in Scope 'S',...
This represents a decl that may have a name.
Definition Decl.h:274
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Definition Decl.h:340
NamedDecl * getMostRecentDecl()
Definition Decl.h:501
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
ExternalPreprocessorSource * getExternalSource() const
Scope - A scope is a transient data structure that is used while parsing the program.
Definition Scope.h:41
bool isDeclScope(const Decl *D) const
isDeclScope - Return true if this is the scope that the specified decl is declared in.
Definition Scope.h:384
bool isFnTryCatchScope() const
Determine whether this scope is a function-level C++ try or catch scope.
Definition Scope.h:594
bool isControlScope() const
Determine whether this scope is a controlling scope in a if/switch/while/for statement.
Definition Scope.h:611
DeclContext * getEntity() const
Get the entity corresponding to this scope.
Definition Scope.h:387
const Scope * getParent() const
getParent - Return the scope that this is nested in.
Definition Scope.h:280
bool isFunctionPrototypeScope() const
isFunctionPrototypeScope - Return true if this scope is a function prototype scope.
Definition Scope.h:473
bool isFunctionScope() const
isFunctionScope() - Return true if this scope is a function scope.
Definition Scope.h:411
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
Definition Address.h:330
__UINTPTR_TYPE__ uintptr_t
An unsigned integer type with the property that any valid pointer to void can be converted to this ty...