150
|
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
|
|
14 #include "clang/AST/ASTImporterLookupTable.h"
|
|
15 #include "clang/AST/Decl.h"
|
|
16 #include "clang/AST/RecursiveASTVisitor.h"
|
|
17
|
|
18 namespace clang {
|
|
19
|
|
20 namespace {
|
|
21
|
|
22 struct Builder : RecursiveASTVisitor<Builder> {
|
|
23 ASTImporterLookupTable <
|
|
24 Builder(ASTImporterLookupTable <) : LT(LT) {}
|
|
25 bool VisitNamedDecl(NamedDecl *D) {
|
|
26 LT.add(D);
|
|
27 return true;
|
|
28 }
|
|
29 // In most cases the FriendDecl contains the declaration of the befriended
|
|
30 // class as a child node, so it is discovered during the recursive
|
|
31 // visitation. However, there are cases when the befriended class is not a
|
|
32 // child, thus it must be fetched explicitly from the FriendDecl, and only
|
|
33 // then can we add it to the lookup table.
|
|
34 bool VisitFriendDecl(FriendDecl *D) {
|
|
35 if (D->getFriendType()) {
|
|
36 QualType Ty = D->getFriendType()->getType();
|
|
37 if (isa<ElaboratedType>(Ty))
|
|
38 Ty = cast<ElaboratedType>(Ty)->getNamedType();
|
|
39 // A FriendDecl with a dependent type (e.g. ClassTemplateSpecialization)
|
|
40 // always has that decl as child node.
|
|
41 // However, there are non-dependent cases which does not have the
|
|
42 // type as a child node. We have to dig up that type now.
|
|
43 if (!Ty->isDependentType()) {
|
|
44 if (const auto *RTy = dyn_cast<RecordType>(Ty))
|
|
45 LT.add(RTy->getAsCXXRecordDecl());
|
|
46 else if (const auto *SpecTy = dyn_cast<TemplateSpecializationType>(Ty))
|
|
47 LT.add(SpecTy->getAsCXXRecordDecl());
|
|
48 else if (isa<TypedefType>(Ty)) {
|
|
49 // We do not put friend typedefs to the lookup table because
|
|
50 // ASTImporter does not organize typedefs into redecl chains.
|
|
51 } else {
|
|
52 llvm_unreachable("Unhandled type of friend class");
|
|
53 }
|
|
54 }
|
|
55 }
|
|
56 return true;
|
|
57 }
|
|
58
|
|
59 // Override default settings of base.
|
|
60 bool shouldVisitTemplateInstantiations() const { return true; }
|
|
61 bool shouldVisitImplicitCode() const { return true; }
|
|
62 };
|
|
63
|
|
64 } // anonymous namespace
|
|
65
|
|
66 ASTImporterLookupTable::ASTImporterLookupTable(TranslationUnitDecl &TU) {
|
|
67 Builder B(*this);
|
|
68 B.TraverseDecl(&TU);
|
|
69 }
|
|
70
|
|
71 void ASTImporterLookupTable::add(DeclContext *DC, NamedDecl *ND) {
|
|
72 DeclList &Decls = LookupTable[DC][ND->getDeclName()];
|
|
73 // Inserts if and only if there is no element in the container equal to it.
|
|
74 Decls.insert(ND);
|
|
75 }
|
|
76
|
|
77 void ASTImporterLookupTable::remove(DeclContext *DC, NamedDecl *ND) {
|
|
78 DeclList &Decls = LookupTable[DC][ND->getDeclName()];
|
|
79 bool EraseResult = Decls.remove(ND);
|
|
80 (void)EraseResult;
|
|
81 assert(EraseResult == true && "Trying to remove not contained Decl");
|
|
82 }
|
|
83
|
|
84 void ASTImporterLookupTable::add(NamedDecl *ND) {
|
|
85 assert(ND);
|
|
86 DeclContext *DC = ND->getDeclContext()->getPrimaryContext();
|
|
87 add(DC, ND);
|
|
88 DeclContext *ReDC = DC->getRedeclContext()->getPrimaryContext();
|
|
89 if (DC != ReDC)
|
|
90 add(ReDC, ND);
|
|
91 }
|
|
92
|
|
93 void ASTImporterLookupTable::remove(NamedDecl *ND) {
|
|
94 assert(ND);
|
|
95 DeclContext *DC = ND->getDeclContext()->getPrimaryContext();
|
|
96 remove(DC, ND);
|
|
97 DeclContext *ReDC = DC->getRedeclContext()->getPrimaryContext();
|
|
98 if (DC != ReDC)
|
|
99 remove(ReDC, ND);
|
|
100 }
|
|
101
|
|
102 ASTImporterLookupTable::LookupResult
|
|
103 ASTImporterLookupTable::lookup(DeclContext *DC, DeclarationName Name) const {
|
|
104 auto DCI = LookupTable.find(DC->getPrimaryContext());
|
|
105 if (DCI == LookupTable.end())
|
|
106 return {};
|
|
107
|
|
108 const auto &FoundNameMap = DCI->second;
|
|
109 auto NamesI = FoundNameMap.find(Name);
|
|
110 if (NamesI == FoundNameMap.end())
|
|
111 return {};
|
|
112
|
|
113 return NamesI->second;
|
|
114 }
|
|
115
|
|
116 void ASTImporterLookupTable::dump(DeclContext *DC) const {
|
|
117 auto DCI = LookupTable.find(DC->getPrimaryContext());
|
|
118 if (DCI == LookupTable.end())
|
|
119 llvm::errs() << "empty\n";
|
|
120 const auto &FoundNameMap = DCI->second;
|
|
121 for (const auto &Entry : FoundNameMap) {
|
|
122 DeclarationName Name = Entry.first;
|
|
123 llvm::errs() << "==== Name: ";
|
|
124 Name.dump();
|
|
125 const DeclList& List = Entry.second;
|
|
126 for (NamedDecl *ND : List) {
|
|
127 ND->dump();
|
|
128 }
|
|
129 }
|
|
130 }
|
|
131
|
|
132 void ASTImporterLookupTable::dump() const {
|
|
133 for (const auto &Entry : LookupTable) {
|
|
134 DeclContext *DC = Entry.first;
|
|
135 StringRef Primary = DC->getPrimaryContext() ? " primary" : "";
|
|
136 llvm::errs() << "== DC:" << cast<Decl>(DC) << Primary << "\n";
|
|
137 dump(DC);
|
|
138 }
|
|
139 }
|
|
140
|
|
141 } // namespace clang
|