clang  19.0.0git
ASTImporterLookupTable.cpp
Go to the documentation of this file.
1 //===- ASTImporterLookupTable.cpp - ASTImporter specific 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 defines the ASTImporterLookupTable class which implements a
10 // lookup procedure for the import mechanism.
11 //
12 //===----------------------------------------------------------------------===//
13 
15 #include "clang/AST/Decl.h"
17 #include "llvm/Support/FormatVariadic.h"
18 
19 namespace clang {
20 
21 namespace {
22 
23 struct Builder : RecursiveASTVisitor<Builder> {
24  ASTImporterLookupTable &LT;
25  Builder(ASTImporterLookupTable &LT) : LT(LT) {}
26 
27  bool VisitTypedefNameDecl(TypedefNameDecl *D) {
28  QualType Ty = D->getUnderlyingType();
29  Ty = Ty.getCanonicalType();
30  if (const auto *RTy = dyn_cast<RecordType>(Ty)) {
31  LT.add(RTy->getAsRecordDecl());
32  // iterate over the field decls, adding them
33  for (auto *it : RTy->getAsRecordDecl()->fields()) {
34  LT.add(it);
35  }
36  }
37  return true;
38  }
39 
40  bool VisitNamedDecl(NamedDecl *D) {
41  LT.add(D);
42  return true;
43  }
44  // In most cases the FriendDecl contains the declaration of the befriended
45  // class as a child node, so it is discovered during the recursive
46  // visitation. However, there are cases when the befriended class is not a
47  // child, thus it must be fetched explicitly from the FriendDecl, and only
48  // then can we add it to the lookup table.
49  bool VisitFriendDecl(FriendDecl *D) {
50  if (D->getFriendType()) {
51  QualType Ty = D->getFriendType()->getType();
52  if (isa<ElaboratedType>(Ty))
53  Ty = cast<ElaboratedType>(Ty)->getNamedType();
54  // A FriendDecl with a dependent type (e.g. ClassTemplateSpecialization)
55  // always has that decl as child node.
56  // However, there are non-dependent cases which does not have the
57  // type as a child node. We have to dig up that type now.
58  if (!Ty->isDependentType()) {
59  if (const auto *RTy = dyn_cast<RecordType>(Ty))
60  LT.add(RTy->getAsCXXRecordDecl());
61  else if (const auto *SpecTy = dyn_cast<TemplateSpecializationType>(Ty))
62  LT.add(SpecTy->getAsCXXRecordDecl());
63  else if (const auto *SubstTy =
64  dyn_cast<SubstTemplateTypeParmType>(Ty)) {
65  if (SubstTy->getAsCXXRecordDecl())
66  LT.add(SubstTy->getAsCXXRecordDecl());
67  } else if (isa<TypedefType>(Ty)) {
68  // We do not put friend typedefs to the lookup table because
69  // ASTImporter does not organize typedefs into redecl chains.
70  } else if (isa<UsingType>(Ty)) {
71  // Similar to TypedefType, not putting into lookup table.
72  } else {
73  llvm_unreachable("Unhandled type of friend class");
74  }
75  }
76  }
77  return true;
78  }
79 
80  // Override default settings of base.
81  bool shouldVisitTemplateInstantiations() const { return true; }
82  bool shouldVisitImplicitCode() const { return true; }
83 };
84 
85 } // anonymous namespace
86 
88  Builder B(*this);
89  B.TraverseDecl(&TU);
90  // The VaList declaration may be created on demand only or not traversed.
91  // To ensure it is present and found during import, add it to the table now.
92  if (auto *D =
93  dyn_cast_or_null<NamedDecl>(TU.getASTContext().getVaListTagDecl())) {
94  // On some platforms (AArch64) the VaList declaration can be inside a 'std'
95  // namespace. This is handled specially and not visible by AST traversal.
96  // ASTImporter must be able to find this namespace to import the VaList
97  // declaration (and the namespace) correctly.
98  if (auto *Ns = dyn_cast<NamespaceDecl>(D->getDeclContext()))
99  add(&TU, Ns);
100  add(D->getDeclContext(), D);
101  }
102 }
103 
104 void ASTImporterLookupTable::add(DeclContext *DC, NamedDecl *ND) {
105  DeclList &Decls = LookupTable[DC][ND->getDeclName()];
106  // Inserts if and only if there is no element in the container equal to it.
107  Decls.insert(ND);
108 }
109 
110 void ASTImporterLookupTable::remove(DeclContext *DC, NamedDecl *ND) {
111  const DeclarationName Name = ND->getDeclName();
112  DeclList &Decls = LookupTable[DC][Name];
113  bool EraseResult = Decls.remove(ND);
114  (void)EraseResult;
115 #ifndef NDEBUG
116  if (!EraseResult) {
117  std::string Message =
118  llvm::formatv("Trying to remove not contained Decl '{0}' of type {1}",
119  Name.getAsString(), DC->getDeclKindName())
120  .str();
121  llvm_unreachable(Message.c_str());
122  }
123 #endif
124 }
125 
126 void ASTImporterLookupTable::add(NamedDecl *ND) {
127  assert(ND);
129  add(DC, ND);
131  if (DC != ReDC)
132  add(ReDC, ND);
133 }
134 
135 void ASTImporterLookupTable::remove(NamedDecl *ND) {
136  assert(ND);
138  remove(DC, ND);
140  if (DC != ReDC)
141  remove(ReDC, ND);
142 }
143 
145  assert(OldDC != ND->getDeclContext() &&
146  "DeclContext should be changed before update");
147  if (contains(ND->getDeclContext(), ND)) {
148  assert(!contains(OldDC, ND) &&
149  "Decl should not be found in the old context if already in the new");
150  return;
151  }
152 
153  remove(OldDC, ND);
154  add(ND);
155 }
156 
158  LookupTable[OldDC][ND->getDeclName()].remove(ND);
159  add(ND);
160 }
161 
164  auto DCI = LookupTable.find(DC->getPrimaryContext());
165  if (DCI == LookupTable.end())
166  return {};
167 
168  const auto &FoundNameMap = DCI->second;
169  auto NamesI = FoundNameMap.find(Name);
170  if (NamesI == FoundNameMap.end())
171  return {};
172 
173  return NamesI->second;
174 }
175 
177  return lookup(DC, ND->getDeclName()).contains(ND);
178 }
179 
181  auto DCI = LookupTable.find(DC->getPrimaryContext());
182  if (DCI == LookupTable.end())
183  llvm::errs() << "empty\n";
184  const auto &FoundNameMap = DCI->second;
185  for (const auto &Entry : FoundNameMap) {
186  DeclarationName Name = Entry.first;
187  llvm::errs() << "==== Name: ";
188  Name.dump();
189  const DeclList& List = Entry.second;
190  for (NamedDecl *ND : List) {
191  ND->dump();
192  }
193  }
194 }
195 
197  for (const auto &Entry : LookupTable) {
198  DeclContext *DC = Entry.first;
199  StringRef Primary = DC->getPrimaryContext() ? " primary" : "";
200  llvm::errs() << "== DC:" << cast<Decl>(DC) << Primary << "\n";
201  dump(DC);
202  }
203 }
204 
205 } // namespace clang
ASTImporterLookupTable & LT
Decl * getVaListTagDecl() const
Retrieve the C type declaration corresponding to the predefined __va_list_tag type used to help defin...
void update(NamedDecl *ND, DeclContext *OldDC)
LookupResult lookup(DeclContext *DC, DeclarationName Name) const
void updateForced(NamedDecl *ND, DeclContext *OldDC)
ASTImporterLookupTable(TranslationUnitDecl &TU)
bool contains(DeclContext *DC, NamedDecl *ND) const
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition: DeclBase.h:1436
DeclContext * getRedeclContext()
getRedeclContext - Retrieve the context in which an entity conflicts with other entities of the same ...
Definition: DeclBase.cpp:1938
DeclContext * getPrimaryContext()
getPrimaryContext - There may be many different declarations of the same entity (including forward de...
Definition: DeclBase.cpp:1372
DeclContext * getDeclContext()
Definition: DeclBase.h:454
The name of a declaration.
This represents a decl that may have a name.
Definition: Decl.h:249
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Definition: Decl.h:315
The top declaration context.
Definition: Decl.h:84
ASTContext & getASTContext() const
Definition: Decl.h:120
The JSON file list parser is used to communicate input to InstallAPI.