/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/AST/ASTImporterLookupTable.cpp
Line | Count | Source (jump to first uncovered line) |
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 | | #include "llvm/Support/FormatVariadic.h" |
18 | | |
19 | | namespace clang { |
20 | | |
21 | | namespace { |
22 | | |
23 | | struct Builder : RecursiveASTVisitor<Builder> { |
24 | | ASTImporterLookupTable < |
25 | 2.43k | Builder(ASTImporterLookupTable <) : LT(LT) {} |
26 | | |
27 | 12.6k | bool VisitTypedefNameDecl(TypedefNameDecl *D) { |
28 | 12.6k | QualType Ty = D->getUnderlyingType(); |
29 | 12.6k | Ty = Ty.getCanonicalType(); |
30 | 12.6k | if (const auto *RTy = dyn_cast<RecordType>(Ty)) { |
31 | 2.29k | LT.add(RTy->getAsRecordDecl()); |
32 | | // iterate over the field decls, adding them |
33 | 9.14k | for (auto *it : RTy->getAsRecordDecl()->fields()) { |
34 | 9.14k | LT.add(it); |
35 | 9.14k | } |
36 | 2.29k | } |
37 | 12.6k | return true; |
38 | 12.6k | } |
39 | | |
40 | 19.0k | bool VisitNamedDecl(NamedDecl *D) { |
41 | 19.0k | LT.add(D); |
42 | 19.0k | return true; |
43 | 19.0k | } |
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 | 132 | bool VisitFriendDecl(FriendDecl *D) { |
50 | 132 | if (D->getFriendType()) { |
51 | 76 | QualType Ty = D->getFriendType()->getType(); |
52 | 76 | if (isa<ElaboratedType>(Ty)) |
53 | 52 | 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 | 76 | if (!Ty->isDependentType()) { |
59 | 64 | if (const auto *RTy = dyn_cast<RecordType>(Ty)) |
60 | 44 | LT.add(RTy->getAsCXXRecordDecl()); |
61 | 20 | else if (const auto *SpecTy = dyn_cast<TemplateSpecializationType>(Ty)) |
62 | 8 | LT.add(SpecTy->getAsCXXRecordDecl()); |
63 | 12 | else if (const auto *SubstTy = |
64 | 12 | dyn_cast<SubstTemplateTypeParmType>(Ty)) { |
65 | 4 | if (SubstTy->getAsCXXRecordDecl()) |
66 | 4 | LT.add(SubstTy->getAsCXXRecordDecl()); |
67 | 8 | } 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 | 8 | } else { |
71 | 0 | llvm_unreachable("Unhandled type of friend class"); |
72 | 0 | } |
73 | 64 | } |
74 | 76 | } |
75 | 132 | return true; |
76 | 132 | } |
77 | | |
78 | | // Override default settings of base. |
79 | 439 | bool shouldVisitTemplateInstantiations() const { return true; } |
80 | 22.3k | bool shouldVisitImplicitCode() const { return true; } |
81 | | }; |
82 | | |
83 | | } // anonymous namespace |
84 | | |
85 | 2.43k | ASTImporterLookupTable::ASTImporterLookupTable(TranslationUnitDecl &TU) { |
86 | 2.43k | Builder B(*this); |
87 | 2.43k | B.TraverseDecl(&TU); |
88 | 2.43k | } |
89 | | |
90 | 49.4k | void ASTImporterLookupTable::add(DeclContext *DC, NamedDecl *ND) { |
91 | 49.4k | DeclList &Decls = LookupTable[DC][ND->getDeclName()]; |
92 | | // Inserts if and only if there is no element in the container equal to it. |
93 | 49.4k | Decls.insert(ND); |
94 | 49.4k | } |
95 | | |
96 | 2.01k | void ASTImporterLookupTable::remove(DeclContext *DC, NamedDecl *ND) { |
97 | 2.01k | const DeclarationName Name = ND->getDeclName(); |
98 | 2.01k | DeclList &Decls = LookupTable[DC][Name]; |
99 | 2.01k | bool EraseResult = Decls.remove(ND); |
100 | 2.01k | (void)EraseResult; |
101 | 2.01k | #ifndef NDEBUG |
102 | 2.01k | if (!EraseResult) { |
103 | 0 | std::string Message = |
104 | 0 | llvm::formatv("Trying to remove not contained Decl '{0}' of type {1}", |
105 | 0 | Name.getAsString(), DC->getDeclKindName()) |
106 | 0 | .str(); |
107 | 0 | llvm_unreachable(Message.c_str()); |
108 | 0 | } |
109 | 2.01k | #endif |
110 | 2.01k | } |
111 | | |
112 | 49.3k | void ASTImporterLookupTable::add(NamedDecl *ND) { |
113 | 49.3k | assert(ND); |
114 | 0 | DeclContext *DC = ND->getDeclContext()->getPrimaryContext(); |
115 | 49.3k | add(DC, ND); |
116 | 49.3k | DeclContext *ReDC = DC->getRedeclContext()->getPrimaryContext(); |
117 | 49.3k | if (DC != ReDC) |
118 | 117 | add(ReDC, ND); |
119 | 49.3k | } |
120 | | |
121 | 129 | void ASTImporterLookupTable::remove(NamedDecl *ND) { |
122 | 129 | assert(ND); |
123 | 0 | DeclContext *DC = ND->getDeclContext()->getPrimaryContext(); |
124 | 129 | remove(DC, ND); |
125 | 129 | DeclContext *ReDC = DC->getRedeclContext()->getPrimaryContext(); |
126 | 129 | if (DC != ReDC) |
127 | 0 | remove(ReDC, ND); |
128 | 129 | } |
129 | | |
130 | 1.89k | void ASTImporterLookupTable::update(NamedDecl *ND, DeclContext *OldDC) { |
131 | 1.89k | assert(OldDC != ND->getDeclContext() && |
132 | 1.89k | "DeclContext should be changed before update"); |
133 | 1.89k | if (contains(ND->getDeclContext(), ND)) { |
134 | 0 | assert(!contains(OldDC, ND) && |
135 | 0 | "Decl should not be found in the old context if already in the new"); |
136 | 0 | return; |
137 | 0 | } |
138 | | |
139 | 1.89k | remove(OldDC, ND); |
140 | 1.89k | add(ND); |
141 | 1.89k | } |
142 | | |
143 | 493 | void ASTImporterLookupTable::updateForced(NamedDecl *ND, DeclContext *OldDC) { |
144 | 493 | LookupTable[OldDC][ND->getDeclName()].remove(ND); |
145 | 493 | add(ND); |
146 | 493 | } |
147 | | |
148 | | ASTImporterLookupTable::LookupResult |
149 | 14.2k | ASTImporterLookupTable::lookup(DeclContext *DC, DeclarationName Name) const { |
150 | 14.2k | auto DCI = LookupTable.find(DC->getPrimaryContext()); |
151 | 14.2k | if (DCI == LookupTable.end()) |
152 | 3.29k | return {}; |
153 | | |
154 | 11.0k | const auto &FoundNameMap = DCI->second; |
155 | 11.0k | auto NamesI = FoundNameMap.find(Name); |
156 | 11.0k | if (NamesI == FoundNameMap.end()) |
157 | 6.25k | return {}; |
158 | | |
159 | 4.74k | return NamesI->second; |
160 | 11.0k | } |
161 | | |
162 | 1.93k | bool ASTImporterLookupTable::contains(DeclContext *DC, NamedDecl *ND) const { |
163 | 1.93k | return lookup(DC, ND->getDeclName()).contains(ND); |
164 | 1.93k | } |
165 | | |
166 | 0 | void ASTImporterLookupTable::dump(DeclContext *DC) const { |
167 | 0 | auto DCI = LookupTable.find(DC->getPrimaryContext()); |
168 | 0 | if (DCI == LookupTable.end()) |
169 | 0 | llvm::errs() << "empty\n"; |
170 | 0 | const auto &FoundNameMap = DCI->second; |
171 | 0 | for (const auto &Entry : FoundNameMap) { |
172 | 0 | DeclarationName Name = Entry.first; |
173 | 0 | llvm::errs() << "==== Name: "; |
174 | 0 | Name.dump(); |
175 | 0 | const DeclList& List = Entry.second; |
176 | 0 | for (NamedDecl *ND : List) { |
177 | 0 | ND->dump(); |
178 | 0 | } |
179 | 0 | } |
180 | 0 | } |
181 | | |
182 | 0 | void ASTImporterLookupTable::dump() const { |
183 | 0 | for (const auto &Entry : LookupTable) { |
184 | 0 | DeclContext *DC = Entry.first; |
185 | 0 | StringRef Primary = DC->getPrimaryContext() ? " primary" : ""; |
186 | 0 | llvm::errs() << "== DC:" << cast<Decl>(DC) << Primary << "\n"; |
187 | 0 | dump(DC); |
188 | 0 | } |
189 | 0 | } |
190 | | |
191 | | } // namespace clang |