clang  14.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 
18 namespace clang {
19 
20 namespace {
21 
22 struct Builder : RecursiveASTVisitor<Builder> {
23  ASTImporterLookupTable &LT;
24  Builder(ASTImporterLookupTable &LT) : LT(LT) {}
25 
26  bool VisitTypedefNameDecl(TypedefNameDecl *D) {
27  QualType Ty = D->getUnderlyingType();
28  Ty = Ty.getCanonicalType();
29  if (const auto *RTy = dyn_cast<RecordType>(Ty)) {
30  LT.add(RTy->getAsRecordDecl());
31  // iterate over the field decls, adding them
32  for (auto *it : RTy->getAsRecordDecl()->fields()) {
33  LT.add(it);
34  }
35  }
36  return true;
37  }
38 
39  bool VisitNamedDecl(NamedDecl *D) {
40  LT.add(D);
41  return true;
42  }
43  // In most cases the FriendDecl contains the declaration of the befriended
44  // class as a child node, so it is discovered during the recursive
45  // visitation. However, there are cases when the befriended class is not a
46  // child, thus it must be fetched explicitly from the FriendDecl, and only
47  // then can we add it to the lookup table.
48  bool VisitFriendDecl(FriendDecl *D) {
49  if (D->getFriendType()) {
50  QualType Ty = D->getFriendType()->getType();
51  if (isa<ElaboratedType>(Ty))
52  Ty = cast<ElaboratedType>(Ty)->getNamedType();
53  // A FriendDecl with a dependent type (e.g. ClassTemplateSpecialization)
54  // always has that decl as child node.
55  // However, there are non-dependent cases which does not have the
56  // type as a child node. We have to dig up that type now.
57  if (!Ty->isDependentType()) {
58  if (const auto *RTy = dyn_cast<RecordType>(Ty))
59  LT.add(RTy->getAsCXXRecordDecl());
60  else if (const auto *SpecTy = dyn_cast<TemplateSpecializationType>(Ty))
61  LT.add(SpecTy->getAsCXXRecordDecl());
62  else if (const auto *SubstTy =
63  dyn_cast<SubstTemplateTypeParmType>(Ty)) {
64  if (SubstTy->getAsCXXRecordDecl())
65  LT.add(SubstTy->getAsCXXRecordDecl());
66  } else if (isa<TypedefType>(Ty)) {
67  // We do not put friend typedefs to the lookup table because
68  // ASTImporter does not organize typedefs into redecl chains.
69  } else {
70  llvm_unreachable("Unhandled type of friend class");
71  }
72  }
73  }
74  return true;
75  }
76 
77  // Override default settings of base.
78  bool shouldVisitTemplateInstantiations() const { return true; }
79  bool shouldVisitImplicitCode() const { return true; }
80 };
81 
82 } // anonymous namespace
83 
85  Builder B(*this);
86  B.TraverseDecl(&TU);
87 }
88 
89 void ASTImporterLookupTable::add(DeclContext *DC, NamedDecl *ND) {
90  DeclList &Decls = LookupTable[DC][ND->getDeclName()];
91  // Inserts if and only if there is no element in the container equal to it.
92  Decls.insert(ND);
93 }
94 
95 void ASTImporterLookupTable::remove(DeclContext *DC, NamedDecl *ND) {
96  DeclList &Decls = LookupTable[DC][ND->getDeclName()];
97  bool EraseResult = Decls.remove(ND);
98  (void)EraseResult;
99  assert(EraseResult == true && "Trying to remove not contained Decl");
100 }
101 
102 void ASTImporterLookupTable::add(NamedDecl *ND) {
103  assert(ND);
105  add(DC, ND);
107  if (DC != ReDC)
108  add(ReDC, ND);
109 }
110 
111 void ASTImporterLookupTable::remove(NamedDecl *ND) {
112  assert(ND);
114  remove(DC, ND);
116  if (DC != ReDC)
117  remove(ReDC, ND);
118 }
119 
121  assert(OldDC != ND->getDeclContext() &&
122  "DeclContext should be changed before update");
123  if (contains(ND->getDeclContext(), ND)) {
124  assert(!contains(OldDC, ND) &&
125  "Decl should not be found in the old context if already in the new");
126  return;
127  }
128 
129  remove(OldDC, ND);
130  add(ND);
131 }
132 
135  auto DCI = LookupTable.find(DC->getPrimaryContext());
136  if (DCI == LookupTable.end())
137  return {};
138 
139  const auto &FoundNameMap = DCI->second;
140  auto NamesI = FoundNameMap.find(Name);
141  if (NamesI == FoundNameMap.end())
142  return {};
143 
144  return NamesI->second;
145 }
146 
148  return 0 < lookup(DC, ND->getDeclName()).count(ND);
149 }
150 
152  auto DCI = LookupTable.find(DC->getPrimaryContext());
153  if (DCI == LookupTable.end())
154  llvm::errs() << "empty\n";
155  const auto &FoundNameMap = DCI->second;
156  for (const auto &Entry : FoundNameMap) {
157  DeclarationName Name = Entry.first;
158  llvm::errs() << "==== Name: ";
159  Name.dump();
160  const DeclList& List = Entry.second;
161  for (NamedDecl *ND : List) {
162  ND->dump();
163  }
164  }
165 }
166 
168  for (const auto &Entry : LookupTable) {
169  DeclContext *DC = Entry.first;
170  StringRef Primary = DC->getPrimaryContext() ? " primary" : "";
171  llvm::errs() << "== DC:" << cast<Decl>(DC) << Primary << "\n";
172  dump(DC);
173  }
174 }
175 
176 } // namespace clang
LT
ASTImporterLookupTable & LT
Definition: ASTImporterLookupTable.cpp:23
clang::DeclContext
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition: DeclBase.h:1347
clang::NamedDecl
This represents a decl that may have a name.
Definition: Decl.h:249
clang::DeclContext::getPrimaryContext
DeclContext * getPrimaryContext()
getPrimaryContext - There may be many different declarations of the same entity (including forward de...
Definition: DeclBase.cpp:1229
clang::ASTImporterLookupTable::lookup
LookupResult lookup(DeclContext *DC, DeclarationName Name) const
Definition: ASTImporterLookupTable.cpp:134
clang::DeclarationName
The name of a declaration.
Definition: DeclarationName.h:145
Decl.h
clang::TranslationUnitDecl
The top declaration context.
Definition: Decl.h:82
clang::ASTImporterLookupTable::contains
bool contains(DeclContext *DC, NamedDecl *ND) const
Definition: ASTImporterLookupTable.cpp:147
clang::ASTImporterLookupTable::update
void update(NamedDecl *ND, DeclContext *OldDC)
Definition: ASTImporterLookupTable.cpp:120
clang::ASTImporterLookupTable::ASTImporterLookupTable
ASTImporterLookupTable(TranslationUnitDecl &TU)
Definition: ASTImporterLookupTable.cpp:84
clang::DeclContext::getRedeclContext
DeclContext * getRedeclContext()
getRedeclContext - Retrieve the context in which an entity conflicts with other entities of the same ...
Definition: DeclBase.cpp:1780
clang::ASTImporterLookupTable::dump
void dump() const
Definition: ASTImporterLookupTable.cpp:167
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:439