1 //===- ASTImporterLookupTable.cpp - ASTImporter specific lookup -----------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file defines the ASTImporterLookupTable class which implements a
10 // lookup procedure for the import mechanism.
12 //===----------------------------------------------------------------------===//
14 #include "clang/AST/ASTImporterLookupTable.h"
15 #include "clang/AST/Decl.h"
16 #include "clang/AST/RecursiveASTVisitor.h"
17 #include "llvm/Support/FormatVariadic.h"
23 struct Builder
: RecursiveASTVisitor
<Builder
> {
24 ASTImporterLookupTable
<
;
25 Builder(ASTImporterLookupTable
<
) : LT(LT
) {}
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()) {
40 bool VisitNamedDecl(NamedDecl
*D
) {
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.
73 llvm_unreachable("Unhandled type of friend class");
80 // Override default settings of base.
81 bool shouldVisitTemplateInstantiations() const { return true; }
82 bool shouldVisitImplicitCode() const { return true; }
85 } // anonymous namespace
87 ASTImporterLookupTable::ASTImporterLookupTable(TranslationUnitDecl
&TU
) {
92 void ASTImporterLookupTable::add(DeclContext
*DC
, NamedDecl
*ND
) {
93 DeclList
&Decls
= LookupTable
[DC
][ND
->getDeclName()];
94 // Inserts if and only if there is no element in the container equal to it.
98 void ASTImporterLookupTable::remove(DeclContext
*DC
, NamedDecl
*ND
) {
99 const DeclarationName Name
= ND
->getDeclName();
100 DeclList
&Decls
= LookupTable
[DC
][Name
];
101 bool EraseResult
= Decls
.remove(ND
);
105 std::string Message
=
106 llvm::formatv("Trying to remove not contained Decl '{0}' of type {1}",
107 Name
.getAsString(), DC
->getDeclKindName())
109 llvm_unreachable(Message
.c_str());
114 void ASTImporterLookupTable::add(NamedDecl
*ND
) {
116 DeclContext
*DC
= ND
->getDeclContext()->getPrimaryContext();
118 DeclContext
*ReDC
= DC
->getRedeclContext()->getPrimaryContext();
123 void ASTImporterLookupTable::remove(NamedDecl
*ND
) {
125 DeclContext
*DC
= ND
->getDeclContext()->getPrimaryContext();
127 DeclContext
*ReDC
= DC
->getRedeclContext()->getPrimaryContext();
132 void ASTImporterLookupTable::update(NamedDecl
*ND
, DeclContext
*OldDC
) {
133 assert(OldDC
!= ND
->getDeclContext() &&
134 "DeclContext should be changed before update");
135 if (contains(ND
->getDeclContext(), ND
)) {
136 assert(!contains(OldDC
, ND
) &&
137 "Decl should not be found in the old context if already in the new");
145 void ASTImporterLookupTable::updateForced(NamedDecl
*ND
, DeclContext
*OldDC
) {
146 LookupTable
[OldDC
][ND
->getDeclName()].remove(ND
);
150 ASTImporterLookupTable::LookupResult
151 ASTImporterLookupTable::lookup(DeclContext
*DC
, DeclarationName Name
) const {
152 auto DCI
= LookupTable
.find(DC
->getPrimaryContext());
153 if (DCI
== LookupTable
.end())
156 const auto &FoundNameMap
= DCI
->second
;
157 auto NamesI
= FoundNameMap
.find(Name
);
158 if (NamesI
== FoundNameMap
.end())
161 return NamesI
->second
;
164 bool ASTImporterLookupTable::contains(DeclContext
*DC
, NamedDecl
*ND
) const {
165 return lookup(DC
, ND
->getDeclName()).contains(ND
);
168 void ASTImporterLookupTable::dump(DeclContext
*DC
) const {
169 auto DCI
= LookupTable
.find(DC
->getPrimaryContext());
170 if (DCI
== LookupTable
.end())
171 llvm::errs() << "empty\n";
172 const auto &FoundNameMap
= DCI
->second
;
173 for (const auto &Entry
: FoundNameMap
) {
174 DeclarationName Name
= Entry
.first
;
175 llvm::errs() << "==== Name: ";
177 const DeclList
& List
= Entry
.second
;
178 for (NamedDecl
*ND
: List
) {
184 void ASTImporterLookupTable::dump() const {
185 for (const auto &Entry
: LookupTable
) {
186 DeclContext
*DC
= Entry
.first
;
187 StringRef Primary
= DC
->getPrimaryContext() ? " primary" : "";
188 llvm::errs() << "== DC:" << cast
<Decl
>(DC
) << Primary
<< "\n";