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 |