Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
14 | pmbaty | 1 | //===- ASTImporter.h - Importing ASTs from other Contexts -------*- 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 defines the ASTImporter class which imports AST nodes from one |
||
10 | // context into another context. |
||
11 | // |
||
12 | //===----------------------------------------------------------------------===// |
||
13 | |||
14 | #ifndef LLVM_CLANG_AST_ASTIMPORTER_H |
||
15 | #define LLVM_CLANG_AST_ASTIMPORTER_H |
||
16 | |||
17 | #include "clang/AST/ASTImportError.h" |
||
18 | #include "clang/AST/DeclBase.h" |
||
19 | #include "clang/AST/DeclarationName.h" |
||
20 | #include "clang/AST/ExprCXX.h" |
||
21 | #include "clang/AST/NestedNameSpecifier.h" |
||
22 | #include "clang/AST/TemplateName.h" |
||
23 | #include "clang/AST/Type.h" |
||
24 | #include "clang/Basic/Diagnostic.h" |
||
25 | #include "clang/Basic/IdentifierTable.h" |
||
26 | #include "clang/Basic/LLVM.h" |
||
27 | #include "clang/Basic/SourceLocation.h" |
||
28 | #include "llvm/ADT/DenseMap.h" |
||
29 | #include "llvm/ADT/DenseSet.h" |
||
30 | #include "llvm/ADT/SmallVector.h" |
||
31 | #include <optional> |
||
32 | #include <utility> |
||
33 | |||
34 | namespace clang { |
||
35 | |||
36 | class ASTContext; |
||
37 | class ASTImporterSharedState; |
||
38 | class Attr; |
||
39 | class CXXBaseSpecifier; |
||
40 | class CXXCtorInitializer; |
||
41 | class Decl; |
||
42 | class DeclContext; |
||
43 | class Expr; |
||
44 | class FileManager; |
||
45 | class NamedDecl; |
||
46 | class Stmt; |
||
47 | class TagDecl; |
||
48 | class TranslationUnitDecl; |
||
49 | class TypeSourceInfo; |
||
50 | |||
51 | // \brief Returns with a list of declarations started from the canonical decl |
||
52 | // then followed by subsequent decls in the translation unit. |
||
53 | // This gives a canonical list for each entry in the redecl chain. |
||
54 | // `Decl::redecls()` gives a list of decls which always start from the |
||
55 | // previous decl and the next item is actually the previous item in the order |
||
56 | // of source locations. Thus, `Decl::redecls()` gives different lists for |
||
57 | // the different entries in a given redecl chain. |
||
58 | llvm::SmallVector<Decl*, 2> getCanonicalForwardRedeclChain(Decl* D); |
||
59 | |||
60 | /// Imports selected nodes from one AST context into another context, |
||
61 | /// merging AST nodes where appropriate. |
||
62 | class ASTImporter { |
||
63 | friend class ASTNodeImporter; |
||
64 | public: |
||
65 | using NonEquivalentDeclSet = llvm::DenseSet<std::pair<Decl *, Decl *>>; |
||
66 | using ImportedCXXBaseSpecifierMap = |
||
67 | llvm::DenseMap<const CXXBaseSpecifier *, CXXBaseSpecifier *>; |
||
68 | |||
69 | enum class ODRHandlingType { Conservative, Liberal }; |
||
70 | |||
71 | // An ImportPath is the list of the AST nodes which we visit during an |
||
72 | // Import call. |
||
73 | // If node `A` depends on node `B` then the path contains an `A`->`B` edge. |
||
74 | // From the call stack of the import functions we can read the very same |
||
75 | // path. |
||
76 | // |
||
77 | // Now imagine the following AST, where the `->` represents dependency in |
||
78 | // therms of the import. |
||
79 | // ``` |
||
80 | // A->B->C->D |
||
81 | // `->E |
||
82 | // ``` |
||
83 | // We would like to import A. |
||
84 | // The import behaves like a DFS, so we will visit the nodes in this order: |
||
85 | // ABCDE. |
||
86 | // During the visitation we will have the following ImportPaths: |
||
87 | // ``` |
||
88 | // A |
||
89 | // AB |
||
90 | // ABC |
||
91 | // ABCD |
||
92 | // ABC |
||
93 | // AB |
||
94 | // ABE |
||
95 | // AB |
||
96 | // A |
||
97 | // ``` |
||
98 | // If during the visit of E there is an error then we set an error for E, |
||
99 | // then as the call stack shrinks for B, then for A: |
||
100 | // ``` |
||
101 | // A |
||
102 | // AB |
||
103 | // ABC |
||
104 | // ABCD |
||
105 | // ABC |
||
106 | // AB |
||
107 | // ABE // Error! Set an error to E |
||
108 | // AB // Set an error to B |
||
109 | // A // Set an error to A |
||
110 | // ``` |
||
111 | // However, during the import we could import C and D without any error and |
||
112 | // they are independent from A,B and E. |
||
113 | // We must not set up an error for C and D. |
||
114 | // So, at the end of the import we have an entry in `ImportDeclErrors` for |
||
115 | // A,B,E but not for C,D. |
||
116 | // |
||
117 | // Now what happens if there is a cycle in the import path? |
||
118 | // Let's consider this AST: |
||
119 | // ``` |
||
120 | // A->B->C->A |
||
121 | // `->E |
||
122 | // ``` |
||
123 | // During the visitation we will have the below ImportPaths and if during |
||
124 | // the visit of E there is an error then we will set up an error for E,B,A. |
||
125 | // But what's up with C? |
||
126 | // ``` |
||
127 | // A |
||
128 | // AB |
||
129 | // ABC |
||
130 | // ABCA |
||
131 | // ABC |
||
132 | // AB |
||
133 | // ABE // Error! Set an error to E |
||
134 | // AB // Set an error to B |
||
135 | // A // Set an error to A |
||
136 | // ``` |
||
137 | // This time we know that both B and C are dependent on A. |
||
138 | // This means we must set up an error for C too. |
||
139 | // As the call stack reverses back we get to A and we must set up an error |
||
140 | // to all nodes which depend on A (this includes C). |
||
141 | // But C is no longer on the import path, it just had been previously. |
||
142 | // Such situation can happen only if during the visitation we had a cycle. |
||
143 | // If we didn't have any cycle, then the normal way of passing an Error |
||
144 | // object through the call stack could handle the situation. |
||
145 | // This is why we must track cycles during the import process for each |
||
146 | // visited declaration. |
||
147 | class ImportPathTy { |
||
148 | public: |
||
149 | using VecTy = llvm::SmallVector<Decl *, 32>; |
||
150 | |||
151 | void push(Decl *D) { |
||
152 | Nodes.push_back(D); |
||
153 | ++Aux[D]; |
||
154 | } |
||
155 | |||
156 | void pop() { |
||
157 | if (Nodes.empty()) |
||
158 | return; |
||
159 | --Aux[Nodes.back()]; |
||
160 | Nodes.pop_back(); |
||
161 | } |
||
162 | |||
163 | /// Returns true if the last element can be found earlier in the path. |
||
164 | bool hasCycleAtBack() const { |
||
165 | auto Pos = Aux.find(Nodes.back()); |
||
166 | return Pos != Aux.end() && Pos->second > 1; |
||
167 | } |
||
168 | |||
169 | using Cycle = llvm::iterator_range<VecTy::const_reverse_iterator>; |
||
170 | Cycle getCycleAtBack() const { |
||
171 | assert(Nodes.size() >= 2); |
||
172 | return Cycle(Nodes.rbegin(), |
||
173 | std::find(Nodes.rbegin() + 1, Nodes.rend(), Nodes.back()) + |
||
174 | 1); |
||
175 | } |
||
176 | |||
177 | /// Returns the copy of the cycle. |
||
178 | VecTy copyCycleAtBack() const { |
||
179 | auto R = getCycleAtBack(); |
||
180 | return VecTy(R.begin(), R.end()); |
||
181 | } |
||
182 | |||
183 | private: |
||
184 | // All nodes of the path. |
||
185 | VecTy Nodes; |
||
186 | // Auxiliary container to be able to answer "Do we have a cycle ending |
||
187 | // at last element?" as fast as possible. |
||
188 | // We count each Decl's occurrence over the path. |
||
189 | llvm::SmallDenseMap<Decl *, int, 32> Aux; |
||
190 | }; |
||
191 | |||
192 | private: |
||
193 | std::shared_ptr<ASTImporterSharedState> SharedState = nullptr; |
||
194 | |||
195 | /// The path which we go through during the import of a given AST node. |
||
196 | ImportPathTy ImportPath; |
||
197 | /// Sometimes we have to save some part of an import path, so later we can |
||
198 | /// set up properties to the saved nodes. |
||
199 | /// We may have several of these import paths associated to one Decl. |
||
200 | using SavedImportPathsForOneDecl = |
||
201 | llvm::SmallVector<ImportPathTy::VecTy, 32>; |
||
202 | using SavedImportPathsTy = |
||
203 | llvm::SmallDenseMap<Decl *, SavedImportPathsForOneDecl, 32>; |
||
204 | SavedImportPathsTy SavedImportPaths; |
||
205 | |||
206 | /// The contexts we're importing to and from. |
||
207 | ASTContext &ToContext, &FromContext; |
||
208 | |||
209 | /// The file managers we're importing to and from. |
||
210 | FileManager &ToFileManager, &FromFileManager; |
||
211 | |||
212 | /// Whether to perform a minimal import. |
||
213 | bool Minimal; |
||
214 | |||
215 | ODRHandlingType ODRHandling; |
||
216 | |||
217 | /// Whether the last diagnostic came from the "from" context. |
||
218 | bool LastDiagFromFrom = false; |
||
219 | |||
220 | /// Mapping from the already-imported types in the "from" context |
||
221 | /// to the corresponding types in the "to" context. |
||
222 | llvm::DenseMap<const Type *, const Type *> ImportedTypes; |
||
223 | |||
224 | /// Mapping from the already-imported declarations in the "from" |
||
225 | /// context to the corresponding declarations in the "to" context. |
||
226 | llvm::DenseMap<Decl *, Decl *> ImportedDecls; |
||
227 | |||
228 | /// Mapping from the already-imported declarations in the "from" |
||
229 | /// context to the error status of the import of that declaration. |
||
230 | /// This map contains only the declarations that were not correctly |
||
231 | /// imported. The same declaration may or may not be included in |
||
232 | /// ImportedDecls. This map is updated continuously during imports and never |
||
233 | /// cleared (like ImportedDecls). |
||
234 | llvm::DenseMap<Decl *, ASTImportError> ImportDeclErrors; |
||
235 | |||
236 | /// Mapping from the already-imported declarations in the "to" |
||
237 | /// context to the corresponding declarations in the "from" context. |
||
238 | llvm::DenseMap<Decl *, Decl *> ImportedFromDecls; |
||
239 | |||
240 | /// Mapping from the already-imported statements in the "from" |
||
241 | /// context to the corresponding statements in the "to" context. |
||
242 | llvm::DenseMap<Stmt *, Stmt *> ImportedStmts; |
||
243 | |||
244 | /// Mapping from the already-imported FileIDs in the "from" source |
||
245 | /// manager to the corresponding FileIDs in the "to" source manager. |
||
246 | llvm::DenseMap<FileID, FileID> ImportedFileIDs; |
||
247 | |||
248 | /// Mapping from the already-imported CXXBasesSpecifier in |
||
249 | /// the "from" source manager to the corresponding CXXBasesSpecifier |
||
250 | /// in the "to" source manager. |
||
251 | ImportedCXXBaseSpecifierMap ImportedCXXBaseSpecifiers; |
||
252 | |||
253 | /// Declaration (from, to) pairs that are known not to be equivalent |
||
254 | /// (which we have already complained about). |
||
255 | NonEquivalentDeclSet NonEquivalentDecls; |
||
256 | |||
257 | using FoundDeclsTy = SmallVector<NamedDecl *, 2>; |
||
258 | FoundDeclsTy findDeclsInToCtx(DeclContext *DC, DeclarationName Name); |
||
259 | |||
260 | void AddToLookupTable(Decl *ToD); |
||
261 | |||
262 | protected: |
||
263 | /// Can be overwritten by subclasses to implement their own import logic. |
||
264 | /// The overwritten method should call this method if it didn't import the |
||
265 | /// decl on its own. |
||
266 | virtual Expected<Decl *> ImportImpl(Decl *From); |
||
267 | |||
268 | /// Used only in unittests to verify the behaviour of the error handling. |
||
269 | virtual bool returnWithErrorInTest() { return false; }; |
||
270 | |||
271 | public: |
||
272 | |||
273 | /// \param ToContext The context we'll be importing into. |
||
274 | /// |
||
275 | /// \param ToFileManager The file manager we'll be importing into. |
||
276 | /// |
||
277 | /// \param FromContext The context we'll be importing from. |
||
278 | /// |
||
279 | /// \param FromFileManager The file manager we'll be importing into. |
||
280 | /// |
||
281 | /// \param MinimalImport If true, the importer will attempt to import |
||
282 | /// as little as it can, e.g., by importing declarations as forward |
||
283 | /// declarations that can be completed at a later point. |
||
284 | /// |
||
285 | /// \param SharedState The importer specific lookup table which may be |
||
286 | /// shared amongst several ASTImporter objects. |
||
287 | /// If not set then the original C/C++ lookup is used. |
||
288 | ASTImporter(ASTContext &ToContext, FileManager &ToFileManager, |
||
289 | ASTContext &FromContext, FileManager &FromFileManager, |
||
290 | bool MinimalImport, |
||
291 | std::shared_ptr<ASTImporterSharedState> SharedState = nullptr); |
||
292 | |||
293 | virtual ~ASTImporter(); |
||
294 | |||
295 | /// Whether the importer will perform a minimal import, creating |
||
296 | /// to-be-completed forward declarations when possible. |
||
297 | bool isMinimalImport() const { return Minimal; } |
||
298 | |||
299 | void setODRHandling(ODRHandlingType T) { ODRHandling = T; } |
||
300 | |||
301 | /// \brief Import the given object, returns the result. |
||
302 | /// |
||
303 | /// \param To Import the object into this variable. |
||
304 | /// \param From Object to import. |
||
305 | /// \return Error information (success or error). |
||
306 | template <typename ImportT> |
||
307 | [[nodiscard]] llvm::Error importInto(ImportT &To, const ImportT &From) { |
||
308 | auto ToOrErr = Import(From); |
||
309 | if (ToOrErr) |
||
310 | To = *ToOrErr; |
||
311 | return ToOrErr.takeError(); |
||
312 | } |
||
313 | |||
314 | /// Import cleanup objects owned by ExprWithCleanup. |
||
315 | llvm::Expected<ExprWithCleanups::CleanupObject> |
||
316 | Import(ExprWithCleanups::CleanupObject From); |
||
317 | |||
318 | /// Import the given type from the "from" context into the "to" |
||
319 | /// context. |
||
320 | /// |
||
321 | /// \returns The equivalent type in the "to" context, or the import error. |
||
322 | llvm::Expected<const Type *> Import(const Type *FromT); |
||
323 | |||
324 | /// Import the given qualified type from the "from" context into the "to" |
||
325 | /// context. A null type is imported as a null type (no error). |
||
326 | /// |
||
327 | /// \returns The equivalent type in the "to" context, or the import error. |
||
328 | llvm::Expected<QualType> Import(QualType FromT); |
||
329 | |||
330 | /// Import the given type source information from the |
||
331 | /// "from" context into the "to" context. |
||
332 | /// |
||
333 | /// \returns The equivalent type source information in the "to" |
||
334 | /// context, or the import error. |
||
335 | llvm::Expected<TypeSourceInfo *> Import(TypeSourceInfo *FromTSI); |
||
336 | |||
337 | /// Import the given attribute from the "from" context into the |
||
338 | /// "to" context. |
||
339 | /// |
||
340 | /// \returns The equivalent attribute in the "to" context, or the import |
||
341 | /// error. |
||
342 | llvm::Expected<Attr *> Import(const Attr *FromAttr); |
||
343 | |||
344 | /// Import the given declaration from the "from" context into the |
||
345 | /// "to" context. |
||
346 | /// |
||
347 | /// \returns The equivalent declaration in the "to" context, or the import |
||
348 | /// error. |
||
349 | llvm::Expected<Decl *> Import(Decl *FromD); |
||
350 | llvm::Expected<const Decl *> Import(const Decl *FromD) { |
||
351 | return Import(const_cast<Decl *>(FromD)); |
||
352 | } |
||
353 | |||
354 | llvm::Expected<InheritedConstructor> |
||
355 | Import(const InheritedConstructor &From); |
||
356 | |||
357 | /// Return the copy of the given declaration in the "to" context if |
||
358 | /// it has already been imported from the "from" context. Otherwise return |
||
359 | /// nullptr. |
||
360 | Decl *GetAlreadyImportedOrNull(const Decl *FromD) const; |
||
361 | |||
362 | /// Return the translation unit from where the declaration was |
||
363 | /// imported. If it does not exist nullptr is returned. |
||
364 | TranslationUnitDecl *GetFromTU(Decl *ToD); |
||
365 | |||
366 | /// Return the declaration in the "from" context from which the declaration |
||
367 | /// in the "to" context was imported. If it was not imported or of the wrong |
||
368 | /// type a null value is returned. |
||
369 | template <typename DeclT> |
||
370 | std::optional<DeclT *> getImportedFromDecl(const DeclT *ToD) const { |
||
371 | auto FromI = ImportedFromDecls.find(ToD); |
||
372 | if (FromI == ImportedFromDecls.end()) |
||
373 | return {}; |
||
374 | auto *FromD = dyn_cast<DeclT>(FromI->second); |
||
375 | if (!FromD) |
||
376 | return {}; |
||
377 | return FromD; |
||
378 | } |
||
379 | |||
380 | /// Import the given declaration context from the "from" |
||
381 | /// AST context into the "to" AST context. |
||
382 | /// |
||
383 | /// \returns the equivalent declaration context in the "to" |
||
384 | /// context, or error value. |
||
385 | llvm::Expected<DeclContext *> ImportContext(DeclContext *FromDC); |
||
386 | |||
387 | /// Import the given expression from the "from" context into the |
||
388 | /// "to" context. |
||
389 | /// |
||
390 | /// \returns The equivalent expression in the "to" context, or the import |
||
391 | /// error. |
||
392 | llvm::Expected<Expr *> Import(Expr *FromE); |
||
393 | |||
394 | /// Import the given statement from the "from" context into the |
||
395 | /// "to" context. |
||
396 | /// |
||
397 | /// \returns The equivalent statement in the "to" context, or the import |
||
398 | /// error. |
||
399 | llvm::Expected<Stmt *> Import(Stmt *FromS); |
||
400 | |||
401 | /// Import the given nested-name-specifier from the "from" |
||
402 | /// context into the "to" context. |
||
403 | /// |
||
404 | /// \returns The equivalent nested-name-specifier in the "to" |
||
405 | /// context, or the import error. |
||
406 | llvm::Expected<NestedNameSpecifier *> Import(NestedNameSpecifier *FromNNS); |
||
407 | |||
408 | /// Import the given nested-name-specifier-loc from the "from" |
||
409 | /// context into the "to" context. |
||
410 | /// |
||
411 | /// \returns The equivalent nested-name-specifier-loc in the "to" |
||
412 | /// context, or the import error. |
||
413 | llvm::Expected<NestedNameSpecifierLoc> |
||
414 | Import(NestedNameSpecifierLoc FromNNS); |
||
415 | |||
416 | /// Import the given template name from the "from" context into the |
||
417 | /// "to" context, or the import error. |
||
418 | llvm::Expected<TemplateName> Import(TemplateName From); |
||
419 | |||
420 | /// Import the given source location from the "from" context into |
||
421 | /// the "to" context. |
||
422 | /// |
||
423 | /// \returns The equivalent source location in the "to" context, or the |
||
424 | /// import error. |
||
425 | llvm::Expected<SourceLocation> Import(SourceLocation FromLoc); |
||
426 | |||
427 | /// Import the given source range from the "from" context into |
||
428 | /// the "to" context. |
||
429 | /// |
||
430 | /// \returns The equivalent source range in the "to" context, or the import |
||
431 | /// error. |
||
432 | llvm::Expected<SourceRange> Import(SourceRange FromRange); |
||
433 | |||
434 | /// Import the given declaration name from the "from" |
||
435 | /// context into the "to" context. |
||
436 | /// |
||
437 | /// \returns The equivalent declaration name in the "to" context, or the |
||
438 | /// import error. |
||
439 | llvm::Expected<DeclarationName> Import(DeclarationName FromName); |
||
440 | |||
441 | /// Import the given identifier from the "from" context |
||
442 | /// into the "to" context. |
||
443 | /// |
||
444 | /// \returns The equivalent identifier in the "to" context. Note: It |
||
445 | /// returns nullptr only if the FromId was nullptr. |
||
446 | IdentifierInfo *Import(const IdentifierInfo *FromId); |
||
447 | |||
448 | /// Import the given Objective-C selector from the "from" |
||
449 | /// context into the "to" context. |
||
450 | /// |
||
451 | /// \returns The equivalent selector in the "to" context, or the import |
||
452 | /// error. |
||
453 | llvm::Expected<Selector> Import(Selector FromSel); |
||
454 | |||
455 | /// Import the given file ID from the "from" context into the |
||
456 | /// "to" context. |
||
457 | /// |
||
458 | /// \returns The equivalent file ID in the source manager of the "to" |
||
459 | /// context, or the import error. |
||
460 | llvm::Expected<FileID> Import(FileID, bool IsBuiltin = false); |
||
461 | |||
462 | /// Import the given C++ constructor initializer from the "from" |
||
463 | /// context into the "to" context. |
||
464 | /// |
||
465 | /// \returns The equivalent initializer in the "to" context, or the import |
||
466 | /// error. |
||
467 | llvm::Expected<CXXCtorInitializer *> Import(CXXCtorInitializer *FromInit); |
||
468 | |||
469 | /// Import the given CXXBaseSpecifier from the "from" context into |
||
470 | /// the "to" context. |
||
471 | /// |
||
472 | /// \returns The equivalent CXXBaseSpecifier in the source manager of the |
||
473 | /// "to" context, or the import error. |
||
474 | llvm::Expected<CXXBaseSpecifier *> Import(const CXXBaseSpecifier *FromSpec); |
||
475 | |||
476 | /// Import the given APValue from the "from" context into |
||
477 | /// the "to" context. |
||
478 | /// |
||
479 | /// \return the equivalent APValue in the "to" context or the import |
||
480 | /// error. |
||
481 | llvm::Expected<APValue> Import(const APValue &FromValue); |
||
482 | |||
483 | /// Import the definition of the given declaration, including all of |
||
484 | /// the declarations it contains. |
||
485 | [[nodiscard]] llvm::Error ImportDefinition(Decl *From); |
||
486 | |||
487 | /// Cope with a name conflict when importing a declaration into the |
||
488 | /// given context. |
||
489 | /// |
||
490 | /// This routine is invoked whenever there is a name conflict while |
||
491 | /// importing a declaration. The returned name will become the name of the |
||
492 | /// imported declaration. By default, the returned name is the same as the |
||
493 | /// original name, leaving the conflict unresolve such that name lookup |
||
494 | /// for this name is likely to find an ambiguity later. |
||
495 | /// |
||
496 | /// Subclasses may override this routine to resolve the conflict, e.g., by |
||
497 | /// renaming the declaration being imported. |
||
498 | /// |
||
499 | /// \param Name the name of the declaration being imported, which conflicts |
||
500 | /// with other declarations. |
||
501 | /// |
||
502 | /// \param DC the declaration context (in the "to" AST context) in which |
||
503 | /// the name is being imported. |
||
504 | /// |
||
505 | /// \param IDNS the identifier namespace in which the name will be found. |
||
506 | /// |
||
507 | /// \param Decls the set of declarations with the same name as the |
||
508 | /// declaration being imported. |
||
509 | /// |
||
510 | /// \param NumDecls the number of conflicting declarations in \p Decls. |
||
511 | /// |
||
512 | /// \returns the name that the newly-imported declaration should have. Or |
||
513 | /// an error if we can't handle the name conflict. |
||
514 | virtual Expected<DeclarationName> |
||
515 | HandleNameConflict(DeclarationName Name, DeclContext *DC, unsigned IDNS, |
||
516 | NamedDecl **Decls, unsigned NumDecls); |
||
517 | |||
518 | /// Retrieve the context that AST nodes are being imported into. |
||
519 | ASTContext &getToContext() const { return ToContext; } |
||
520 | |||
521 | /// Retrieve the context that AST nodes are being imported from. |
||
522 | ASTContext &getFromContext() const { return FromContext; } |
||
523 | |||
524 | /// Retrieve the file manager that AST nodes are being imported into. |
||
525 | FileManager &getToFileManager() const { return ToFileManager; } |
||
526 | |||
527 | /// Retrieve the file manager that AST nodes are being imported from. |
||
528 | FileManager &getFromFileManager() const { return FromFileManager; } |
||
529 | |||
530 | /// Report a diagnostic in the "to" context. |
||
531 | DiagnosticBuilder ToDiag(SourceLocation Loc, unsigned DiagID); |
||
532 | |||
533 | /// Report a diagnostic in the "from" context. |
||
534 | DiagnosticBuilder FromDiag(SourceLocation Loc, unsigned DiagID); |
||
535 | |||
536 | /// Return the set of declarations that we know are not equivalent. |
||
537 | NonEquivalentDeclSet &getNonEquivalentDecls() { return NonEquivalentDecls; } |
||
538 | |||
539 | /// Called for ObjCInterfaceDecl, ObjCProtocolDecl, and TagDecl. |
||
540 | /// Mark the Decl as complete, filling it in as much as possible. |
||
541 | /// |
||
542 | /// \param D A declaration in the "to" context. |
||
543 | virtual void CompleteDecl(Decl* D); |
||
544 | |||
545 | /// Subclasses can override this function to observe all of the \c From -> |
||
546 | /// \c To declaration mappings as they are imported. |
||
547 | virtual void Imported(Decl *From, Decl *To) {} |
||
548 | |||
549 | void RegisterImportedDecl(Decl *FromD, Decl *ToD); |
||
550 | |||
551 | /// Store and assign the imported declaration to its counterpart. |
||
552 | /// It may happen that several decls from the 'from' context are mapped to |
||
553 | /// the same decl in the 'to' context. |
||
554 | Decl *MapImported(Decl *From, Decl *To); |
||
555 | |||
556 | /// Called by StructuralEquivalenceContext. If a RecordDecl is |
||
557 | /// being compared to another RecordDecl as part of import, completing the |
||
558 | /// other RecordDecl may trigger importation of the first RecordDecl. This |
||
559 | /// happens especially for anonymous structs. If the original of the second |
||
560 | /// RecordDecl can be found, we can complete it without the need for |
||
561 | /// importation, eliminating this loop. |
||
562 | virtual Decl *GetOriginalDecl(Decl *To) { return nullptr; } |
||
563 | |||
564 | /// Return if import of the given declaration has failed and if yes |
||
565 | /// the kind of the problem. This gives the first error encountered with |
||
566 | /// the node. |
||
567 | std::optional<ASTImportError> getImportDeclErrorIfAny(Decl *FromD) const; |
||
568 | |||
569 | /// Mark (newly) imported declaration with error. |
||
570 | void setImportDeclError(Decl *From, ASTImportError Error); |
||
571 | |||
572 | /// Determine whether the given types are structurally |
||
573 | /// equivalent. |
||
574 | bool IsStructurallyEquivalent(QualType From, QualType To, |
||
575 | bool Complain = true); |
||
576 | |||
577 | /// Determine the index of a field in its parent record. |
||
578 | /// F should be a field (or indirect field) declaration. |
||
579 | /// \returns The index of the field in its parent context (starting from 0). |
||
580 | /// On error `std::nullopt` is returned (parent context is non-record). |
||
581 | static std::optional<unsigned> getFieldIndex(Decl *F); |
||
582 | }; |
||
583 | |||
584 | } // namespace clang |
||
585 | |||
586 | #endif // LLVM_CLANG_AST_ASTIMPORTER_H |