clang  16.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 {
71  llvm_unreachable("Unhandled type of friend class");
72  }
73  }
74  }
75  return true;
76  }
77 
78  // Override default settings of base.
79  bool shouldVisitTemplateInstantiations() const { return true; }
80  bool shouldVisitImplicitCode() const { return true; }
81 };
82 
83 } // anonymous namespace
84 
86  Builder B(*this);
87  B.TraverseDecl(&TU);
88 }
89 
90 void ASTImporterLookupTable::add(DeclContext *DC, NamedDecl *ND) {
91  DeclList &Decls = LookupTable[DC][ND->getDeclName()];
92  // Inserts if and only if there is no element in the container equal to it.
93  Decls.insert(ND);
94 }
95 
96 void ASTImporterLookupTable::remove(DeclContext *DC, NamedDecl *ND) {
97  const DeclarationName Name = ND->getDeclName();
98  DeclList &Decls = LookupTable[DC][Name];
99  bool EraseResult = Decls.remove(ND);
100  (void)EraseResult;
101 #ifndef NDEBUG
102  if (!EraseResult) {
103  std::string Message =
104  llvm::formatv("Trying to remove not contained Decl '{0}' of type {1}",
105  Name.getAsString(), DC->getDeclKindName())
106  .str();
107  llvm_unreachable(Message.c_str());
108  }
109 #endif
110 }
111 
112 void ASTImporterLookupTable::add(NamedDecl *ND) {
113  assert(ND);
115  add(DC, ND);
117  if (DC != ReDC)
118  add(ReDC, ND);
119 }
120 
121 void ASTImporterLookupTable::remove(NamedDecl *ND) {
122  assert(ND);
124  remove(DC, ND);
126  if (DC != ReDC)
127  remove(ReDC, ND);
128 }
129 
131  assert(OldDC != ND->getDeclContext() &&
132  "DeclContext should be changed before update");
133  if (contains(ND->getDeclContext(), ND)) {
134  assert(!contains(OldDC, ND) &&
135  "Decl should not be found in the old context if already in the new");
136  return;
137  }
138 
139  remove(OldDC, ND);
140  add(ND);
141 }
142 
144  LookupTable[OldDC][ND->getDeclName()].remove(ND);
145  add(ND);
146 }
147 
150  auto DCI = LookupTable.find(DC->getPrimaryContext());
151  if (DCI == LookupTable.end())
152  return {};
153 
154  const auto &FoundNameMap = DCI->second;
155  auto NamesI = FoundNameMap.find(Name);
156  if (NamesI == FoundNameMap.end())
157  return {};
158 
159  return NamesI->second;
160 }
161 
163  return lookup(DC, ND->getDeclName()).contains(ND);
164 }
165 
167  auto DCI = LookupTable.find(DC->getPrimaryContext());
168  if (DCI == LookupTable.end())
169  llvm::errs() << "empty\n";
170  const auto &FoundNameMap = DCI->second;
171  for (const auto &Entry : FoundNameMap) {
172  DeclarationName Name = Entry.first;
173  llvm::errs() << "==== Name: ";
174  Name.dump();
175  const DeclList& List = Entry.second;
176  for (NamedDecl *ND : List) {
177  ND->dump();
178  }
179  }
180 }
181 
183  for (const auto &Entry : LookupTable) {
184  DeclContext *DC = Entry.first;
185  StringRef Primary = DC->getPrimaryContext() ? " primary" : "";
186  llvm::errs() << "== DC:" << cast<Decl>(DC) << Primary << "\n";
187  dump(DC);
188  }
189 }
190 
191 } // namespace clang
LT
ASTImporterLookupTable & LT
Definition: ASTImporterLookupTable.cpp:24
string
string(SUBSTRING ${CMAKE_CURRENT_BINARY_DIR} 0 ${PATH_LIB_START} PATH_HEAD) string(SUBSTRING $
Definition: CMakeLists.txt:22
clang::DeclContext
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition: DeclBase.h:1389
clang::RISCV::TU
@ TU
Definition: RISCVVIntrinsicUtils.h:97
clang::NamedDecl
This represents a decl that may have a name.
Definition: Decl.h:247
clang::DeclContext::getPrimaryContext
DeclContext * getPrimaryContext()
getPrimaryContext - There may be many different declarations of the same entity (including forward de...
Definition: DeclBase.cpp:1263
clang::ASTImporterLookupTable::lookup
LookupResult lookup(DeclContext *DC, DeclarationName Name) const
Definition: ASTImporterLookupTable.cpp:149
clang::DeclarationName
The name of a declaration.
Definition: DeclarationName.h:144
Decl.h
clang::TranslationUnitDecl
The top declaration context.
Definition: Decl.h:80
clang::ASTImporterLookupTable::contains
bool contains(DeclContext *DC, NamedDecl *ND) const
Definition: ASTImporterLookupTable.cpp:162
clang::ASTImporterLookupTable::update
void update(NamedDecl *ND, DeclContext *OldDC)
Definition: ASTImporterLookupTable.cpp:130
clang::ASTImporterLookupTable::ASTImporterLookupTable
ASTImporterLookupTable(TranslationUnitDecl &TU)
Definition: ASTImporterLookupTable.cpp:85
clang::DeclContext::getRedeclContext
DeclContext * getRedeclContext()
getRedeclContext - Retrieve the context in which an entity conflicts with other entities of the same ...
Definition: DeclBase.cpp:1828
clang::ASTImporterLookupTable::updateForced
void updateForced(NamedDecl *ND, DeclContext *OldDC)
Definition: ASTImporterLookupTable.cpp:143
clang::ASTImporterLookupTable::dump
void dump() const
Definition: ASTImporterLookupTable.cpp:182
clang
Definition: CalledOnceCheck.h:17
RecursiveASTVisitor.h
clang::NamedDecl::getDeclName
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Definition: Decl.h:313
ASTImporterLookupTable.h
llvm::SmallSetVector
Definition: ExternalSemaSource.h:23
clang::Decl::getDeclContext
DeclContext * getDeclContext()
Definition: DeclBase.h:441