- //===- ASTImporter.h - Importing ASTs from other Contexts -------*- C++ -*-===// 
- // 
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 
- // See https://llvm.org/LICENSE.txt for license information. 
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 
- // 
- //===----------------------------------------------------------------------===// 
- // 
- //  This file defines the ASTImporter class which imports AST nodes from one 
- //  context into another context. 
- // 
- //===----------------------------------------------------------------------===// 
-   
- #ifndef LLVM_CLANG_AST_ASTIMPORTER_H 
- #define LLVM_CLANG_AST_ASTIMPORTER_H 
-   
- #include "clang/AST/ASTImportError.h" 
- #include "clang/AST/DeclBase.h" 
- #include "clang/AST/DeclarationName.h" 
- #include "clang/AST/ExprCXX.h" 
- #include "clang/AST/NestedNameSpecifier.h" 
- #include "clang/AST/TemplateName.h" 
- #include "clang/AST/Type.h" 
- #include "clang/Basic/Diagnostic.h" 
- #include "clang/Basic/IdentifierTable.h" 
- #include "clang/Basic/LLVM.h" 
- #include "clang/Basic/SourceLocation.h" 
- #include "llvm/ADT/DenseMap.h" 
- #include "llvm/ADT/DenseSet.h" 
- #include "llvm/ADT/SmallVector.h" 
- #include <optional> 
- #include <utility> 
-   
- namespace clang { 
-   
- class ASTContext; 
- class ASTImporterSharedState; 
- class Attr; 
- class CXXBaseSpecifier; 
- class CXXCtorInitializer; 
- class Decl; 
- class DeclContext; 
- class Expr; 
- class FileManager; 
- class NamedDecl; 
- class Stmt; 
- class TagDecl; 
- class TranslationUnitDecl; 
- class TypeSourceInfo; 
-   
-   // \brief Returns with a list of declarations started from the canonical decl 
-   // then followed by subsequent decls in the translation unit. 
-   // This gives a canonical list for each entry in the redecl chain. 
-   // `Decl::redecls()` gives a list of decls which always start from the 
-   // previous decl and the next item is actually the previous item in the order 
-   // of source locations.  Thus, `Decl::redecls()` gives different lists for 
-   // the different entries in a given redecl chain. 
-   llvm::SmallVector<Decl*, 2> getCanonicalForwardRedeclChain(Decl* D); 
-   
-   /// Imports selected nodes from one AST context into another context, 
-   /// merging AST nodes where appropriate. 
-   class ASTImporter { 
-     friend class ASTNodeImporter; 
-   public: 
-     using NonEquivalentDeclSet = llvm::DenseSet<std::pair<Decl *, Decl *>>; 
-     using ImportedCXXBaseSpecifierMap = 
-         llvm::DenseMap<const CXXBaseSpecifier *, CXXBaseSpecifier *>; 
-   
-     enum class ODRHandlingType { Conservative, Liberal }; 
-   
-     // An ImportPath is the list of the AST nodes which we visit during an 
-     // Import call. 
-     // If node `A` depends on node `B` then the path contains an `A`->`B` edge. 
-     // From the call stack of the import functions we can read the very same 
-     // path. 
-     // 
-     // Now imagine the following AST, where the `->` represents dependency in 
-     // therms of the import. 
-     // ``` 
-     // A->B->C->D 
-     //    `->E 
-     // ``` 
-     // We would like to import A. 
-     // The import behaves like a DFS, so we will visit the nodes in this order: 
-     // ABCDE. 
-     // During the visitation we will have the following ImportPaths: 
-     // ``` 
-     // A 
-     // AB 
-     // ABC 
-     // ABCD 
-     // ABC 
-     // AB 
-     // ABE 
-     // AB 
-     // A 
-     // ``` 
-     // If during the visit of E there is an error then we set an error for E, 
-     // then as the call stack shrinks for B, then for A: 
-     // ``` 
-     // A 
-     // AB 
-     // ABC 
-     // ABCD 
-     // ABC 
-     // AB 
-     // ABE // Error! Set an error to E 
-     // AB  // Set an error to B 
-     // A   // Set an error to A 
-     // ``` 
-     // However, during the import we could import C and D without any error and 
-     // they are independent from A,B and E. 
-     // We must not set up an error for C and D. 
-     // So, at the end of the import we have an entry in `ImportDeclErrors` for 
-     // A,B,E but not for C,D. 
-     // 
-     // Now what happens if there is a cycle in the import path? 
-     // Let's consider this AST: 
-     // ``` 
-     // A->B->C->A 
-     //    `->E 
-     // ``` 
-     // During the visitation we will have the below ImportPaths and if during 
-     // the visit of E there is an error then we will set up an error for E,B,A. 
-     // But what's up with C? 
-     // ``` 
-     // A 
-     // AB 
-     // ABC 
-     // ABCA 
-     // ABC 
-     // AB 
-     // ABE // Error! Set an error to E 
-     // AB  // Set an error to B 
-     // A   // Set an error to A 
-     // ``` 
-     // This time we know that both B and C are dependent on A. 
-     // This means we must set up an error for C too. 
-     // As the call stack reverses back we get to A and we must set up an error 
-     // to all nodes which depend on A (this includes C). 
-     // But C is no longer on the import path, it just had been previously. 
-     // Such situation can happen only if during the visitation we had a cycle. 
-     // If we didn't have any cycle, then the normal way of passing an Error 
-     // object through the call stack could handle the situation. 
-     // This is why we must track cycles during the import process for each 
-     // visited declaration. 
-     class ImportPathTy { 
-     public: 
-       using VecTy = llvm::SmallVector<Decl *, 32>; 
-   
-       void push(Decl *D) { 
-         Nodes.push_back(D); 
-         ++Aux[D]; 
-       } 
-   
-       void pop() { 
-         if (Nodes.empty()) 
-           return; 
-         --Aux[Nodes.back()]; 
-         Nodes.pop_back(); 
-       } 
-   
-       /// Returns true if the last element can be found earlier in the path. 
-       bool hasCycleAtBack() const { 
-         auto Pos = Aux.find(Nodes.back()); 
-         return Pos != Aux.end() && Pos->second > 1; 
-       } 
-   
-       using Cycle = llvm::iterator_range<VecTy::const_reverse_iterator>; 
-       Cycle getCycleAtBack() const { 
-         assert(Nodes.size() >= 2); 
-         return Cycle(Nodes.rbegin(), 
-                      std::find(Nodes.rbegin() + 1, Nodes.rend(), Nodes.back()) + 
-                          1); 
-       } 
-   
-       /// Returns the copy of the cycle. 
-       VecTy copyCycleAtBack() const { 
-         auto R = getCycleAtBack(); 
-         return VecTy(R.begin(), R.end()); 
-       } 
-   
-     private: 
-       // All nodes of the path. 
-       VecTy Nodes; 
-       // Auxiliary container to be able to answer "Do we have a cycle ending 
-       // at last element?" as fast as possible. 
-       // We count each Decl's occurrence over the path. 
-       llvm::SmallDenseMap<Decl *, int, 32> Aux; 
-     }; 
-   
-   private: 
-     std::shared_ptr<ASTImporterSharedState> SharedState = nullptr; 
-   
-     /// The path which we go through during the import of a given AST node. 
-     ImportPathTy ImportPath; 
-     /// Sometimes we have to save some part of an import path, so later we can 
-     /// set up properties to the saved nodes. 
-     /// We may have several of these import paths associated to one Decl. 
-     using SavedImportPathsForOneDecl = 
-         llvm::SmallVector<ImportPathTy::VecTy, 32>; 
-     using SavedImportPathsTy = 
-         llvm::SmallDenseMap<Decl *, SavedImportPathsForOneDecl, 32>; 
-     SavedImportPathsTy SavedImportPaths; 
-   
-     /// The contexts we're importing to and from. 
-     ASTContext &ToContext, &FromContext; 
-   
-     /// The file managers we're importing to and from. 
-     FileManager &ToFileManager, &FromFileManager; 
-   
-     /// Whether to perform a minimal import. 
-     bool Minimal; 
-   
-     ODRHandlingType ODRHandling; 
-   
-     /// Whether the last diagnostic came from the "from" context. 
-     bool LastDiagFromFrom = false; 
-   
-     /// Mapping from the already-imported types in the "from" context 
-     /// to the corresponding types in the "to" context. 
-     llvm::DenseMap<const Type *, const Type *> ImportedTypes; 
-   
-     /// Mapping from the already-imported declarations in the "from" 
-     /// context to the corresponding declarations in the "to" context. 
-     llvm::DenseMap<Decl *, Decl *> ImportedDecls; 
-   
-     /// Mapping from the already-imported declarations in the "from" 
-     /// context to the error status of the import of that declaration. 
-     /// This map contains only the declarations that were not correctly 
-     /// imported. The same declaration may or may not be included in 
-     /// ImportedDecls. This map is updated continuously during imports and never 
-     /// cleared (like ImportedDecls). 
-     llvm::DenseMap<Decl *, ASTImportError> ImportDeclErrors; 
-   
-     /// Mapping from the already-imported declarations in the "to" 
-     /// context to the corresponding declarations in the "from" context. 
-     llvm::DenseMap<Decl *, Decl *> ImportedFromDecls; 
-   
-     /// Mapping from the already-imported statements in the "from" 
-     /// context to the corresponding statements in the "to" context. 
-     llvm::DenseMap<Stmt *, Stmt *> ImportedStmts; 
-   
-     /// Mapping from the already-imported FileIDs in the "from" source 
-     /// manager to the corresponding FileIDs in the "to" source manager. 
-     llvm::DenseMap<FileID, FileID> ImportedFileIDs; 
-   
-     /// Mapping from the already-imported CXXBasesSpecifier in 
-     ///  the "from" source manager to the corresponding CXXBasesSpecifier 
-     ///  in the "to" source manager. 
-     ImportedCXXBaseSpecifierMap ImportedCXXBaseSpecifiers; 
-   
-     /// Declaration (from, to) pairs that are known not to be equivalent 
-     /// (which we have already complained about). 
-     NonEquivalentDeclSet NonEquivalentDecls; 
-   
-     using FoundDeclsTy = SmallVector<NamedDecl *, 2>; 
-     FoundDeclsTy findDeclsInToCtx(DeclContext *DC, DeclarationName Name); 
-   
-     void AddToLookupTable(Decl *ToD); 
-   
-   protected: 
-     /// Can be overwritten by subclasses to implement their own import logic. 
-     /// The overwritten method should call this method if it didn't import the 
-     /// decl on its own. 
-     virtual Expected<Decl *> ImportImpl(Decl *From); 
-   
-     /// Used only in unittests to verify the behaviour of the error handling. 
-     virtual bool returnWithErrorInTest() { return false; }; 
-   
-   public: 
-   
-     /// \param ToContext The context we'll be importing into. 
-     /// 
-     /// \param ToFileManager The file manager we'll be importing into. 
-     /// 
-     /// \param FromContext The context we'll be importing from. 
-     /// 
-     /// \param FromFileManager The file manager we'll be importing into. 
-     /// 
-     /// \param MinimalImport If true, the importer will attempt to import 
-     /// as little as it can, e.g., by importing declarations as forward 
-     /// declarations that can be completed at a later point. 
-     /// 
-     /// \param SharedState The importer specific lookup table which may be 
-     /// shared amongst several ASTImporter objects. 
-     /// If not set then the original C/C++ lookup is used. 
-     ASTImporter(ASTContext &ToContext, FileManager &ToFileManager, 
-                 ASTContext &FromContext, FileManager &FromFileManager, 
-                 bool MinimalImport, 
-                 std::shared_ptr<ASTImporterSharedState> SharedState = nullptr); 
-   
-     virtual ~ASTImporter(); 
-   
-     /// Whether the importer will perform a minimal import, creating 
-     /// to-be-completed forward declarations when possible. 
-     bool isMinimalImport() const { return Minimal; } 
-   
-     void setODRHandling(ODRHandlingType T) { ODRHandling = T; } 
-   
-     /// \brief Import the given object, returns the result. 
-     /// 
-     /// \param To Import the object into this variable. 
-     /// \param From Object to import. 
-     /// \return Error information (success or error). 
-     template <typename ImportT> 
-     [[nodiscard]] llvm::Error importInto(ImportT &To, const ImportT &From) { 
-       auto ToOrErr = Import(From); 
-       if (ToOrErr) 
-         To = *ToOrErr; 
-       return ToOrErr.takeError(); 
-     } 
-   
-     /// Import cleanup objects owned by ExprWithCleanup. 
-     llvm::Expected<ExprWithCleanups::CleanupObject> 
-     Import(ExprWithCleanups::CleanupObject From); 
-   
-     /// Import the given type from the "from" context into the "to" 
-     /// context. 
-     /// 
-     /// \returns The equivalent type in the "to" context, or the import error. 
-     llvm::Expected<const Type *> Import(const Type *FromT); 
-   
-     /// Import the given qualified type from the "from" context into the "to" 
-     /// context. A null type is imported as a null type (no error). 
-     /// 
-     /// \returns The equivalent type in the "to" context, or the import error. 
-     llvm::Expected<QualType> Import(QualType FromT); 
-   
-     /// Import the given type source information from the 
-     /// "from" context into the "to" context. 
-     /// 
-     /// \returns The equivalent type source information in the "to" 
-     /// context, or the import error. 
-     llvm::Expected<TypeSourceInfo *> Import(TypeSourceInfo *FromTSI); 
-   
-     /// Import the given attribute from the "from" context into the 
-     /// "to" context. 
-     /// 
-     /// \returns The equivalent attribute in the "to" context, or the import 
-     /// error. 
-     llvm::Expected<Attr *> Import(const Attr *FromAttr); 
-   
-     /// Import the given declaration from the "from" context into the 
-     /// "to" context. 
-     /// 
-     /// \returns The equivalent declaration in the "to" context, or the import 
-     /// error. 
-     llvm::Expected<Decl *> Import(Decl *FromD); 
-     llvm::Expected<const Decl *> Import(const Decl *FromD) { 
-       return Import(const_cast<Decl *>(FromD)); 
-     } 
-   
-     llvm::Expected<InheritedConstructor> 
-     Import(const InheritedConstructor &From); 
-   
-     /// Return the copy of the given declaration in the "to" context if 
-     /// it has already been imported from the "from" context.  Otherwise return 
-     /// nullptr. 
-     Decl *GetAlreadyImportedOrNull(const Decl *FromD) const; 
-   
-     /// Return the translation unit from where the declaration was 
-     /// imported. If it does not exist nullptr is returned. 
-     TranslationUnitDecl *GetFromTU(Decl *ToD); 
-   
-     /// Return the declaration in the "from" context from which the declaration 
-     /// in the "to" context was imported. If it was not imported or of the wrong 
-     /// type a null value is returned. 
-     template <typename DeclT> 
-     std::optional<DeclT *> getImportedFromDecl(const DeclT *ToD) const { 
-       auto FromI = ImportedFromDecls.find(ToD); 
-       if (FromI == ImportedFromDecls.end()) 
-         return {}; 
-       auto *FromD = dyn_cast<DeclT>(FromI->second); 
-       if (!FromD) 
-         return {}; 
-       return FromD; 
-     } 
-   
-     /// Import the given declaration context from the "from" 
-     /// AST context into the "to" AST context. 
-     /// 
-     /// \returns the equivalent declaration context in the "to" 
-     /// context, or error value. 
-     llvm::Expected<DeclContext *> ImportContext(DeclContext *FromDC); 
-   
-     /// Import the given expression from the "from" context into the 
-     /// "to" context. 
-     /// 
-     /// \returns The equivalent expression in the "to" context, or the import 
-     /// error. 
-     llvm::Expected<Expr *> Import(Expr *FromE); 
-   
-     /// Import the given statement from the "from" context into the 
-     /// "to" context. 
-     /// 
-     /// \returns The equivalent statement in the "to" context, or the import 
-     /// error. 
-     llvm::Expected<Stmt *> Import(Stmt *FromS); 
-   
-     /// Import the given nested-name-specifier from the "from" 
-     /// context into the "to" context. 
-     /// 
-     /// \returns The equivalent nested-name-specifier in the "to" 
-     /// context, or the import error. 
-     llvm::Expected<NestedNameSpecifier *> Import(NestedNameSpecifier *FromNNS); 
-   
-     /// Import the given nested-name-specifier-loc from the "from" 
-     /// context into the "to" context. 
-     /// 
-     /// \returns The equivalent nested-name-specifier-loc in the "to" 
-     /// context, or the import error. 
-     llvm::Expected<NestedNameSpecifierLoc> 
-     Import(NestedNameSpecifierLoc FromNNS); 
-   
-     /// Import the given template name from the "from" context into the 
-     /// "to" context, or the import error. 
-     llvm::Expected<TemplateName> Import(TemplateName From); 
-   
-     /// Import the given source location from the "from" context into 
-     /// the "to" context. 
-     /// 
-     /// \returns The equivalent source location in the "to" context, or the 
-     /// import error. 
-     llvm::Expected<SourceLocation> Import(SourceLocation FromLoc); 
-   
-     /// Import the given source range from the "from" context into 
-     /// the "to" context. 
-     /// 
-     /// \returns The equivalent source range in the "to" context, or the import 
-     /// error. 
-     llvm::Expected<SourceRange> Import(SourceRange FromRange); 
-   
-     /// Import the given declaration name from the "from" 
-     /// context into the "to" context. 
-     /// 
-     /// \returns The equivalent declaration name in the "to" context, or the 
-     /// import error. 
-     llvm::Expected<DeclarationName> Import(DeclarationName FromName); 
-   
-     /// Import the given identifier from the "from" context 
-     /// into the "to" context. 
-     /// 
-     /// \returns The equivalent identifier in the "to" context. Note: It 
-     /// returns nullptr only if the FromId was nullptr. 
-     IdentifierInfo *Import(const IdentifierInfo *FromId); 
-   
-     /// Import the given Objective-C selector from the "from" 
-     /// context into the "to" context. 
-     /// 
-     /// \returns The equivalent selector in the "to" context, or the import 
-     /// error. 
-     llvm::Expected<Selector> Import(Selector FromSel); 
-   
-     /// Import the given file ID from the "from" context into the 
-     /// "to" context. 
-     /// 
-     /// \returns The equivalent file ID in the source manager of the "to" 
-     /// context, or the import error. 
-     llvm::Expected<FileID> Import(FileID, bool IsBuiltin = false); 
-   
-     /// Import the given C++ constructor initializer from the "from" 
-     /// context into the "to" context. 
-     /// 
-     /// \returns The equivalent initializer in the "to" context, or the import 
-     /// error. 
-     llvm::Expected<CXXCtorInitializer *> Import(CXXCtorInitializer *FromInit); 
-   
-     /// Import the given CXXBaseSpecifier from the "from" context into 
-     /// the "to" context. 
-     /// 
-     /// \returns The equivalent CXXBaseSpecifier in the source manager of the 
-     /// "to" context, or the import error. 
-     llvm::Expected<CXXBaseSpecifier *> Import(const CXXBaseSpecifier *FromSpec); 
-   
-     /// Import the given APValue from the "from" context into 
-     /// the "to" context. 
-     /// 
-     /// \return the equivalent APValue in the "to" context or the import 
-     /// error. 
-     llvm::Expected<APValue> Import(const APValue &FromValue); 
-   
-     /// Import the definition of the given declaration, including all of 
-     /// the declarations it contains. 
-     [[nodiscard]] llvm::Error ImportDefinition(Decl *From); 
-   
-     /// Cope with a name conflict when importing a declaration into the 
-     /// given context. 
-     /// 
-     /// This routine is invoked whenever there is a name conflict while 
-     /// importing a declaration. The returned name will become the name of the 
-     /// imported declaration. By default, the returned name is the same as the 
-     /// original name, leaving the conflict unresolve such that name lookup 
-     /// for this name is likely to find an ambiguity later. 
-     /// 
-     /// Subclasses may override this routine to resolve the conflict, e.g., by 
-     /// renaming the declaration being imported. 
-     /// 
-     /// \param Name the name of the declaration being imported, which conflicts 
-     /// with other declarations. 
-     /// 
-     /// \param DC the declaration context (in the "to" AST context) in which 
-     /// the name is being imported. 
-     /// 
-     /// \param IDNS the identifier namespace in which the name will be found. 
-     /// 
-     /// \param Decls the set of declarations with the same name as the 
-     /// declaration being imported. 
-     /// 
-     /// \param NumDecls the number of conflicting declarations in \p Decls. 
-     /// 
-     /// \returns the name that the newly-imported declaration should have. Or 
-     /// an error if we can't handle the name conflict. 
-     virtual Expected<DeclarationName> 
-     HandleNameConflict(DeclarationName Name, DeclContext *DC, unsigned IDNS, 
-                        NamedDecl **Decls, unsigned NumDecls); 
-   
-     /// Retrieve the context that AST nodes are being imported into. 
-     ASTContext &getToContext() const { return ToContext; } 
-   
-     /// Retrieve the context that AST nodes are being imported from. 
-     ASTContext &getFromContext() const { return FromContext; } 
-   
-     /// Retrieve the file manager that AST nodes are being imported into. 
-     FileManager &getToFileManager() const { return ToFileManager; } 
-   
-     /// Retrieve the file manager that AST nodes are being imported from. 
-     FileManager &getFromFileManager() const { return FromFileManager; } 
-   
-     /// Report a diagnostic in the "to" context. 
-     DiagnosticBuilder ToDiag(SourceLocation Loc, unsigned DiagID); 
-   
-     /// Report a diagnostic in the "from" context. 
-     DiagnosticBuilder FromDiag(SourceLocation Loc, unsigned DiagID); 
-   
-     /// Return the set of declarations that we know are not equivalent. 
-     NonEquivalentDeclSet &getNonEquivalentDecls() { return NonEquivalentDecls; } 
-   
-     /// Called for ObjCInterfaceDecl, ObjCProtocolDecl, and TagDecl. 
-     /// Mark the Decl as complete, filling it in as much as possible. 
-     /// 
-     /// \param D A declaration in the "to" context. 
-     virtual void CompleteDecl(Decl* D); 
-   
-     /// Subclasses can override this function to observe all of the \c From -> 
-     /// \c To declaration mappings as they are imported. 
-     virtual void Imported(Decl *From, Decl *To) {} 
-   
-     void RegisterImportedDecl(Decl *FromD, Decl *ToD); 
-   
-     /// Store and assign the imported declaration to its counterpart. 
-     /// It may happen that several decls from the 'from' context are mapped to 
-     /// the same decl in the 'to' context. 
-     Decl *MapImported(Decl *From, Decl *To); 
-   
-     /// Called by StructuralEquivalenceContext.  If a RecordDecl is 
-     /// being compared to another RecordDecl as part of import, completing the 
-     /// other RecordDecl may trigger importation of the first RecordDecl. This 
-     /// happens especially for anonymous structs.  If the original of the second 
-     /// RecordDecl can be found, we can complete it without the need for 
-     /// importation, eliminating this loop. 
-     virtual Decl *GetOriginalDecl(Decl *To) { return nullptr; } 
-   
-     /// Return if import of the given declaration has failed and if yes 
-     /// the kind of the problem. This gives the first error encountered with 
-     /// the node. 
-     std::optional<ASTImportError> getImportDeclErrorIfAny(Decl *FromD) const; 
-   
-     /// Mark (newly) imported declaration with error. 
-     void setImportDeclError(Decl *From, ASTImportError Error); 
-   
-     /// Determine whether the given types are structurally 
-     /// equivalent. 
-     bool IsStructurallyEquivalent(QualType From, QualType To, 
-                                   bool Complain = true); 
-   
-     /// Determine the index of a field in its parent record. 
-     /// F should be a field (or indirect field) declaration. 
-     /// \returns The index of the field in its parent context (starting from 0). 
-     /// On error `std::nullopt` is returned (parent context is non-record). 
-     static std::optional<unsigned> getFieldIndex(Decl *F); 
-   }; 
-   
- } // namespace clang 
-   
- #endif // LLVM_CLANG_AST_ASTIMPORTER_H 
-