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 |