/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/AST/ExternalASTMerger.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===- ExternalASTMerger.cpp - Merging External AST Interface ---*- C++ -*-===// |
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 implements the ExternalASTMerger, which vends a combination of |
10 | | // ASTs from several different ASTContext/FileManager pairs |
11 | | // |
12 | | //===----------------------------------------------------------------------===// |
13 | | |
14 | | #include "clang/AST/ASTContext.h" |
15 | | #include "clang/AST/Decl.h" |
16 | | #include "clang/AST/DeclCXX.h" |
17 | | #include "clang/AST/DeclObjC.h" |
18 | | #include "clang/AST/DeclTemplate.h" |
19 | | #include "clang/AST/ExternalASTMerger.h" |
20 | | |
21 | | using namespace clang; |
22 | | |
23 | | namespace { |
24 | | |
25 | | template <typename T> struct Source { |
26 | | T t; |
27 | 11.3k | Source(T t) : t(t) {} ExternalASTMerger.cpp:(anonymous namespace)::Source<clang::DeclContext const*>::Source(clang::DeclContext const*) Line | Count | Source | 27 | 5.01k | Source(T t) : t(t) {} |
ExternalASTMerger.cpp:(anonymous namespace)::Source<clang::DeclarationName>::Source(clang::DeclarationName) Line | Count | Source | 27 | 1.67k | Source(T t) : t(t) {} |
ExternalASTMerger.cpp:(anonymous namespace)::Source<clang::TranslationUnitDecl*>::Source(clang::TranslationUnitDecl*) Line | Count | Source | 27 | 2.95k | Source(T t) : t(t) {} |
ExternalASTMerger.cpp:(anonymous namespace)::Source<clang::DeclContext*>::Source(clang::DeclContext*) Line | Count | Source | 27 | 739 | Source(T t) : t(t) {} |
ExternalASTMerger.cpp:(anonymous namespace)::Source<clang::NamedDecl*>::Source(clang::NamedDecl*) Line | Count | Source | 27 | 955 | Source(T t) : t(t) {} |
|
28 | 6.35k | operator T() { return t; } ExternalASTMerger.cpp:(anonymous namespace)::Source<clang::DeclContext const*>::operator clang::DeclContext const*() Line | Count | Source | 28 | 4.68k | operator T() { return t; } |
ExternalASTMerger.cpp:(anonymous namespace)::Source<clang::DeclContext*>::operator clang::DeclContext*() Line | Count | Source | 28 | 1.66k | operator T() { return t; } |
|
29 | 5.79k | template <typename U = T> U &get() { return t; } ExternalASTMerger.cpp:clang::DeclarationName& (anonymous namespace)::Source<clang::DeclarationName>::get<clang::DeclarationName>() Line | Count | Source | 29 | 1.67k | template <typename U = T> U &get() { return t; } |
ExternalASTMerger.cpp:clang::DeclContext const*& (anonymous namespace)::Source<clang::DeclContext const*>::get<clang::DeclContext const*>() Line | Count | Source | 29 | 4.12k | template <typename U = T> U &get() { return t; } |
|
30 | 1.98k | template <typename U = T> const U &get() const { return t; } |
31 | 2.95k | template <typename U> operator Source<U>() { return Source<U>(t); } |
32 | | }; |
33 | | |
34 | | typedef std::pair<Source<NamedDecl *>, ASTImporter *> Candidate; |
35 | | |
36 | | /// For the given DC, return the DC that is safe to perform lookups on. This is |
37 | | /// the DC we actually want to work with most of the time. |
38 | 4.68k | const DeclContext *CanonicalizeDC(const DeclContext *DC) { |
39 | 4.68k | if (isa<LinkageSpecDecl>(DC)) |
40 | 6 | return DC->getRedeclContext(); |
41 | 4.68k | return DC; |
42 | 4.68k | } |
43 | | |
44 | | Source<const DeclContext *> |
45 | | LookupSameContext(Source<TranslationUnitDecl *> SourceTU, const DeclContext *DC, |
46 | 4.68k | ASTImporter &ReverseImporter) { |
47 | 4.68k | DC = CanonicalizeDC(DC); |
48 | 4.68k | if (DC->isTranslationUnit()) { |
49 | 2.95k | return SourceTU; |
50 | 2.95k | } |
51 | 1.73k | Source<const DeclContext *> SourceParentDC = |
52 | 1.73k | LookupSameContext(SourceTU, DC->getParent(), ReverseImporter); |
53 | 1.73k | if (!SourceParentDC) { |
54 | | // If we couldn't find the parent DC in this TranslationUnit, give up. |
55 | 55 | return nullptr; |
56 | 55 | } |
57 | 1.67k | auto *ND = cast<NamedDecl>(DC); |
58 | 1.67k | DeclarationName Name = ND->getDeclName(); |
59 | 1.67k | auto SourceNameOrErr = ReverseImporter.Import(Name); |
60 | 1.67k | if (!SourceNameOrErr) { |
61 | 2 | llvm::consumeError(SourceNameOrErr.takeError()); |
62 | 2 | return nullptr; |
63 | 2 | } |
64 | 1.67k | Source<DeclarationName> SourceName = *SourceNameOrErr; |
65 | 1.67k | DeclContext::lookup_result SearchResult = |
66 | 1.67k | SourceParentDC.get()->lookup(SourceName.get()); |
67 | | |
68 | | // There are two cases here. First, we might not find the name. |
69 | | // We might also find multiple copies, in which case we have no |
70 | | // guarantee that the one we wanted is the one we pick. (E.g., |
71 | | // if we have two specializations of the same template it is |
72 | | // very hard to determine which is the one you want.) |
73 | | // |
74 | | // The Origins map fixes this problem by allowing the origin to be |
75 | | // explicitly recorded, so we trigger that recording by returning |
76 | | // nothing (rather than a possibly-inaccurate guess) here. |
77 | 1.67k | if (SearchResult.isSingleResult()) { |
78 | 1.42k | NamedDecl *SearchResultDecl = SearchResult.front(); |
79 | 1.42k | if (isa<DeclContext>(SearchResultDecl) && |
80 | 1.42k | SearchResultDecl->getKind() == DC->getDeclKind()1.36k ) |
81 | 1.36k | return cast<DeclContext>(SearchResultDecl)->getPrimaryContext(); |
82 | 55 | return nullptr; // This type of lookup is unsupported |
83 | 1.42k | } else { |
84 | 253 | return nullptr; |
85 | 253 | } |
86 | 1.67k | } |
87 | | |
88 | | /// A custom implementation of ASTImporter, for ExternalASTMerger's purposes. |
89 | | /// |
90 | | /// There are several modifications: |
91 | | /// |
92 | | /// - It enables lazy lookup (via the HasExternalLexicalStorage flag and a few |
93 | | /// others), which instructs Clang to refer to ExternalASTMerger. Also, it |
94 | | /// forces MinimalImport to true, which is necessary to make this work. |
95 | | /// - It maintains a reverse importer for use with names. This allows lookup of |
96 | | /// arbitrary names in the source context. |
97 | | /// - It updates the ExternalASTMerger's origin map as needed whenever a |
98 | | /// it sees a DeclContext. |
99 | | class LazyASTImporter : public ASTImporter { |
100 | | private: |
101 | | ExternalASTMerger &Parent; |
102 | | ASTImporter Reverse; |
103 | | const ExternalASTMerger::OriginMap &FromOrigins; |
104 | | /// @see ExternalASTMerger::ImporterSource::Temporary |
105 | | bool TemporarySource; |
106 | | /// Map of imported declarations back to the declarations they originated |
107 | | /// from. |
108 | | llvm::DenseMap<Decl *, Decl *> ToOrigin; |
109 | | /// @see ExternalASTMerger::ImporterSource::Merger |
110 | | ExternalASTMerger *SourceMerger; |
111 | 0 | llvm::raw_ostream &logs() { return Parent.logs(); } |
112 | | public: |
113 | | LazyASTImporter(ExternalASTMerger &_Parent, ASTContext &ToContext, |
114 | | FileManager &ToFileManager, |
115 | | const ExternalASTMerger::ImporterSource &S, |
116 | | std::shared_ptr<ASTImporterSharedState> SharedState) |
117 | | : ASTImporter(ToContext, ToFileManager, S.getASTContext(), |
118 | | S.getFileManager(), |
119 | | /*MinimalImport=*/true, SharedState), |
120 | | Parent(_Parent), |
121 | | Reverse(S.getASTContext(), S.getFileManager(), ToContext, ToFileManager, |
122 | | /*MinimalImport=*/true), |
123 | | FromOrigins(S.getOriginMap()), TemporarySource(S.isTemporary()), |
124 | 132 | SourceMerger(S.getMerger()) {} |
125 | | |
126 | 2.37k | llvm::Expected<Decl *> ImportImpl(Decl *FromD) override { |
127 | 2.37k | if (!TemporarySource || !SourceMerger0 ) |
128 | 2.37k | return ASTImporter::ImportImpl(FromD); |
129 | | |
130 | | // If we get here, then this source is importing from a temporary ASTContext |
131 | | // that also has another ExternalASTMerger attached. It could be |
132 | | // possible that the current ExternalASTMerger and the temporary ASTContext |
133 | | // share a common ImporterSource, which means that the temporary |
134 | | // AST could contain declarations that were imported from a source |
135 | | // that this ExternalASTMerger can access directly. Instead of importing |
136 | | // such declarations from the temporary ASTContext, they should instead |
137 | | // be directly imported by this ExternalASTMerger from the original |
138 | | // source. This way the ExternalASTMerger can safely do a minimal import |
139 | | // without creating incomplete declarations originated from a temporary |
140 | | // ASTContext. If we would try to complete such declarations later on, we |
141 | | // would fail to do so as their temporary AST could be deleted (which means |
142 | | // that the missing parts of the minimally imported declaration in that |
143 | | // ASTContext were also deleted). |
144 | | // |
145 | | // The following code tracks back any declaration that needs to be |
146 | | // imported from the temporary ASTContext to a persistent ASTContext. |
147 | | // Then the ExternalASTMerger tries to import from the persistent |
148 | | // ASTContext directly by using the associated ASTImporter. If that |
149 | | // succeeds, this ASTImporter just maps the declarations imported by |
150 | | // the other (persistent) ASTImporter to this (temporary) ASTImporter. |
151 | | // The steps can be visualized like this: |
152 | | // |
153 | | // Target AST <--- 3. Indirect import --- Persistent AST |
154 | | // ^ of persistent decl ^ |
155 | | // | | |
156 | | // 1. Current import 2. Tracking back to persistent decl |
157 | | // 4. Map persistent decl | |
158 | | // & pretend we imported. | |
159 | | // | | |
160 | | // Temporary AST -------------------------------' |
161 | | |
162 | | // First, ask the ExternalASTMerger of the source where the temporary |
163 | | // declaration originated from. |
164 | 0 | Decl *Persistent = SourceMerger->FindOriginalDecl(FromD); |
165 | | // FromD isn't from a persistent AST, so just do a normal import. |
166 | 0 | if (!Persistent) |
167 | 0 | return ASTImporter::ImportImpl(FromD); |
168 | | // Now ask the current ExternalASTMerger to try import the persistent |
169 | | // declaration into the target. |
170 | 0 | ASTContext &PersistentCtx = Persistent->getASTContext(); |
171 | 0 | ASTImporter &OtherImporter = Parent.ImporterForOrigin(PersistentCtx); |
172 | | // Check that we never end up in the current Importer again. |
173 | 0 | assert((&PersistentCtx != &getFromContext()) && (&OtherImporter != this) && |
174 | 0 | "Delegated to same Importer?"); |
175 | 0 | auto DeclOrErr = OtherImporter.Import(Persistent); |
176 | | // Errors when importing the persistent decl are treated as if we |
177 | | // had errors with importing the temporary decl. |
178 | 0 | if (!DeclOrErr) |
179 | 0 | return DeclOrErr.takeError(); |
180 | 0 | Decl *D = *DeclOrErr; |
181 | | // Tell the current ASTImporter that this has already been imported |
182 | | // to prevent any further queries for the temporary decl. |
183 | 0 | MapImported(FromD, D); |
184 | 0 | return D; |
185 | 0 | } |
186 | | |
187 | | /// Implements the ASTImporter interface for tracking back a declaration |
188 | | /// to its original declaration it came from. |
189 | 61 | Decl *GetOriginalDecl(Decl *To) override { |
190 | 61 | auto It = ToOrigin.find(To); |
191 | 61 | if (It != ToOrigin.end()) |
192 | 54 | return It->second; |
193 | 7 | return nullptr; |
194 | 61 | } |
195 | | |
196 | | /// Whenever a DeclContext is imported, ensure that ExternalASTSource's origin |
197 | | /// map is kept up to date. Also set the appropriate flags. |
198 | 2.37k | void Imported(Decl *From, Decl *To) override { |
199 | 2.37k | ToOrigin[To] = From; |
200 | | |
201 | 2.37k | if (auto *ToDC = dyn_cast<DeclContext>(To)) { |
202 | 739 | const bool LoggingEnabled = Parent.LoggingEnabled(); |
203 | 739 | if (LoggingEnabled) |
204 | 0 | logs() << "(ExternalASTMerger*)" << (void*)&Parent |
205 | 0 | << " imported (DeclContext*)" << (void*)ToDC |
206 | 0 | << ", (ASTContext*)" << (void*)&getToContext() |
207 | 0 | << " from (DeclContext*)" << (void*)llvm::cast<DeclContext>(From) |
208 | 0 | << ", (ASTContext*)" << (void*)&getFromContext() |
209 | 0 | << "\n"; |
210 | 739 | Source<DeclContext *> FromDC( |
211 | 739 | cast<DeclContext>(From)->getPrimaryContext()); |
212 | 739 | if (FromOrigins.count(FromDC) && |
213 | 739 | Parent.HasImporterForOrigin(*FromOrigins.at(FromDC).AST)187 ) { |
214 | 4 | if (LoggingEnabled) |
215 | 0 | logs() << "(ExternalASTMerger*)" << (void*)&Parent |
216 | 0 | << " forced origin (DeclContext*)" |
217 | 0 | << (void*)FromOrigins.at(FromDC).DC |
218 | 0 | << ", (ASTContext*)" |
219 | 0 | << (void*)FromOrigins.at(FromDC).AST |
220 | 0 | << "\n"; |
221 | 4 | Parent.ForceRecordOrigin(ToDC, FromOrigins.at(FromDC)); |
222 | 735 | } else { |
223 | 735 | if (LoggingEnabled) |
224 | 0 | logs() << "(ExternalASTMerger*)" << (void*)&Parent |
225 | 0 | << " maybe recording origin (DeclContext*)" << (void*)FromDC |
226 | 0 | << ", (ASTContext*)" << (void*)&getFromContext() |
227 | 0 | << "\n"; |
228 | 735 | Parent.MaybeRecordOrigin(ToDC, {FromDC, &getFromContext()}); |
229 | 735 | } |
230 | 739 | } |
231 | 2.37k | if (auto *ToTag = dyn_cast<TagDecl>(To)) { |
232 | 468 | ToTag->setHasExternalLexicalStorage(); |
233 | 468 | ToTag->getPrimaryContext()->setMustBuildLookupTable(); |
234 | 468 | assert(Parent.CanComplete(ToTag)); |
235 | 1.90k | } else if (auto *ToNamespace = dyn_cast<NamespaceDecl>(To)) { |
236 | 24 | ToNamespace->setHasExternalVisibleStorage(); |
237 | 24 | assert(Parent.CanComplete(ToNamespace)); |
238 | 1.88k | } else if (auto *ToContainer = dyn_cast<ObjCContainerDecl>(To)) { |
239 | 32 | ToContainer->setHasExternalLexicalStorage(); |
240 | 32 | ToContainer->getPrimaryContext()->setMustBuildLookupTable(); |
241 | 32 | assert(Parent.CanComplete(ToContainer)); |
242 | 32 | } |
243 | 2.37k | } |
244 | 3.28k | ASTImporter &GetReverse() { return Reverse; } |
245 | | }; |
246 | | |
247 | 955 | bool HasDeclOfSameType(llvm::ArrayRef<Candidate> Decls, const Candidate &C) { |
248 | 955 | if (isa<FunctionDecl>(C.first.get())) |
249 | 75 | return false; |
250 | 880 | return llvm::any_of(Decls, [&](const Candidate &D) { |
251 | 76 | return C.first.get()->getKind() == D.first.get()->getKind(); |
252 | 76 | }); |
253 | 955 | } |
254 | | |
255 | | } // end namespace |
256 | | |
257 | 1.06k | ASTImporter &ExternalASTMerger::ImporterForOrigin(ASTContext &OriginContext) { |
258 | 1.06k | for (const std::unique_ptr<ASTImporter> &I : Importers) |
259 | 1.10k | if (&I->getFromContext() == &OriginContext) |
260 | 1.06k | return *I; |
261 | 0 | llvm_unreachable("We should have an importer for this origin!"); |
262 | 0 | } |
263 | | |
264 | | namespace { |
265 | | LazyASTImporter &LazyImporterForOrigin(ExternalASTMerger &Merger, |
266 | 1.06k | ASTContext &OriginContext) { |
267 | 1.06k | return static_cast<LazyASTImporter &>( |
268 | 1.06k | Merger.ImporterForOrigin(OriginContext)); |
269 | 1.06k | } |
270 | | } |
271 | | |
272 | 187 | bool ExternalASTMerger::HasImporterForOrigin(ASTContext &OriginContext) { |
273 | 187 | for (const std::unique_ptr<ASTImporter> &I : Importers) |
274 | 215 | if (&I->getFromContext() == &OriginContext) |
275 | 4 | return true; |
276 | 183 | return false; |
277 | 187 | } |
278 | | |
279 | | template <typename CallbackType> |
280 | | void ExternalASTMerger::ForEachMatchingDC(const DeclContext *DC, |
281 | 2.39k | CallbackType Callback) { |
282 | 2.39k | if (Origins.count(DC)) { |
283 | 329 | ExternalASTMerger::DCOrigin Origin = Origins[DC]; |
284 | 329 | LazyASTImporter &Importer = LazyImporterForOrigin(*this, *Origin.AST); |
285 | 329 | Callback(Importer, Importer.GetReverse(), Origin.DC); |
286 | 2.06k | } else { |
287 | 2.06k | bool DidCallback = false; |
288 | 2.22k | for (const std::unique_ptr<ASTImporter> &Importer : Importers) { |
289 | 2.22k | Source<TranslationUnitDecl *> SourceTU = |
290 | 2.22k | Importer->getFromContext().getTranslationUnitDecl(); |
291 | 2.22k | ASTImporter &Reverse = |
292 | 2.22k | static_cast<LazyASTImporter *>(Importer.get())->GetReverse(); |
293 | 2.22k | if (auto SourceDC = LookupSameContext(SourceTU, DC, Reverse)) { |
294 | 2.19k | DidCallback = true; |
295 | 2.19k | if (Callback(*Importer, Reverse, SourceDC)) |
296 | 331 | break; |
297 | 2.19k | } |
298 | 2.22k | } |
299 | 2.06k | if (!DidCallback && LoggingEnabled()0 ) |
300 | 0 | logs() << "(ExternalASTMerger*)" << (void*)this |
301 | 0 | << " asserting for (DeclContext*)" << (const void*)DC |
302 | 0 | << ", (ASTContext*)" << (void*)&Target.AST |
303 | 0 | << "\n"; |
304 | 2.06k | assert(DidCallback && "Couldn't find a source context matching our DC"); |
305 | 2.06k | } |
306 | 2.39k | } ExternalASTMerger.cpp:void clang::ExternalASTMerger::ForEachMatchingDC<clang::ExternalASTMerger::CompleteType(clang::TagDecl*)::$_0>(clang::DeclContext const*, clang::ExternalASTMerger::CompleteType(clang::TagDecl*)::$_0) Line | Count | Source | 281 | 6 | CallbackType Callback) { | 282 | 6 | if (Origins.count(DC)) { | 283 | 0 | ExternalASTMerger::DCOrigin Origin = Origins[DC]; | 284 | 0 | LazyASTImporter &Importer = LazyImporterForOrigin(*this, *Origin.AST); | 285 | 0 | Callback(Importer, Importer.GetReverse(), Origin.DC); | 286 | 6 | } else { | 287 | 6 | bool DidCallback = false; | 288 | 8 | for (const std::unique_ptr<ASTImporter> &Importer : Importers) { | 289 | 8 | Source<TranslationUnitDecl *> SourceTU = | 290 | 8 | Importer->getFromContext().getTranslationUnitDecl(); | 291 | 8 | ASTImporter &Reverse = | 292 | 8 | static_cast<LazyASTImporter *>(Importer.get())->GetReverse(); | 293 | 8 | if (auto SourceDC = LookupSameContext(SourceTU, DC, Reverse)) { | 294 | 8 | DidCallback = true; | 295 | 8 | if (Callback(*Importer, Reverse, SourceDC)) | 296 | 4 | break; | 297 | 8 | } | 298 | 8 | } | 299 | 6 | if (!DidCallback && LoggingEnabled()0 ) | 300 | 0 | logs() << "(ExternalASTMerger*)" << (void*)this | 301 | 0 | << " asserting for (DeclContext*)" << (const void*)DC | 302 | 0 | << ", (ASTContext*)" << (void*)&Target.AST | 303 | 0 | << "\n"; | 304 | 6 | assert(DidCallback && "Couldn't find a source context matching our DC"); | 305 | 6 | } | 306 | 6 | } |
ExternalASTMerger.cpp:void clang::ExternalASTMerger::ForEachMatchingDC<clang::ExternalASTMerger::CompleteType(clang::ObjCInterfaceDecl*)::$_1>(clang::DeclContext const*, clang::ExternalASTMerger::CompleteType(clang::ObjCInterfaceDecl*)::$_1) Line | Count | Source | 281 | 3 | CallbackType Callback) { | 282 | 3 | if (Origins.count(DC)) { | 283 | 0 | ExternalASTMerger::DCOrigin Origin = Origins[DC]; | 284 | 0 | LazyASTImporter &Importer = LazyImporterForOrigin(*this, *Origin.AST); | 285 | 0 | Callback(Importer, Importer.GetReverse(), Origin.DC); | 286 | 3 | } else { | 287 | 3 | bool DidCallback = false; | 288 | 4 | for (const std::unique_ptr<ASTImporter> &Importer : Importers) { | 289 | 4 | Source<TranslationUnitDecl *> SourceTU = | 290 | 4 | Importer->getFromContext().getTranslationUnitDecl(); | 291 | 4 | ASTImporter &Reverse = | 292 | 4 | static_cast<LazyASTImporter *>(Importer.get())->GetReverse(); | 293 | 4 | if (auto SourceDC = LookupSameContext(SourceTU, DC, Reverse)) { | 294 | 4 | DidCallback = true; | 295 | 4 | if (Callback(*Importer, Reverse, SourceDC)) | 296 | 2 | break; | 297 | 4 | } | 298 | 4 | } | 299 | 3 | if (!DidCallback && LoggingEnabled()0 ) | 300 | 0 | logs() << "(ExternalASTMerger*)" << (void*)this | 301 | 0 | << " asserting for (DeclContext*)" << (const void*)DC | 302 | 0 | << ", (ASTContext*)" << (void*)&Target.AST | 303 | 0 | << "\n"; | 304 | 3 | assert(DidCallback && "Couldn't find a source context matching our DC"); | 305 | 3 | } | 306 | 3 | } |
ExternalASTMerger.cpp:void clang::ExternalASTMerger::ForEachMatchingDC<clang::ExternalASTMerger::CanComplete(clang::DeclContext*)::$_2>(clang::DeclContext const*, clang::ExternalASTMerger::CanComplete(clang::DeclContext*)::$_2) Line | Count | Source | 281 | 524 | CallbackType Callback) { | 282 | 524 | if (Origins.count(DC)) { | 283 | 199 | ExternalASTMerger::DCOrigin Origin = Origins[DC]; | 284 | 199 | LazyASTImporter &Importer = LazyImporterForOrigin(*this, *Origin.AST); | 285 | 199 | Callback(Importer, Importer.GetReverse(), Origin.DC); | 286 | 325 | } else { | 287 | 325 | bool DidCallback = false; | 288 | 335 | for (const std::unique_ptr<ASTImporter> &Importer : Importers) { | 289 | 335 | Source<TranslationUnitDecl *> SourceTU = | 290 | 335 | Importer->getFromContext().getTranslationUnitDecl(); | 291 | 335 | ASTImporter &Reverse = | 292 | 335 | static_cast<LazyASTImporter *>(Importer.get())->GetReverse(); | 293 | 335 | if (auto SourceDC = LookupSameContext(SourceTU, DC, Reverse)) { | 294 | 325 | DidCallback = true; | 295 | 325 | if (Callback(*Importer, Reverse, SourceDC)) | 296 | 325 | break; | 297 | 325 | } | 298 | 335 | } | 299 | 325 | if (!DidCallback && LoggingEnabled()0 ) | 300 | 0 | logs() << "(ExternalASTMerger*)" << (void*)this | 301 | 0 | << " asserting for (DeclContext*)" << (const void*)DC | 302 | 0 | << ", (ASTContext*)" << (void*)&Target.AST | 303 | 0 | << "\n"; | 304 | 325 | assert(DidCallback && "Couldn't find a source context matching our DC"); | 305 | 325 | } | 306 | 524 | } |
ExternalASTMerger.cpp:void clang::ExternalASTMerger::ForEachMatchingDC<clang::ExternalASTMerger::FindExternalVisibleDeclsByName(clang::DeclContext const*, clang::DeclarationName)::$_5>(clang::DeclContext const*, clang::ExternalASTMerger::FindExternalVisibleDeclsByName(clang::DeclContext const*, clang::DeclarationName)::$_5) Line | Count | Source | 281 | 1.58k | CallbackType Callback) { | 282 | 1.58k | if (Origins.count(DC)) { | 283 | 30 | ExternalASTMerger::DCOrigin Origin = Origins[DC]; | 284 | 30 | LazyASTImporter &Importer = LazyImporterForOrigin(*this, *Origin.AST); | 285 | 30 | Callback(Importer, Importer.GetReverse(), Origin.DC); | 286 | 1.55k | } else { | 287 | 1.55k | bool DidCallback = false; | 288 | 1.68k | for (const std::unique_ptr<ASTImporter> &Importer : Importers) { | 289 | 1.68k | Source<TranslationUnitDecl *> SourceTU = | 290 | 1.68k | Importer->getFromContext().getTranslationUnitDecl(); | 291 | 1.68k | ASTImporter &Reverse = | 292 | 1.68k | static_cast<LazyASTImporter *>(Importer.get())->GetReverse(); | 293 | 1.68k | if (auto SourceDC = LookupSameContext(SourceTU, DC, Reverse)) { | 294 | 1.67k | DidCallback = true; | 295 | 1.67k | if (Callback(*Importer, Reverse, SourceDC)) | 296 | 0 | break; | 297 | 1.67k | } | 298 | 1.68k | } | 299 | 1.55k | if (!DidCallback && LoggingEnabled()0 ) | 300 | 0 | logs() << "(ExternalASTMerger*)" << (void*)this | 301 | 0 | << " asserting for (DeclContext*)" << (const void*)DC | 302 | 0 | << ", (ASTContext*)" << (void*)&Target.AST | 303 | 0 | << "\n"; | 304 | 1.55k | assert(DidCallback && "Couldn't find a source context matching our DC"); | 305 | 1.55k | } | 306 | 1.58k | } |
ExternalASTMerger.cpp:void clang::ExternalASTMerger::ForEachMatchingDC<clang::ExternalASTMerger::FindExternalLexicalDecls(clang::DeclContext const*, llvm::function_ref<bool (clang::Decl::Kind)>, llvm::SmallVectorImpl<clang::Decl*>&)::$_6>(clang::DeclContext const*, clang::ExternalASTMerger::FindExternalLexicalDecls(clang::DeclContext const*, llvm::function_ref<bool (clang::Decl::Kind)>, llvm::SmallVectorImpl<clang::Decl*>&)::$_6) Line | Count | Source | 281 | 274 | CallbackType Callback) { | 282 | 274 | if (Origins.count(DC)) { | 283 | 100 | ExternalASTMerger::DCOrigin Origin = Origins[DC]; | 284 | 100 | LazyASTImporter &Importer = LazyImporterForOrigin(*this, *Origin.AST); | 285 | 100 | Callback(Importer, Importer.GetReverse(), Origin.DC); | 286 | 174 | } else { | 287 | 174 | bool DidCallback = false; | 288 | 194 | for (const std::unique_ptr<ASTImporter> &Importer : Importers) { | 289 | 194 | Source<TranslationUnitDecl *> SourceTU = | 290 | 194 | Importer->getFromContext().getTranslationUnitDecl(); | 291 | 194 | ASTImporter &Reverse = | 292 | 194 | static_cast<LazyASTImporter *>(Importer.get())->GetReverse(); | 293 | 194 | if (auto SourceDC = LookupSameContext(SourceTU, DC, Reverse)) { | 294 | 184 | DidCallback = true; | 295 | 184 | if (Callback(*Importer, Reverse, SourceDC)) | 296 | 0 | break; | 297 | 184 | } | 298 | 194 | } | 299 | 174 | if (!DidCallback && LoggingEnabled()0 ) | 300 | 0 | logs() << "(ExternalASTMerger*)" << (void*)this | 301 | 0 | << " asserting for (DeclContext*)" << (const void*)DC | 302 | 0 | << ", (ASTContext*)" << (void*)&Target.AST | 303 | 0 | << "\n"; | 304 | 174 | assert(DidCallback && "Couldn't find a source context matching our DC"); | 305 | 174 | } | 306 | 274 | } |
|
307 | | |
308 | 6 | void ExternalASTMerger::CompleteType(TagDecl *Tag) { |
309 | 6 | assert(Tag->hasExternalLexicalStorage()); |
310 | 0 | ForEachMatchingDC(Tag, [&](ASTImporter &Forward, ASTImporter &Reverse, |
311 | 8 | Source<const DeclContext *> SourceDC) -> bool { |
312 | 8 | auto *SourceTag = const_cast<TagDecl *>(cast<TagDecl>(SourceDC.get())); |
313 | 8 | if (SourceTag->hasExternalLexicalStorage()) |
314 | 4 | SourceTag->getASTContext().getExternalSource()->CompleteType(SourceTag); |
315 | 8 | if (!SourceTag->getDefinition()) |
316 | 4 | return false; |
317 | 4 | Forward.MapImported(SourceTag, Tag); |
318 | 4 | if (llvm::Error Err = Forward.ImportDefinition(SourceTag)) |
319 | 0 | llvm::consumeError(std::move(Err)); |
320 | 4 | Tag->setCompleteDefinition(SourceTag->isCompleteDefinition()); |
321 | 4 | return true; |
322 | 8 | }); |
323 | 6 | } |
324 | | |
325 | 3 | void ExternalASTMerger::CompleteType(ObjCInterfaceDecl *Interface) { |
326 | 3 | assert(Interface->hasExternalLexicalStorage()); |
327 | 0 | ForEachMatchingDC( |
328 | 3 | Interface, [&](ASTImporter &Forward, ASTImporter &Reverse, |
329 | 4 | Source<const DeclContext *> SourceDC) -> bool { |
330 | 4 | auto *SourceInterface = const_cast<ObjCInterfaceDecl *>( |
331 | 4 | cast<ObjCInterfaceDecl>(SourceDC.get())); |
332 | 4 | if (SourceInterface->hasExternalLexicalStorage()) |
333 | 2 | SourceInterface->getASTContext().getExternalSource()->CompleteType( |
334 | 2 | SourceInterface); |
335 | 4 | if (!SourceInterface->getDefinition()) |
336 | 2 | return false; |
337 | 2 | Forward.MapImported(SourceInterface, Interface); |
338 | 2 | if (llvm::Error Err = Forward.ImportDefinition(SourceInterface)) |
339 | 0 | llvm::consumeError(std::move(Err)); |
340 | 2 | return true; |
341 | 4 | }); |
342 | 3 | } |
343 | | |
344 | 524 | bool ExternalASTMerger::CanComplete(DeclContext *Interface) { |
345 | 524 | assert(Interface->hasExternalLexicalStorage() || |
346 | 524 | Interface->hasExternalVisibleStorage()); |
347 | 0 | bool FoundMatchingDC = false; |
348 | 524 | ForEachMatchingDC(Interface, |
349 | 524 | [&](ASTImporter &Forward, ASTImporter &Reverse, |
350 | 524 | Source<const DeclContext *> SourceDC) -> bool { |
351 | 524 | FoundMatchingDC = true; |
352 | 524 | return true; |
353 | 524 | }); |
354 | 524 | return FoundMatchingDC; |
355 | 524 | } |
356 | | |
357 | | namespace { |
358 | 1.34k | bool IsSameDC(const DeclContext *D1, const DeclContext *D2) { |
359 | 1.34k | if (isa<ObjCContainerDecl>(D1) && isa<ObjCContainerDecl>(D2)42 ) |
360 | 42 | return true; // There are many cases where Objective-C is ambiguous. |
361 | 1.30k | if (auto *T1 = dyn_cast<TagDecl>(D1)) |
362 | 1.16k | if (auto *T2 = dyn_cast<TagDecl>(D2)) |
363 | 1.16k | if (T1->getFirstDecl() == T2->getFirstDecl()) |
364 | 1.16k | return true; |
365 | 136 | return D1 == D2 || D1 == CanonicalizeDC(D2)2 ; |
366 | 1.30k | } |
367 | | } |
368 | | |
369 | | void ExternalASTMerger::MaybeRecordOrigin(const DeclContext *ToDC, |
370 | 735 | DCOrigin Origin) { |
371 | 735 | LazyASTImporter &Importer = LazyImporterForOrigin(*this, *Origin.AST); |
372 | 735 | ASTImporter &Reverse = Importer.GetReverse(); |
373 | 735 | Source<const DeclContext *> FoundFromDC = |
374 | 735 | LookupSameContext(Origin.AST->getTranslationUnitDecl(), ToDC, Reverse); |
375 | 735 | const bool DoRecord = !FoundFromDC || !IsSameDC(FoundFromDC.get(), Origin.DC)448 ; |
376 | 735 | if (DoRecord) |
377 | 287 | RecordOriginImpl(ToDC, Origin, Importer); |
378 | 735 | if (LoggingEnabled()) |
379 | 0 | logs() << "(ExternalASTMerger*)" << (void*)this |
380 | 0 | << (DoRecord ? " decided " : " decided NOT") |
381 | 0 | << " to record origin (DeclContext*)" << (void*)Origin.DC |
382 | 0 | << ", (ASTContext*)" << (void*)&Origin.AST |
383 | 0 | << "\n"; |
384 | 735 | } |
385 | | |
386 | | void ExternalASTMerger::ForceRecordOrigin(const DeclContext *ToDC, |
387 | 4 | DCOrigin Origin) { |
388 | 4 | RecordOriginImpl(ToDC, Origin, ImporterForOrigin(*Origin.AST)); |
389 | 4 | } |
390 | | |
391 | | void ExternalASTMerger::RecordOriginImpl(const DeclContext *ToDC, DCOrigin Origin, |
392 | 291 | ASTImporter &Importer) { |
393 | 291 | Origins[ToDC] = Origin; |
394 | 291 | Importer.ASTImporter::MapImported(cast<Decl>(Origin.DC), const_cast<Decl*>(cast<Decl>(ToDC))); |
395 | 291 | } |
396 | | |
397 | | ExternalASTMerger::ExternalASTMerger(const ImporterTarget &Target, |
398 | 121 | llvm::ArrayRef<ImporterSource> Sources) : LogStream(&llvm::nulls()), Target(Target) { |
399 | 121 | SharedState = std::make_shared<ASTImporterSharedState>( |
400 | 121 | *Target.AST.getTranslationUnitDecl()); |
401 | 121 | AddSources(Sources); |
402 | 121 | } |
403 | | |
404 | 0 | Decl *ExternalASTMerger::FindOriginalDecl(Decl *D) { |
405 | 0 | assert(&D->getASTContext() == &Target.AST); |
406 | 0 | for (const auto &I : Importers) |
407 | 0 | if (auto Result = I->GetOriginalDecl(D)) |
408 | 0 | return Result; |
409 | 0 | return nullptr; |
410 | 0 | } |
411 | | |
412 | 121 | void ExternalASTMerger::AddSources(llvm::ArrayRef<ImporterSource> Sources) { |
413 | 132 | for (const ImporterSource &S : Sources) { |
414 | 132 | assert(&S.getASTContext() != &Target.AST); |
415 | | // Check that the associated merger actually imports into the source AST. |
416 | 0 | assert(!S.getMerger() || &S.getMerger()->Target.AST == &S.getASTContext()); |
417 | 0 | Importers.push_back(std::make_unique<LazyASTImporter>( |
418 | 132 | *this, Target.AST, Target.FM, S, SharedState)); |
419 | 132 | } |
420 | 121 | } |
421 | | |
422 | 55 | void ExternalASTMerger::RemoveSources(llvm::ArrayRef<ImporterSource> Sources) { |
423 | 55 | if (LoggingEnabled()) |
424 | 0 | for (const ImporterSource &S : Sources) |
425 | 0 | logs() << "(ExternalASTMerger*)" << (void *)this |
426 | 0 | << " removing source (ASTContext*)" << (void *)&S.getASTContext() |
427 | 0 | << "\n"; |
428 | 55 | llvm::erase_if(Importers, |
429 | 66 | [&Sources](std::unique_ptr<ASTImporter> &Importer) -> bool { |
430 | 80 | for (const ImporterSource &S : Sources) { |
431 | 80 | if (&Importer->getFromContext() == &S.getASTContext()) |
432 | 66 | return true; |
433 | 80 | } |
434 | 0 | return false; |
435 | 66 | }); |
436 | 135 | for (OriginMap::iterator OI = Origins.begin(), OE = Origins.end(); OI != OE; ) { |
437 | 80 | std::pair<const DeclContext *, DCOrigin> Origin = *OI; |
438 | 80 | bool Erase = false; |
439 | 88 | for (const ImporterSource &S : Sources) { |
440 | 88 | if (&S.getASTContext() == Origin.second.AST) { |
441 | 80 | Erase = true; |
442 | 80 | break; |
443 | 80 | } |
444 | 88 | } |
445 | 80 | if (Erase) |
446 | 80 | OI = Origins.erase(OI); |
447 | 0 | else |
448 | 0 | ++OI; |
449 | 80 | } |
450 | 55 | } |
451 | | |
452 | | template <typename DeclTy> |
453 | 14 | static bool importSpecializations(DeclTy *D, ASTImporter *Importer) { |
454 | 14 | for (auto *Spec : D->specializations()) { |
455 | 8 | auto ImportedSpecOrError = Importer->Import(Spec); |
456 | 8 | if (!ImportedSpecOrError) { |
457 | 0 | llvm::consumeError(ImportedSpecOrError.takeError()); |
458 | 0 | return true; |
459 | 0 | } |
460 | 8 | } |
461 | 14 | return false; |
462 | 14 | } ExternalASTMerger.cpp:bool importSpecializations<clang::FunctionTemplateDecl>(clang::FunctionTemplateDecl*, clang::ASTImporter*) Line | Count | Source | 453 | 4 | static bool importSpecializations(DeclTy *D, ASTImporter *Importer) { | 454 | 4 | for (auto *Spec : D->specializations()) { | 455 | 4 | auto ImportedSpecOrError = Importer->Import(Spec); | 456 | 4 | if (!ImportedSpecOrError) { | 457 | 0 | llvm::consumeError(ImportedSpecOrError.takeError()); | 458 | 0 | return true; | 459 | 0 | } | 460 | 4 | } | 461 | 4 | return false; | 462 | 4 | } |
ExternalASTMerger.cpp:bool importSpecializations<clang::ClassTemplateDecl>(clang::ClassTemplateDecl*, clang::ASTImporter*) Line | Count | Source | 453 | 10 | static bool importSpecializations(DeclTy *D, ASTImporter *Importer) { | 454 | 10 | for (auto *Spec : D->specializations()) { | 455 | 4 | auto ImportedSpecOrError = Importer->Import(Spec); | 456 | 4 | if (!ImportedSpecOrError) { | 457 | 0 | llvm::consumeError(ImportedSpecOrError.takeError()); | 458 | 0 | return true; | 459 | 0 | } | 460 | 4 | } | 461 | 10 | return false; | 462 | 10 | } |
Unexecuted instantiation: ExternalASTMerger.cpp:bool importSpecializations<clang::VarTemplateDecl>(clang::VarTemplateDecl*, clang::ASTImporter*) |
463 | | |
464 | | /// Imports specializations from template declarations that can be specialized. |
465 | 880 | static bool importSpecializationsIfNeeded(Decl *D, ASTImporter *Importer) { |
466 | 880 | if (!isa<TemplateDecl>(D)) |
467 | 858 | return false; |
468 | 22 | if (auto *FunctionTD = dyn_cast<FunctionTemplateDecl>(D)) |
469 | 4 | return importSpecializations(FunctionTD, Importer); |
470 | 18 | else if (auto *ClassTD = dyn_cast<ClassTemplateDecl>(D)) |
471 | 10 | return importSpecializations(ClassTD, Importer); |
472 | 8 | else if (auto *VarTD = dyn_cast<VarTemplateDecl>(D)) |
473 | 0 | return importSpecializations(VarTD, Importer); |
474 | 8 | return false; |
475 | 22 | } |
476 | | |
477 | | bool ExternalASTMerger::FindExternalVisibleDeclsByName(const DeclContext *DC, |
478 | 1.58k | DeclarationName Name) { |
479 | 1.58k | llvm::SmallVector<NamedDecl *, 1> Decls; |
480 | 1.58k | llvm::SmallVector<Candidate, 4> Candidates; |
481 | | |
482 | 1.58k | auto FilterFoundDecl = [&Candidates](const Candidate &C) { |
483 | 955 | if (!HasDeclOfSameType(Candidates, C)) |
484 | 880 | Candidates.push_back(C); |
485 | 955 | }; |
486 | | |
487 | 1.58k | ForEachMatchingDC(DC, |
488 | 1.58k | [&](ASTImporter &Forward, ASTImporter &Reverse, |
489 | 1.70k | Source<const DeclContext *> SourceDC) -> bool { |
490 | 1.70k | auto FromNameOrErr = Reverse.Import(Name); |
491 | 1.70k | if (!FromNameOrErr) { |
492 | 0 | llvm::consumeError(FromNameOrErr.takeError()); |
493 | 0 | return false; |
494 | 0 | } |
495 | 1.70k | DeclContextLookupResult Result = |
496 | 1.70k | SourceDC.get()->lookup(*FromNameOrErr); |
497 | 1.70k | for (NamedDecl *FromD : Result) { |
498 | 955 | FilterFoundDecl(std::make_pair(FromD, &Forward)); |
499 | 955 | } |
500 | 1.70k | return false; |
501 | 1.70k | }); |
502 | | |
503 | 1.58k | if (Candidates.empty()) |
504 | 708 | return false; |
505 | | |
506 | 876 | Decls.reserve(Candidates.size()); |
507 | 880 | for (const Candidate &C : Candidates) { |
508 | 880 | Decl *LookupRes = C.first.get(); |
509 | 880 | ASTImporter *Importer = C.second; |
510 | 880 | auto NDOrErr = Importer->Import(LookupRes); |
511 | 880 | NamedDecl *ND = cast<NamedDecl>(llvm::cantFail(std::move(NDOrErr))); |
512 | 880 | assert(ND); |
513 | | // If we don't import specialization, they are not available via lookup |
514 | | // because the lookup result is imported TemplateDecl and it does not |
515 | | // reference its specializations until they are imported explicitly. |
516 | 0 | bool IsSpecImportFailed = |
517 | 880 | importSpecializationsIfNeeded(LookupRes, Importer); |
518 | 880 | assert(!IsSpecImportFailed); |
519 | 0 | (void)IsSpecImportFailed; |
520 | 880 | Decls.push_back(ND); |
521 | 880 | } |
522 | 876 | SetExternalVisibleDeclsForName(DC, Name, Decls); |
523 | 876 | return true; |
524 | 1.58k | } |
525 | | |
526 | | void ExternalASTMerger::FindExternalLexicalDecls( |
527 | | const DeclContext *DC, llvm::function_ref<bool(Decl::Kind)> IsKindWeWant, |
528 | 274 | SmallVectorImpl<Decl *> &Result) { |
529 | 274 | ForEachMatchingDC(DC, [&](ASTImporter &Forward, ASTImporter &Reverse, |
530 | 284 | Source<const DeclContext *> SourceDC) -> bool { |
531 | 940 | for (const Decl *SourceDecl : SourceDC.get()->decls()) { |
532 | 940 | if (IsKindWeWant(SourceDecl->getKind())) { |
533 | 895 | auto ImportedDeclOrErr = Forward.Import(SourceDecl); |
534 | 895 | if (ImportedDeclOrErr) |
535 | 895 | assert(!(*ImportedDeclOrErr) || |
536 | 895 | IsSameDC((*ImportedDeclOrErr)->getDeclContext(), DC)); |
537 | 0 | else |
538 | 0 | llvm::consumeError(ImportedDeclOrErr.takeError()); |
539 | 895 | } |
540 | 940 | } |
541 | 284 | return false; |
542 | 284 | }); |
543 | 274 | } |
544 | | |