1e5dd7070Spatrick //===- IdentifierResolver.cpp - Lexical Scope Name lookup -----------------===//
2e5dd7070Spatrick //
3e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information.
5e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e5dd7070Spatrick //
7e5dd7070Spatrick //===----------------------------------------------------------------------===//
8e5dd7070Spatrick //
9e5dd7070Spatrick // This file implements the IdentifierResolver class, which is used for lexical
10e5dd7070Spatrick // scoped lookup, based on declaration names.
11e5dd7070Spatrick //
12e5dd7070Spatrick //===----------------------------------------------------------------------===//
13e5dd7070Spatrick
14e5dd7070Spatrick #include "clang/Sema/IdentifierResolver.h"
15e5dd7070Spatrick #include "clang/AST/Decl.h"
16e5dd7070Spatrick #include "clang/AST/DeclBase.h"
17e5dd7070Spatrick #include "clang/AST/DeclarationName.h"
18e5dd7070Spatrick #include "clang/Basic/IdentifierTable.h"
19e5dd7070Spatrick #include "clang/Basic/LangOptions.h"
20e5dd7070Spatrick #include "clang/Lex/ExternalPreprocessorSource.h"
21e5dd7070Spatrick #include "clang/Lex/Preprocessor.h"
22e5dd7070Spatrick #include "clang/Sema/Scope.h"
23e5dd7070Spatrick #include "llvm/Support/ErrorHandling.h"
24e5dd7070Spatrick #include <cassert>
25e5dd7070Spatrick #include <cstdint>
26e5dd7070Spatrick
27e5dd7070Spatrick using namespace clang;
28e5dd7070Spatrick
29e5dd7070Spatrick //===----------------------------------------------------------------------===//
30e5dd7070Spatrick // IdDeclInfoMap class
31e5dd7070Spatrick //===----------------------------------------------------------------------===//
32e5dd7070Spatrick
33e5dd7070Spatrick /// IdDeclInfoMap - Associates IdDeclInfos with declaration names.
34e5dd7070Spatrick /// Allocates 'pools' (vectors of IdDeclInfos) to avoid allocating each
35e5dd7070Spatrick /// individual IdDeclInfo to heap.
36e5dd7070Spatrick class IdentifierResolver::IdDeclInfoMap {
37e5dd7070Spatrick static const unsigned int POOL_SIZE = 512;
38e5dd7070Spatrick
39e5dd7070Spatrick /// We use our own linked-list implementation because it is sadly
40e5dd7070Spatrick /// impossible to add something to a pre-C++0x STL container without
41e5dd7070Spatrick /// a completely unnecessary copy.
42e5dd7070Spatrick struct IdDeclInfoPool {
43e5dd7070Spatrick IdDeclInfoPool *Next;
44e5dd7070Spatrick IdDeclInfo Pool[POOL_SIZE];
45e5dd7070Spatrick
IdDeclInfoPoolIdentifierResolver::IdDeclInfoMap::IdDeclInfoPool46e5dd7070Spatrick IdDeclInfoPool(IdDeclInfoPool *Next) : Next(Next) {}
47e5dd7070Spatrick };
48e5dd7070Spatrick
49e5dd7070Spatrick IdDeclInfoPool *CurPool = nullptr;
50e5dd7070Spatrick unsigned int CurIndex = POOL_SIZE;
51e5dd7070Spatrick
52e5dd7070Spatrick public:
53e5dd7070Spatrick IdDeclInfoMap() = default;
54e5dd7070Spatrick
~IdDeclInfoMap()55e5dd7070Spatrick ~IdDeclInfoMap() {
56e5dd7070Spatrick IdDeclInfoPool *Cur = CurPool;
57e5dd7070Spatrick while (IdDeclInfoPool *P = Cur) {
58e5dd7070Spatrick Cur = Cur->Next;
59e5dd7070Spatrick delete P;
60e5dd7070Spatrick }
61e5dd7070Spatrick }
62e5dd7070Spatrick
63e5dd7070Spatrick /// Returns the IdDeclInfo associated to the DeclarationName.
64e5dd7070Spatrick /// It creates a new IdDeclInfo if one was not created before for this id.
65e5dd7070Spatrick IdDeclInfo &operator[](DeclarationName Name);
66e5dd7070Spatrick };
67e5dd7070Spatrick
68e5dd7070Spatrick //===----------------------------------------------------------------------===//
69e5dd7070Spatrick // IdDeclInfo Implementation
70e5dd7070Spatrick //===----------------------------------------------------------------------===//
71e5dd7070Spatrick
72e5dd7070Spatrick /// RemoveDecl - Remove the decl from the scope chain.
73e5dd7070Spatrick /// The decl must already be part of the decl chain.
RemoveDecl(NamedDecl * D)74e5dd7070Spatrick void IdentifierResolver::IdDeclInfo::RemoveDecl(NamedDecl *D) {
75e5dd7070Spatrick for (DeclsTy::iterator I = Decls.end(); I != Decls.begin(); --I) {
76e5dd7070Spatrick if (D == *(I-1)) {
77e5dd7070Spatrick Decls.erase(I-1);
78e5dd7070Spatrick return;
79e5dd7070Spatrick }
80e5dd7070Spatrick }
81e5dd7070Spatrick
82e5dd7070Spatrick llvm_unreachable("Didn't find this decl on its identifier's chain!");
83e5dd7070Spatrick }
84e5dd7070Spatrick
85e5dd7070Spatrick //===----------------------------------------------------------------------===//
86e5dd7070Spatrick // IdentifierResolver Implementation
87e5dd7070Spatrick //===----------------------------------------------------------------------===//
88e5dd7070Spatrick
IdentifierResolver(Preprocessor & PP)89e5dd7070Spatrick IdentifierResolver::IdentifierResolver(Preprocessor &PP)
90e5dd7070Spatrick : LangOpt(PP.getLangOpts()), PP(PP), IdDeclInfos(new IdDeclInfoMap) {}
91e5dd7070Spatrick
~IdentifierResolver()92e5dd7070Spatrick IdentifierResolver::~IdentifierResolver() {
93e5dd7070Spatrick delete IdDeclInfos;
94e5dd7070Spatrick }
95e5dd7070Spatrick
96e5dd7070Spatrick /// isDeclInScope - If 'Ctx' is a function/method, isDeclInScope returns true
97e5dd7070Spatrick /// if 'D' is in Scope 'S', otherwise 'S' is ignored and isDeclInScope returns
98e5dd7070Spatrick /// true if 'D' belongs to the given declaration context.
isDeclInScope(Decl * D,DeclContext * Ctx,Scope * S,bool AllowInlineNamespace) const99e5dd7070Spatrick bool IdentifierResolver::isDeclInScope(Decl *D, DeclContext *Ctx, Scope *S,
100e5dd7070Spatrick bool AllowInlineNamespace) const {
101e5dd7070Spatrick Ctx = Ctx->getRedeclContext();
102*12c85518Srobert // The names for HLSL cbuffer/tbuffers only used by the CPU-side
103*12c85518Srobert // reflection API which supports querying bindings. It will not have name
104*12c85518Srobert // conflict with other Decls.
105*12c85518Srobert if (LangOpt.HLSL && isa<HLSLBufferDecl>(D))
106*12c85518Srobert return false;
107e5dd7070Spatrick if (Ctx->isFunctionOrMethod() || (S && S->isFunctionPrototypeScope())) {
108e5dd7070Spatrick // Ignore the scopes associated within transparent declaration contexts.
109e5dd7070Spatrick while (S->getEntity() && S->getEntity()->isTransparentContext())
110e5dd7070Spatrick S = S->getParent();
111e5dd7070Spatrick
112e5dd7070Spatrick if (S->isDeclScope(D))
113e5dd7070Spatrick return true;
114e5dd7070Spatrick if (LangOpt.CPlusPlus) {
115e5dd7070Spatrick // C++ 3.3.2p3:
116e5dd7070Spatrick // The name declared in a catch exception-declaration is local to the
117e5dd7070Spatrick // handler and shall not be redeclared in the outermost block of the
118e5dd7070Spatrick // handler.
119e5dd7070Spatrick // C++ 3.3.2p4:
120e5dd7070Spatrick // Names declared in the for-init-statement, and in the condition of if,
121e5dd7070Spatrick // while, for, and switch statements are local to the if, while, for, or
122e5dd7070Spatrick // switch statement (including the controlled statement), and shall not be
123e5dd7070Spatrick // redeclared in a subsequent condition of that statement nor in the
124e5dd7070Spatrick // outermost block (or, for the if statement, any of the outermost blocks)
125e5dd7070Spatrick // of the controlled statement.
126e5dd7070Spatrick //
127e5dd7070Spatrick assert(S->getParent() && "No TUScope?");
128*12c85518Srobert // If the current decl is in a lambda, we shouldn't consider this is a
129*12c85518Srobert // redefinition as lambda has its own scope.
130*12c85518Srobert if (S->getParent()->isControlScope() && !S->isFunctionScope()) {
131e5dd7070Spatrick S = S->getParent();
132e5dd7070Spatrick if (S->isDeclScope(D))
133e5dd7070Spatrick return true;
134e5dd7070Spatrick }
135*12c85518Srobert if (S->isFnTryCatchScope())
136e5dd7070Spatrick return S->getParent()->isDeclScope(D);
137e5dd7070Spatrick }
138e5dd7070Spatrick return false;
139e5dd7070Spatrick }
140e5dd7070Spatrick
141e5dd7070Spatrick // FIXME: If D is a local extern declaration, this check doesn't make sense;
142e5dd7070Spatrick // we should be checking its lexical context instead in that case, because
143e5dd7070Spatrick // that is its scope.
144e5dd7070Spatrick DeclContext *DCtx = D->getDeclContext()->getRedeclContext();
145e5dd7070Spatrick return AllowInlineNamespace ? Ctx->InEnclosingNamespaceSetOf(DCtx)
146e5dd7070Spatrick : Ctx->Equals(DCtx);
147e5dd7070Spatrick }
148e5dd7070Spatrick
149e5dd7070Spatrick /// AddDecl - Link the decl to its shadowed decl chain.
AddDecl(NamedDecl * D)150e5dd7070Spatrick void IdentifierResolver::AddDecl(NamedDecl *D) {
151e5dd7070Spatrick DeclarationName Name = D->getDeclName();
152e5dd7070Spatrick if (IdentifierInfo *II = Name.getAsIdentifierInfo())
153e5dd7070Spatrick updatingIdentifier(*II);
154e5dd7070Spatrick
155e5dd7070Spatrick void *Ptr = Name.getFETokenInfo();
156e5dd7070Spatrick
157e5dd7070Spatrick if (!Ptr) {
158e5dd7070Spatrick Name.setFETokenInfo(D);
159e5dd7070Spatrick return;
160e5dd7070Spatrick }
161e5dd7070Spatrick
162e5dd7070Spatrick IdDeclInfo *IDI;
163e5dd7070Spatrick
164e5dd7070Spatrick if (isDeclPtr(Ptr)) {
165e5dd7070Spatrick Name.setFETokenInfo(nullptr);
166e5dd7070Spatrick IDI = &(*IdDeclInfos)[Name];
167e5dd7070Spatrick NamedDecl *PrevD = static_cast<NamedDecl*>(Ptr);
168e5dd7070Spatrick IDI->AddDecl(PrevD);
169e5dd7070Spatrick } else
170e5dd7070Spatrick IDI = toIdDeclInfo(Ptr);
171e5dd7070Spatrick
172e5dd7070Spatrick IDI->AddDecl(D);
173e5dd7070Spatrick }
174e5dd7070Spatrick
InsertDeclAfter(iterator Pos,NamedDecl * D)175e5dd7070Spatrick void IdentifierResolver::InsertDeclAfter(iterator Pos, NamedDecl *D) {
176e5dd7070Spatrick DeclarationName Name = D->getDeclName();
177e5dd7070Spatrick if (IdentifierInfo *II = Name.getAsIdentifierInfo())
178e5dd7070Spatrick updatingIdentifier(*II);
179e5dd7070Spatrick
180e5dd7070Spatrick void *Ptr = Name.getFETokenInfo();
181e5dd7070Spatrick
182e5dd7070Spatrick if (!Ptr) {
183e5dd7070Spatrick AddDecl(D);
184e5dd7070Spatrick return;
185e5dd7070Spatrick }
186e5dd7070Spatrick
187e5dd7070Spatrick if (isDeclPtr(Ptr)) {
188e5dd7070Spatrick // We only have a single declaration: insert before or after it,
189e5dd7070Spatrick // as appropriate.
190e5dd7070Spatrick if (Pos == iterator()) {
191e5dd7070Spatrick // Add the new declaration before the existing declaration.
192e5dd7070Spatrick NamedDecl *PrevD = static_cast<NamedDecl*>(Ptr);
193e5dd7070Spatrick RemoveDecl(PrevD);
194e5dd7070Spatrick AddDecl(D);
195e5dd7070Spatrick AddDecl(PrevD);
196e5dd7070Spatrick } else {
197e5dd7070Spatrick // Add new declaration after the existing declaration.
198e5dd7070Spatrick AddDecl(D);
199e5dd7070Spatrick }
200e5dd7070Spatrick
201e5dd7070Spatrick return;
202e5dd7070Spatrick }
203e5dd7070Spatrick
204e5dd7070Spatrick // General case: insert the declaration at the appropriate point in the
205e5dd7070Spatrick // list, which already has at least two elements.
206e5dd7070Spatrick IdDeclInfo *IDI = toIdDeclInfo(Ptr);
207e5dd7070Spatrick if (Pos.isIterator()) {
208e5dd7070Spatrick IDI->InsertDecl(Pos.getIterator() + 1, D);
209e5dd7070Spatrick } else
210e5dd7070Spatrick IDI->InsertDecl(IDI->decls_begin(), D);
211e5dd7070Spatrick }
212e5dd7070Spatrick
213e5dd7070Spatrick /// RemoveDecl - Unlink the decl from its shadowed decl chain.
214e5dd7070Spatrick /// The decl must already be part of the decl chain.
RemoveDecl(NamedDecl * D)215e5dd7070Spatrick void IdentifierResolver::RemoveDecl(NamedDecl *D) {
216e5dd7070Spatrick assert(D && "null param passed");
217e5dd7070Spatrick DeclarationName Name = D->getDeclName();
218e5dd7070Spatrick if (IdentifierInfo *II = Name.getAsIdentifierInfo())
219e5dd7070Spatrick updatingIdentifier(*II);
220e5dd7070Spatrick
221e5dd7070Spatrick void *Ptr = Name.getFETokenInfo();
222e5dd7070Spatrick
223e5dd7070Spatrick assert(Ptr && "Didn't find this decl on its identifier's chain!");
224e5dd7070Spatrick
225e5dd7070Spatrick if (isDeclPtr(Ptr)) {
226e5dd7070Spatrick assert(D == Ptr && "Didn't find this decl on its identifier's chain!");
227e5dd7070Spatrick Name.setFETokenInfo(nullptr);
228e5dd7070Spatrick return;
229e5dd7070Spatrick }
230e5dd7070Spatrick
231e5dd7070Spatrick return toIdDeclInfo(Ptr)->RemoveDecl(D);
232e5dd7070Spatrick }
233e5dd7070Spatrick
234e5dd7070Spatrick /// begin - Returns an iterator for decls with name 'Name'.
235e5dd7070Spatrick IdentifierResolver::iterator
begin(DeclarationName Name)236e5dd7070Spatrick IdentifierResolver::begin(DeclarationName Name) {
237e5dd7070Spatrick if (IdentifierInfo *II = Name.getAsIdentifierInfo())
238e5dd7070Spatrick readingIdentifier(*II);
239e5dd7070Spatrick
240e5dd7070Spatrick void *Ptr = Name.getFETokenInfo();
241e5dd7070Spatrick if (!Ptr) return end();
242e5dd7070Spatrick
243e5dd7070Spatrick if (isDeclPtr(Ptr))
244e5dd7070Spatrick return iterator(static_cast<NamedDecl*>(Ptr));
245e5dd7070Spatrick
246e5dd7070Spatrick IdDeclInfo *IDI = toIdDeclInfo(Ptr);
247e5dd7070Spatrick
248e5dd7070Spatrick IdDeclInfo::DeclsTy::iterator I = IDI->decls_end();
249e5dd7070Spatrick if (I != IDI->decls_begin())
250e5dd7070Spatrick return iterator(I-1);
251e5dd7070Spatrick // No decls found.
252e5dd7070Spatrick return end();
253e5dd7070Spatrick }
254e5dd7070Spatrick
255e5dd7070Spatrick namespace {
256e5dd7070Spatrick
257e5dd7070Spatrick enum DeclMatchKind {
258e5dd7070Spatrick DMK_Different,
259e5dd7070Spatrick DMK_Replace,
260e5dd7070Spatrick DMK_Ignore
261e5dd7070Spatrick };
262e5dd7070Spatrick
263e5dd7070Spatrick } // namespace
264e5dd7070Spatrick
265e5dd7070Spatrick /// Compare two declarations to see whether they are different or,
266e5dd7070Spatrick /// if they are the same, whether the new declaration should replace the
267e5dd7070Spatrick /// existing declaration.
compareDeclarations(NamedDecl * Existing,NamedDecl * New)268e5dd7070Spatrick static DeclMatchKind compareDeclarations(NamedDecl *Existing, NamedDecl *New) {
269e5dd7070Spatrick // If the declarations are identical, ignore the new one.
270e5dd7070Spatrick if (Existing == New)
271e5dd7070Spatrick return DMK_Ignore;
272e5dd7070Spatrick
273e5dd7070Spatrick // If the declarations have different kinds, they're obviously different.
274e5dd7070Spatrick if (Existing->getKind() != New->getKind())
275e5dd7070Spatrick return DMK_Different;
276e5dd7070Spatrick
277e5dd7070Spatrick // If the declarations are redeclarations of each other, keep the newest one.
278e5dd7070Spatrick if (Existing->getCanonicalDecl() == New->getCanonicalDecl()) {
279e5dd7070Spatrick // If we're adding an imported declaration, don't replace another imported
280e5dd7070Spatrick // declaration.
281e5dd7070Spatrick if (Existing->isFromASTFile() && New->isFromASTFile())
282e5dd7070Spatrick return DMK_Different;
283e5dd7070Spatrick
284e5dd7070Spatrick // If either of these is the most recent declaration, use it.
285e5dd7070Spatrick Decl *MostRecent = Existing->getMostRecentDecl();
286e5dd7070Spatrick if (Existing == MostRecent)
287e5dd7070Spatrick return DMK_Ignore;
288e5dd7070Spatrick
289e5dd7070Spatrick if (New == MostRecent)
290e5dd7070Spatrick return DMK_Replace;
291e5dd7070Spatrick
292e5dd7070Spatrick // If the existing declaration is somewhere in the previous declaration
293e5dd7070Spatrick // chain of the new declaration, then prefer the new declaration.
294*12c85518Srobert for (auto *RD : New->redecls()) {
295e5dd7070Spatrick if (RD == Existing)
296e5dd7070Spatrick return DMK_Replace;
297e5dd7070Spatrick
298e5dd7070Spatrick if (RD->isCanonicalDecl())
299e5dd7070Spatrick break;
300e5dd7070Spatrick }
301e5dd7070Spatrick
302e5dd7070Spatrick return DMK_Ignore;
303e5dd7070Spatrick }
304e5dd7070Spatrick
305e5dd7070Spatrick return DMK_Different;
306e5dd7070Spatrick }
307e5dd7070Spatrick
tryAddTopLevelDecl(NamedDecl * D,DeclarationName Name)308e5dd7070Spatrick bool IdentifierResolver::tryAddTopLevelDecl(NamedDecl *D, DeclarationName Name){
309e5dd7070Spatrick if (IdentifierInfo *II = Name.getAsIdentifierInfo())
310e5dd7070Spatrick readingIdentifier(*II);
311e5dd7070Spatrick
312e5dd7070Spatrick void *Ptr = Name.getFETokenInfo();
313e5dd7070Spatrick
314e5dd7070Spatrick if (!Ptr) {
315e5dd7070Spatrick Name.setFETokenInfo(D);
316e5dd7070Spatrick return true;
317e5dd7070Spatrick }
318e5dd7070Spatrick
319e5dd7070Spatrick IdDeclInfo *IDI;
320e5dd7070Spatrick
321e5dd7070Spatrick if (isDeclPtr(Ptr)) {
322e5dd7070Spatrick NamedDecl *PrevD = static_cast<NamedDecl*>(Ptr);
323e5dd7070Spatrick
324e5dd7070Spatrick switch (compareDeclarations(PrevD, D)) {
325e5dd7070Spatrick case DMK_Different:
326e5dd7070Spatrick break;
327e5dd7070Spatrick
328e5dd7070Spatrick case DMK_Ignore:
329e5dd7070Spatrick return false;
330e5dd7070Spatrick
331e5dd7070Spatrick case DMK_Replace:
332e5dd7070Spatrick Name.setFETokenInfo(D);
333e5dd7070Spatrick return true;
334e5dd7070Spatrick }
335e5dd7070Spatrick
336e5dd7070Spatrick Name.setFETokenInfo(nullptr);
337e5dd7070Spatrick IDI = &(*IdDeclInfos)[Name];
338e5dd7070Spatrick
339e5dd7070Spatrick // If the existing declaration is not visible in translation unit scope,
340e5dd7070Spatrick // then add the new top-level declaration first.
341e5dd7070Spatrick if (!PrevD->getDeclContext()->getRedeclContext()->isTranslationUnit()) {
342e5dd7070Spatrick IDI->AddDecl(D);
343e5dd7070Spatrick IDI->AddDecl(PrevD);
344e5dd7070Spatrick } else {
345e5dd7070Spatrick IDI->AddDecl(PrevD);
346e5dd7070Spatrick IDI->AddDecl(D);
347e5dd7070Spatrick }
348e5dd7070Spatrick return true;
349e5dd7070Spatrick }
350e5dd7070Spatrick
351e5dd7070Spatrick IDI = toIdDeclInfo(Ptr);
352e5dd7070Spatrick
353e5dd7070Spatrick // See whether this declaration is identical to any existing declarations.
354e5dd7070Spatrick // If not, find the right place to insert it.
355e5dd7070Spatrick for (IdDeclInfo::DeclsTy::iterator I = IDI->decls_begin(),
356e5dd7070Spatrick IEnd = IDI->decls_end();
357e5dd7070Spatrick I != IEnd; ++I) {
358e5dd7070Spatrick
359e5dd7070Spatrick switch (compareDeclarations(*I, D)) {
360e5dd7070Spatrick case DMK_Different:
361e5dd7070Spatrick break;
362e5dd7070Spatrick
363e5dd7070Spatrick case DMK_Ignore:
364e5dd7070Spatrick return false;
365e5dd7070Spatrick
366e5dd7070Spatrick case DMK_Replace:
367e5dd7070Spatrick *I = D;
368e5dd7070Spatrick return true;
369e5dd7070Spatrick }
370e5dd7070Spatrick
371e5dd7070Spatrick if (!(*I)->getDeclContext()->getRedeclContext()->isTranslationUnit()) {
372e5dd7070Spatrick // We've found a declaration that is not visible from the translation
373e5dd7070Spatrick // unit (it's in an inner scope). Insert our declaration here.
374e5dd7070Spatrick IDI->InsertDecl(I, D);
375e5dd7070Spatrick return true;
376e5dd7070Spatrick }
377e5dd7070Spatrick }
378e5dd7070Spatrick
379e5dd7070Spatrick // Add the declaration to the end.
380e5dd7070Spatrick IDI->AddDecl(D);
381e5dd7070Spatrick return true;
382e5dd7070Spatrick }
383e5dd7070Spatrick
readingIdentifier(IdentifierInfo & II)384e5dd7070Spatrick void IdentifierResolver::readingIdentifier(IdentifierInfo &II) {
385e5dd7070Spatrick if (II.isOutOfDate())
386e5dd7070Spatrick PP.getExternalSource()->updateOutOfDateIdentifier(II);
387e5dd7070Spatrick }
388e5dd7070Spatrick
updatingIdentifier(IdentifierInfo & II)389e5dd7070Spatrick void IdentifierResolver::updatingIdentifier(IdentifierInfo &II) {
390e5dd7070Spatrick if (II.isOutOfDate())
391e5dd7070Spatrick PP.getExternalSource()->updateOutOfDateIdentifier(II);
392e5dd7070Spatrick
393e5dd7070Spatrick if (II.isFromAST())
394e5dd7070Spatrick II.setFETokenInfoChangedSinceDeserialization();
395e5dd7070Spatrick }
396e5dd7070Spatrick
397e5dd7070Spatrick //===----------------------------------------------------------------------===//
398e5dd7070Spatrick // IdDeclInfoMap Implementation
399e5dd7070Spatrick //===----------------------------------------------------------------------===//
400e5dd7070Spatrick
401e5dd7070Spatrick /// Returns the IdDeclInfo associated to the DeclarationName.
402e5dd7070Spatrick /// It creates a new IdDeclInfo if one was not created before for this id.
403e5dd7070Spatrick IdentifierResolver::IdDeclInfo &
operator [](DeclarationName Name)404e5dd7070Spatrick IdentifierResolver::IdDeclInfoMap::operator[](DeclarationName Name) {
405e5dd7070Spatrick void *Ptr = Name.getFETokenInfo();
406e5dd7070Spatrick
407e5dd7070Spatrick if (Ptr) return *toIdDeclInfo(Ptr);
408e5dd7070Spatrick
409e5dd7070Spatrick if (CurIndex == POOL_SIZE) {
410e5dd7070Spatrick CurPool = new IdDeclInfoPool(CurPool);
411e5dd7070Spatrick CurIndex = 0;
412e5dd7070Spatrick }
413e5dd7070Spatrick IdDeclInfo *IDI = &CurPool->Pool[CurIndex];
414e5dd7070Spatrick Name.setFETokenInfo(reinterpret_cast<void*>(
415e5dd7070Spatrick reinterpret_cast<uintptr_t>(IDI) | 0x1)
416e5dd7070Spatrick );
417e5dd7070Spatrick ++CurIndex;
418e5dd7070Spatrick return *IDI;
419e5dd7070Spatrick }
420e5dd7070Spatrick
incrementSlowCase()421e5dd7070Spatrick void IdentifierResolver::iterator::incrementSlowCase() {
422e5dd7070Spatrick NamedDecl *D = **this;
423e5dd7070Spatrick void *InfoPtr = D->getDeclName().getFETokenInfo();
424e5dd7070Spatrick assert(!isDeclPtr(InfoPtr) && "Decl with wrong id ?");
425e5dd7070Spatrick IdDeclInfo *Info = toIdDeclInfo(InfoPtr);
426e5dd7070Spatrick
427e5dd7070Spatrick BaseIter I = getIterator();
428e5dd7070Spatrick if (I != Info->decls_begin())
429e5dd7070Spatrick *this = iterator(I-1);
430e5dd7070Spatrick else // No more decls.
431e5dd7070Spatrick *this = iterator();
432e5dd7070Spatrick }
433