//===- ASTImporter.cpp - Importing ASTs from other Contexts ---------------===//
//
// 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.
//
//===----------------------------------------------------------------------===//

#include "clang/AST/ASTImporter.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTDiagnostic.h"
#include "clang/AST/ASTImporterSharedState.h"
#include "clang/AST/ASTLambda.h"
#include "clang/AST/ASTStructuralEquivalence.h"
#include "clang/AST/Attr.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclAccessPair.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclFriend.h"
#include "clang/AST/DeclGroup.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/DeclVisitor.h"
#include "clang/AST/DeclarationName.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
#include "clang/AST/ExternalASTSource.h"
#include "clang/AST/LambdaCapture.h"
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/OperationKinds.h"
#include "clang/AST/Stmt.h"
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtObjC.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/AST/TemplateBase.h"
#include "clang/AST/TemplateName.h"
#include "clang/AST/Type.h"
#include "clang/AST/TypeLoc.h"
#include "clang/AST/TypeVisitor.h"
#include "clang/AST/UnresolvedSet.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/ExceptionSpecificationType.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/Specifiers.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MemoryBuffer.h"
#include <algorithm>
#include <cassert>
#include <cstddef>
#include <memory>
#include <optional>
#include <type_traits>
#include <utility>

namespace clang {

  using llvm::make_error;
  using llvm::Error;
  using llvm::Expected;
  using ExpectedTypePtr = llvm::Expected<const Type *>;
  using ExpectedType = llvm::Expected<QualType>;
  using ExpectedStmt = llvm::Expected<Stmt *>;
  using ExpectedExpr = llvm::Expected<Expr *>;
  using ExpectedDecl = llvm::Expected<Decl *>;
  using ExpectedSLoc = llvm::Expected<SourceLocation>;
  using ExpectedName = llvm::Expected<DeclarationName>;

  std::string ASTImportError::toString() const {
    // FIXME: Improve error texts.
    switch (Error) {
    case NameConflict:
      return "NameConflict";
    case UnsupportedConstruct:
      return "UnsupportedConstruct";
    case Unknown:
      return "Unknown error";
    }
    llvm_unreachable("Invalid error code.");
    return "Invalid error code.";
  }

  void ASTImportError::log(raw_ostream &OS) const { OS << toString(); }

  std::error_code ASTImportError::convertToErrorCode() const {
    llvm_unreachable("Function not implemented.");
  }

  char ASTImportError::ID;

  template <class T>
  static SmallVector<Decl *, 2>
  getCanonicalForwardRedeclChain(Redeclarable<T> *D) {
    SmallVector<Decl *, 2> Redecls;
    for (auto *R : D->getFirstDecl()->redecls()) {
      if (R != D->getFirstDecl())
        Redecls.push_back(R);
    }
    Redecls.push_back(D->getFirstDecl());
    std::reverse(Redecls.begin(), Redecls.end());
    return Redecls;
  }

  SmallVector<Decl*, 2> getCanonicalForwardRedeclChain(Decl* D) {
    if (auto *FD = dyn_cast<FunctionDecl>(D))
      return getCanonicalForwardRedeclChain<FunctionDecl>(FD);
    if (auto *VD = dyn_cast<VarDecl>(D))
      return getCanonicalForwardRedeclChain<VarDecl>(VD);
    if (auto *TD = dyn_cast<TagDecl>(D))
      return getCanonicalForwardRedeclChain<TagDecl>(TD);
    llvm_unreachable("Bad declaration kind");
  }

  static void updateFlags(const Decl *From, Decl *To) {
    // Check if some flags or attrs are new in 'From' and copy into 'To'.
    // FIXME: Other flags or attrs?
    if (From->isUsed(false) && !To->isUsed(false))
      To->setIsUsed();
  }

  /// How to handle import errors that occur when import of a child declaration
  /// of a DeclContext fails.
  class ChildErrorHandlingStrategy {
    /// This context is imported (in the 'from' domain).
    /// It is nullptr if a non-DeclContext is imported.
    const DeclContext *const FromDC;
    /// Ignore import errors of the children.
    /// If true, the context can be imported successfully if a child
    /// of it failed to import. Otherwise the import errors of the child nodes
    /// are accumulated (joined) into the import error object of the parent.
    /// (Import of a parent can fail in other ways.)
    bool const IgnoreChildErrors;

  public:
    ChildErrorHandlingStrategy(const DeclContext *FromDC)
        : FromDC(FromDC), IgnoreChildErrors(!isa<TagDecl>(FromDC)) {}
    ChildErrorHandlingStrategy(const Decl *FromD)
        : FromDC(dyn_cast<DeclContext>(FromD)),
          IgnoreChildErrors(!isa<TagDecl>(FromD)) {}

    /// Process the import result of a child (of the current declaration).
    /// \param ResultErr The import error that can be used as result of
    /// importing the parent. This may be changed by the function.
    /// \param ChildErr Result of importing a child. Can be success or error.
    void handleChildImportResult(Error &ResultErr, Error &&ChildErr) {
      if (ChildErr && !IgnoreChildErrors)
        ResultErr = joinErrors(std::move(ResultErr), std::move(ChildErr));
      else
        consumeError(std::move(ChildErr));
    }

    /// Determine if import failure of a child does not cause import failure of
    /// its parent.
    bool ignoreChildErrorOnParent(Decl *FromChildD) const {
      if (!IgnoreChildErrors || !FromDC)
        return false;
      return FromDC->containsDecl(FromChildD);
    }
  };

  class ASTNodeImporter : public TypeVisitor<ASTNodeImporter, ExpectedType>,
                          public DeclVisitor<ASTNodeImporter, ExpectedDecl>,
                          public StmtVisitor<ASTNodeImporter, ExpectedStmt> {
    ASTImporter &Importer;

    // Use this instead of Importer.importInto .
    template <typename ImportT>
    [[nodiscard]] Error importInto(ImportT &To, const ImportT &From) {
      return Importer.importInto(To, From);
    }

    // Use this to import pointers of specific type.
    template <typename ImportT>
    [[nodiscard]] Error importInto(ImportT *&To, ImportT *From) {
      auto ToOrErr = Importer.Import(From);
      if (ToOrErr)
        To = cast_or_null<ImportT>(*ToOrErr);
      return ToOrErr.takeError();
    }

    // Call the import function of ASTImporter for a baseclass of type `T` and
    // cast the return value to `T`.
    template <typename T>
    auto import(T *From)
        -> std::conditional_t<std::is_base_of_v<Type, T>, Expected<const T *>,
                              Expected<T *>> {
      auto ToOrErr = Importer.Import(From);
      if (!ToOrErr)
        return ToOrErr.takeError();
      return cast_or_null<T>(*ToOrErr);
    }

    template <typename T>
    auto import(const T *From) {
      return import(const_cast<T *>(From));
    }

    // Call the import function of ASTImporter for type `T`.
    template <typename T>
    Expected<T> import(const T &From) {
      return Importer.Import(From);
    }

    // Import an std::optional<T> by importing the contained T, if any.
    template <typename T>
    Expected<std::optional<T>> import(std::optional<T> From) {
      if (!From)
        return std::nullopt;
      return import(*From);
    }

    ExplicitSpecifier importExplicitSpecifier(Error &Err,
                                              ExplicitSpecifier ESpec);

    // Wrapper for an overload set.
    template <typename ToDeclT> struct CallOverloadedCreateFun {
      template <typename... Args> decltype(auto) operator()(Args &&... args) {
        return ToDeclT::Create(std::forward<Args>(args)...);
      }
    };

    // Always use these functions to create a Decl during import. There are
    // certain tasks which must be done after the Decl was created, e.g. we
    // must immediately register that as an imported Decl.  The parameter `ToD`
    // will be set to the newly created Decl or if had been imported before
    // then to the already imported Decl.  Returns a bool value set to true if
    // the `FromD` had been imported before.
    template <typename ToDeclT, typename FromDeclT, typename... Args>
    [[nodiscard]] bool GetImportedOrCreateDecl(ToDeclT *&ToD, FromDeclT *FromD,
                                               Args &&...args) {
      // There may be several overloads of ToDeclT::Create. We must make sure
      // to call the one which would be chosen by the arguments, thus we use a
      // wrapper for the overload set.
      CallOverloadedCreateFun<ToDeclT> OC;
      return GetImportedOrCreateSpecialDecl(ToD, OC, FromD,
                                            std::forward<Args>(args)...);
    }
    // Use this overload if a special Type is needed to be created.  E.g if we
    // want to create a `TypeAliasDecl` and assign that to a `TypedefNameDecl`
    // then:
    // TypedefNameDecl *ToTypedef;
    // GetImportedOrCreateDecl<TypeAliasDecl>(ToTypedef, FromD, ...);
    template <typename NewDeclT, typename ToDeclT, typename FromDeclT,
              typename... Args>
    [[nodiscard]] bool GetImportedOrCreateDecl(ToDeclT *&ToD, FromDeclT *FromD,
                                               Args &&...args) {
      CallOverloadedCreateFun<NewDeclT> OC;
      return GetImportedOrCreateSpecialDecl(ToD, OC, FromD,
                                            std::forward<Args>(args)...);
    }
    // Use this version if a special create function must be
    // used, e.g. CXXRecordDecl::CreateLambda .
    template <typename ToDeclT, typename CreateFunT, typename FromDeclT,
              typename... Args>
    [[nodiscard]] bool
    GetImportedOrCreateSpecialDecl(ToDeclT *&ToD, CreateFunT CreateFun,
                                   FromDeclT *FromD, Args &&...args) {
      if (Importer.getImportDeclErrorIfAny(FromD)) {
        ToD = nullptr;
        return true; // Already imported but with error.
      }
      ToD = cast_or_null<ToDeclT>(Importer.GetAlreadyImportedOrNull(FromD));
      if (ToD)
        return true; // Already imported.
      ToD = CreateFun(std::forward<Args>(args)...);
      // Keep track of imported Decls.
      Importer.RegisterImportedDecl(FromD, ToD);
      Importer.SharedState->markAsNewDecl(ToD);
      InitializeImportedDecl(FromD, ToD);
      return false; // A new Decl is created.
    }

    void InitializeImportedDecl(Decl *FromD, Decl *ToD) {
      ToD->IdentifierNamespace = FromD->IdentifierNamespace;
      if (FromD->isUsed())
        ToD->setIsUsed();
      if (FromD->isImplicit())
        ToD->setImplicit();
    }

    // Check if we have found an existing definition.  Returns with that
    // definition if yes, otherwise returns null.
    Decl *FindAndMapDefinition(FunctionDecl *D, FunctionDecl *FoundFunction) {
      const FunctionDecl *Definition = nullptr;
      if (D->doesThisDeclarationHaveABody() &&
          FoundFunction->hasBody(Definition))
        return Importer.MapImported(D, const_cast<FunctionDecl *>(Definition));
      return nullptr;
    }

    void addDeclToContexts(Decl *FromD, Decl *ToD) {
      if (Importer.isMinimalImport()) {
        // In minimal import case the decl must be added even if it is not
        // contained in original context, for LLDB compatibility.
        // FIXME: Check if a better solution is possible.
        if (!FromD->getDescribedTemplate() &&
            FromD->getFriendObjectKind() == Decl::FOK_None)
          ToD->getLexicalDeclContext()->addDeclInternal(ToD);
        return;
      }

      DeclContext *FromDC = FromD->getDeclContext();
      DeclContext *FromLexicalDC = FromD->getLexicalDeclContext();
      DeclContext *ToDC = ToD->getDeclContext();
      DeclContext *ToLexicalDC = ToD->getLexicalDeclContext();

      bool Visible = false;
      if (FromDC->containsDeclAndLoad(FromD)) {
        ToDC->addDeclInternal(ToD);
        Visible = true;
      }
      if (ToDC != ToLexicalDC && FromLexicalDC->containsDeclAndLoad(FromD)) {
        ToLexicalDC->addDeclInternal(ToD);
        Visible = true;
      }

      // If the Decl was added to any context, it was made already visible.
      // Otherwise it is still possible that it should be visible.
      if (!Visible) {
        if (auto *FromNamed = dyn_cast<NamedDecl>(FromD)) {
          auto *ToNamed = cast<NamedDecl>(ToD);
          DeclContextLookupResult FromLookup =
              FromDC->lookup(FromNamed->getDeclName());
          if (llvm::is_contained(FromLookup, FromNamed))
            ToDC->makeDeclVisibleInContext(ToNamed);
        }
      }
    }

    void updateLookupTableForTemplateParameters(TemplateParameterList &Params,
                                                DeclContext *OldDC) {
      ASTImporterLookupTable *LT = Importer.SharedState->getLookupTable();
      if (!LT)
        return;

      for (NamedDecl *TP : Params)
        LT->update(TP, OldDC);
    }

    void updateLookupTableForTemplateParameters(TemplateParameterList &Params) {
      updateLookupTableForTemplateParameters(
          Params, Importer.getToContext().getTranslationUnitDecl());
    }

    template <typename TemplateParmDeclT>
    Error importTemplateParameterDefaultArgument(const TemplateParmDeclT *D,
                                                 TemplateParmDeclT *ToD) {
      if (D->hasDefaultArgument()) {
        if (D->defaultArgumentWasInherited()) {
          Expected<TemplateParmDeclT *> ToInheritedFromOrErr =
              import(D->getDefaultArgStorage().getInheritedFrom());
          if (!ToInheritedFromOrErr)
            return ToInheritedFromOrErr.takeError();
          TemplateParmDeclT *ToInheritedFrom = *ToInheritedFromOrErr;
          if (!ToInheritedFrom->hasDefaultArgument()) {
            // Resolve possible circular dependency between default value of the
            // template argument and the template declaration.
            Expected<TemplateArgumentLoc> ToInheritedDefaultArgOrErr =
                import(D->getDefaultArgStorage()
                           .getInheritedFrom()
                           ->getDefaultArgument());
            if (!ToInheritedDefaultArgOrErr)
              return ToInheritedDefaultArgOrErr.takeError();
            ToInheritedFrom->setDefaultArgument(Importer.getToContext(),
                                                *ToInheritedDefaultArgOrErr);
          }
          ToD->setInheritedDefaultArgument(ToD->getASTContext(),
                                           ToInheritedFrom);
        } else {
          Expected<TemplateArgumentLoc> ToDefaultArgOrErr =
              import(D->getDefaultArgument());
          if (!ToDefaultArgOrErr)
            return ToDefaultArgOrErr.takeError();
          // Default argument could have been set in the
          // '!ToInheritedFrom->hasDefaultArgument()' branch above.
          if (!ToD->hasDefaultArgument())
            ToD->setDefaultArgument(Importer.getToContext(),
                                    *ToDefaultArgOrErr);
        }
      }
      return Error::success();
    }

  public:
    explicit ASTNodeImporter(ASTImporter &Importer) : Importer(Importer) {}

    using TypeVisitor<ASTNodeImporter, ExpectedType>::Visit;
    using DeclVisitor<ASTNodeImporter, ExpectedDecl>::Visit;
    using StmtVisitor<ASTNodeImporter, ExpectedStmt>::Visit;

    // Importing types
    ExpectedType VisitType(const Type *T);
#define TYPE(Class, Base)                                                    \
    ExpectedType Visit##Class##Type(const Class##Type *T);
#include "clang/AST/TypeNodes.inc"

    // Importing declarations
    Error ImportDeclParts(NamedDecl *D, DeclarationName &Name, NamedDecl *&ToD,
                          SourceLocation &Loc);
    Error ImportDeclParts(
        NamedDecl *D, DeclContext *&DC, DeclContext *&LexicalDC,
        DeclarationName &Name, NamedDecl *&ToD, SourceLocation &Loc);
    Error ImportDefinitionIfNeeded(Decl *FromD, Decl *ToD = nullptr);
    Error ImportDeclarationNameLoc(
        const DeclarationNameInfo &From, DeclarationNameInfo &To);
    Error ImportDeclContext(DeclContext *FromDC, bool ForceImport = false);
    Error ImportDeclContext(
        Decl *From, DeclContext *&ToDC, DeclContext *&ToLexicalDC);
    Error ImportImplicitMethods(const CXXRecordDecl *From, CXXRecordDecl *To);

    Error ImportFieldDeclDefinition(const FieldDecl *From, const FieldDecl *To);
    Expected<CXXCastPath> ImportCastPath(CastExpr *E);
    Expected<APValue> ImportAPValue(const APValue &FromValue);

    using Designator = DesignatedInitExpr::Designator;

    /// What we should import from the definition.
    enum ImportDefinitionKind {
      /// Import the default subset of the definition, which might be
      /// nothing (if minimal import is set) or might be everything (if minimal
      /// import is not set).
      IDK_Default,
      /// Import everything.
      IDK_Everything,
      /// Import only the bare bones needed to establish a valid
      /// DeclContext.
      IDK_Basic
    };

    bool shouldForceImportDeclContext(ImportDefinitionKind IDK) {
      return IDK == IDK_Everything ||
             (IDK == IDK_Default && !Importer.isMinimalImport());
    }

    Error ImportInitializer(VarDecl *From, VarDecl *To);
    Error ImportDefinition(
        RecordDecl *From, RecordDecl *To,
        ImportDefinitionKind Kind = IDK_Default);
    Error ImportDefinition(
        EnumDecl *From, EnumDecl *To,
        ImportDefinitionKind Kind = IDK_Default);
    Error ImportDefinition(
        ObjCInterfaceDecl *From, ObjCInterfaceDecl *To,
        ImportDefinitionKind Kind = IDK_Default);
    Error ImportDefinition(
        ObjCProtocolDecl *From, ObjCProtocolDecl *To,
        ImportDefinitionKind Kind = IDK_Default);
    Error ImportTemplateArguments(ArrayRef<TemplateArgument> FromArgs,
                                  SmallVectorImpl<TemplateArgument> &ToArgs);
    Expected<TemplateArgument>
    ImportTemplateArgument(const TemplateArgument &From);

    template <typename InContainerTy>
    Error ImportTemplateArgumentListInfo(
        const InContainerTy &Container, TemplateArgumentListInfo &ToTAInfo);

    template<typename InContainerTy>
    Error ImportTemplateArgumentListInfo(
      SourceLocation FromLAngleLoc, SourceLocation FromRAngleLoc,
      const InContainerTy &Container, TemplateArgumentListInfo &Result);

    using TemplateArgsTy = SmallVector<TemplateArgument, 8>;
    using FunctionTemplateAndArgsTy =
        std::tuple<FunctionTemplateDecl *, TemplateArgsTy>;
    Expected<FunctionTemplateAndArgsTy>
    ImportFunctionTemplateWithTemplateArgsFromSpecialization(
        FunctionDecl *FromFD);

    template <typename DeclTy>
    Error ImportTemplateParameterLists(const DeclTy *FromD, DeclTy *ToD);

    Error ImportTemplateInformation(FunctionDecl *FromFD, FunctionDecl *ToFD);

    Error ImportFunctionDeclBody(FunctionDecl *FromFD, FunctionDecl *ToFD);

    Error ImportDefaultArgOfParmVarDecl(const ParmVarDecl *FromParam,
                                        ParmVarDecl *ToParam);

    Expected<InheritedConstructor>
    ImportInheritedConstructor(const InheritedConstructor &From);

    // Use for allocating string for newly imported object.
    StringRef ImportASTStringRef(StringRef FromStr);
    Error ImportConstraintSatisfaction(const ASTConstraintSatisfaction &FromSat,
                                       ConstraintSatisfaction &ToSat);
    Expected<concepts::Requirement *>
    ImportTypeRequirement(concepts::TypeRequirement *From);
    Expected<concepts::Requirement *>
    ImportExprRequirement(concepts::ExprRequirement *From);
    Expected<concepts::Requirement *>
    ImportNestedRequirement(concepts::NestedRequirement *From);

    template <typename T>
    bool hasSameVisibilityContextAndLinkage(T *Found, T *From);

    bool IsStructuralMatch(Decl *From, Decl *To, bool Complain = true,
                           bool IgnoreTemplateParmDepth = false);
    ExpectedDecl VisitDecl(Decl *D);
    ExpectedDecl VisitImportDecl(ImportDecl *D);
    ExpectedDecl VisitEmptyDecl(EmptyDecl *D);
    ExpectedDecl VisitAccessSpecDecl(AccessSpecDecl *D);
    ExpectedDecl VisitStaticAssertDecl(StaticAssertDecl *D);
    ExpectedDecl VisitTranslationUnitDecl(TranslationUnitDecl *D);
    ExpectedDecl VisitBindingDecl(BindingDecl *D);
    ExpectedDecl VisitNamespaceDecl(NamespaceDecl *D);
    ExpectedDecl VisitNamespaceAliasDecl(NamespaceAliasDecl *D);
    ExpectedDecl VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias);
    ExpectedDecl VisitTypedefDecl(TypedefDecl *D);
    ExpectedDecl VisitTypeAliasDecl(TypeAliasDecl *D);
    ExpectedDecl VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D);
    ExpectedDecl VisitLabelDecl(LabelDecl *D);
    ExpectedDecl VisitEnumDecl(EnumDecl *D);
    ExpectedDecl VisitRecordDecl(RecordDecl *D);
    ExpectedDecl VisitEnumConstantDecl(EnumConstantDecl *D);
    ExpectedDecl VisitFunctionDecl(FunctionDecl *D);
    ExpectedDecl VisitCXXMethodDecl(CXXMethodDecl *D);
    ExpectedDecl VisitCXXConstructorDecl(CXXConstructorDecl *D);
    ExpectedDecl VisitCXXDestructorDecl(CXXDestructorDecl *D);
    ExpectedDecl VisitCXXConversionDecl(CXXConversionDecl *D);
    ExpectedDecl VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D);
    ExpectedDecl VisitFieldDecl(FieldDecl *D);
    ExpectedDecl VisitIndirectFieldDecl(IndirectFieldDecl *D);
    ExpectedDecl VisitFriendDecl(FriendDecl *D);
    ExpectedDecl VisitObjCIvarDecl(ObjCIvarDecl *D);
    ExpectedDecl VisitVarDecl(VarDecl *D);
    ExpectedDecl VisitImplicitParamDecl(ImplicitParamDecl *D);
    ExpectedDecl VisitParmVarDecl(ParmVarDecl *D);
    ExpectedDecl VisitObjCMethodDecl(ObjCMethodDecl *D);
    ExpectedDecl VisitObjCTypeParamDecl(ObjCTypeParamDecl *D);
    ExpectedDecl VisitObjCCategoryDecl(ObjCCategoryDecl *D);
    ExpectedDecl VisitObjCProtocolDecl(ObjCProtocolDecl *D);
    ExpectedDecl VisitLinkageSpecDecl(LinkageSpecDecl *D);
    ExpectedDecl VisitUsingDecl(UsingDecl *D);
    ExpectedDecl VisitUsingShadowDecl(UsingShadowDecl *D);
    ExpectedDecl VisitUsingDirectiveDecl(UsingDirectiveDecl *D);
    ExpectedDecl VisitUsingPackDecl(UsingPackDecl *D);
    ExpectedDecl ImportUsingShadowDecls(BaseUsingDecl *D, BaseUsingDecl *ToSI);
    ExpectedDecl VisitUsingEnumDecl(UsingEnumDecl *D);
    ExpectedDecl VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
    ExpectedDecl VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
    ExpectedDecl VisitBuiltinTemplateDecl(BuiltinTemplateDecl *D);
    ExpectedDecl
    VisitLifetimeExtendedTemporaryDecl(LifetimeExtendedTemporaryDecl *D);

    Expected<ObjCTypeParamList *>
    ImportObjCTypeParamList(ObjCTypeParamList *list);

    ExpectedDecl VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);
    ExpectedDecl VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D);
    ExpectedDecl VisitObjCImplementationDecl(ObjCImplementationDecl *D);
    ExpectedDecl VisitObjCPropertyDecl(ObjCPropertyDecl *D);
    ExpectedDecl VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D);
    ExpectedDecl VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D);
    ExpectedDecl VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
    ExpectedDecl VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
    ExpectedDecl VisitClassTemplateDecl(ClassTemplateDecl *D);
    ExpectedDecl VisitClassTemplateSpecializationDecl(
                                            ClassTemplateSpecializationDecl *D);
    ExpectedDecl VisitVarTemplateDecl(VarTemplateDecl *D);
    ExpectedDecl VisitVarTemplateSpecializationDecl(VarTemplateSpecializationDecl *D);
    ExpectedDecl VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
    ExpectedDecl VisitConceptDecl(ConceptDecl* D);
    ExpectedDecl VisitRequiresExprBodyDecl(RequiresExprBodyDecl* E);
    ExpectedDecl VisitImplicitConceptSpecializationDecl(ImplicitConceptSpecializationDecl* D);

    // Importing statements
    ExpectedStmt VisitStmt(Stmt *S);
    ExpectedStmt VisitGCCAsmStmt(GCCAsmStmt *S);
    ExpectedStmt VisitDeclStmt(DeclStmt *S);
    ExpectedStmt VisitNullStmt(NullStmt *S);
    ExpectedStmt VisitCompoundStmt(CompoundStmt *S);
    ExpectedStmt VisitCaseStmt(CaseStmt *S);
    ExpectedStmt VisitDefaultStmt(DefaultStmt *S);
    ExpectedStmt VisitLabelStmt(LabelStmt *S);
    ExpectedStmt VisitAttributedStmt(AttributedStmt *S);
    ExpectedStmt VisitIfStmt(IfStmt *S);
    ExpectedStmt VisitSwitchStmt(SwitchStmt *S);
    ExpectedStmt VisitWhileStmt(WhileStmt *S);
    ExpectedStmt VisitDoStmt(DoStmt *S);
    ExpectedStmt VisitForStmt(ForStmt *S);
    ExpectedStmt VisitGotoStmt(GotoStmt *S);
    ExpectedStmt VisitIndirectGotoStmt(IndirectGotoStmt *S);
    ExpectedStmt VisitContinueStmt(ContinueStmt *S);
    ExpectedStmt VisitBreakStmt(BreakStmt *S);
    ExpectedStmt VisitReturnStmt(ReturnStmt *S);
    // FIXME: MSAsmStmt
    // FIXME: SEHExceptStmt
    // FIXME: SEHFinallyStmt
    // FIXME: SEHTryStmt
    // FIXME: SEHLeaveStmt
    // FIXME: CapturedStmt
    ExpectedStmt VisitCXXCatchStmt(CXXCatchStmt *S);
    ExpectedStmt VisitCXXTryStmt(CXXTryStmt *S);
    ExpectedStmt VisitCXXForRangeStmt(CXXForRangeStmt *S);
    // FIXME: MSDependentExistsStmt
    ExpectedStmt VisitObjCForCollectionStmt(ObjCForCollectionStmt *S);
    ExpectedStmt VisitObjCAtCatchStmt(ObjCAtCatchStmt *S);
    ExpectedStmt VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *S);
    ExpectedStmt VisitObjCAtTryStmt(ObjCAtTryStmt *S);
    ExpectedStmt VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S);
    ExpectedStmt VisitObjCAtThrowStmt(ObjCAtThrowStmt *S);
    ExpectedStmt VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S);

    // Importing expressions
    ExpectedStmt VisitExpr(Expr *E);
    ExpectedStmt VisitSourceLocExpr(SourceLocExpr *E);
    ExpectedStmt VisitVAArgExpr(VAArgExpr *E);
    ExpectedStmt VisitChooseExpr(ChooseExpr *E);
    ExpectedStmt VisitConvertVectorExpr(ConvertVectorExpr *E);
    ExpectedStmt VisitShuffleVectorExpr(ShuffleVectorExpr *E);
    ExpectedStmt VisitGNUNullExpr(GNUNullExpr *E);
    ExpectedStmt VisitGenericSelectionExpr(GenericSelectionExpr *E);
    ExpectedStmt VisitPredefinedExpr(PredefinedExpr *E);
    ExpectedStmt VisitDeclRefExpr(DeclRefExpr *E);
    ExpectedStmt VisitImplicitValueInitExpr(ImplicitValueInitExpr *E);
    ExpectedStmt VisitDesignatedInitExpr(DesignatedInitExpr *E);
    ExpectedStmt VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E);
    ExpectedStmt VisitIntegerLiteral(IntegerLiteral *E);
    ExpectedStmt VisitFloatingLiteral(FloatingLiteral *E);
    ExpectedStmt VisitImaginaryLiteral(ImaginaryLiteral *E);
    ExpectedStmt VisitFixedPointLiteral(FixedPointLiteral *E);
    ExpectedStmt VisitCharacterLiteral(CharacterLiteral *E);
    ExpectedStmt VisitStringLiteral(StringLiteral *E);
    ExpectedStmt VisitCompoundLiteralExpr(CompoundLiteralExpr *E);
    ExpectedStmt VisitAtomicExpr(AtomicExpr *E);
    ExpectedStmt VisitAddrLabelExpr(AddrLabelExpr *E);
    ExpectedStmt VisitConstantExpr(ConstantExpr *E);
    ExpectedStmt VisitParenExpr(ParenExpr *E);
    ExpectedStmt VisitParenListExpr(ParenListExpr *E);
    ExpectedStmt VisitStmtExpr(StmtExpr *E);
    ExpectedStmt VisitUnaryOperator(UnaryOperator *E);
    ExpectedStmt VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E);
    ExpectedStmt VisitBinaryOperator(BinaryOperator *E);
    ExpectedStmt VisitConditionalOperator(ConditionalOperator *E);
    ExpectedStmt VisitBinaryConditionalOperator(BinaryConditionalOperator *E);
    ExpectedStmt VisitCXXRewrittenBinaryOperator(CXXRewrittenBinaryOperator *E);
    ExpectedStmt VisitOpaqueValueExpr(OpaqueValueExpr *E);
    ExpectedStmt VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E);
    ExpectedStmt VisitExpressionTraitExpr(ExpressionTraitExpr *E);
    ExpectedStmt VisitArraySubscriptExpr(ArraySubscriptExpr *E);
    ExpectedStmt VisitCompoundAssignOperator(CompoundAssignOperator *E);
    ExpectedStmt VisitImplicitCastExpr(ImplicitCastExpr *E);
    ExpectedStmt VisitExplicitCastExpr(ExplicitCastExpr *E);
    ExpectedStmt VisitOffsetOfExpr(OffsetOfExpr *OE);
    ExpectedStmt VisitCXXThrowExpr(CXXThrowExpr *E);
    ExpectedStmt VisitCXXNoexceptExpr(CXXNoexceptExpr *E);
    ExpectedStmt VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E);
    ExpectedStmt VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E);
    ExpectedStmt VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E);
    ExpectedStmt VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E);
    ExpectedStmt VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E);
    ExpectedStmt VisitPackExpansionExpr(PackExpansionExpr *E);
    ExpectedStmt VisitSizeOfPackExpr(SizeOfPackExpr *E);
    ExpectedStmt VisitCXXNewExpr(CXXNewExpr *E);
    ExpectedStmt VisitCXXDeleteExpr(CXXDeleteExpr *E);
    ExpectedStmt VisitCXXConstructExpr(CXXConstructExpr *E);
    ExpectedStmt VisitCXXMemberCallExpr(CXXMemberCallExpr *E);
    ExpectedStmt VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E);
    ExpectedStmt VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E);
    ExpectedStmt VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *E);
    ExpectedStmt VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E);
    ExpectedStmt VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E);
    ExpectedStmt VisitExprWithCleanups(ExprWithCleanups *E);
    ExpectedStmt VisitCXXThisExpr(CXXThisExpr *E);
    ExpectedStmt VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E);
    ExpectedStmt VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E);
    ExpectedStmt VisitMemberExpr(MemberExpr *E);
    ExpectedStmt VisitCallExpr(CallExpr *E);
    ExpectedStmt VisitLambdaExpr(LambdaExpr *LE);
    ExpectedStmt VisitInitListExpr(InitListExpr *E);
    ExpectedStmt VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *E);
    ExpectedStmt VisitCXXInheritedCtorInitExpr(CXXInheritedCtorInitExpr *E);
    ExpectedStmt VisitArrayInitLoopExpr(ArrayInitLoopExpr *E);
    ExpectedStmt VisitArrayInitIndexExpr(ArrayInitIndexExpr *E);
    ExpectedStmt VisitCXXDefaultInitExpr(CXXDefaultInitExpr *E);
    ExpectedStmt VisitCXXNamedCastExpr(CXXNamedCastExpr *E);
    ExpectedStmt VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *E);
    ExpectedStmt VisitTypeTraitExpr(TypeTraitExpr *E);
    ExpectedStmt VisitCXXTypeidExpr(CXXTypeidExpr *E);
    ExpectedStmt VisitCXXFoldExpr(CXXFoldExpr *E);
    ExpectedStmt VisitRequiresExpr(RequiresExpr* E);
    ExpectedStmt VisitConceptSpecializationExpr(ConceptSpecializationExpr* E);

    // Helper for chaining together multiple imports. If an error is detected,
    // subsequent imports will return default constructed nodes, so that failure
    // can be detected with a single conditional branch after a sequence of
    // imports.
    template <typename T> T importChecked(Error &Err, const T &From) {
      // Don't attempt to import nodes if we hit an error earlier.
      if (Err)
        return T{};
      Expected<T> MaybeVal = import(From);
      if (!MaybeVal) {
        Err = MaybeVal.takeError();
        return T{};
      }
      return *MaybeVal;
    }

    template<typename IIter, typename OIter>
    Error ImportArrayChecked(IIter Ibegin, IIter Iend, OIter Obegin) {
      using ItemT = std::remove_reference_t<decltype(*Obegin)>;
      for (; Ibegin != Iend; ++Ibegin, ++Obegin) {
        Expected<ItemT> ToOrErr = import(*Ibegin);
        if (!ToOrErr)
          return ToOrErr.takeError();
        *Obegin = *ToOrErr;
      }
      return Error::success();
    }

    // Import every item from a container structure into an output container.
    // If error occurs, stops at first error and returns the error.
    // The output container should have space for all needed elements (it is not
    // expanded, new items are put into from the beginning).
    template<typename InContainerTy, typename OutContainerTy>
    Error ImportContainerChecked(
        const InContainerTy &InContainer, OutContainerTy &OutContainer) {
      return ImportArrayChecked(
          InContainer.begin(), InContainer.end(), OutContainer.begin());
    }

    template<typename InContainerTy, typename OIter>
    Error ImportArrayChecked(const InContainerTy &InContainer, OIter Obegin) {
      return ImportArrayChecked(InContainer.begin(), InContainer.end(), Obegin);
    }

    Error ImportOverriddenMethods(CXXMethodDecl *ToMethod,
                                  CXXMethodDecl *FromMethod);

    Expected<FunctionDecl *> FindFunctionTemplateSpecialization(
        FunctionDecl *FromFD);

    // Returns true if the given function has a placeholder return type and
    // that type is declared inside the body of the function.
    // E.g. auto f() { struct X{}; return X(); }
    bool hasReturnTypeDeclaredInside(FunctionDecl *D);
  };

template <typename InContainerTy>
Error ASTNodeImporter::ImportTemplateArgumentListInfo(
    SourceLocation FromLAngleLoc, SourceLocation FromRAngleLoc,
    const InContainerTy &Container, TemplateArgumentListInfo &Result) {
  auto ToLAngleLocOrErr = import(FromLAngleLoc);
  if (!ToLAngleLocOrErr)
    return ToLAngleLocOrErr.takeError();
  auto ToRAngleLocOrErr = import(FromRAngleLoc);
  if (!ToRAngleLocOrErr)
    return ToRAngleLocOrErr.takeError();

  TemplateArgumentListInfo ToTAInfo(*ToLAngleLocOrErr, *ToRAngleLocOrErr);
  if (auto Err = ImportTemplateArgumentListInfo(Container, ToTAInfo))
    return Err;
  Result = ToTAInfo;
  return Error::success();
}

template <>
Error ASTNodeImporter::ImportTemplateArgumentListInfo<TemplateArgumentListInfo>(
    const TemplateArgumentListInfo &From, TemplateArgumentListInfo &Result) {
  return ImportTemplateArgumentListInfo(
      From.getLAngleLoc(), From.getRAngleLoc(), From.arguments(), Result);
}

template <>
Error ASTNodeImporter::ImportTemplateArgumentListInfo<
    ASTTemplateArgumentListInfo>(
        const ASTTemplateArgumentListInfo &From,
        TemplateArgumentListInfo &Result) {
  return ImportTemplateArgumentListInfo(
      From.LAngleLoc, From.RAngleLoc, From.arguments(), Result);
}

Expected<ASTNodeImporter::FunctionTemplateAndArgsTy>
ASTNodeImporter::ImportFunctionTemplateWithTemplateArgsFromSpecialization(
    FunctionDecl *FromFD) {
  assert(FromFD->getTemplatedKind() ==
      FunctionDecl::TK_FunctionTemplateSpecialization);

  FunctionTemplateAndArgsTy Result;

  auto *FTSInfo = FromFD->getTemplateSpecializationInfo();
  if (Error Err = importInto(std::get<0>(Result), FTSInfo->getTemplate()))
    return std::move(Err);

  // Import template arguments.
  if (Error Err = ImportTemplateArguments(FTSInfo->TemplateArguments->asArray(),
                                          std::get<1>(Result)))
    return std::move(Err);

  return Result;
}

template <>
Expected<TemplateParameterList *>
ASTNodeImporter::import(TemplateParameterList *From) {
  SmallVector<NamedDecl *, 4> To(From->size());
  if (Error Err = ImportContainerChecked(*From, To))
    return std::move(Err);

  ExpectedExpr ToRequiresClause = import(From->getRequiresClause());
  if (!ToRequiresClause)
    return ToRequiresClause.takeError();

  auto ToTemplateLocOrErr = import(From->getTemplateLoc());
  if (!ToTemplateLocOrErr)
    return ToTemplateLocOrErr.takeError();
  auto ToLAngleLocOrErr = import(From->getLAngleLoc());
  if (!ToLAngleLocOrErr)
    return ToLAngleLocOrErr.takeError();
  auto ToRAngleLocOrErr = import(From->getRAngleLoc());
  if (!ToRAngleLocOrErr)
    return ToRAngleLocOrErr.takeError();

  return TemplateParameterList::Create(
      Importer.getToContext(),
      *ToTemplateLocOrErr,
      *ToLAngleLocOrErr,
      To,
      *ToRAngleLocOrErr,
      *ToRequiresClause);
}

template <>
Expected<TemplateArgument>
ASTNodeImporter::import(const TemplateArgument &From) {
  switch (From.getKind()) {
  case TemplateArgument::Null:
    return TemplateArgument();

  case TemplateArgument::Type: {
    ExpectedType ToTypeOrErr = import(From.getAsType());
    if (!ToTypeOrErr)
      return ToTypeOrErr.takeError();
    return TemplateArgument(*ToTypeOrErr, /*isNullPtr*/ false,
                            From.getIsDefaulted());
  }

  case TemplateArgument::Integral: {
    ExpectedType ToTypeOrErr = import(From.getIntegralType());
    if (!ToTypeOrErr)
      return ToTypeOrErr.takeError();
    return TemplateArgument(From, *ToTypeOrErr);
  }

  case TemplateArgument::Declaration: {
    Expected<ValueDecl *> ToOrErr = import(From.getAsDecl());
    if (!ToOrErr)
      return ToOrErr.takeError();
    ExpectedType ToTypeOrErr = import(From.getParamTypeForDecl());
    if (!ToTypeOrErr)
      return ToTypeOrErr.takeError();
    return TemplateArgument(dyn_cast<ValueDecl>((*ToOrErr)->getCanonicalDecl()),
                            *ToTypeOrErr, From.getIsDefaulted());
  }

  case TemplateArgument::NullPtr: {
    ExpectedType ToTypeOrErr = import(From.getNullPtrType());
    if (!ToTypeOrErr)
      return ToTypeOrErr.takeError();
    return TemplateArgument(*ToTypeOrErr, /*isNullPtr*/ true,
                            From.getIsDefaulted());
  }

  case TemplateArgument::StructuralValue: {
    ExpectedType ToTypeOrErr = import(From.getStructuralValueType());
    if (!ToTypeOrErr)
      return ToTypeOrErr.takeError();
    Expected<APValue> ToValueOrErr = import(From.getAsStructuralValue());
    if (!ToValueOrErr)
      return ToValueOrErr.takeError();
    return TemplateArgument(Importer.getToContext(), *ToTypeOrErr,
                            *ToValueOrErr);
  }

  case TemplateArgument::Template: {
    Expected<TemplateName> ToTemplateOrErr = import(From.getAsTemplate());
    if (!ToTemplateOrErr)
      return ToTemplateOrErr.takeError();

    return TemplateArgument(*ToTemplateOrErr, From.getIsDefaulted());
  }

  case TemplateArgument::TemplateExpansion: {
    Expected<TemplateName> ToTemplateOrErr =
        import(From.getAsTemplateOrTemplatePattern());
    if (!ToTemplateOrErr)
      return ToTemplateOrErr.takeError();

    return TemplateArgument(*ToTemplateOrErr, From.getNumTemplateExpansions(),
                            From.getIsDefaulted());
  }

  case TemplateArgument::Expression:
    if (ExpectedExpr ToExpr = import(From.getAsExpr()))
      return TemplateArgument(*ToExpr, From.isCanonicalExpr(),
                              From.getIsDefaulted());
    else
      return ToExpr.takeError();

  case TemplateArgument::Pack: {
    SmallVector<TemplateArgument, 2> ToPack;
    ToPack.reserve(From.pack_size());
    if (Error Err = ImportTemplateArguments(From.pack_elements(), ToPack))
      return std::move(Err);

    return TemplateArgument(ArrayRef(ToPack).copy(Importer.getToContext()));
  }
  }

  llvm_unreachable("Invalid template argument kind");
}

template <>
Expected<TemplateArgumentLoc>
ASTNodeImporter::import(const TemplateArgumentLoc &TALoc) {
  Expected<TemplateArgument> ArgOrErr = import(TALoc.getArgument());
  if (!ArgOrErr)
    return ArgOrErr.takeError();
  TemplateArgument Arg = *ArgOrErr;

  TemplateArgumentLocInfo FromInfo = TALoc.getLocInfo();

  TemplateArgumentLocInfo ToInfo;
  if (Arg.getKind() == TemplateArgument::Expression) {
    ExpectedExpr E = import(FromInfo.getAsExpr());
    if (!E)
      return E.takeError();
    ToInfo = TemplateArgumentLocInfo(*E);
  } else if (Arg.getKind() == TemplateArgument::Type) {
    if (auto TSIOrErr = import(FromInfo.getAsTypeSourceInfo()))
      ToInfo = TemplateArgumentLocInfo(*TSIOrErr);
    else
      return TSIOrErr.takeError();
  } else {
    auto ToTemplateQualifierLocOrErr =
        import(FromInfo.getTemplateQualifierLoc());
    if (!ToTemplateQualifierLocOrErr)
      return ToTemplateQualifierLocOrErr.takeError();
    auto ToTemplateNameLocOrErr = import(FromInfo.getTemplateNameLoc());
    if (!ToTemplateNameLocOrErr)
      return ToTemplateNameLocOrErr.takeError();
    auto ToTemplateEllipsisLocOrErr =
        import(FromInfo.getTemplateEllipsisLoc());
    if (!ToTemplateEllipsisLocOrErr)
      return ToTemplateEllipsisLocOrErr.takeError();
    ToInfo = TemplateArgumentLocInfo(
        Importer.getToContext(), *ToTemplateQualifierLocOrErr,
        *ToTemplateNameLocOrErr, *ToTemplateEllipsisLocOrErr);
  }

  return TemplateArgumentLoc(Arg, ToInfo);
}

template <>
Expected<DeclGroupRef> ASTNodeImporter::import(const DeclGroupRef &DG) {
  if (DG.isNull())
    return DeclGroupRef::Create(Importer.getToContext(), nullptr, 0);
  size_t NumDecls = DG.end() - DG.begin();
  SmallVector<Decl *, 1> ToDecls;
  ToDecls.reserve(NumDecls);
  for (Decl *FromD : DG) {
    if (auto ToDOrErr = import(FromD))
      ToDecls.push_back(*ToDOrErr);
    else
      return ToDOrErr.takeError();
  }
  return DeclGroupRef::Create(Importer.getToContext(),
                              ToDecls.begin(),
                              NumDecls);
}

template <>
Expected<ASTNodeImporter::Designator>
ASTNodeImporter::import(const Designator &D) {
  if (D.isFieldDesignator()) {
    IdentifierInfo *ToFieldName = Importer.Import(D.getFieldName());

    ExpectedSLoc ToDotLocOrErr = import(D.getDotLoc());
    if (!ToDotLocOrErr)
      return ToDotLocOrErr.takeError();

    ExpectedSLoc ToFieldLocOrErr = import(D.getFieldLoc());
    if (!ToFieldLocOrErr)
      return ToFieldLocOrErr.takeError();

    return DesignatedInitExpr::Designator::CreateFieldDesignator(
        ToFieldName, *ToDotLocOrErr, *ToFieldLocOrErr);
  }

  ExpectedSLoc ToLBracketLocOrErr = import(D.getLBracketLoc());
  if (!ToLBracketLocOrErr)
    return ToLBracketLocOrErr.takeError();

  ExpectedSLoc ToRBracketLocOrErr = import(D.getRBracketLoc());
  if (!ToRBracketLocOrErr)
    return ToRBracketLocOrErr.takeError();

  if (D.isArrayDesignator())
    return Designator::CreateArrayDesignator(D.getArrayIndex(),
                                             *ToLBracketLocOrErr,
                                             *ToRBracketLocOrErr);

  ExpectedSLoc ToEllipsisLocOrErr = import(D.getEllipsisLoc());
  if (!ToEllipsisLocOrErr)
    return ToEllipsisLocOrErr.takeError();

  assert(D.isArrayRangeDesignator());
  return Designator::CreateArrayRangeDesignator(
      D.getArrayIndex(), *ToLBracketLocOrErr, *ToEllipsisLocOrErr,
      *ToRBracketLocOrErr);
}

template <>
Expected<ConceptReference *> ASTNodeImporter::import(ConceptReference *From) {
  Error Err = Error::success();
  auto ToNNS = importChecked(Err, From->getNestedNameSpecifierLoc());
  auto ToTemplateKWLoc = importChecked(Err, From->getTemplateKWLoc());
  auto ToConceptNameLoc =
      importChecked(Err, From->getConceptNameInfo().getLoc());
  auto ToConceptName = importChecked(Err, From->getConceptNameInfo().getName());
  auto ToFoundDecl = importChecked(Err, From->getFoundDecl());
  auto ToNamedConcept = importChecked(Err, From->getNamedConcept());
  if (Err)
    return std::move(Err);
  TemplateArgumentListInfo ToTAInfo;
  const auto *ASTTemplateArgs = From->getTemplateArgsAsWritten();
  if (ASTTemplateArgs)
    if (Error Err = ImportTemplateArgumentListInfo(*ASTTemplateArgs, ToTAInfo))
      return std::move(Err);
  auto *ConceptRef = ConceptReference::Create(
      Importer.getToContext(), ToNNS, ToTemplateKWLoc,
      DeclarationNameInfo(ToConceptName, ToConceptNameLoc), ToFoundDecl,
      ToNamedConcept,
      ASTTemplateArgs ? ASTTemplateArgumentListInfo::Create(
                            Importer.getToContext(), ToTAInfo)
                      : nullptr);
  return ConceptRef;
}

StringRef ASTNodeImporter::ImportASTStringRef(StringRef FromStr) {
  char *ToStore = new (Importer.getToContext()) char[FromStr.size()];
  std::copy(FromStr.begin(), FromStr.end(), ToStore);
  return StringRef(ToStore, FromStr.size());
}

Error ASTNodeImporter::ImportConstraintSatisfaction(
    const ASTConstraintSatisfaction &FromSat, ConstraintSatisfaction &ToSat) {
  ToSat.IsSatisfied = FromSat.IsSatisfied;
  ToSat.ContainsErrors = FromSat.ContainsErrors;
  if (!ToSat.IsSatisfied) {
    for (auto Record = FromSat.begin(); Record != FromSat.end(); ++Record) {
      if (Expr *E = Record->dyn_cast<Expr *>()) {
        ExpectedExpr ToSecondExpr = import(E);
        if (!ToSecondExpr)
          return ToSecondExpr.takeError();
        ToSat.Details.emplace_back(ToSecondExpr.get());
      } else {
        auto Pair = Record->dyn_cast<std::pair<SourceLocation, StringRef> *>();

        ExpectedSLoc ToPairFirst = import(Pair->first);
        if (!ToPairFirst)
          return ToPairFirst.takeError();
        StringRef ToPairSecond = ImportASTStringRef(Pair->second);
        ToSat.Details.emplace_back(
            new (Importer.getToContext())
                ConstraintSatisfaction::SubstitutionDiagnostic{
                    ToPairFirst.get(), ToPairSecond});
      }
    }
  }
  return Error::success();
}

template <>
Expected<concepts::Requirement::SubstitutionDiagnostic *>
ASTNodeImporter::import(
    concepts::Requirement::SubstitutionDiagnostic *FromDiag) {
  StringRef ToEntity = ImportASTStringRef(FromDiag->SubstitutedEntity);
  ExpectedSLoc ToLoc = import(FromDiag->DiagLoc);
  if (!ToLoc)
    return ToLoc.takeError();
  StringRef ToDiagMessage = ImportASTStringRef(FromDiag->DiagMessage);
  return new (Importer.getToContext())
      concepts::Requirement::SubstitutionDiagnostic{ToEntity, ToLoc.get(),
                                                    ToDiagMessage};
}

Expected<concepts::Requirement *>
ASTNodeImporter::ImportTypeRequirement(concepts::TypeRequirement *From) {
  using namespace concepts;

  if (From->isSubstitutionFailure()) {
    auto DiagOrErr = import(From->getSubstitutionDiagnostic());
    if (!DiagOrErr)
      return DiagOrErr.takeError();
    return new (Importer.getToContext()) TypeRequirement(*DiagOrErr);
  } else {
    Expected<TypeSourceInfo *> ToType = import(From->getType());
    if (!ToType)
      return ToType.takeError();
    return new (Importer.getToContext()) TypeRequirement(*ToType);
  }
}

Expected<concepts::Requirement *>
ASTNodeImporter::ImportExprRequirement(concepts::ExprRequirement *From) {
  using namespace concepts;

  bool IsRKSimple = From->getKind() == Requirement::RK_Simple;
  ExprRequirement::SatisfactionStatus Status = From->getSatisfactionStatus();

  std::optional<ExprRequirement::ReturnTypeRequirement> Req;
  ConceptSpecializationExpr *SubstitutedConstraintExpr = nullptr;

  if (IsRKSimple) {
    Req.emplace();
  } else {
    const ExprRequirement::ReturnTypeRequirement &FromTypeRequirement =
        From->getReturnTypeRequirement();

    if (FromTypeRequirement.isTypeConstraint()) {
      const bool IsDependent = FromTypeRequirement.isDependent();
      auto ParamsOrErr =
          import(FromTypeRequirement.getTypeConstraintTemplateParameterList());
      if (!ParamsOrErr)
        return ParamsOrErr.takeError();
      if (Status >= ExprRequirement::SS_ConstraintsNotSatisfied) {
        auto SubstConstraintExprOrErr =
            import(From->getReturnTypeRequirementSubstitutedConstraintExpr());
        if (!SubstConstraintExprOrErr)
          return SubstConstraintExprOrErr.takeError();
        SubstitutedConstraintExpr = SubstConstraintExprOrErr.get();
      }
      Req.emplace(ParamsOrErr.get(), IsDependent);
    } else if (FromTypeRequirement.isSubstitutionFailure()) {
      auto DiagOrErr = import(FromTypeRequirement.getSubstitutionDiagnostic());
      if (!DiagOrErr)
        return DiagOrErr.takeError();
      Req.emplace(DiagOrErr.get());
    } else {
      Req.emplace();
    }
  }

  ExpectedSLoc NoexceptLocOrErr = import(From->getNoexceptLoc());
  if (!NoexceptLocOrErr)
    return NoexceptLocOrErr.takeError();

  if (Status == ExprRequirement::SS_ExprSubstitutionFailure) {
    auto DiagOrErr = import(From->getExprSubstitutionDiagnostic());
    if (!DiagOrErr)
      return DiagOrErr.takeError();
    return new (Importer.getToContext()) ExprRequirement(
        *DiagOrErr, IsRKSimple, *NoexceptLocOrErr, std::move(*Req));
  } else {
    Expected<Expr *> ExprOrErr = import(From->getExpr());
    if (!ExprOrErr)
      return ExprOrErr.takeError();
    return new (Importer.getToContext()) concepts::ExprRequirement(
        *ExprOrErr, IsRKSimple, *NoexceptLocOrErr, std::move(*Req), Status,
        SubstitutedConstraintExpr);
  }
}

Expected<concepts::Requirement *>
ASTNodeImporter::ImportNestedRequirement(concepts::NestedRequirement *From) {
  using namespace concepts;

  const ASTConstraintSatisfaction &FromSatisfaction =
      From->getConstraintSatisfaction();
  if (From->hasInvalidConstraint()) {
    StringRef ToEntity = ImportASTStringRef(From->getInvalidConstraintEntity());
    ASTConstraintSatisfaction *ToSatisfaction =
        ASTConstraintSatisfaction::Rebuild(Importer.getToContext(),
                                           FromSatisfaction);
    return new (Importer.getToContext())
        NestedRequirement(ToEntity, ToSatisfaction);
  } else {
    ExpectedExpr ToExpr = import(From->getConstraintExpr());
    if (!ToExpr)
      return ToExpr.takeError();
    if (ToExpr.get()->isInstantiationDependent()) {
      return new (Importer.getToContext()) NestedRequirement(ToExpr.get());
    } else {
      ConstraintSatisfaction Satisfaction;
      if (Error Err =
              ImportConstraintSatisfaction(FromSatisfaction, Satisfaction))
        return std::move(Err);
      return new (Importer.getToContext()) NestedRequirement(
          Importer.getToContext(), ToExpr.get(), Satisfaction);
    }
  }
}

template <>
Expected<concepts::Requirement *>
ASTNodeImporter::import(concepts::Requirement *FromRequire) {
  switch (FromRequire->getKind()) {
  case concepts::Requirement::RequirementKind::RK_Type:
    return ImportTypeRequirement(cast<concepts::TypeRequirement>(FromRequire));
  case concepts::Requirement::RequirementKind::RK_Compound:
  case concepts::Requirement::RequirementKind::RK_Simple:
    return ImportExprRequirement(cast<concepts::ExprRequirement>(FromRequire));
  case concepts::Requirement::RequirementKind::RK_Nested:
    return ImportNestedRequirement(
        cast<concepts::NestedRequirement>(FromRequire));
  }
  llvm_unreachable("Unhandled requirement kind");
}

template <>
Expected<LambdaCapture> ASTNodeImporter::import(const LambdaCapture &From) {
  ValueDecl *Var = nullptr;
  if (From.capturesVariable()) {
    if (auto VarOrErr = import(From.getCapturedVar()))
      Var = *VarOrErr;
    else
      return VarOrErr.takeError();
  }

  auto LocationOrErr = import(From.getLocation());
  if (!LocationOrErr)
    return LocationOrErr.takeError();

  SourceLocation EllipsisLoc;
  if (From.isPackExpansion())
    if (Error Err = importInto(EllipsisLoc, From.getEllipsisLoc()))
      return std::move(Err);

  return LambdaCapture(
      *LocationOrErr, From.isImplicit(), From.getCaptureKind(), Var,
      EllipsisLoc);
}

template <typename T>
bool ASTNodeImporter::hasSameVisibilityContextAndLinkage(T *Found, T *From) {
  if (Found->getLinkageInternal() != From->getLinkageInternal())
    return false;

  if (From->hasExternalFormalLinkage())
    return Found->hasExternalFormalLinkage();
  if (Importer.GetFromTU(Found) != From->getTranslationUnitDecl())
    return false;
  if (From->isInAnonymousNamespace())
    return Found->isInAnonymousNamespace();
  else
    return !Found->isInAnonymousNamespace() &&
           !Found->hasExternalFormalLinkage();
}

template <>
bool ASTNodeImporter::hasSameVisibilityContextAndLinkage(TypedefNameDecl *Found,
                                               TypedefNameDecl *From) {
  if (Found->getLinkageInternal() != From->getLinkageInternal())
    return false;

  if (From->isInAnonymousNamespace() && Found->isInAnonymousNamespace())
    return Importer.GetFromTU(Found) == From->getTranslationUnitDecl();
  return From->isInAnonymousNamespace() == Found->isInAnonymousNamespace();
}

} // namespace clang

//----------------------------------------------------------------------------
// Import Types
//----------------------------------------------------------------------------

using namespace clang;

ExpectedType ASTNodeImporter::VisitType(const Type *T) {
  Importer.FromDiag(SourceLocation(), diag::err_unsupported_ast_node)
    << T->getTypeClassName();
  return make_error<ASTImportError>(ASTImportError::UnsupportedConstruct);
}

ExpectedType ASTNodeImporter::VisitAtomicType(const AtomicType *T){
  ExpectedType UnderlyingTypeOrErr = import(T->getValueType());
  if (!UnderlyingTypeOrErr)
    return UnderlyingTypeOrErr.takeError();

  return Importer.getToContext().getAtomicType(*UnderlyingTypeOrErr);
}

ExpectedType ASTNodeImporter::VisitBuiltinType(const BuiltinType *T) {
  switch (T->getKind()) {
#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
  case BuiltinType::Id: \
    return Importer.getToContext().SingletonId;
#include "clang/Basic/OpenCLImageTypes.def"
#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
  case BuiltinType::Id: \
    return Importer.getToContext().Id##Ty;
#include "clang/Basic/OpenCLExtensionTypes.def"
#define SVE_TYPE(Name, Id, SingletonId) \
  case BuiltinType::Id: \
    return Importer.getToContext().SingletonId;
#include "clang/Basic/AArch64ACLETypes.def"
#define PPC_VECTOR_TYPE(Name, Id, Size) \
  case BuiltinType::Id: \
    return Importer.getToContext().Id##Ty;
#include "clang/Basic/PPCTypes.def"
#define RVV_TYPE(Name, Id, SingletonId)                                        \
  case BuiltinType::Id:                                                        \
    return Importer.getToContext().SingletonId;
#include "clang/Basic/RISCVVTypes.def"
#define WASM_TYPE(Name, Id, SingletonId)                                       \
  case BuiltinType::Id:                                                        \
    return Importer.getToContext().SingletonId;
#include "clang/Basic/WebAssemblyReferenceTypes.def"
#define AMDGPU_TYPE(Name, Id, SingletonId, Width, Align)                       \
  case BuiltinType::Id:                                                        \
    return Importer.getToContext().SingletonId;
#include "clang/Basic/AMDGPUTypes.def"
#define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId)                            \
  case BuiltinType::Id:                                                        \
    return Importer.getToContext().SingletonId;
#include "clang/Basic/HLSLIntangibleTypes.def"
#define SHARED_SINGLETON_TYPE(Expansion)
#define BUILTIN_TYPE(Id, SingletonId) \
  case BuiltinType::Id: return Importer.getToContext().SingletonId;
#include "clang/AST/BuiltinTypes.def"

  // FIXME: for Char16, Char32, and NullPtr, make sure that the "to"
  // context supports C++.

  // FIXME: for ObjCId, ObjCClass, and ObjCSel, make sure that the "to"
  // context supports ObjC.

  case BuiltinType::Char_U:
    // The context we're importing from has an unsigned 'char'. If we're
    // importing into a context with a signed 'char', translate to
    // 'unsigned char' instead.
    if (Importer.getToContext().getLangOpts().CharIsSigned)
      return Importer.getToContext().UnsignedCharTy;

    return Importer.getToContext().CharTy;

  case BuiltinType::Char_S:
    // The context we're importing from has an unsigned 'char'. If we're
    // importing into a context with a signed 'char', translate to
    // 'unsigned char' instead.
    if (!Importer.getToContext().getLangOpts().CharIsSigned)
      return Importer.getToContext().SignedCharTy;

    return Importer.getToContext().CharTy;

  case BuiltinType::WChar_S:
  case BuiltinType::WChar_U:
    // FIXME: If not in C++, shall we translate to the C equivalent of
    // wchar_t?
    return Importer.getToContext().WCharTy;
  }

  llvm_unreachable("Invalid BuiltinType Kind!");
}

ExpectedType ASTNodeImporter::VisitDecayedType(const DecayedType *T) {
  ExpectedType ToOriginalTypeOrErr = import(T->getOriginalType());
  if (!ToOriginalTypeOrErr)
    return ToOriginalTypeOrErr.takeError();

  return Importer.getToContext().getDecayedType(*ToOriginalTypeOrErr);
}

ExpectedType ASTNodeImporter::VisitComplexType(const ComplexType *T) {
  ExpectedType ToElementTypeOrErr = import(T->getElementType());
  if (!ToElementTypeOrErr)
    return ToElementTypeOrErr.takeError();

  return Importer.getToContext().getComplexType(*ToElementTypeOrErr);
}

ExpectedType ASTNodeImporter::VisitPointerType(const PointerType *T) {
  ExpectedType ToPointeeTypeOrErr = import(T->getPointeeType());
  if (!ToPointeeTypeOrErr)
    return ToPointeeTypeOrErr.takeError();

  return Importer.getToContext().getPointerType(*ToPointeeTypeOrErr);
}

ExpectedType ASTNodeImporter::VisitBlockPointerType(const BlockPointerType *T) {
  // FIXME: Check for blocks support in "to" context.
  ExpectedType ToPointeeTypeOrErr = import(T->getPointeeType());
  if (!ToPointeeTypeOrErr)
    return ToPointeeTypeOrErr.takeError();

  return Importer.getToContext().getBlockPointerType(*ToPointeeTypeOrErr);
}

ExpectedType
ASTNodeImporter::VisitLValueReferenceType(const LValueReferenceType *T) {
  // FIXME: Check for C++ support in "to" context.
  ExpectedType ToPointeeTypeOrErr = import(T->getPointeeTypeAsWritten());
  if (!ToPointeeTypeOrErr)
    return ToPointeeTypeOrErr.takeError();

  return Importer.getToContext().getLValueReferenceType(*ToPointeeTypeOrErr);
}

ExpectedType
ASTNodeImporter::VisitRValueReferenceType(const RValueReferenceType *T) {
  // FIXME: Check for C++0x support in "to" context.
  ExpectedType ToPointeeTypeOrErr = import(T->getPointeeTypeAsWritten());
  if (!ToPointeeTypeOrErr)
    return ToPointeeTypeOrErr.takeError();

  return Importer.getToContext().getRValueReferenceType(*ToPointeeTypeOrErr);
}

ExpectedType
ASTNodeImporter::VisitMemberPointerType(const MemberPointerType *T) {
  // FIXME: Check for C++ support in "to" context.
  ExpectedType ToPointeeTypeOrErr = import(T->getPointeeType());
  if (!ToPointeeTypeOrErr)
    return ToPointeeTypeOrErr.takeError();

  auto QualifierOrErr = import(T->getQualifier());
  if (!QualifierOrErr)
    return QualifierOrErr.takeError();

  auto ClsOrErr = import(T->getMostRecentCXXRecordDecl());
  if (!ClsOrErr)
    return ClsOrErr.takeError();

  return Importer.getToContext().getMemberPointerType(
      *ToPointeeTypeOrErr, *QualifierOrErr, *ClsOrErr);
}

ExpectedType
ASTNodeImporter::VisitConstantArrayType(const ConstantArrayType *T) {
  Error Err = Error::success();
  auto ToElementType = importChecked(Err, T->getElementType());
  auto ToSizeExpr = importChecked(Err, T->getSizeExpr());
  if (Err)
    return std::move(Err);

  return Importer.getToContext().getConstantArrayType(
      ToElementType, T->getSize(), ToSizeExpr, T->getSizeModifier(),
      T->getIndexTypeCVRQualifiers());
}

ExpectedType
ASTNodeImporter::VisitArrayParameterType(const ArrayParameterType *T) {
  ExpectedType ToArrayTypeOrErr = VisitConstantArrayType(T);
  if (!ToArrayTypeOrErr)
    return ToArrayTypeOrErr.takeError();

  return Importer.getToContext().getArrayParameterType(*ToArrayTypeOrErr);
}

ExpectedType
ASTNodeImporter::VisitIncompleteArrayType(const IncompleteArrayType *T) {
  ExpectedType ToElementTypeOrErr = import(T->getElementType());
  if (!ToElementTypeOrErr)
    return ToElementTypeOrErr.takeError();

  return Importer.getToContext().getIncompleteArrayType(*ToElementTypeOrErr,
                                                        T->getSizeModifier(),
                                                T->getIndexTypeCVRQualifiers());
}

ExpectedType
ASTNodeImporter::VisitVariableArrayType(const VariableArrayType *T) {
  Error Err = Error::success();
  QualType ToElementType = importChecked(Err, T->getElementType());
  Expr *ToSizeExpr = importChecked(Err, T->getSizeExpr());
  if (Err)
    return std::move(Err);
  return Importer.getToContext().getVariableArrayType(
      ToElementType, ToSizeExpr, T->getSizeModifier(),
      T->getIndexTypeCVRQualifiers());
}

ExpectedType ASTNodeImporter::VisitDependentSizedArrayType(
    const DependentSizedArrayType *T) {
  Error Err = Error::success();
  QualType ToElementType = importChecked(Err, T->getElementType());
  Expr *ToSizeExpr = importChecked(Err, T->getSizeExpr());
  if (Err)
    return std::move(Err);
  // SizeExpr may be null if size is not specified directly.
  // For example, 'int a[]'.

  return Importer.getToContext().getDependentSizedArrayType(
      ToElementType, ToSizeExpr, T->getSizeModifier(),
      T->getIndexTypeCVRQualifiers());
}

ExpectedType ASTNodeImporter::VisitDependentSizedExtVectorType(
    const DependentSizedExtVectorType *T) {
  Error Err = Error::success();
  QualType ToElementType = importChecked(Err, T->getElementType());
  Expr *ToSizeExpr = importChecked(Err, T->getSizeExpr());
  SourceLocation ToAttrLoc = importChecked(Err, T->getAttributeLoc());
  if (Err)
    return std::move(Err);
  return Importer.getToContext().getDependentSizedExtVectorType(
      ToElementType, ToSizeExpr, ToAttrLoc);
}

ExpectedType ASTNodeImporter::VisitVectorType(const VectorType *T) {
  ExpectedType ToElementTypeOrErr = import(T->getElementType());
  if (!ToElementTypeOrErr)
    return ToElementTypeOrErr.takeError();

  return Importer.getToContext().getVectorType(*ToElementTypeOrErr,
                                               T->getNumElements(),
                                               T->getVectorKind());
}

ExpectedType ASTNodeImporter::VisitExtVectorType(const ExtVectorType *T) {
  ExpectedType ToElementTypeOrErr = import(T->getElementType());
  if (!ToElementTypeOrErr)
    return ToElementTypeOrErr.takeError();

  return Importer.getToContext().getExtVectorType(*ToElementTypeOrErr,
                                                  T->getNumElements());
}

ExpectedType
ASTNodeImporter::VisitFunctionNoProtoType(const FunctionNoProtoType *T) {
  // FIXME: What happens if we're importing a function without a prototype
  // into C++? Should we make it variadic?
  ExpectedType ToReturnTypeOrErr = import(T->getReturnType());
  if (!ToReturnTypeOrErr)
    return ToReturnTypeOrErr.takeError();

  return Importer.getToContext().getFunctionNoProtoType(*ToReturnTypeOrErr,
                                                        T->getExtInfo());
}

ExpectedType
ASTNodeImporter::VisitFunctionProtoType(const FunctionProtoType *T) {
  ExpectedType ToReturnTypeOrErr = import(T->getReturnType());
  if (!ToReturnTypeOrErr)
    return ToReturnTypeOrErr.takeError();

  // Import argument types
  SmallVector<QualType, 4> ArgTypes;
  for (const auto &A : T->param_types()) {
    ExpectedType TyOrErr = import(A);
    if (!TyOrErr)
      return TyOrErr.takeError();
    ArgTypes.push_back(*TyOrErr);
  }

  // Import exception types
  SmallVector<QualType, 4> ExceptionTypes;
  for (const auto &E : T->exceptions()) {
    ExpectedType TyOrErr = import(E);
    if (!TyOrErr)
      return TyOrErr.takeError();
    ExceptionTypes.push_back(*TyOrErr);
  }

  FunctionProtoType::ExtProtoInfo FromEPI = T->getExtProtoInfo();
  Error Err = Error::success();
  FunctionProtoType::ExtProtoInfo ToEPI;
  ToEPI.ExtInfo = FromEPI.ExtInfo;
  ToEPI.Variadic = FromEPI.Variadic;
  ToEPI.HasTrailingReturn = FromEPI.HasTrailingReturn;
  ToEPI.TypeQuals = FromEPI.TypeQuals;
  ToEPI.RefQualifier = FromEPI.RefQualifier;
  ToEPI.ExceptionSpec.Type = FromEPI.ExceptionSpec.Type;
  ToEPI.ExceptionSpec.NoexceptExpr =
      importChecked(Err, FromEPI.ExceptionSpec.NoexceptExpr);
  ToEPI.ExceptionSpec.SourceDecl =
      importChecked(Err, FromEPI.ExceptionSpec.SourceDecl);
  ToEPI.ExceptionSpec.SourceTemplate =
      importChecked(Err, FromEPI.ExceptionSpec.SourceTemplate);
  ToEPI.ExceptionSpec.Exceptions = ExceptionTypes;

  if (Err)
    return std::move(Err);

  return Importer.getToContext().getFunctionType(
      *ToReturnTypeOrErr, ArgTypes, ToEPI);
}

ExpectedType ASTNodeImporter::VisitUnresolvedUsingType(
    const UnresolvedUsingType *T) {
  Error Err = Error::success();
  auto ToD = importChecked(Err, T->getDecl());
  auto ToPrevD = importChecked(Err, T->getDecl()->getPreviousDecl());
  if (Err)
    return std::move(Err);

  return Importer.getToContext().getTypeDeclType(
      ToD, cast_or_null<TypeDecl>(ToPrevD));
}

ExpectedType ASTNodeImporter::VisitParenType(const ParenType *T) {
  ExpectedType ToInnerTypeOrErr = import(T->getInnerType());
  if (!ToInnerTypeOrErr)
    return ToInnerTypeOrErr.takeError();

  return Importer.getToContext().getParenType(*ToInnerTypeOrErr);
}

ExpectedType
ASTNodeImporter::VisitPackIndexingType(clang::PackIndexingType const *T) {

  ExpectedType Pattern = import(T->getPattern());
  if (!Pattern)
    return Pattern.takeError();
  ExpectedExpr Index = import(T->getIndexExpr());
  if (!Index)
    return Index.takeError();
  return Importer.getToContext().getPackIndexingType(*Pattern, *Index);
}

ExpectedType ASTNodeImporter::VisitTypedefType(const TypedefType *T) {
  Expected<TypedefNameDecl *> ToDeclOrErr = import(T->getDecl());
  if (!ToDeclOrErr)
    return ToDeclOrErr.takeError();

  TypedefNameDecl *ToDecl = *ToDeclOrErr;
  if (ToDecl->getTypeForDecl())
    return QualType(ToDecl->getTypeForDecl(), 0);

  ExpectedType ToUnderlyingTypeOrErr = import(T->desugar());
  if (!ToUnderlyingTypeOrErr)
    return ToUnderlyingTypeOrErr.takeError();

  return Importer.getToContext().getTypedefType(ToDecl, *ToUnderlyingTypeOrErr);
}

ExpectedType ASTNodeImporter::VisitTypeOfExprType(const TypeOfExprType *T) {
  ExpectedExpr ToExprOrErr = import(T->getUnderlyingExpr());
  if (!ToExprOrErr)
    return ToExprOrErr.takeError();
  return Importer.getToContext().getTypeOfExprType(*ToExprOrErr, T->getKind());
}

ExpectedType ASTNodeImporter::VisitTypeOfType(const TypeOfType *T) {
  ExpectedType ToUnderlyingTypeOrErr = import(T->getUnmodifiedType());
  if (!ToUnderlyingTypeOrErr)
    return ToUnderlyingTypeOrErr.takeError();
  return Importer.getToContext().getTypeOfType(*ToUnderlyingTypeOrErr,
                                               T->getKind());
}

ExpectedType ASTNodeImporter::VisitUsingType(const UsingType *T) {
  Expected<UsingShadowDecl *> FoundOrErr = import(T->getFoundDecl());
  if (!FoundOrErr)
    return FoundOrErr.takeError();
  Expected<QualType> UnderlyingOrErr = import(T->getUnderlyingType());
  if (!UnderlyingOrErr)
    return UnderlyingOrErr.takeError();

  return Importer.getToContext().getUsingType(*FoundOrErr, *UnderlyingOrErr);
}

ExpectedType ASTNodeImporter::VisitDecltypeType(const DecltypeType *T) {
  // FIXME: Make sure that the "to" context supports C++0x!
  ExpectedExpr ToExprOrErr = import(T->getUnderlyingExpr());
  if (!ToExprOrErr)
    return ToExprOrErr.takeError();

  ExpectedType ToUnderlyingTypeOrErr = import(T->getUnderlyingType());
  if (!ToUnderlyingTypeOrErr)
    return ToUnderlyingTypeOrErr.takeError();

  return Importer.getToContext().getDecltypeType(
      *ToExprOrErr, *ToUnderlyingTypeOrErr);
}

ExpectedType
ASTNodeImporter::VisitUnaryTransformType(const UnaryTransformType *T) {
  ExpectedType ToBaseTypeOrErr = import(T->getBaseType());
  if (!ToBaseTypeOrErr)
    return ToBaseTypeOrErr.takeError();

  ExpectedType ToUnderlyingTypeOrErr = import(T->getUnderlyingType());
  if (!ToUnderlyingTypeOrErr)
    return ToUnderlyingTypeOrErr.takeError();

  return Importer.getToContext().getUnaryTransformType(
      *ToBaseTypeOrErr, *ToUnderlyingTypeOrErr, T->getUTTKind());
}

ExpectedType ASTNodeImporter::VisitAutoType(const AutoType *T) {
  // FIXME: Make sure that the "to" context supports C++11!
  ExpectedType ToDeducedTypeOrErr = import(T->getDeducedType());
  if (!ToDeducedTypeOrErr)
    return ToDeducedTypeOrErr.takeError();

  ExpectedDecl ToTypeConstraintConcept = import(T->getTypeConstraintConcept());
  if (!ToTypeConstraintConcept)
    return ToTypeConstraintConcept.takeError();

  SmallVector<TemplateArgument, 2> ToTemplateArgs;
  if (Error Err = ImportTemplateArguments(T->getTypeConstraintArguments(),
                                          ToTemplateArgs))
    return std::move(Err);

  return Importer.getToContext().getAutoType(
      *ToDeducedTypeOrErr, T->getKeyword(), /*IsDependent*/false,
      /*IsPack=*/false, cast_or_null<ConceptDecl>(*ToTypeConstraintConcept),
      ToTemplateArgs);
}

ExpectedType ASTNodeImporter::VisitDeducedTemplateSpecializationType(
    const DeducedTemplateSpecializationType *T) {
  // FIXME: Make sure that the "to" context supports C++17!
  Expected<TemplateName> ToTemplateNameOrErr = import(T->getTemplateName());
  if (!ToTemplateNameOrErr)
    return ToTemplateNameOrErr.takeError();
  ExpectedType ToDeducedTypeOrErr = import(T->getDeducedType());
  if (!ToDeducedTypeOrErr)
    return ToDeducedTypeOrErr.takeError();

  return Importer.getToContext().getDeducedTemplateSpecializationType(
      *ToTemplateNameOrErr, *ToDeducedTypeOrErr, T->isDependentType());
}

ExpectedType ASTNodeImporter::VisitInjectedClassNameType(
    const InjectedClassNameType *T) {
  Expected<CXXRecordDecl *> ToDeclOrErr = import(T->getDecl());
  if (!ToDeclOrErr)
    return ToDeclOrErr.takeError();

  // The InjectedClassNameType is created in VisitRecordDecl when the
  // T->getDecl() is imported. Here we can return the existing type.
  const Type *Ty = (*ToDeclOrErr)->getTypeForDecl();
  assert(isa_and_nonnull<InjectedClassNameType>(Ty));
  return QualType(Ty, 0);
}

ExpectedType ASTNodeImporter::VisitRecordType(const RecordType *T) {
  Expected<RecordDecl *> ToDeclOrErr = import(T->getDecl());
  if (!ToDeclOrErr)
    return ToDeclOrErr.takeError();

  return Importer.getToContext().getTagDeclType(*ToDeclOrErr);
}

ExpectedType ASTNodeImporter::VisitEnumType(const EnumType *T) {
  Expected<EnumDecl *> ToDeclOrErr = import(T->getDecl());
  if (!ToDeclOrErr)
    return ToDeclOrErr.takeError();

  return Importer.getToContext().getTagDeclType(*ToDeclOrErr);
}

ExpectedType ASTNodeImporter::VisitAttributedType(const AttributedType *T) {
  ExpectedType ToModifiedTypeOrErr = import(T->getModifiedType());
  if (!ToModifiedTypeOrErr)
    return ToModifiedTypeOrErr.takeError();
  ExpectedType ToEquivalentTypeOrErr = import(T->getEquivalentType());
  if (!ToEquivalentTypeOrErr)
    return ToEquivalentTypeOrErr.takeError();

  return Importer.getToContext().getAttributedType(
      T->getAttrKind(), *ToModifiedTypeOrErr, *ToEquivalentTypeOrErr,
      T->getAttr());
}

ExpectedType
ASTNodeImporter::VisitCountAttributedType(const CountAttributedType *T) {
  ExpectedType ToWrappedTypeOrErr = import(T->desugar());
  if (!ToWrappedTypeOrErr)
    return ToWrappedTypeOrErr.takeError();

  Error Err = Error::success();
  Expr *CountExpr = importChecked(Err, T->getCountExpr());

  SmallVector<TypeCoupledDeclRefInfo, 1> CoupledDecls;
  for (const TypeCoupledDeclRefInfo &TI : T->dependent_decls()) {
    Expected<ValueDecl *> ToDeclOrErr = import(TI.getDecl());
    if (!ToDeclOrErr)
      return ToDeclOrErr.takeError();
    CoupledDecls.emplace_back(*ToDeclOrErr, TI.isDeref());
  }

  return Importer.getToContext().getCountAttributedType(
      *ToWrappedTypeOrErr, CountExpr, T->isCountInBytes(), T->isOrNull(),
      ArrayRef(CoupledDecls));
}

ExpectedType ASTNodeImporter::VisitTemplateTypeParmType(
    const TemplateTypeParmType *T) {
  Expected<TemplateTypeParmDecl *> ToDeclOrErr = import(T->getDecl());
  if (!ToDeclOrErr)
    return ToDeclOrErr.takeError();

  return Importer.getToContext().getTemplateTypeParmType(
      T->getDepth(), T->getIndex(), T->isParameterPack(), *ToDeclOrErr);
}

ExpectedType ASTNodeImporter::VisitSubstTemplateTypeParmType(
    const SubstTemplateTypeParmType *T) {
  Expected<Decl *> ReplacedOrErr = import(T->getAssociatedDecl());
  if (!ReplacedOrErr)
    return ReplacedOrErr.takeError();

  ExpectedType ToReplacementTypeOrErr = import(T->getReplacementType());
  if (!ToReplacementTypeOrErr)
    return ToReplacementTypeOrErr.takeError();

  return Importer.getToContext().getSubstTemplateTypeParmType(
      *ToReplacementTypeOrErr, *ReplacedOrErr, T->getIndex(), T->getPackIndex(),
      T->getFinal());
}

ExpectedType ASTNodeImporter::VisitSubstTemplateTypeParmPackType(
    const SubstTemplateTypeParmPackType *T) {
  Expected<Decl *> ReplacedOrErr = import(T->getAssociatedDecl());
  if (!ReplacedOrErr)
    return ReplacedOrErr.takeError();

  Expected<TemplateArgument> ToArgumentPack = import(T->getArgumentPack());
  if (!ToArgumentPack)
    return ToArgumentPack.takeError();

  return Importer.getToContext().getSubstTemplateTypeParmPackType(
      *ReplacedOrErr, T->getIndex(), T->getFinal(), *ToArgumentPack);
}

ExpectedType ASTNodeImporter::VisitTemplateSpecializationType(
                                       const TemplateSpecializationType *T) {
  auto ToTemplateOrErr = import(T->getTemplateName());
  if (!ToTemplateOrErr)
    return ToTemplateOrErr.takeError();

  SmallVector<TemplateArgument, 2> ToTemplateArgs;
  if (Error Err =
          ImportTemplateArguments(T->template_arguments(), ToTemplateArgs))
    return std::move(Err);

  ExpectedType ToUnderlyingOrErr =
      T->isCanonicalUnqualified() ? QualType() : import(T->desugar());
  if (!ToUnderlyingOrErr)
    return ToUnderlyingOrErr.takeError();
  return Importer.getToContext().getTemplateSpecializationType(
      *ToTemplateOrErr, ToTemplateArgs, {}, *ToUnderlyingOrErr);
}

ExpectedType ASTNodeImporter::VisitElaboratedType(const ElaboratedType *T) {
  // Note: the qualifier in an ElaboratedType is optional.
  auto ToQualifierOrErr = import(T->getQualifier());
  if (!ToQualifierOrErr)
    return ToQualifierOrErr.takeError();

  ExpectedType ToNamedTypeOrErr = import(T->getNamedType());
  if (!ToNamedTypeOrErr)
    return ToNamedTypeOrErr.takeError();

  Expected<TagDecl *> ToOwnedTagDeclOrErr = import(T->getOwnedTagDecl());
  if (!ToOwnedTagDeclOrErr)
    return ToOwnedTagDeclOrErr.takeError();

  return Importer.getToContext().getElaboratedType(T->getKeyword(),
                                                   *ToQualifierOrErr,
                                                   *ToNamedTypeOrErr,
                                                   *ToOwnedTagDeclOrErr);
}

ExpectedType
ASTNodeImporter::VisitPackExpansionType(const PackExpansionType *T) {
  ExpectedType ToPatternOrErr = import(T->getPattern());
  if (!ToPatternOrErr)
    return ToPatternOrErr.takeError();

  return Importer.getToContext().getPackExpansionType(*ToPatternOrErr,
                                                      T->getNumExpansions(),
                                                      /*ExpactPack=*/false);
}

ExpectedType ASTNodeImporter::VisitDependentTemplateSpecializationType(
    const DependentTemplateSpecializationType *T) {
  const DependentTemplateStorage &DTN = T->getDependentTemplateName();
  auto QualifierOrErr = import(DTN.getQualifier());
  if (!QualifierOrErr)
    return QualifierOrErr.takeError();

  SmallVector<TemplateArgument, 2> ToPack;
  ToPack.reserve(T->template_arguments().size());
  if (Error Err = ImportTemplateArguments(T->template_arguments(), ToPack))
    return std::move(Err);

  return Importer.getToContext().getDependentTemplateSpecializationType(
      T->getKeyword(),
      {*QualifierOrErr, Importer.Import(DTN.getName()),
       DTN.hasTemplateKeyword()},
      ToPack);
}

ExpectedType
ASTNodeImporter::VisitDependentNameType(const DependentNameType *T) {
  auto ToQualifierOrErr = import(T->getQualifier());
  if (!ToQualifierOrErr)
    return ToQualifierOrErr.takeError();

  IdentifierInfo *Name = Importer.Import(T->getIdentifier());
  return Importer.getToContext().getDependentNameType(T->getKeyword(),
                                                      *ToQualifierOrErr, Name);
}

ExpectedType
ASTNodeImporter::VisitObjCInterfaceType(const ObjCInterfaceType *T) {
  Expected<ObjCInterfaceDecl *> ToDeclOrErr = import(T->getDecl());
  if (!ToDeclOrErr)
    return ToDeclOrErr.takeError();

  return Importer.getToContext().getObjCInterfaceType(*ToDeclOrErr);
}

ExpectedType ASTNodeImporter::VisitObjCObjectType(const ObjCObjectType *T) {
  ExpectedType ToBaseTypeOrErr = import(T->getBaseType());
  if (!ToBaseTypeOrErr)
    return ToBaseTypeOrErr.takeError();

  SmallVector<QualType, 4> TypeArgs;
  for (auto TypeArg : T->getTypeArgsAsWritten()) {
    if (ExpectedType TyOrErr = import(TypeArg))
      TypeArgs.push_back(*TyOrErr);
    else
      return TyOrErr.takeError();
  }

  SmallVector<ObjCProtocolDecl *, 4> Protocols;
  for (auto *P : T->quals()) {
    if (Expected<ObjCProtocolDecl *> ProtocolOrErr = import(P))
      Protocols.push_back(*ProtocolOrErr);
    else
      return ProtocolOrErr.takeError();

  }

  return Importer.getToContext().getObjCObjectType(*ToBaseTypeOrErr, TypeArgs,
                                                   Protocols,
                                                   T->isKindOfTypeAsWritten());
}

ExpectedType
ASTNodeImporter::VisitObjCObjectPointerType(const ObjCObjectPointerType *T) {
  ExpectedType ToPointeeTypeOrErr = import(T->getPointeeType());
  if (!ToPointeeTypeOrErr)
    return ToPointeeTypeOrErr.takeError();

  return Importer.getToContext().getObjCObjectPointerType(*ToPointeeTypeOrErr);
}

ExpectedType
ASTNodeImporter::VisitMacroQualifiedType(const MacroQualifiedType *T) {
  ExpectedType ToUnderlyingTypeOrErr = import(T->getUnderlyingType());
  if (!ToUnderlyingTypeOrErr)
    return ToUnderlyingTypeOrErr.takeError();

  IdentifierInfo *ToIdentifier = Importer.Import(T->getMacroIdentifier());
  return Importer.getToContext().getMacroQualifiedType(*ToUnderlyingTypeOrErr,
                                                       ToIdentifier);
}

ExpectedType clang::ASTNodeImporter::VisitAdjustedType(const AdjustedType *T) {
  Error Err = Error::success();
  QualType ToOriginalType = importChecked(Err, T->getOriginalType());
  QualType ToAdjustedType = importChecked(Err, T->getAdjustedType());
  if (Err)
    return std::move(Err);

  return Importer.getToContext().getAdjustedType(ToOriginalType,
                                                 ToAdjustedType);
}

ExpectedType clang::ASTNodeImporter::VisitBitIntType(const BitIntType *T) {
  return Importer.getToContext().getBitIntType(T->isUnsigned(),
                                               T->getNumBits());
}

ExpectedType clang::ASTNodeImporter::VisitBTFTagAttributedType(
    const clang::BTFTagAttributedType *T) {
  Error Err = Error::success();
  const BTFTypeTagAttr *ToBTFAttr = importChecked(Err, T->getAttr());
  QualType ToWrappedType = importChecked(Err, T->getWrappedType());
  if (Err)
    return std::move(Err);

  return Importer.getToContext().getBTFTagAttributedType(ToBTFAttr,
                                                         ToWrappedType);
}

ExpectedType clang::ASTNodeImporter::VisitHLSLAttributedResourceType(
    const clang::HLSLAttributedResourceType *T) {
  Error Err = Error::success();
  const HLSLAttributedResourceType::Attributes &ToAttrs = T->getAttrs();
  QualType ToWrappedType = importChecked(Err, T->getWrappedType());
  QualType ToContainedType = importChecked(Err, T->getContainedType());
  if (Err)
    return std::move(Err);

  return Importer.getToContext().getHLSLAttributedResourceType(
      ToWrappedType, ToContainedType, ToAttrs);
}

ExpectedType clang::ASTNodeImporter::VisitHLSLInlineSpirvType(
    const clang::HLSLInlineSpirvType *T) {
  Error Err = Error::success();

  uint32_t ToOpcode = T->getOpcode();
  uint32_t ToSize = T->getSize();
  uint32_t ToAlignment = T->getAlignment();

  llvm::SmallVector<SpirvOperand> ToOperands;

  for (auto &Operand : T->getOperands()) {
    using SpirvOperandKind = SpirvOperand::SpirvOperandKind;

    switch (Operand.getKind()) {
    case SpirvOperandKind::ConstantId:
      ToOperands.push_back(SpirvOperand::createConstant(
          importChecked(Err, Operand.getResultType()), Operand.getValue()));
      break;
    case SpirvOperandKind::Literal:
      ToOperands.push_back(SpirvOperand::createLiteral(Operand.getValue()));
      break;
    case SpirvOperandKind::TypeId:
      ToOperands.push_back(SpirvOperand::createType(
          importChecked(Err, Operand.getResultType())));
      break;
    default:
      llvm_unreachable("Invalid SpirvOperand kind");
    }

    if (Err)
      return std::move(Err);
  }

  return Importer.getToContext().getHLSLInlineSpirvType(
      ToOpcode, ToSize, ToAlignment, ToOperands);
}

ExpectedType clang::ASTNodeImporter::VisitConstantMatrixType(
    const clang::ConstantMatrixType *T) {
  ExpectedType ToElementTypeOrErr = import(T->getElementType());
  if (!ToElementTypeOrErr)
    return ToElementTypeOrErr.takeError();

  return Importer.getToContext().getConstantMatrixType(
      *ToElementTypeOrErr, T->getNumRows(), T->getNumColumns());
}

ExpectedType clang::ASTNodeImporter::VisitDependentAddressSpaceType(
    const clang::DependentAddressSpaceType *T) {
  Error Err = Error::success();
  QualType ToPointeeType = importChecked(Err, T->getPointeeType());
  Expr *ToAddrSpaceExpr = importChecked(Err, T->getAddrSpaceExpr());
  SourceLocation ToAttrLoc = importChecked(Err, T->getAttributeLoc());
  if (Err)
    return std::move(Err);

  return Importer.getToContext().getDependentAddressSpaceType(
      ToPointeeType, ToAddrSpaceExpr, ToAttrLoc);
}

ExpectedType clang::ASTNodeImporter::VisitDependentBitIntType(
    const clang::DependentBitIntType *T) {
  ExpectedExpr ToNumBitsExprOrErr = import(T->getNumBitsExpr());
  if (!ToNumBitsExprOrErr)
    return ToNumBitsExprOrErr.takeError();
  return Importer.getToContext().getDependentBitIntType(T->isUnsigned(),
                                                        *ToNumBitsExprOrErr);
}

ExpectedType clang::ASTNodeImporter::VisitPredefinedSugarType(
    const clang::PredefinedSugarType *T) {
  return Importer.getToContext().getPredefinedSugarType(T->getKind());
}

ExpectedType clang::ASTNodeImporter::VisitDependentSizedMatrixType(
    const clang::DependentSizedMatrixType *T) {
  Error Err = Error::success();
  QualType ToElementType = importChecked(Err, T->getElementType());
  Expr *ToRowExpr = importChecked(Err, T->getRowExpr());
  Expr *ToColumnExpr = importChecked(Err, T->getColumnExpr());
  SourceLocation ToAttrLoc = importChecked(Err, T->getAttributeLoc());
  if (Err)
    return std::move(Err);

  return Importer.getToContext().getDependentSizedMatrixType(
      ToElementType, ToRowExpr, ToColumnExpr, ToAttrLoc);
}

ExpectedType clang::ASTNodeImporter::VisitDependentVectorType(
    const clang::DependentVectorType *T) {
  Error Err = Error::success();
  QualType ToElementType = importChecked(Err, T->getElementType());
  Expr *ToSizeExpr = importChecked(Err, T->getSizeExpr());
  SourceLocation ToAttrLoc = importChecked(Err, T->getAttributeLoc());
  if (Err)
    return std::move(Err);

  return Importer.getToContext().getDependentVectorType(
      ToElementType, ToSizeExpr, ToAttrLoc, T->getVectorKind());
}

ExpectedType clang::ASTNodeImporter::VisitObjCTypeParamType(
    const clang::ObjCTypeParamType *T) {
  Expected<ObjCTypeParamDecl *> ToDeclOrErr = import(T->getDecl());
  if (!ToDeclOrErr)
    return ToDeclOrErr.takeError();

  SmallVector<ObjCProtocolDecl *, 4> ToProtocols;
  for (ObjCProtocolDecl *FromProtocol : T->getProtocols()) {
    Expected<ObjCProtocolDecl *> ToProtocolOrErr = import(FromProtocol);
    if (!ToProtocolOrErr)
      return ToProtocolOrErr.takeError();
    ToProtocols.push_back(*ToProtocolOrErr);
  }

  return Importer.getToContext().getObjCTypeParamType(*ToDeclOrErr,
                                                      ToProtocols);
}

ExpectedType clang::ASTNodeImporter::VisitPipeType(const clang::PipeType *T) {
  ExpectedType ToElementTypeOrErr = import(T->getElementType());
  if (!ToElementTypeOrErr)
    return ToElementTypeOrErr.takeError();

  ASTContext &ToCtx = Importer.getToContext();
  if (T->isReadOnly())
    return ToCtx.getReadPipeType(*ToElementTypeOrErr);
  else
    return ToCtx.getWritePipeType(*ToElementTypeOrErr);
}

//----------------------------------------------------------------------------
// Import Declarations
//----------------------------------------------------------------------------
Error ASTNodeImporter::ImportDeclParts(
    NamedDecl *D, DeclContext *&DC, DeclContext *&LexicalDC,
    DeclarationName &Name, NamedDecl *&ToD, SourceLocation &Loc) {
  // Check if RecordDecl is in FunctionDecl parameters to avoid infinite loop.
  // example: int struct_in_proto(struct data_t{int a;int b;} *d);
  // FIXME: We could support these constructs by importing a different type of
  // this parameter and by importing the original type of the parameter only
  // after the FunctionDecl is created. See
  // VisitFunctionDecl::UsedDifferentProtoType.
  DeclContext *OrigDC = D->getDeclContext();
  FunctionDecl *FunDecl;
  if (isa<RecordDecl>(D) && (FunDecl = dyn_cast<FunctionDecl>(OrigDC)) &&
      FunDecl->hasBody()) {
    auto getLeafPointeeType = [](const Type *T) {
      while (T->isPointerType() || T->isArrayType()) {
        T = T->getPointeeOrArrayElementType();
      }
      return T;
    };
    for (const ParmVarDecl *P : FunDecl->parameters()) {
      const Type *LeafT =
          getLeafPointeeType(P->getType().getCanonicalType().getTypePtr());
      auto *RT = dyn_cast<RecordType>(LeafT);
      if (RT && RT->getDecl() == D) {
        Importer.FromDiag(D->getLocation(), diag::err_unsupported_ast_node)
            << D->getDeclKindName();
        return make_error<ASTImportError>(ASTImportError::UnsupportedConstruct);
      }
    }
  }

  // Import the context of this declaration.
  if (Error Err = ImportDeclContext(D, DC, LexicalDC))
    return Err;

  // Import the name of this declaration.
  if (Error Err = importInto(Name, D->getDeclName()))
    return Err;

  // Import the location of this declaration.
  if (Error Err = importInto(Loc, D->getLocation()))
    return Err;

  ToD = cast_or_null<NamedDecl>(Importer.GetAlreadyImportedOrNull(D));
  if (ToD)
    if (Error Err = ASTNodeImporter(*this).ImportDefinitionIfNeeded(D, ToD))
      return Err;

  return Error::success();
}

Error ASTNodeImporter::ImportDeclParts(NamedDecl *D, DeclarationName &Name,
                                       NamedDecl *&ToD, SourceLocation &Loc) {

  // Import the name of this declaration.
  if (Error Err = importInto(Name, D->getDeclName()))
    return Err;

  // Import the location of this declaration.
  if (Error Err = importInto(Loc, D->getLocation()))
    return Err;

  ToD = cast_or_null<NamedDecl>(Importer.GetAlreadyImportedOrNull(D));
  if (ToD)
    if (Error Err = ASTNodeImporter(*this).ImportDefinitionIfNeeded(D, ToD))
      return Err;

  return Error::success();
}

Error ASTNodeImporter::ImportDefinitionIfNeeded(Decl *FromD, Decl *ToD) {
  if (!FromD)
    return Error::success();

  if (!ToD)
    if (Error Err = importInto(ToD, FromD))
      return Err;

  if (RecordDecl *FromRecord = dyn_cast<RecordDecl>(FromD)) {
    if (RecordDecl *ToRecord = cast<RecordDecl>(ToD)) {
      if (FromRecord->getDefinition() && FromRecord->isCompleteDefinition() &&
          !ToRecord->getDefinition()) {
        if (Error Err = ImportDefinition(FromRecord, ToRecord))
          return Err;
      }
    }
    return Error::success();
  }

  if (EnumDecl *FromEnum = dyn_cast<EnumDecl>(FromD)) {
    if (EnumDecl *ToEnum = cast<EnumDecl>(ToD)) {
      if (FromEnum->getDefinition() && !ToEnum->getDefinition()) {
        if (Error Err = ImportDefinition(FromEnum, ToEnum))
          return Err;
      }
    }
    return Error::success();
  }

  return Error::success();
}

Error
ASTNodeImporter::ImportDeclarationNameLoc(
    const DeclarationNameInfo &From, DeclarationNameInfo& To) {
  // NOTE: To.Name and To.Loc are already imported.
  // We only have to import To.LocInfo.
  switch (To.getName().getNameKind()) {
  case DeclarationName::Identifier:
  case DeclarationName::ObjCZeroArgSelector:
  case DeclarationName::ObjCOneArgSelector:
  case DeclarationName::ObjCMultiArgSelector:
  case DeclarationName::CXXUsingDirective:
  case DeclarationName::CXXDeductionGuideName:
    return Error::success();

  case DeclarationName::CXXOperatorName: {
    if (auto ToRangeOrErr = import(From.getCXXOperatorNameRange()))
      To.setCXXOperatorNameRange(*ToRangeOrErr);
    else
      return ToRangeOrErr.takeError();
    return Error::success();
  }
  case DeclarationName::CXXLiteralOperatorName: {
    if (ExpectedSLoc LocOrErr = import(From.getCXXLiteralOperatorNameLoc()))
      To.setCXXLiteralOperatorNameLoc(*LocOrErr);
    else
      return LocOrErr.takeError();
    return Error::success();
  }
  case DeclarationName::CXXConstructorName:
  case DeclarationName::CXXDestructorName:
  case DeclarationName::CXXConversionFunctionName: {
    if (auto ToTInfoOrErr = import(From.getNamedTypeInfo()))
      To.setNamedTypeInfo(*ToTInfoOrErr);
    else
      return ToTInfoOrErr.takeError();
    return Error::success();
  }
  }
  llvm_unreachable("Unknown name kind.");
}

Error
ASTNodeImporter::ImportDeclContext(DeclContext *FromDC, bool ForceImport) {
  if (Importer.isMinimalImport() && !ForceImport) {
    auto ToDCOrErr = Importer.ImportContext(FromDC);
    return ToDCOrErr.takeError();
  }

  // We use strict error handling in case of records and enums, but not
  // with e.g. namespaces.
  //
  // FIXME Clients of the ASTImporter should be able to choose an
  // appropriate error handling strategy for their needs.  For instance,
  // they may not want to mark an entire namespace as erroneous merely
  // because there is an ODR error with two typedefs.  As another example,
  // the client may allow EnumConstantDecls with same names but with
  // different values in two distinct translation units.
  ChildErrorHandlingStrategy HandleChildErrors(FromDC);

  auto MightNeedReordering = [](const Decl *D) {
    return isa<FieldDecl>(D) || isa<IndirectFieldDecl>(D) || isa<FriendDecl>(D);
  };

  // Import everything that might need reordering first.
  Error ChildErrors = Error::success();
  for (auto *From : FromDC->decls()) {
    if (!MightNeedReordering(From))
      continue;

    ExpectedDecl ImportedOrErr = import(From);

    // If we are in the process of ImportDefinition(...) for a RecordDecl we
    // want to make sure that we are also completing each FieldDecl. There
    // are currently cases where this does not happen and this is correctness
    // fix since operations such as code generation will expect this to be so.
    if (!ImportedOrErr) {
      HandleChildErrors.handleChildImportResult(ChildErrors,
                                                ImportedOrErr.takeError());
      continue;
    }
    FieldDecl *FieldFrom = dyn_cast_or_null<FieldDecl>(From);
    Decl *ImportedDecl = *ImportedOrErr;
    FieldDecl *FieldTo = dyn_cast_or_null<FieldDecl>(ImportedDecl);
    if (FieldFrom && FieldTo) {
      Error Err = ImportFieldDeclDefinition(FieldFrom, FieldTo);
      HandleChildErrors.handleChildImportResult(ChildErrors, std::move(Err));
    }
  }

  // We reorder declarations in RecordDecls because they may have another order
  // in the "to" context than they have in the "from" context. This may happen
  // e.g when we import a class like this:
  //    struct declToImport {
  //        int a = c + b;
  //        int b = 1;
  //        int c = 2;
  //    };
  // During the import of `a` we import first the dependencies in sequence,
  // thus the order would be `c`, `b`, `a`. We will get the normal order by
  // first removing the already imported members and then adding them in the
  // order as they appear in the "from" context.
  //
  // Keeping field order is vital because it determines structure layout.
  //
  // Here and below, we cannot call field_begin() method and its callers on
  // ToDC if it has an external storage. Calling field_begin() will
  // automatically load all the fields by calling
  // LoadFieldsFromExternalStorage(). LoadFieldsFromExternalStorage() would
  // call ASTImporter::Import(). This is because the ExternalASTSource
  // interface in LLDB is implemented by the means of the ASTImporter. However,
  // calling an import at this point would result in an uncontrolled import, we
  // must avoid that.

  auto ToDCOrErr = Importer.ImportContext(FromDC);
  if (!ToDCOrErr) {
    consumeError(std::move(ChildErrors));
    return ToDCOrErr.takeError();
  }

  if (const auto *FromRD = dyn_cast<RecordDecl>(FromDC)) {
    DeclContext *ToDC = *ToDCOrErr;
    // Remove all declarations, which may be in wrong order in the
    // lexical DeclContext and then add them in the proper order.
    for (auto *D : FromRD->decls()) {
      if (!MightNeedReordering(D))
        continue;

      assert(D && "DC contains a null decl");
      if (Decl *ToD = Importer.GetAlreadyImportedOrNull(D)) {
        // Remove only the decls which we successfully imported.
        assert(ToDC == ToD->getLexicalDeclContext() && ToDC->containsDecl(ToD));
        // Remove the decl from its wrong place in the linked list.
        ToDC->removeDecl(ToD);
        // Add the decl to the end of the linked list.
        // This time it will be at the proper place because the enclosing for
        // loop iterates in the original (good) order of the decls.
        ToDC->addDeclInternal(ToD);
      }
    }
  }

  // Import everything else.
  for (auto *From : FromDC->decls()) {
    if (MightNeedReordering(From))
      continue;

    ExpectedDecl ImportedOrErr = import(From);
    if (!ImportedOrErr)
      HandleChildErrors.handleChildImportResult(ChildErrors,
                                                ImportedOrErr.takeError());
  }

  return ChildErrors;
}

Error ASTNodeImporter::ImportFieldDeclDefinition(const FieldDecl *From,
                                                 const FieldDecl *To) {
  RecordDecl *FromRecordDecl = nullptr;
  RecordDecl *ToRecordDecl = nullptr;
  // If we have a field that is an ArrayType we need to check if the array
  // element is a RecordDecl and if so we need to import the definition.
  QualType FromType = From->getType();
  QualType ToType = To->getType();
  if (FromType->isArrayType()) {
    // getBaseElementTypeUnsafe(...) handles multi-dimensional arrays for us.
    FromRecordDecl = FromType->getBaseElementTypeUnsafe()->getAsRecordDecl();
    ToRecordDecl = ToType->getBaseElementTypeUnsafe()->getAsRecordDecl();
  }

  if (!FromRecordDecl || !ToRecordDecl) {
    const RecordType *RecordFrom = FromType->getAs<RecordType>();
    const RecordType *RecordTo = ToType->getAs<RecordType>();

    if (RecordFrom && RecordTo) {
      FromRecordDecl = RecordFrom->getDecl();
      ToRecordDecl = RecordTo->getDecl();
    }
  }

  if (FromRecordDecl && ToRecordDecl) {
    if (FromRecordDecl->isCompleteDefinition() &&
        !ToRecordDecl->isCompleteDefinition())
      return ImportDefinition(FromRecordDecl, ToRecordDecl);
  }

  return Error::success();
}

Error ASTNodeImporter::ImportDeclContext(
    Decl *FromD, DeclContext *&ToDC, DeclContext *&ToLexicalDC) {
  auto ToDCOrErr = Importer.ImportContext(FromD->getDeclContext());
  if (!ToDCOrErr)
    return ToDCOrErr.takeError();
  ToDC = *ToDCOrErr;

  if (FromD->getDeclContext() != FromD->getLexicalDeclContext()) {
    auto ToLexicalDCOrErr = Importer.ImportContext(
        FromD->getLexicalDeclContext());
    if (!ToLexicalDCOrErr)
      return ToLexicalDCOrErr.takeError();
    ToLexicalDC = *ToLexicalDCOrErr;
  } else
    ToLexicalDC = ToDC;

  return Error::success();
}

Error ASTNodeImporter::ImportImplicitMethods(
    const CXXRecordDecl *From, CXXRecordDecl *To) {
  assert(From->isCompleteDefinition() && To->getDefinition() == To &&
      "Import implicit methods to or from non-definition");

  for (CXXMethodDecl *FromM : From->methods())
    if (FromM->isImplicit()) {
      Expected<CXXMethodDecl *> ToMOrErr = import(FromM);
      if (!ToMOrErr)
        return ToMOrErr.takeError();
    }

  return Error::success();
}

static Error setTypedefNameForAnonDecl(TagDecl *From, TagDecl *To,
                                       ASTImporter &Importer) {
  if (TypedefNameDecl *FromTypedef = From->getTypedefNameForAnonDecl()) {
    if (ExpectedDecl ToTypedefOrErr = Importer.Import(FromTypedef))
      To->setTypedefNameForAnonDecl(cast<TypedefNameDecl>(*ToTypedefOrErr));
    else
      return ToTypedefOrErr.takeError();
  }
  return Error::success();
}

Error ASTNodeImporter::ImportDefinition(
    RecordDecl *From, RecordDecl *To, ImportDefinitionKind Kind) {
  auto DefinitionCompleter = [To]() {
    // There are cases in LLDB when we first import a class without its
    // members. The class will have DefinitionData, but no members. Then,
    // importDefinition is called from LLDB, which tries to get the members, so
    // when we get here, the class already has the DefinitionData set, so we
    // must unset the CompleteDefinition here to be able to complete again the
    // definition.
    To->setCompleteDefinition(false);
    To->completeDefinition();
  };

  if (To->getDefinition() || To->isBeingDefined()) {
    if (Kind == IDK_Everything ||
        // In case of lambdas, the class already has a definition ptr set, but
        // the contained decls are not imported yet. Also, isBeingDefined was
        // set in CXXRecordDecl::CreateLambda.  We must import the contained
        // decls here and finish the definition.
        (To->isLambda() && shouldForceImportDeclContext(Kind))) {
      if (To->isLambda()) {
        auto *FromCXXRD = cast<CXXRecordDecl>(From);
        SmallVector<LambdaCapture, 8> ToCaptures;
        ToCaptures.reserve(FromCXXRD->capture_size());
        for (const auto &FromCapture : FromCXXRD->captures()) {
          if (auto ToCaptureOrErr = import(FromCapture))
            ToCaptures.push_back(*ToCaptureOrErr);
          else
            return ToCaptureOrErr.takeError();
        }
        cast<CXXRecordDecl>(To)->setCaptures(Importer.getToContext(),
                                             ToCaptures);
      }

      Error Result = ImportDeclContext(From, /*ForceImport=*/true);
      // Finish the definition of the lambda, set isBeingDefined to false.
      if (To->isLambda())
        DefinitionCompleter();
      return Result;
    }

    return Error::success();
  }

  To->startDefinition();
  // Set the definition to complete even if it is really not complete during
  // import. Some AST constructs (expressions) require the record layout
  // to be calculated (see 'clang::computeDependence') at the time they are
  // constructed. Import of such AST node is possible during import of the
  // same record, there is no way to have a completely defined record (all
  // fields imported) at that time without multiple AST import passes.
  if (!Importer.isMinimalImport())
    To->setCompleteDefinition(true);
  // Complete the definition even if error is returned.
  // The RecordDecl may be already part of the AST so it is better to
  // have it in complete state even if something is wrong with it.
  auto DefinitionCompleterScopeExit =
      llvm::make_scope_exit(DefinitionCompleter);

  if (Error Err = setTypedefNameForAnonDecl(From, To, Importer))
    return Err;

  // Add base classes.
  auto *ToCXX = dyn_cast<CXXRecordDecl>(To);
  auto *FromCXX = dyn_cast<CXXRecordDecl>(From);
  if (ToCXX && FromCXX && ToCXX->dataPtr() && FromCXX->dataPtr()) {

    struct CXXRecordDecl::DefinitionData &ToData = ToCXX->data();
    struct CXXRecordDecl::DefinitionData &FromData = FromCXX->data();

    #define FIELD(Name, Width, Merge) \
    ToData.Name = FromData.Name;
    #include "clang/AST/CXXRecordDeclDefinitionBits.def"

    // Copy over the data stored in RecordDeclBits
    ToCXX->setArgPassingRestrictions(FromCXX->getArgPassingRestrictions());

    SmallVector<CXXBaseSpecifier *, 4> Bases;
    for (const auto &Base1 : FromCXX->bases()) {
      ExpectedType TyOrErr = import(Base1.getType());
      if (!TyOrErr)
        return TyOrErr.takeError();

      SourceLocation EllipsisLoc;
      if (Base1.isPackExpansion()) {
        if (ExpectedSLoc LocOrErr = import(Base1.getEllipsisLoc()))
          EllipsisLoc = *LocOrErr;
        else
          return LocOrErr.takeError();
      }

      // Ensure that we have a definition for the base.
      if (Error Err =
          ImportDefinitionIfNeeded(Base1.getType()->getAsCXXRecordDecl()))
        return Err;

      auto RangeOrErr = import(Base1.getSourceRange());
      if (!RangeOrErr)
        return RangeOrErr.takeError();

      auto TSIOrErr = import(Base1.getTypeSourceInfo());
      if (!TSIOrErr)
        return TSIOrErr.takeError();

      Bases.push_back(
          new (Importer.getToContext()) CXXBaseSpecifier(
              *RangeOrErr,
              Base1.isVirtual(),
              Base1.isBaseOfClass(),
              Base1.getAccessSpecifierAsWritten(),
              *TSIOrErr,
              EllipsisLoc));
    }
    if (!Bases.empty())
      ToCXX->setBases(Bases.data(), Bases.size());
  }

  if (shouldForceImportDeclContext(Kind)) {
    if (Error Err = ImportDeclContext(From, /*ForceImport=*/true))
      return Err;
  }

  return Error::success();
}

Error ASTNodeImporter::ImportInitializer(VarDecl *From, VarDecl *To) {
  if (To->getAnyInitializer())
    return Error::success();

  Expr *FromInit = From->getInit();
  if (!FromInit)
    return Error::success();

  ExpectedExpr ToInitOrErr = import(FromInit);
  if (!ToInitOrErr)
    return ToInitOrErr.takeError();

  To->setInit(*ToInitOrErr);
  if (EvaluatedStmt *FromEval = From->getEvaluatedStmt()) {
    EvaluatedStmt *ToEval = To->ensureEvaluatedStmt();
    ToEval->HasConstantInitialization = FromEval->HasConstantInitialization;
    ToEval->HasConstantDestruction = FromEval->HasConstantDestruction;
    // FIXME: Also import the initializer value.
  }

  // FIXME: Other bits to merge?
  return Error::success();
}

Error ASTNodeImporter::ImportDefinition(
    EnumDecl *From, EnumDecl *To, ImportDefinitionKind Kind) {
  if (To->getDefinition() || To->isBeingDefined()) {
    if (Kind == IDK_Everything)
      return ImportDeclContext(From, /*ForceImport=*/true);
    return Error::success();
  }

  To->startDefinition();

  if (Error Err = setTypedefNameForAnonDecl(From, To, Importer))
    return Err;

  ExpectedType ToTypeOrErr =
      import(Importer.getFromContext().getTypeDeclType(From));
  if (!ToTypeOrErr)
    return ToTypeOrErr.takeError();

  ExpectedType ToPromotionTypeOrErr = import(From->getPromotionType());
  if (!ToPromotionTypeOrErr)
    return ToPromotionTypeOrErr.takeError();

  if (shouldForceImportDeclContext(Kind))
    if (Error Err = ImportDeclContext(From, /*ForceImport=*/true))
      return Err;

  // FIXME: we might need to merge the number of positive or negative bits
  // if the enumerator lists don't match.
  To->completeDefinition(*ToTypeOrErr, *ToPromotionTypeOrErr,
                         From->getNumPositiveBits(),
                         From->getNumNegativeBits());
  return Error::success();
}

Error ASTNodeImporter::ImportTemplateArguments(
    ArrayRef<TemplateArgument> FromArgs,
    SmallVectorImpl<TemplateArgument> &ToArgs) {
  for (const auto &Arg : FromArgs) {
    if (auto ToOrErr = import(Arg))
      ToArgs.push_back(*ToOrErr);
    else
      return ToOrErr.takeError();
  }

  return Error::success();
}

// FIXME: Do not forget to remove this and use only 'import'.
Expected<TemplateArgument>
ASTNodeImporter::ImportTemplateArgument(const TemplateArgument &From) {
  return import(From);
}

template <typename InContainerTy>
Error ASTNodeImporter::ImportTemplateArgumentListInfo(
    const InContainerTy &Container, TemplateArgumentListInfo &ToTAInfo) {
  for (const auto &FromLoc : Container) {
    if (auto ToLocOrErr = import(FromLoc))
      ToTAInfo.addArgument(*ToLocOrErr);
    else
      return ToLocOrErr.takeError();
  }
  return Error::success();
}

static StructuralEquivalenceKind
getStructuralEquivalenceKind(const ASTImporter &Importer) {
  return Importer.isMinimalImport() ? StructuralEquivalenceKind::Minimal
                                    : StructuralEquivalenceKind::Default;
}

bool ASTNodeImporter::IsStructuralMatch(Decl *From, Decl *To, bool Complain,
                                        bool IgnoreTemplateParmDepth) {
  // Eliminate a potential failure point where we attempt to re-import
  // something we're trying to import while completing ToRecord.
  Decl *ToOrigin = Importer.GetOriginalDecl(To);
  if (ToOrigin) {
    To = ToOrigin;
  }

  StructuralEquivalenceContext Ctx(
      Importer.getToContext().getLangOpts(), Importer.getFromContext(),
      Importer.getToContext(), Importer.getNonEquivalentDecls(),
      getStructuralEquivalenceKind(Importer),
      /*StrictTypeSpelling=*/false, Complain, /*ErrorOnTagTypeMismatch=*/false,
      IgnoreTemplateParmDepth);
  return Ctx.IsEquivalent(From, To);
}

ExpectedDecl ASTNodeImporter::VisitDecl(Decl *D) {
  Importer.FromDiag(D->getLocation(), diag::err_unsupported_ast_node)
    << D->getDeclKindName();
  return make_error<ASTImportError>(ASTImportError::UnsupportedConstruct);
}

ExpectedDecl ASTNodeImporter::VisitImportDecl(ImportDecl *D) {
  Importer.FromDiag(D->getLocation(), diag::err_unsupported_ast_node)
      << D->getDeclKindName();
  return make_error<ASTImportError>(ASTImportError::UnsupportedConstruct);
}

ExpectedDecl ASTNodeImporter::VisitEmptyDecl(EmptyDecl *D) {
  // Import the context of this declaration.
  DeclContext *DC, *LexicalDC;
  if (Error Err = ImportDeclContext(D, DC, LexicalDC))
    return std::move(Err);

  // Import the location of this declaration.
  ExpectedSLoc LocOrErr = import(D->getLocation());
  if (!LocOrErr)
    return LocOrErr.takeError();

  EmptyDecl *ToD;
  if (GetImportedOrCreateDecl(ToD, D, Importer.getToContext(), DC, *LocOrErr))
    return ToD;

  ToD->setLexicalDeclContext(LexicalDC);
  LexicalDC->addDeclInternal(ToD);
  return ToD;
}

ExpectedDecl ASTNodeImporter::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
  TranslationUnitDecl *ToD =
    Importer.getToContext().getTranslationUnitDecl();

  Importer.MapImported(D, ToD);

  return ToD;
}

ExpectedDecl ASTNodeImporter::VisitBindingDecl(BindingDecl *D) {
  DeclContext *DC, *LexicalDC;
  DeclarationName Name;
  SourceLocation Loc;
  NamedDecl *ToND;
  if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToND, Loc))
    return std::move(Err);
  if (ToND)
    return ToND;

  BindingDecl *ToD;
  if (GetImportedOrCreateDecl(ToD, D, Importer.getToContext(), DC, Loc,
                              Name.getAsIdentifierInfo(), D->getType()))
    return ToD;

  Error Err = Error::success();
  QualType ToType = importChecked(Err, D->getType());
  Expr *ToBinding = importChecked(Err, D->getBinding());
  ValueDecl *ToDecomposedDecl = importChecked(Err, D->getDecomposedDecl());
  if (Err)
    return std::move(Err);

  ToD->setBinding(ToType, ToBinding);
  ToD->setDecomposedDecl(ToDecomposedDecl);
  addDeclToContexts(D, ToD);

  return ToD;
}

ExpectedDecl ASTNodeImporter::VisitAccessSpecDecl(AccessSpecDecl *D) {
  ExpectedSLoc LocOrErr = import(D->getLocation());
  if (!LocOrErr)
    return LocOrErr.takeError();
  auto ColonLocOrErr = import(D->getColonLoc());
  if (!ColonLocOrErr)
    return ColonLocOrErr.takeError();

  // Import the context of this declaration.
  auto DCOrErr = Importer.ImportContext(D->getDeclContext());
  if (!DCOrErr)
    return DCOrErr.takeError();
  DeclContext *DC = *DCOrErr;

  AccessSpecDecl *ToD;
  if (GetImportedOrCreateDecl(ToD, D, Importer.getToContext(), D->getAccess(),
                              DC, *LocOrErr, *ColonLocOrErr))
    return ToD;

  // Lexical DeclContext and Semantic DeclContext
  // is always the same for the accessSpec.
  ToD->setLexicalDeclContext(DC);
  DC->addDeclInternal(ToD);

  return ToD;
}

ExpectedDecl ASTNodeImporter::VisitStaticAssertDecl(StaticAssertDecl *D) {
  auto DCOrErr = Importer.ImportContext(D->getDeclContext());
  if (!DCOrErr)
    return DCOrErr.takeError();
  DeclContext *DC = *DCOrErr;
  DeclContext *LexicalDC = DC;

  Error Err = Error::success();
  auto ToLocation = importChecked(Err, D->getLocation());
  auto ToRParenLoc = importChecked(Err, D->getRParenLoc());
  auto ToAssertExpr = importChecked(Err, D->getAssertExpr());
  auto ToMessage = importChecked(Err, D->getMessage());
  if (Err)
    return std::move(Err);

  StaticAssertDecl *ToD;
  if (GetImportedOrCreateDecl(
      ToD, D, Importer.getToContext(), DC, ToLocation, ToAssertExpr, ToMessage,
      ToRParenLoc, D->isFailed()))
    return ToD;

  ToD->setLexicalDeclContext(LexicalDC);
  LexicalDC->addDeclInternal(ToD);
  return ToD;
}

ExpectedDecl ASTNodeImporter::VisitNamespaceDecl(NamespaceDecl *D) {
  // Import the major distinguishing characteristics of this namespace.
  DeclContext *DC, *LexicalDC;
  DeclarationName Name;
  SourceLocation Loc;
  NamedDecl *ToD;
  if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
    return std::move(Err);
  if (ToD)
    return ToD;

  NamespaceDecl *MergeWithNamespace = nullptr;
  if (!Name) {
    // This is an anonymous namespace. Adopt an existing anonymous
    // namespace if we can.
    DeclContext *EnclosingDC = DC->getEnclosingNamespaceContext();
    if (auto *TU = dyn_cast<TranslationUnitDecl>(EnclosingDC))
      MergeWithNamespace = TU->getAnonymousNamespace();
    else
      MergeWithNamespace =
          cast<NamespaceDecl>(EnclosingDC)->getAnonymousNamespace();
  } else {
    SmallVector<NamedDecl *, 4> ConflictingDecls;
    auto FoundDecls = Importer.findDeclsInToCtx(DC, Name);
    for (auto *FoundDecl : FoundDecls) {
      if (!FoundDecl->isInIdentifierNamespace(Decl::IDNS_Namespace))
        continue;

      if (auto *FoundNS = dyn_cast<NamespaceDecl>(FoundDecl)) {
        MergeWithNamespace = FoundNS;
        ConflictingDecls.clear();
        break;
      }

      ConflictingDecls.push_back(FoundDecl);
    }

    if (!ConflictingDecls.empty()) {
      ExpectedName NameOrErr = Importer.HandleNameConflict(
          Name, DC, Decl::IDNS_Namespace, ConflictingDecls.data(),
          ConflictingDecls.size());
      if (NameOrErr)
        Name = NameOrErr.get();
      else
        return NameOrErr.takeError();
    }
  }

  ExpectedSLoc BeginLocOrErr = import(D->getBeginLoc());
  if (!BeginLocOrErr)
    return BeginLocOrErr.takeError();
  ExpectedSLoc RBraceLocOrErr = import(D->getRBraceLoc());
  if (!RBraceLocOrErr)
    return RBraceLocOrErr.takeError();

  // Create the "to" namespace, if needed.
  NamespaceDecl *ToNamespace = MergeWithNamespace;
  if (!ToNamespace) {
    if (GetImportedOrCreateDecl(ToNamespace, D, Importer.getToContext(), DC,
                                D->isInline(), *BeginLocOrErr, Loc,
                                Name.getAsIdentifierInfo(),
                                /*PrevDecl=*/nullptr, D->isNested()))
      return ToNamespace;
    ToNamespace->setRBraceLoc(*RBraceLocOrErr);
    ToNamespace->setLexicalDeclContext(LexicalDC);
    LexicalDC->addDeclInternal(ToNamespace);

    // If this is an anonymous namespace, register it as the anonymous
    // namespace within its context.
    if (!Name) {
      if (auto *TU = dyn_cast<TranslationUnitDecl>(DC))
        TU->setAnonymousNamespace(ToNamespace);
      else
        cast<NamespaceDecl>(DC)->setAnonymousNamespace(ToNamespace);
    }
  }
  Importer.MapImported(D, ToNamespace);

  if (Error Err = ImportDeclContext(D))
    return std::move(Err);

  return ToNamespace;
}

ExpectedDecl ASTNodeImporter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
  // Import the major distinguishing characteristics of this namespace.
  DeclContext *DC, *LexicalDC;
  DeclarationName Name;
  SourceLocation Loc;
  NamedDecl *LookupD;
  if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, LookupD, Loc))
    return std::move(Err);
  if (LookupD)
    return LookupD;

  // NOTE: No conflict resolution is done for namespace aliases now.

  Error Err = Error::success();
  auto ToNamespaceLoc = importChecked(Err, D->getNamespaceLoc());
  auto ToAliasLoc = importChecked(Err, D->getAliasLoc());
  auto ToQualifierLoc = importChecked(Err, D->getQualifierLoc());
  auto ToTargetNameLoc = importChecked(Err, D->getTargetNameLoc());
  auto ToNamespace = importChecked(Err, D->getNamespace());
  if (Err)
    return std::move(Err);

  IdentifierInfo *ToIdentifier = Importer.Import(D->getIdentifier());

  NamespaceAliasDecl *ToD;
  if (GetImportedOrCreateDecl(
      ToD, D, Importer.getToContext(), DC, ToNamespaceLoc, ToAliasLoc,
      ToIdentifier, ToQualifierLoc, ToTargetNameLoc, ToNamespace))
    return ToD;

  ToD->setLexicalDeclContext(LexicalDC);
  LexicalDC->addDeclInternal(ToD);

  return ToD;
}

ExpectedDecl
ASTNodeImporter::VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias) {
  // Import the major distinguishing characteristics of this typedef.
  DeclarationName Name;
  SourceLocation Loc;
  NamedDecl *ToD;
  // Do not import the DeclContext, we will import it once the TypedefNameDecl
  // is created.
  if (Error Err = ImportDeclParts(D, Name, ToD, Loc))
    return std::move(Err);
  if (ToD)
    return ToD;

  DeclContext *DC = cast_or_null<DeclContext>(
      Importer.GetAlreadyImportedOrNull(cast<Decl>(D->getDeclContext())));
  DeclContext *LexicalDC =
      cast_or_null<DeclContext>(Importer.GetAlreadyImportedOrNull(
          cast<Decl>(D->getLexicalDeclContext())));

  // If this typedef is not in block scope, determine whether we've
  // seen a typedef with the same name (that we can merge with) or any
  // other entity by that name (which name lookup could conflict with).
  // Note: Repeated typedefs are not valid in C99:
  // 'typedef int T; typedef int T;' is invalid
  // We do not care about this now.
  if (DC && !DC->isFunctionOrMethod()) {
    SmallVector<NamedDecl *, 4> ConflictingDecls;
    unsigned IDNS = Decl::IDNS_Ordinary;
    auto FoundDecls = Importer.findDeclsInToCtx(DC, Name);
    for (auto *FoundDecl : FoundDecls) {
      if (!FoundDecl->isInIdentifierNamespace(IDNS))
        continue;
      if (auto *FoundTypedef = dyn_cast<TypedefNameDecl>(FoundDecl)) {
        if (!hasSameVisibilityContextAndLinkage(FoundTypedef, D))
          continue;

        QualType FromUT = D->getUnderlyingType();
        QualType FoundUT = FoundTypedef->getUnderlyingType();
        if (Importer.IsStructurallyEquivalent(FromUT, FoundUT)) {
          // If the underlying declarations are unnamed records these can be
          // imported as different types. We should create a distinct typedef
          // node in this case.
          // If we found an existing underlying type with a record in a
          // different context (than the imported), this is already reason for
          // having distinct typedef nodes for these.
          // Again this can create situation like
          // 'typedef int T; typedef int T;' but this is hard to avoid without
          // a rename strategy at import.
          if (!FromUT.isNull() && !FoundUT.isNull()) {
            RecordDecl *FromR = FromUT->getAsRecordDecl();
            RecordDecl *FoundR = FoundUT->getAsRecordDecl();
            if (FromR && FoundR &&
                !hasSameVisibilityContextAndLinkage(FoundR, FromR))
              continue;
          }
          // If the "From" context has a complete underlying type but we
          // already have a complete underlying type then return with that.
          if (!FromUT->isIncompleteType() && !FoundUT->isIncompleteType())
            return Importer.MapImported(D, FoundTypedef);
          // FIXME Handle redecl chain. When you do that make consistent changes
          // in ASTImporterLookupTable too.
        } else {
          ConflictingDecls.push_back(FoundDecl);
        }
      }
    }

    if (!ConflictingDecls.empty()) {
      ExpectedName NameOrErr = Importer.HandleNameConflict(
          Name, DC, IDNS, ConflictingDecls.data(), ConflictingDecls.size());
      if (NameOrErr)
        Name = NameOrErr.get();
      else
        return NameOrErr.takeError();
    }
  }

  Error Err = Error::success();
  auto ToUnderlyingType = importChecked(Err, D->getUnderlyingType());
  auto ToTypeSourceInfo = importChecked(Err, D->getTypeSourceInfo());
  auto ToBeginLoc = importChecked(Err, D->getBeginLoc());
  if (Err)
    return std::move(Err);

  // Create the new typedef node.
  // FIXME: ToUnderlyingType is not used.
  (void)ToUnderlyingType;
  TypedefNameDecl *ToTypedef;
  if (IsAlias) {
    if (GetImportedOrCreateDecl<TypeAliasDecl>(
        ToTypedef, D, Importer.getToContext(), DC, ToBeginLoc, Loc,
        Name.getAsIdentifierInfo(), ToTypeSourceInfo))
      return ToTypedef;
  } else if (GetImportedOrCreateDecl<TypedefDecl>(
      ToTypedef, D, Importer.getToContext(), DC, ToBeginLoc, Loc,
      Name.getAsIdentifierInfo(), ToTypeSourceInfo))
    return ToTypedef;

  // Import the DeclContext and set it to the Typedef.
  if ((Err = ImportDeclContext(D, DC, LexicalDC)))
    return std::move(Err);
  ToTypedef->setDeclContext(DC);
  ToTypedef->setLexicalDeclContext(LexicalDC);
  // Add to the lookupTable because we could not do that in MapImported.
  Importer.AddToLookupTable(ToTypedef);

  ToTypedef->setAccess(D->getAccess());

  // Templated declarations should not appear in DeclContext.
  TypeAliasDecl *FromAlias = IsAlias ? cast<TypeAliasDecl>(D) : nullptr;
  if (!FromAlias || !FromAlias->getDescribedAliasTemplate())
    LexicalDC->addDeclInternal(ToTypedef);

  return ToTypedef;
}

ExpectedDecl ASTNodeImporter::VisitTypedefDecl(TypedefDecl *D) {
  return VisitTypedefNameDecl(D, /*IsAlias=*/false);
}

ExpectedDecl ASTNodeImporter::VisitTypeAliasDecl(TypeAliasDecl *D) {
  return VisitTypedefNameDecl(D, /*IsAlias=*/true);
}

ExpectedDecl
ASTNodeImporter::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) {
  // Import the major distinguishing characteristics of this typedef.
  DeclContext *DC, *LexicalDC;
  DeclarationName Name;
  SourceLocation Loc;
  NamedDecl *FoundD;
  if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, FoundD, Loc))
    return std::move(Err);
  if (FoundD)
    return FoundD;

  // If this typedef is not in block scope, determine whether we've
  // seen a typedef with the same name (that we can merge with) or any
  // other entity by that name (which name lookup could conflict with).
  if (!DC->isFunctionOrMethod()) {
    SmallVector<NamedDecl *, 4> ConflictingDecls;
    unsigned IDNS = Decl::IDNS_Ordinary;
    auto FoundDecls = Importer.findDeclsInToCtx(DC, Name);
    for (auto *FoundDecl : FoundDecls) {
      if (!FoundDecl->isInIdentifierNamespace(IDNS))
        continue;
      if (auto *FoundAlias = dyn_cast<TypeAliasTemplateDecl>(FoundDecl)) {
        if (IsStructuralMatch(D, FoundAlias))
          return Importer.MapImported(D, FoundAlias);
        ConflictingDecls.push_back(FoundDecl);
      }
    }

    if (!ConflictingDecls.empty()) {
      ExpectedName NameOrErr = Importer.HandleNameConflict(
          Name, DC, IDNS, ConflictingDecls.data(), ConflictingDecls.size());
      if (NameOrErr)
        Name = NameOrErr.get();
      else
        return NameOrErr.takeError();
    }
  }

  Error Err = Error::success();
  auto ToTemplateParameters = importChecked(Err, D->getTemplateParameters());
  auto ToTemplatedDecl = importChecked(Err, D->getTemplatedDecl());
  if (Err)
    return std::move(Err);

  TypeAliasTemplateDecl *ToAlias;
  if (GetImportedOrCreateDecl(ToAlias, D, Importer.getToContext(), DC, Loc,
                              Name, ToTemplateParameters, ToTemplatedDecl))
    return ToAlias;

  ToTemplatedDecl->setDescribedAliasTemplate(ToAlias);

  ToAlias->setAccess(D->getAccess());
  ToAlias->setLexicalDeclContext(LexicalDC);
  LexicalDC->addDeclInternal(ToAlias);
  if (DC != Importer.getToContext().getTranslationUnitDecl())
    updateLookupTableForTemplateParameters(*ToTemplateParameters);
  return ToAlias;
}

ExpectedDecl ASTNodeImporter::VisitLabelDecl(LabelDecl *D) {
  // Import the major distinguishing characteristics of this label.
  DeclContext *DC, *LexicalDC;
  DeclarationName Name;
  SourceLocation Loc;
  NamedDecl *ToD;
  if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
    return std::move(Err);
  if (ToD)
    return ToD;

  assert(LexicalDC->isFunctionOrMethod());

  LabelDecl *ToLabel;
  if (D->isGnuLocal()) {
    ExpectedSLoc BeginLocOrErr = import(D->getBeginLoc());
    if (!BeginLocOrErr)
      return BeginLocOrErr.takeError();
    if (GetImportedOrCreateDecl(ToLabel, D, Importer.getToContext(), DC, Loc,
                                Name.getAsIdentifierInfo(), *BeginLocOrErr))
      return ToLabel;

  } else {
    if (GetImportedOrCreateDecl(ToLabel, D, Importer.getToContext(), DC, Loc,
                                Name.getAsIdentifierInfo()))
      return ToLabel;

  }

  Expected<LabelStmt *> ToStmtOrErr = import(D->getStmt());
  if (!ToStmtOrErr)
    return ToStmtOrErr.takeError();

  ToLabel->setStmt(*ToStmtOrErr);
  ToLabel->setLexicalDeclContext(LexicalDC);
  LexicalDC->addDeclInternal(ToLabel);
  return ToLabel;
}

ExpectedDecl ASTNodeImporter::VisitEnumDecl(EnumDecl *D) {
  // Import the major distinguishing characteristics of this enum.
  DeclContext *DC, *LexicalDC;
  DeclarationName Name;
  SourceLocation Loc;
  NamedDecl *ToD;
  if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
    return std::move(Err);
  if (ToD)
    return ToD;

  // Figure out what enum name we're looking for.
  unsigned IDNS = Decl::IDNS_Tag;
  DeclarationName SearchName = Name;
  if (!SearchName && D->getTypedefNameForAnonDecl()) {
    if (Error Err = importInto(
        SearchName, D->getTypedefNameForAnonDecl()->getDeclName()))
      return std::move(Err);
    IDNS = Decl::IDNS_Ordinary;
  } else if (Importer.getToContext().getLangOpts().CPlusPlus)
    IDNS |= Decl::IDNS_Ordinary;

  // We may already have an enum of the same name; try to find and match it.
  EnumDecl *PrevDecl = nullptr;
  if (!DC->isFunctionOrMethod()) {
    SmallVector<NamedDecl *, 4> ConflictingDecls;
    auto FoundDecls =
        Importer.findDeclsInToCtx(DC, SearchName);
    for (auto *FoundDecl : FoundDecls) {
      if (!FoundDecl->isInIdentifierNamespace(IDNS))
        continue;

      if (auto *Typedef = dyn_cast<TypedefNameDecl>(FoundDecl)) {
        if (const auto *Tag = Typedef->getUnderlyingType()->getAs<TagType>())
          FoundDecl = Tag->getDecl();
      }

      if (auto *FoundEnum = dyn_cast<EnumDecl>(FoundDecl)) {
        if (!hasSameVisibilityContextAndLinkage(FoundEnum, D))
          continue;
        if (IsStructuralMatch(D, FoundEnum, !SearchName.isEmpty())) {
          EnumDecl *FoundDef = FoundEnum->getDefinition();
          if (D->isThisDeclarationADefinition() && FoundDef)
            return Importer.MapImported(D, FoundDef);
          PrevDecl = FoundEnum->getMostRecentDecl();
          break;
        }
        ConflictingDecls.push_back(FoundDecl);
      }
    }

    // In case of unnamed enums, we try to find an existing similar one, if none
    // was found, perform the import always.
    // Structural in-equivalence is not detected in this way here, but it may
    // be found when the parent decl is imported (if the enum is part of a
    // class). To make this totally exact a more difficult solution is needed.
    if (SearchName && !ConflictingDecls.empty()) {
      ExpectedName NameOrErr = Importer.HandleNameConflict(
          SearchName, DC, IDNS, ConflictingDecls.data(),
          ConflictingDecls.size());
      if (NameOrErr)
        Name = NameOrErr.get();
      else
        return NameOrErr.takeError();
    }
  }

  Error Err = Error::success();
  auto ToBeginLoc = importChecked(Err, D->getBeginLoc());
  auto ToQualifierLoc = importChecked(Err, D->getQualifierLoc());
  auto ToIntegerType = importChecked(Err, D->getIntegerType());
  auto ToBraceRange = importChecked(Err, D->getBraceRange());
  if (Err)
    return std::move(Err);

  // Create the enum declaration.
  EnumDecl *D2;
  if (GetImportedOrCreateDecl(
          D2, D, Importer.getToContext(), DC, ToBeginLoc,
          Loc, Name.getAsIdentifierInfo(), PrevDecl, D->isScoped(),
          D->isScopedUsingClassTag(), D->isFixed()))
    return D2;

  D2->setQualifierInfo(ToQualifierLoc);
  D2->setIntegerType(ToIntegerType);
  D2->setBraceRange(ToBraceRange);
  D2->setAccess(D->getAccess());
  D2->setLexicalDeclContext(LexicalDC);
  addDeclToContexts(D, D2);

  if (MemberSpecializationInfo *MemberInfo = D->getMemberSpecializationInfo()) {
    TemplateSpecializationKind SK = MemberInfo->getTemplateSpecializationKind();
    EnumDecl *FromInst = D->getInstantiatedFromMemberEnum();
    if (Expected<EnumDecl *> ToInstOrErr = import(FromInst))
      D2->setInstantiationOfMemberEnum(*ToInstOrErr, SK);
    else
      return ToInstOrErr.takeError();
    if (ExpectedSLoc POIOrErr = import(MemberInfo->getPointOfInstantiation()))
      D2->getMemberSpecializationInfo()->setPointOfInstantiation(*POIOrErr);
    else
      return POIOrErr.takeError();
  }

  // Import the definition
  if (D->isCompleteDefinition())
    if (Error Err = ImportDefinition(D, D2))
      return std::move(Err);

  return D2;
}

ExpectedDecl ASTNodeImporter::VisitRecordDecl(RecordDecl *D) {
  bool IsFriendTemplate = false;
  if (auto *DCXX = dyn_cast<CXXRecordDecl>(D)) {
    IsFriendTemplate =
        DCXX->getDescribedClassTemplate() &&
        DCXX->getDescribedClassTemplate()->getFriendObjectKind() !=
            Decl::FOK_None;
  }

  // Import the major distinguishing characteristics of this record.
  DeclContext *DC = nullptr, *LexicalDC = nullptr;
  DeclarationName Name;
  SourceLocation Loc;
  NamedDecl *ToD = nullptr;
  if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
    return std::move(Err);
  if (ToD)
    return ToD;

  // Figure out what structure name we're looking for.
  unsigned IDNS = Decl::IDNS_Tag;
  DeclarationName SearchName = Name;
  if (!SearchName && D->getTypedefNameForAnonDecl()) {
    if (Error Err = importInto(
        SearchName, D->getTypedefNameForAnonDecl()->getDeclName()))
      return std::move(Err);
    IDNS = Decl::IDNS_Ordinary;
  } else if (Importer.getToContext().getLangOpts().CPlusPlus)
    IDNS |= Decl::IDNS_Ordinary | Decl::IDNS_TagFriend;

  bool IsDependentContext = DC != LexicalDC ? LexicalDC->isDependentContext()
                                            : DC->isDependentContext();
  bool DependentFriend = IsFriendTemplate && IsDependentContext;

  // We may already have a record of the same name; try to find and match it.
  RecordDecl *PrevDecl = nullptr;
  if (!DependentFriend && !DC->isFunctionOrMethod() && !D->isLambda()) {
    SmallVector<NamedDecl *, 4> ConflictingDecls;
    auto FoundDecls =
        Importer.findDeclsInToCtx(DC, SearchName);
    if (!FoundDecls.empty()) {
      // We're going to have to compare D against potentially conflicting Decls,
      // so complete it.
      if (D->hasExternalLexicalStorage() && !D->isCompleteDefinition())
        D->getASTContext().getExternalSource()->CompleteType(D);
    }

    for (auto *FoundDecl : FoundDecls) {
      if (!FoundDecl->isInIdentifierNamespace(IDNS))
        continue;

      Decl *Found = FoundDecl;
      if (auto *Typedef = dyn_cast<TypedefNameDecl>(Found)) {
        if (const auto *Tag = Typedef->getUnderlyingType()->getAs<TagType>())
          Found = Tag->getDecl();
      }

      if (auto *FoundRecord = dyn_cast<RecordDecl>(Found)) {
        // Do not emit false positive diagnostic in case of unnamed
        // struct/union and in case of anonymous structs.  Would be false
        // because there may be several anonymous/unnamed structs in a class.
        // E.g. these are both valid:
        //  struct A { // unnamed structs
        //    struct { struct A *next; } entry0;
        //    struct { struct A *next; } entry1;
        //  };
        //  struct X { struct { int a; }; struct { int b; }; }; // anon structs
        if (!SearchName)
          if (!IsStructuralMatch(D, FoundRecord, false))
            continue;

        if (!hasSameVisibilityContextAndLinkage(FoundRecord, D))
          continue;

        if (IsStructuralMatch(D, FoundRecord)) {
          RecordDecl *FoundDef = FoundRecord->getDefinition();
          if (D->isThisDeclarationADefinition() && FoundDef) {
            // FIXME: Structural equivalence check should check for same
            // user-defined methods.
            Importer.MapImported(D, FoundDef);
            if (const auto *DCXX = dyn_cast<CXXRecordDecl>(D)) {
              auto *FoundCXX = dyn_cast<CXXRecordDecl>(FoundDef);
              assert(FoundCXX && "Record type mismatch");

              if (!Importer.isMinimalImport())
                // FoundDef may not have every implicit method that D has
                // because implicit methods are created only if they are used.
                if (Error Err = ImportImplicitMethods(DCXX, FoundCXX))
                  return std::move(Err);
            }
            // FIXME: We can return FoundDef here.
          }
          PrevDecl = FoundRecord->getMostRecentDecl();
          break;
        }
        ConflictingDecls.push_back(FoundDecl);
      } // kind is RecordDecl
    } // for

    if (!ConflictingDecls.empty() && SearchName) {
      ExpectedName NameOrErr = Importer.HandleNameConflict(
          SearchName, DC, IDNS, ConflictingDecls.data(),
          ConflictingDecls.size());
      if (NameOrErr)
        Name = NameOrErr.get();
      else
        return NameOrErr.takeError();
    }
  }

  ExpectedSLoc BeginLocOrErr = import(D->getBeginLoc());
  if (!BeginLocOrErr)
    return BeginLocOrErr.takeError();

  // Create the record declaration.
  RecordDecl *D2 = nullptr;
  CXXRecordDecl *D2CXX = nullptr;
  if (auto *DCXX = dyn_cast<CXXRecordDecl>(D)) {
    if (DCXX->isLambda()) {
      auto TInfoOrErr = import(DCXX->getLambdaTypeInfo());
      if (!TInfoOrErr)
        return TInfoOrErr.takeError();
      if (GetImportedOrCreateSpecialDecl(
              D2CXX, CXXRecordDecl::CreateLambda, D, Importer.getToContext(),
              DC, *TInfoOrErr, Loc, DCXX->getLambdaDependencyKind(),
              DCXX->isGenericLambda(), DCXX->getLambdaCaptureDefault()))
        return D2CXX;
      CXXRecordDecl::LambdaNumbering Numbering = DCXX->getLambdaNumbering();
      ExpectedDecl CDeclOrErr = import(Numbering.ContextDecl);
      if (!CDeclOrErr)
        return CDeclOrErr.takeError();
      Numbering.ContextDecl = *CDeclOrErr;
      D2CXX->setLambdaNumbering(Numbering);
   } else if (DCXX->isInjectedClassName()) {
      // We have to be careful to do a similar dance to the one in
      // Sema::ActOnStartCXXMemberDeclarations
      const bool DelayTypeCreation = true;
      if (GetImportedOrCreateDecl(
              D2CXX, D, Importer.getToContext(), D->getTagKind(), DC,
              *BeginLocOrErr, Loc, Name.getAsIdentifierInfo(),
              cast_or_null<CXXRecordDecl>(PrevDecl), DelayTypeCreation))
        return D2CXX;
      Importer.getToContext().getTypeDeclType(
          D2CXX, dyn_cast<CXXRecordDecl>(DC));
    } else {
      if (GetImportedOrCreateDecl(D2CXX, D, Importer.getToContext(),
                                  D->getTagKind(), DC, *BeginLocOrErr, Loc,
                                  Name.getAsIdentifierInfo(),
                                  cast_or_null<CXXRecordDecl>(PrevDecl)))
        return D2CXX;
    }

    D2 = D2CXX;
    D2->setAccess(D->getAccess());
    D2->setLexicalDeclContext(LexicalDC);
    addDeclToContexts(D, D2);

    if (ClassTemplateDecl *FromDescribed =
        DCXX->getDescribedClassTemplate()) {
      ClassTemplateDecl *ToDescribed;
      if (Error Err = importInto(ToDescribed, FromDescribed))
        return std::move(Err);
      D2CXX->setDescribedClassTemplate(ToDescribed);
      if (!DCXX->isInjectedClassName() && !IsFriendTemplate) {
        // In a record describing a template the type should be an
        // InjectedClassNameType (see Sema::CheckClassTemplate). Update the
        // previously set type to the correct value here (ToDescribed is not
        // available at record create).
        CXXRecordDecl *Injected = nullptr;
        for (NamedDecl *Found : D2CXX->noload_lookup(Name)) {
          auto *Record = dyn_cast<CXXRecordDecl>(Found);
          if (Record && Record->isInjectedClassName()) {
            Injected = Record;
            break;
          }
        }
        // Create an injected type for the whole redecl chain.
        // The chain may contain an already existing injected type at the start,
        // if yes this should be reused. We must ensure that only one type
        // object exists for the injected type (including the injected record
        // declaration), ASTContext does not check it.
        SmallVector<Decl *, 2> Redecls =
            getCanonicalForwardRedeclChain(D2CXX);
        const Type *FrontTy =
            cast<CXXRecordDecl>(Redecls.front())->getTypeForDecl();
        QualType InjSpec;
        if (auto *InjTy = FrontTy->getAs<InjectedClassNameType>())
          InjSpec = InjTy->getInjectedSpecializationType();
        else
          InjSpec = ToDescribed->getInjectedClassNameSpecialization();
        for (auto *R : Redecls) {
          auto *RI = cast<CXXRecordDecl>(R);
          if (R != Redecls.front() ||
              !isa<InjectedClassNameType>(RI->getTypeForDecl()))
            RI->setTypeForDecl(nullptr);
          // This function tries to get the injected type from getTypeForDecl,
          // then from the previous declaration if possible. If not, it creates
          // a new type.
          Importer.getToContext().getInjectedClassNameType(RI, InjSpec);
        }
        // Set the new type for the injected decl too.
        if (Injected) {
          Injected->setTypeForDecl(nullptr);
          // This function will copy the injected type from D2CXX into Injected.
          // The injected decl does not have a previous decl to copy from.
          Importer.getToContext().getTypeDeclType(Injected, D2CXX);
        }
      }
    } else if (MemberSpecializationInfo *MemberInfo =
                   DCXX->getMemberSpecializationInfo()) {
        TemplateSpecializationKind SK =
            MemberInfo->getTemplateSpecializationKind();
        CXXRecordDecl *FromInst = DCXX->getInstantiatedFromMemberClass();

        if (Expected<CXXRecordDecl *> ToInstOrErr = import(FromInst))
          D2CXX->setInstantiationOfMemberClass(*ToInstOrErr, SK);
        else
          return ToInstOrErr.takeError();

        if (ExpectedSLoc POIOrErr =
            import(MemberInfo->getPointOfInstantiation()))
          D2CXX->getMemberSpecializationInfo()->setPointOfInstantiation(
            *POIOrErr);
        else
          return POIOrErr.takeError();
    }

  } else {
    if (GetImportedOrCreateDecl(D2, D, Importer.getToContext(),
                                D->getTagKind(), DC, *BeginLocOrErr, Loc,
                                Name.getAsIdentifierInfo(), PrevDecl))
      return D2;
    D2->setLexicalDeclContext(LexicalDC);
    addDeclToContexts(D, D2);
  }

  if (auto BraceRangeOrErr = import(D->getBraceRange()))
    D2->setBraceRange(*BraceRangeOrErr);
  else
    return BraceRangeOrErr.takeError();
  if (auto QualifierLocOrErr = import(D->getQualifierLoc()))
    D2->setQualifierInfo(*QualifierLocOrErr);
  else
    return QualifierLocOrErr.takeError();

  if (D->isAnonymousStructOrUnion())
    D2->setAnonymousStructOrUnion(true);

  if (D->isCompleteDefinition())
    if (Error Err = ImportDefinition(D, D2, IDK_Default))
      return std::move(Err);

  return D2;
}

ExpectedDecl ASTNodeImporter::VisitEnumConstantDecl(EnumConstantDecl *D) {
  // Import the major distinguishing characteristics of this enumerator.
  DeclContext *DC, *LexicalDC;
  DeclarationName Name;
  SourceLocation Loc;
  NamedDecl *ToD;
  if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
    return std::move(Err);
  if (ToD)
    return ToD;

  // Determine whether there are any other declarations with the same name and
  // in the same context.
  if (!LexicalDC->isFunctionOrMethod()) {
    SmallVector<NamedDecl *, 4> ConflictingDecls;
    unsigned IDNS = Decl::IDNS_Ordinary;
    auto FoundDecls = Importer.findDeclsInToCtx(DC, Name);
    for (auto *FoundDecl : FoundDecls) {
      if (!FoundDecl->isInIdentifierNamespace(IDNS))
        continue;

      if (auto *FoundEnumConstant = dyn_cast<EnumConstantDecl>(FoundDecl)) {
        if (IsStructuralMatch(D, FoundEnumConstant))
          return Importer.MapImported(D, FoundEnumConstant);
        ConflictingDecls.push_back(FoundDecl);
      }
    }

    if (!ConflictingDecls.empty()) {
      ExpectedName NameOrErr = Importer.HandleNameConflict(
          Name, DC, IDNS, ConflictingDecls.data(), ConflictingDecls.size());
      if (NameOrErr)
        Name = NameOrErr.get();
      else
        return NameOrErr.takeError();
    }
  }

  ExpectedType TypeOrErr = import(D->getType());
  if (!TypeOrErr)
    return TypeOrErr.takeError();

  ExpectedExpr InitOrErr = import(D->getInitExpr());
  if (!InitOrErr)
    return InitOrErr.takeError();

  EnumConstantDecl *ToEnumerator;
  if (GetImportedOrCreateDecl(
          ToEnumerator, D, Importer.getToContext(), cast<EnumDecl>(DC), Loc,
          Name.getAsIdentifierInfo(), *TypeOrErr, *InitOrErr, D->getInitVal()))
    return ToEnumerator;

  ToEnumerator->setAccess(D->getAccess());
  ToEnumerator->setLexicalDeclContext(LexicalDC);
  LexicalDC->addDeclInternal(ToEnumerator);
  return ToEnumerator;
}

template <typename DeclTy>
Error ASTNodeImporter::ImportTemplateParameterLists(const DeclTy *FromD,
                                                    DeclTy *ToD) {
  unsigned int Num = FromD->getNumTemplateParameterLists();
  if (Num == 0)
    return Error::success();
  SmallVector<TemplateParameterList *, 2> ToTPLists(Num);
  for (unsigned int I = 0; I < Num; ++I)
    if (Expected<TemplateParameterList *> ToTPListOrErr =
            import(FromD->getTemplateParameterList(I)))
      ToTPLists[I] = *ToTPListOrErr;
    else
      return ToTPListOrErr.takeError();
  ToD->setTemplateParameterListsInfo(Importer.ToContext, ToTPLists);
  return Error::success();
}

Error ASTNodeImporter::ImportTemplateInformation(
    FunctionDecl *FromFD, FunctionDecl *ToFD) {
  switch (FromFD->getTemplatedKind()) {
  case FunctionDecl::TK_NonTemplate:
  case FunctionDecl::TK_FunctionTemplate:
    return Error::success();

  case FunctionDecl::TK_DependentNonTemplate:
    if (Expected<FunctionDecl *> InstFDOrErr =
            import(FromFD->getInstantiatedFromDecl()))
      ToFD->setInstantiatedFromDecl(*InstFDOrErr);
    return Error::success();
  case FunctionDecl::TK_MemberSpecialization: {
    TemplateSpecializationKind TSK = FromFD->getTemplateSpecializationKind();

    if (Expected<FunctionDecl *> InstFDOrErr =
        import(FromFD->getInstantiatedFromMemberFunction()))
      ToFD->setInstantiationOfMemberFunction(*InstFDOrErr, TSK);
    else
      return InstFDOrErr.takeError();

    if (ExpectedSLoc POIOrErr = import(
        FromFD->getMemberSpecializationInfo()->getPointOfInstantiation()))
      ToFD->getMemberSpecializationInfo()->setPointOfInstantiation(*POIOrErr);
    else
      return POIOrErr.takeError();

    return Error::success();
  }

  case FunctionDecl::TK_FunctionTemplateSpecialization: {
    auto FunctionAndArgsOrErr =
        ImportFunctionTemplateWithTemplateArgsFromSpecialization(FromFD);
    if (!FunctionAndArgsOrErr)
      return FunctionAndArgsOrErr.takeError();

    TemplateArgumentList *ToTAList = TemplateArgumentList::CreateCopy(
          Importer.getToContext(), std::get<1>(*FunctionAndArgsOrErr));

    auto *FTSInfo = FromFD->getTemplateSpecializationInfo();
    TemplateArgumentListInfo ToTAInfo;
    const auto *FromTAArgsAsWritten = FTSInfo->TemplateArgumentsAsWritten;
    if (FromTAArgsAsWritten)
      if (Error Err = ImportTemplateArgumentListInfo(
          *FromTAArgsAsWritten, ToTAInfo))
        return Err;

    ExpectedSLoc POIOrErr = import(FTSInfo->getPointOfInstantiation());
    if (!POIOrErr)
      return POIOrErr.takeError();

    if (Error Err = ImportTemplateParameterLists(FromFD, ToFD))
      return Err;

    TemplateSpecializationKind TSK = FTSInfo->getTemplateSpecializationKind();
    ToFD->setFunctionTemplateSpecialization(
        std::get<0>(*FunctionAndArgsOrErr), ToTAList, /* InsertPos= */ nullptr,
        TSK, FromTAArgsAsWritten ? &ToTAInfo : nullptr, *POIOrErr);
    return Error::success();
  }

  case FunctionDecl::TK_DependentFunctionTemplateSpecialization: {
    auto *FromInfo = FromFD->getDependentSpecializationInfo();
    UnresolvedSet<8> Candidates;
    for (FunctionTemplateDecl *FTD : FromInfo->getCandidates()) {
      if (Expected<FunctionTemplateDecl *> ToFTDOrErr = import(FTD))
        Candidates.addDecl(*ToFTDOrErr);
      else
        return ToFTDOrErr.takeError();
    }

    // Import TemplateArgumentListInfo.
    TemplateArgumentListInfo ToTAInfo;
    const auto *FromTAArgsAsWritten = FromInfo->TemplateArgumentsAsWritten;
    if (FromTAArgsAsWritten)
      if (Error Err =
              ImportTemplateArgumentListInfo(*FromTAArgsAsWritten, ToTAInfo))
        return Err;

    ToFD->setDependentTemplateSpecialization(
        Importer.getToContext(), Candidates,
        FromTAArgsAsWritten ? &ToTAInfo : nullptr);
    return Error::success();
  }
  }
  llvm_unreachable("All cases should be covered!");
}

Expected<FunctionDecl *>
ASTNodeImporter::FindFunctionTemplateSpecialization(FunctionDecl *FromFD) {
  auto FunctionAndArgsOrErr =
      ImportFunctionTemplateWithTemplateArgsFromSpecialization(FromFD);
  if (!FunctionAndArgsOrErr)
    return FunctionAndArgsOrErr.takeError();

  FunctionTemplateDecl *Template;
  TemplateArgsTy ToTemplArgs;
  std::tie(Template, ToTemplArgs) = *FunctionAndArgsOrErr;
  void *InsertPos = nullptr;
  auto *FoundSpec = Template->findSpecialization(ToTemplArgs, InsertPos);
  return FoundSpec;
}

Error ASTNodeImporter::ImportFunctionDeclBody(FunctionDecl *FromFD,
                                              FunctionDecl *ToFD) {
  if (Stmt *FromBody = FromFD->getBody()) {
    if (ExpectedStmt ToBodyOrErr = import(FromBody))
      ToFD->setBody(*ToBodyOrErr);
    else
      return ToBodyOrErr.takeError();
  }
  return Error::success();
}

// Returns true if the given D has a DeclContext up to the TranslationUnitDecl
// which is equal to the given DC, or D is equal to DC.
static bool isAncestorDeclContextOf(const DeclContext *DC, const Decl *D) {
  const DeclContext *DCi = dyn_cast<DeclContext>(D);
  if (!DCi)
    DCi = D->getDeclContext();
  assert(DCi && "Declaration should have a context");
  while (DCi != D->getTranslationUnitDecl()) {
    if (DCi == DC)
      return true;
    DCi = DCi->getParent();
  }
  return false;
}

// Check if there is a declaration that has 'DC' as parent context and is
// referenced from statement 'S' or one of its children. The search is done in
// BFS order through children of 'S'.
static bool isAncestorDeclContextOf(const DeclContext *DC, const Stmt *S) {
  SmallVector<const Stmt *> ToProcess;
  ToProcess.push_back(S);
  while (!ToProcess.empty()) {
    const Stmt *CurrentS = ToProcess.pop_back_val();
    ToProcess.append(CurrentS->child_begin(), CurrentS->child_end());
    if (const auto *DeclRef = dyn_cast<DeclRefExpr>(CurrentS)) {
      if (const Decl *D = DeclRef->getDecl())
        if (isAncestorDeclContextOf(DC, D))
          return true;
    } else if (const auto *E =
                   dyn_cast_or_null<SubstNonTypeTemplateParmExpr>(CurrentS)) {
      if (const Decl *D = E->getAssociatedDecl())
        if (isAncestorDeclContextOf(DC, D))
          return true;
    }
  }
  return false;
}

namespace {
/// Check if a type has any reference to a declaration that is inside the body
/// of a function.
/// The \c CheckType(QualType) function should be used to determine
/// this property.
///
/// The type visitor visits one type object only (not recursive).
/// To find all referenced declarations we must discover all type objects until
/// the canonical type is reached (walk over typedef and similar objects). This
/// is done by loop over all "sugar" type objects. For every such type we must
/// check all declarations that are referenced from it. For this check the
/// visitor is used. In the visit functions all referenced declarations except
/// the one that follows in the sugar chain (if any) must be checked. For this
/// check the same visitor is re-used (it has no state-dependent data).
///
/// The visit functions have 3 possible return values:
///  - True, found a declaration inside \c ParentDC.
///  - False, found declarations only outside \c ParentDC and it is not possible
///    to find more declarations (the "sugar" chain does not continue).
///  - Empty optional value, found no declarations or only outside \c ParentDC,
///    but it is possible to find more declarations in the type "sugar" chain.
/// The loop over the "sugar" types can be implemented by using type visit
/// functions only (call \c CheckType with the desugared type). With the current
/// solution no visit function is needed if the type has only a desugared type
/// as data.
class IsTypeDeclaredInsideVisitor
    : public TypeVisitor<IsTypeDeclaredInsideVisitor, std::optional<bool>> {
public:
  IsTypeDeclaredInsideVisitor(const FunctionDecl *ParentDC)
      : ParentDC(ParentDC) {}

  bool CheckType(QualType T) {
    // Check the chain of "sugar" types.
    // The "sugar" types are typedef or similar types that have the same
    // canonical type.
    if (std::optional<bool> Res = Visit(T.getTypePtr()))
      return *Res;
    QualType DsT =
        T.getSingleStepDesugaredType(ParentDC->getParentASTContext());
    while (DsT != T) {
      if (std::optional<bool> Res = Visit(DsT.getTypePtr()))
        return *Res;
      T = DsT;
      DsT = T.getSingleStepDesugaredType(ParentDC->getParentASTContext());
    }
    return false;
  }

  std::optional<bool> VisitTagType(const TagType *T) {
    if (auto *Spec = dyn_cast<ClassTemplateSpecializationDecl>(T->getDecl()))
      for (const auto &Arg : Spec->getTemplateArgs().asArray())
        if (checkTemplateArgument(Arg))
          return true;
    return isAncestorDeclContextOf(ParentDC, T->getDecl());
  }

  std::optional<bool> VisitPointerType(const PointerType *T) {
    return CheckType(T->getPointeeType());
  }

  std::optional<bool> VisitReferenceType(const ReferenceType *T) {
    return CheckType(T->getPointeeTypeAsWritten());
  }

  std::optional<bool> VisitTypedefType(const TypedefType *T) {
    const TypedefNameDecl *TD = T->getDecl();
    assert(TD);
    return isAncestorDeclContextOf(ParentDC, TD);
  }

  std::optional<bool> VisitUsingType(const UsingType *T) {
    if (T->getFoundDecl() &&
        isAncestorDeclContextOf(ParentDC, T->getFoundDecl()))
      return true;

    return {};
  }

  std::optional<bool>
  VisitTemplateSpecializationType(const TemplateSpecializationType *T) {
    for (const auto &Arg : T->template_arguments())
      if (checkTemplateArgument(Arg))
        return true;
    // This type is a "sugar" to a record type, it can have a desugared type.
    return {};
  }

  std::optional<bool> VisitUnaryTransformType(const UnaryTransformType *T) {
    return CheckType(T->getBaseType());
  }

  std::optional<bool>
  VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T) {
    // The "associated declaration" can be the same as ParentDC.
    if (isAncestorDeclContextOf(ParentDC, T->getAssociatedDecl()))
      return true;
    return {};
  }

  std::optional<bool> VisitConstantArrayType(const ConstantArrayType *T) {
    if (T->getSizeExpr() && isAncestorDeclContextOf(ParentDC, T->getSizeExpr()))
      return true;

    return CheckType(T->getElementType());
  }

  std::optional<bool> VisitVariableArrayType(const VariableArrayType *T) {
    llvm_unreachable(
        "Variable array should not occur in deduced return type of a function");
  }

  std::optional<bool> VisitIncompleteArrayType(const IncompleteArrayType *T) {
    llvm_unreachable("Incomplete array should not occur in deduced return type "
                     "of a function");
  }

  std::optional<bool> VisitDependentArrayType(const IncompleteArrayType *T) {
    llvm_unreachable("Dependent array should not occur in deduced return type "
                     "of a function");
  }

private:
  const DeclContext *const ParentDC;

  bool checkTemplateArgument(const TemplateArgument &Arg) {
    switch (Arg.getKind()) {
    case TemplateArgument::Null:
      return false;
    case TemplateArgument::Integral:
      return CheckType(Arg.getIntegralType());
    case TemplateArgument::Type:
      return CheckType(Arg.getAsType());
    case TemplateArgument::Expression:
      return isAncestorDeclContextOf(ParentDC, Arg.getAsExpr());
    case TemplateArgument::Declaration:
      // FIXME: The declaration in this case is not allowed to be in a function?
      return isAncestorDeclContextOf(ParentDC, Arg.getAsDecl());
    case TemplateArgument::NullPtr:
      // FIXME: The type is not allowed to be in the function?
      return CheckType(Arg.getNullPtrType());
    case TemplateArgument::StructuralValue:
      return CheckType(Arg.getStructuralValueType());
    case TemplateArgument::Pack:
      for (const auto &PackArg : Arg.getPackAsArray())
        if (checkTemplateArgument(PackArg))
          return true;
      return false;
    case TemplateArgument::Template:
      // Templates can not be defined locally in functions.
      // A template passed as argument can be not in ParentDC.
      return false;
    case TemplateArgument::TemplateExpansion:
      // Templates can not be defined locally in functions.
      // A template passed as argument can be not in ParentDC.
      return false;
    }
    llvm_unreachable("Unknown TemplateArgument::ArgKind enum");
  };
};
} // namespace

/// This function checks if the given function has a return type that contains
/// a reference (in any way) to a declaration inside the same function.
bool ASTNodeImporter::hasReturnTypeDeclaredInside(FunctionDecl *D) {
  QualType FromTy = D->getType();
  const auto *FromFPT = FromTy->getAs<FunctionProtoType>();
  assert(FromFPT && "Must be called on FunctionProtoType");

  auto IsCXX11Lambda = [&]() {
    if (Importer.FromContext.getLangOpts().CPlusPlus14) // C++14 or later
      return false;

    return isLambdaMethod(D);
  };

  QualType RetT = FromFPT->getReturnType();
  if (isa<AutoType>(RetT.getTypePtr()) || IsCXX11Lambda()) {
    FunctionDecl *Def = D->getDefinition();
    IsTypeDeclaredInsideVisitor Visitor(Def ? Def : D);
    return Visitor.CheckType(RetT);
  }

  return false;
}

ExplicitSpecifier
ASTNodeImporter::importExplicitSpecifier(Error &Err, ExplicitSpecifier ESpec) {
  Expr *ExplicitExpr = ESpec.getExpr();
  if (ExplicitExpr)
    ExplicitExpr = importChecked(Err, ESpec.getExpr());
  return ExplicitSpecifier(ExplicitExpr, ESpec.getKind());
}

ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {

  SmallVector<Decl *, 2> Redecls = getCanonicalForwardRedeclChain(D);
  auto RedeclIt = Redecls.begin();
  // Import the first part of the decl chain. I.e. import all previous
  // declarations starting from the canonical decl.
  for (; RedeclIt != Redecls.end() && *RedeclIt != D; ++RedeclIt) {
    ExpectedDecl ToRedeclOrErr = import(*RedeclIt);
    if (!ToRedeclOrErr)
      return ToRedeclOrErr.takeError();
  }
  assert(*RedeclIt == D);

  // Import the major distinguishing characteristics of this function.
  DeclContext *DC, *LexicalDC;
  DeclarationName Name;
  SourceLocation Loc;
  NamedDecl *ToD;
  if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
    return std::move(Err);
  if (ToD)
    return ToD;

  FunctionDecl *FoundByLookup = nullptr;
  FunctionTemplateDecl *FromFT = D->getDescribedFunctionTemplate();

  // If this is a function template specialization, then try to find the same
  // existing specialization in the "to" context. The lookup below will not
  // find any specialization, but would find the primary template; thus, we
  // have to skip normal lookup in case of specializations.
  // FIXME handle member function templates (TK_MemberSpecialization) similarly?
  if (D->getTemplatedKind() ==
      FunctionDecl::TK_FunctionTemplateSpecialization) {
    auto FoundFunctionOrErr = FindFunctionTemplateSpecialization(D);
    if (!FoundFunctionOrErr)
      return FoundFunctionOrErr.takeError();
    if (FunctionDecl *FoundFunction = *FoundFunctionOrErr) {
      if (Decl *Def = FindAndMapDefinition(D, FoundFunction))
        return Def;
      FoundByLookup = FoundFunction;
    }
  }
  // Try to find a function in our own ("to") context with the same name, same
  // type, and in the same context as the function we're importing.
  else if (!LexicalDC->isFunctionOrMethod()) {
    SmallVector<NamedDecl *, 4> ConflictingDecls;
    unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_OrdinaryFriend;
    auto FoundDecls = Importer.findDeclsInToCtx(DC, Name);
    for (auto *FoundDecl : FoundDecls) {
      if (!FoundDecl->isInIdentifierNamespace(IDNS))
        continue;

      if (auto *FoundFunction = dyn_cast<FunctionDecl>(FoundDecl)) {
        if (!hasSameVisibilityContextAndLinkage(FoundFunction, D))
          continue;

        if (IsStructuralMatch(D, FoundFunction)) {
          if (Decl *Def = FindAndMapDefinition(D, FoundFunction))
            return Def;
          FoundByLookup = FoundFunction;
          break;
        }
        // FIXME: Check for overloading more carefully, e.g., by boosting
        // Sema::IsOverload out to the AST library.

        // Function overloading is okay in C++.
        if (Importer.getToContext().getLangOpts().CPlusPlus)
          continue;

        // Complain about inconsistent function types.
        Importer.ToDiag(Loc, diag::warn_odr_function_type_inconsistent)
            << Name << D->getType() << FoundFunction->getType();
        Importer.ToDiag(FoundFunction->getLocation(), diag::note_odr_value_here)
            << FoundFunction->getType();
        ConflictingDecls.push_back(FoundDecl);
      }
    }

    if (!ConflictingDecls.empty()) {
      ExpectedName NameOrErr = Importer.HandleNameConflict(
          Name, DC, IDNS, ConflictingDecls.data(), ConflictingDecls.size());
      if (NameOrErr)
        Name = NameOrErr.get();
      else
        return NameOrErr.takeError();
    }
  }

  // We do not allow more than one in-class declaration of a function. This is
  // because AST clients like VTableBuilder asserts on this. VTableBuilder
  // assumes there is only one in-class declaration. Building a redecl
  // chain would result in more than one in-class declaration for
  // overrides (even if they are part of the same redecl chain inside the
  // derived class.)
  if (FoundByLookup) {
    if (isa<CXXMethodDecl>(FoundByLookup)) {
      if (D->getLexicalDeclContext() == D->getDeclContext()) {
        if (!D->doesThisDeclarationHaveABody()) {
          if (FunctionTemplateDecl *DescribedD =
                  D->getDescribedFunctionTemplate()) {
            // Handle a "templated" function together with its described
            // template. This avoids need for a similar check at import of the
            // described template.
            assert(FoundByLookup->getDescribedFunctionTemplate() &&
                   "Templated function mapped to non-templated?");
            Importer.MapImported(DescribedD,
                                 FoundByLookup->getDescribedFunctionTemplate());
          }
          return Importer.MapImported(D, FoundByLookup);
        } else {
          // Let's continue and build up the redecl chain in this case.
          // FIXME Merge the functions into one decl.
        }
      }
    }
  }

  DeclarationNameInfo NameInfo(Name, Loc);
  // Import additional name location/type info.
  if (Error Err = ImportDeclarationNameLoc(D->getNameInfo(), NameInfo))
    return std::move(Err);

  QualType FromTy = D->getType();
  TypeSourceInfo *FromTSI = D->getTypeSourceInfo();
  // Set to true if we do not import the type of the function as is. There are
  // cases when the original type would result in an infinite recursion during
  // the import. To avoid an infinite recursion when importing, we create the
  // FunctionDecl with a simplified function type and update it only after the
  // relevant AST nodes are already imported.
  // The type is related to TypeSourceInfo (it references the type), so we must
  // do the same with TypeSourceInfo.
  bool UsedDifferentProtoType = false;
  if (const auto *FromFPT = FromTy->getAs<FunctionProtoType>()) {
    QualType FromReturnTy = FromFPT->getReturnType();
    // Functions with auto return type may define a struct inside their body
    // and the return type could refer to that struct.
    // E.g.: auto foo() { struct X{}; return X(); }
    // To avoid an infinite recursion when importing, create the FunctionDecl
    // with a simplified return type.
    if (hasReturnTypeDeclaredInside(D)) {
      FromReturnTy = Importer.getFromContext().VoidTy;
      UsedDifferentProtoType = true;
    }
    FunctionProtoType::ExtProtoInfo FromEPI = FromFPT->getExtProtoInfo();
    // FunctionProtoType::ExtProtoInfo's ExceptionSpecDecl can point to the
    // FunctionDecl that we are importing the FunctionProtoType for.
    // To avoid an infinite recursion when importing, create the FunctionDecl
    // with a simplified function type.
    if (FromEPI.ExceptionSpec.SourceDecl ||
        FromEPI.ExceptionSpec.SourceTemplate ||
        FromEPI.ExceptionSpec.NoexceptExpr) {
      FunctionProtoType::ExtProtoInfo DefaultEPI;
      FromEPI = DefaultEPI;
      UsedDifferentProtoType = true;
    }
    FromTy = Importer.getFromContext().getFunctionType(
        FromReturnTy, FromFPT->getParamTypes(), FromEPI);
    FromTSI = Importer.getFromContext().getTrivialTypeSourceInfo(
        FromTy, D->getBeginLoc());
  }

  Error Err = Error::success();
  auto T = importChecked(Err, FromTy);
  auto TInfo = importChecked(Err, FromTSI);
  auto ToInnerLocStart = importChecked(Err, D->getInnerLocStart());
  auto ToEndLoc = importChecked(Err, D->getEndLoc());
  auto ToDefaultLoc = importChecked(Err, D->getDefaultLoc());
  auto ToQualifierLoc = importChecked(Err, D->getQualifierLoc());
  AssociatedConstraint TrailingRequiresClause = D->getTrailingRequiresClause();
  TrailingRequiresClause.ConstraintExpr =
      importChecked(Err, TrailingRequiresClause.ConstraintExpr);
  if (Err)
    return std::move(Err);

  // Import the function parameters.
  SmallVector<ParmVarDecl *, 8> Parameters;
  for (auto *P : D->parameters()) {
    if (Expected<ParmVarDecl *> ToPOrErr = import(P))
      Parameters.push_back(*ToPOrErr);
    else
      return ToPOrErr.takeError();
  }

  // Create the imported function.
  FunctionDecl *ToFunction = nullptr;
  if (auto *FromConstructor = dyn_cast<CXXConstructorDecl>(D)) {
    ExplicitSpecifier ESpec =
        importExplicitSpecifier(Err, FromConstructor->getExplicitSpecifier());
    if (Err)
      return std::move(Err);
    auto ToInheritedConstructor = InheritedConstructor();
    if (FromConstructor->isInheritingConstructor()) {
      Expected<InheritedConstructor> ImportedInheritedCtor =
          import(FromConstructor->getInheritedConstructor());
      if (!ImportedInheritedCtor)
        return ImportedInheritedCtor.takeError();
      ToInheritedConstructor = *ImportedInheritedCtor;
    }
    if (GetImportedOrCreateDecl<CXXConstructorDecl>(
            ToFunction, D, Importer.getToContext(), cast<CXXRecordDecl>(DC),
            ToInnerLocStart, NameInfo, T, TInfo, ESpec, D->UsesFPIntrin(),
            D->isInlineSpecified(), D->isImplicit(), D->getConstexprKind(),
            ToInheritedConstructor, TrailingRequiresClause))
      return ToFunction;
  } else if (CXXDestructorDecl *FromDtor = dyn_cast<CXXDestructorDecl>(D)) {

    Error Err = Error::success();
    auto ToOperatorDelete = importChecked(
        Err, const_cast<FunctionDecl *>(FromDtor->getOperatorDelete()));
    auto ToThisArg = importChecked(Err, FromDtor->getOperatorDeleteThisArg());
    if (Err)
      return std::move(Err);

    if (GetImportedOrCreateDecl<CXXDestructorDecl>(
            ToFunction, D, Importer.getToContext(), cast<CXXRecordDecl>(DC),
            ToInnerLocStart, NameInfo, T, TInfo, D->UsesFPIntrin(),
            D->isInlineSpecified(), D->isImplicit(), D->getConstexprKind(),
            TrailingRequiresClause))
      return ToFunction;

    CXXDestructorDecl *ToDtor = cast<CXXDestructorDecl>(ToFunction);

    ToDtor->setOperatorDelete(ToOperatorDelete, ToThisArg);
  } else if (CXXConversionDecl *FromConversion =
                 dyn_cast<CXXConversionDecl>(D)) {
    ExplicitSpecifier ESpec =
        importExplicitSpecifier(Err, FromConversion->getExplicitSpecifier());
    if (Err)
      return std::move(Err);
    if (GetImportedOrCreateDecl<CXXConversionDecl>(
            ToFunction, D, Importer.getToContext(), cast<CXXRecordDecl>(DC),
            ToInnerLocStart, NameInfo, T, TInfo, D->UsesFPIntrin(),
            D->isInlineSpecified(), ESpec, D->getConstexprKind(),
            SourceLocation(), TrailingRequiresClause))
      return ToFunction;
  } else if (auto *Method = dyn_cast<CXXMethodDecl>(D)) {
    if (GetImportedOrCreateDecl<CXXMethodDecl>(
            ToFunction, D, Importer.getToContext(), cast<CXXRecordDecl>(DC),
            ToInnerLocStart, NameInfo, T, TInfo, Method->getStorageClass(),
            Method->UsesFPIntrin(), Method->isInlineSpecified(),
            D->getConstexprKind(), SourceLocation(), TrailingRequiresClause))
      return ToFunction;
  } else if (auto *Guide = dyn_cast<CXXDeductionGuideDecl>(D)) {
    ExplicitSpecifier ESpec =
        importExplicitSpecifier(Err, Guide->getExplicitSpecifier());
    CXXConstructorDecl *Ctor =
        importChecked(Err, Guide->getCorrespondingConstructor());
    const CXXDeductionGuideDecl *SourceDG =
        importChecked(Err, Guide->getSourceDeductionGuide());
    if (Err)
      return std::move(Err);
    if (GetImportedOrCreateDecl<CXXDeductionGuideDecl>(
            ToFunction, D, Importer.getToContext(), DC, ToInnerLocStart, ESpec,
            NameInfo, T, TInfo, ToEndLoc, Ctor,
            Guide->getDeductionCandidateKind(), TrailingRequiresClause,
            SourceDG, Guide->getSourceDeductionGuideKind()))
      return ToFunction;
  } else {
    if (GetImportedOrCreateDecl(
            ToFunction, D, Importer.getToContext(), DC, ToInnerLocStart,
            NameInfo, T, TInfo, D->getStorageClass(), D->UsesFPIntrin(),
            D->isInlineSpecified(), D->hasWrittenPrototype(),
            D->getConstexprKind(), TrailingRequiresClause))
      return ToFunction;
  }

  // Connect the redecl chain.
  if (FoundByLookup) {
    auto *Recent = const_cast<FunctionDecl *>(
          FoundByLookup->getMostRecentDecl());
    ToFunction->setPreviousDecl(Recent);
    // FIXME Probably we should merge exception specifications.  E.g. In the
    // "To" context the existing function may have exception specification with
    // noexcept-unevaluated, while the newly imported function may have an
    // evaluated noexcept.  A call to adjustExceptionSpec() on the imported
    // decl and its redeclarations may be required.
  }

  StringLiteral *Msg = D->getDeletedMessage();
  if (Msg) {
    auto Imported = import(Msg);
    if (!Imported)
      return Imported.takeError();
    Msg = *Imported;
  }

  ToFunction->setQualifierInfo(ToQualifierLoc);
  ToFunction->setAccess(D->getAccess());
  ToFunction->setLexicalDeclContext(LexicalDC);
  ToFunction->setVirtualAsWritten(D->isVirtualAsWritten());
  ToFunction->setTrivial(D->isTrivial());
  ToFunction->setIsPureVirtual(D->isPureVirtual());
  ToFunction->setDefaulted(D->isDefaulted());
  ToFunction->setExplicitlyDefaulted(D->isExplicitlyDefaulted());
  ToFunction->setDeletedAsWritten(D->isDeletedAsWritten());
  ToFunction->setFriendConstraintRefersToEnclosingTemplate(
      D->FriendConstraintRefersToEnclosingTemplate());
  ToFunction->setIsDestroyingOperatorDelete(D->isDestroyingOperatorDelete());
  ToFunction->setIsTypeAwareOperatorNewOrDelete(
      D->isTypeAwareOperatorNewOrDelete());
  ToFunction->setRangeEnd(ToEndLoc);
  ToFunction->setDefaultLoc(ToDefaultLoc);

  if (Msg)
    ToFunction->setDefaultedOrDeletedInfo(
        FunctionDecl::DefaultedOrDeletedFunctionInfo::Create(
            Importer.getToContext(), {}, Msg));

  // Set the parameters.
  for (auto *Param : Parameters) {
    Param->setOwningFunction(ToFunction);
    ToFunction->addDeclInternal(Param);
    if (ASTImporterLookupTable *LT = Importer.SharedState->getLookupTable())
      LT->update(Param, Importer.getToContext().getTranslationUnitDecl());
  }
  ToFunction->setParams(Parameters);

  // We need to complete creation of FunctionProtoTypeLoc manually with setting
  // params it refers to.
  if (TInfo) {
    if (auto ProtoLoc =
        TInfo->getTypeLoc().IgnoreParens().getAs<FunctionProtoTypeLoc>()) {
      for (unsigned I = 0, N = Parameters.size(); I != N; ++I)
        ProtoLoc.setParam(I, Parameters[I]);
    }
  }

  // Import the describing template function, if any.
  if (FromFT) {
    auto ToFTOrErr = import(FromFT);
    if (!ToFTOrErr)
      return ToFTOrErr.takeError();
  }

  // Import Ctor initializers.
  if (auto *FromConstructor = dyn_cast<CXXConstructorDecl>(D)) {
    if (unsigned NumInitializers = FromConstructor->getNumCtorInitializers()) {
      SmallVector<CXXCtorInitializer *, 4> CtorInitializers(NumInitializers);
      // Import first, then allocate memory and copy if there was no error.
      if (Error Err = ImportContainerChecked(
          FromConstructor->inits(), CtorInitializers))
        return std::move(Err);
      auto **Memory =
          new (Importer.getToContext()) CXXCtorInitializer *[NumInitializers];
      llvm::copy(CtorInitializers, Memory);
      auto *ToCtor = cast<CXXConstructorDecl>(ToFunction);
      ToCtor->setCtorInitializers(Memory);
      ToCtor->setNumCtorInitializers(NumInitializers);
    }
  }

  // If it is a template, import all related things.
  if (Error Err = ImportTemplateInformation(D, ToFunction))
    return std::move(Err);

  if (auto *FromCXXMethod = dyn_cast<CXXMethodDecl>(D))
    if (Error Err = ImportOverriddenMethods(cast<CXXMethodDecl>(ToFunction),
                                            FromCXXMethod))
      return std::move(Err);

  if (D->doesThisDeclarationHaveABody()) {
    Error Err = ImportFunctionDeclBody(D, ToFunction);

    if (Err)
      return std::move(Err);
  }

  // Import and set the original type in case we used another type.
  if (UsedDifferentProtoType) {
    if (ExpectedType TyOrErr = import(D->getType()))
      ToFunction->setType(*TyOrErr);
    else
      return TyOrErr.takeError();
    if (Expected<TypeSourceInfo *> TSIOrErr = import(D->getTypeSourceInfo()))
      ToFunction->setTypeSourceInfo(*TSIOrErr);
    else
      return TSIOrErr.takeError();
  }

  // FIXME: Other bits to merge?

  addDeclToContexts(D, ToFunction);

  // Import the rest of the chain. I.e. import all subsequent declarations.
  for (++RedeclIt; RedeclIt != Redecls.end(); ++RedeclIt) {
    ExpectedDecl ToRedeclOrErr = import(*RedeclIt);
    if (!ToRedeclOrErr)
      return ToRedeclOrErr.takeError();
  }

  return ToFunction;
}

ExpectedDecl ASTNodeImporter::VisitCXXMethodDecl(CXXMethodDecl *D) {
  return VisitFunctionDecl(D);
}

ExpectedDecl ASTNodeImporter::VisitCXXConstructorDecl(CXXConstructorDecl *D) {
  return VisitCXXMethodDecl(D);
}

ExpectedDecl ASTNodeImporter::VisitCXXDestructorDecl(CXXDestructorDecl *D) {
  return VisitCXXMethodDecl(D);
}

ExpectedDecl ASTNodeImporter::VisitCXXConversionDecl(CXXConversionDecl *D) {
  return VisitCXXMethodDecl(D);
}

ExpectedDecl
ASTNodeImporter::VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D) {
  return VisitFunctionDecl(D);
}

ExpectedDecl ASTNodeImporter::VisitFieldDecl(FieldDecl *D) {
  // Import the major distinguishing characteristics of a variable.
  DeclContext *DC, *LexicalDC;
  DeclarationName Name;
  SourceLocation Loc;
  NamedDecl *ToD;
  if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
    return std::move(Err);
  if (ToD)
    return ToD;

  // Determine whether we've already imported this field.
  auto FoundDecls = Importer.findDeclsInToCtx(DC, Name);
  for (auto *FoundDecl : FoundDecls) {
    if (FieldDecl *FoundField = dyn_cast<FieldDecl>(FoundDecl)) {
      // For anonymous fields, match up by index.
      if (!Name &&
          ASTImporter::getFieldIndex(D) !=
          ASTImporter::getFieldIndex(FoundField))
        continue;

      if (Importer.IsStructurallyEquivalent(D->getType(),
                                            FoundField->getType())) {
        Importer.MapImported(D, FoundField);
        // In case of a FieldDecl of a ClassTemplateSpecializationDecl, the
        // initializer of a FieldDecl might not had been instantiated in the
        // "To" context.  However, the "From" context might instantiated that,
        // thus we have to merge that.
        // Note: `hasInClassInitializer()` is not the same as non-null
        // `getInClassInitializer()` value.
        if (Expr *FromInitializer = D->getInClassInitializer()) {
          if (ExpectedExpr ToInitializerOrErr = import(FromInitializer)) {
            // Import of the FromInitializer may result in the setting of
            // InClassInitializer. If not, set it here.
            assert(FoundField->hasInClassInitializer() &&
                   "Field should have an in-class initializer if it has an "
                   "expression for it.");
            if (!FoundField->getInClassInitializer())
              FoundField->setInClassInitializer(*ToInitializerOrErr);
          } else {
              return ToInitializerOrErr.takeError();
          }
        }
        return FoundField;
      }

      // FIXME: Why is this case not handled with calling HandleNameConflict?
      Importer.ToDiag(Loc, diag::warn_odr_field_type_inconsistent)
        << Name << D->getType() << FoundField->getType();
      Importer.ToDiag(FoundField->getLocation(), diag::note_odr_value_here)
        << FoundField->getType();

      return make_error<ASTImportError>(ASTImportError::NameConflict);
    }
  }

  Error Err = Error::success();
  auto ToType = importChecked(Err, D->getType());
  auto ToTInfo = importChecked(Err, D->getTypeSourceInfo());
  auto ToBitWidth = importChecked(Err, D->getBitWidth());
  auto ToInnerLocStart = importChecked(Err, D->getInnerLocStart());
  if (Err)
    return std::move(Err);
  const Type *ToCapturedVLAType = nullptr;
  if (Error Err = Importer.importInto(
          ToCapturedVLAType, cast_or_null<Type>(D->getCapturedVLAType())))
    return std::move(Err);

  FieldDecl *ToField;
  if (GetImportedOrCreateDecl(ToField, D, Importer.getToContext(), DC,
                              ToInnerLocStart, Loc, Name.getAsIdentifierInfo(),
                              ToType, ToTInfo, ToBitWidth, D->isMutable(),
                              D->getInClassInitStyle()))
    return ToField;

  ToField->setAccess(D->getAccess());
  ToField->setLexicalDeclContext(LexicalDC);
  ToField->setImplicit(D->isImplicit());
  if (ToCapturedVLAType)
    ToField->setCapturedVLAType(cast<VariableArrayType>(ToCapturedVLAType));
  LexicalDC->addDeclInternal(ToField);
  // Import initializer only after the field was created, it may have recursive
  // reference to the field.
  auto ToInitializer = importChecked(Err, D->getInClassInitializer());
  if (Err)
    return std::move(Err);
  if (ToInitializer) {
    auto *AlreadyImported = ToField->getInClassInitializer();
    if (AlreadyImported)
      assert(ToInitializer == AlreadyImported &&
             "Duplicate import of in-class initializer.");
    else
      ToField->setInClassInitializer(ToInitializer);
  }

  return ToField;
}

ExpectedDecl ASTNodeImporter::VisitIndirectFieldDecl(IndirectFieldDecl *D) {
  // Import the major distinguishing characteristics of a variable.
  DeclContext *DC, *LexicalDC;
  DeclarationName Name;
  SourceLocation Loc;
  NamedDecl *ToD;
  if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
    return std::move(Err);
  if (ToD)
    return ToD;

  // Determine whether we've already imported this field.
  auto FoundDecls = Importer.findDeclsInToCtx(DC, Name);
  for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
    if (auto *FoundField = dyn_cast<IndirectFieldDecl>(FoundDecls[I])) {
      // For anonymous indirect fields, match up by index.
      if (!Name &&
          ASTImporter::getFieldIndex(D) !=
          ASTImporter::getFieldIndex(FoundField))
        continue;

      if (Importer.IsStructurallyEquivalent(D->getType(),
                                            FoundField->getType(),
                                            !Name.isEmpty())) {
        Importer.MapImported(D, FoundField);
        return FoundField;
      }

      // If there are more anonymous fields to check, continue.
      if (!Name && I < N-1)
        continue;

      // FIXME: Why is this case not handled with calling HandleNameConflict?
      Importer.ToDiag(Loc, diag::warn_odr_field_type_inconsistent)
        << Name << D->getType() << FoundField->getType();
      Importer.ToDiag(FoundField->getLocation(), diag::note_odr_value_here)
        << FoundField->getType();

      return make_error<ASTImportError>(ASTImportError::NameConflict);
    }
  }

  // Import the type.
  auto TypeOrErr = import(D->getType());
  if (!TypeOrErr)
    return TypeOrErr.takeError();

  auto **NamedChain =
    new (Importer.getToContext()) NamedDecl*[D->getChainingSize()];

  unsigned i = 0;
  for (auto *PI : D->chain())
    if (Expected<NamedDecl *> ToD = import(PI))
      NamedChain[i++] = *ToD;
    else
      return ToD.takeError();

  MutableArrayRef<NamedDecl *> CH = {NamedChain, D->getChainingSize()};
  IndirectFieldDecl *ToIndirectField;
  if (GetImportedOrCreateDecl(ToIndirectField, D, Importer.getToContext(), DC,
                              Loc, Name.getAsIdentifierInfo(), *TypeOrErr, CH))
    // FIXME here we leak `NamedChain` which is allocated before
    return ToIndirectField;

  ToIndirectField->setAccess(D->getAccess());
  ToIndirectField->setLexicalDeclContext(LexicalDC);
  LexicalDC->addDeclInternal(ToIndirectField);
  return ToIndirectField;
}

/// Used as return type of getFriendCountAndPosition.
struct FriendCountAndPosition {
  /// Number of similar looking friends.
  unsigned int TotalCount;
  /// Index of the specific FriendDecl.
  unsigned int IndexOfDecl;
};

static bool IsEquivalentFriend(ASTImporter &Importer, FriendDecl *FD1,
                               FriendDecl *FD2) {
  if ((!FD1->getFriendType()) != (!FD2->getFriendType()))
    return false;

  if (const TypeSourceInfo *TSI = FD1->getFriendType())
    return Importer.IsStructurallyEquivalent(
        TSI->getType(), FD2->getFriendType()->getType(), /*Complain=*/false);

  ASTImporter::NonEquivalentDeclSet NonEquivalentDecls;
  StructuralEquivalenceContext Ctx(
      Importer.getToContext().getLangOpts(), FD1->getASTContext(),
      FD2->getASTContext(), NonEquivalentDecls,
      StructuralEquivalenceKind::Default,
      /* StrictTypeSpelling = */ false, /* Complain = */ false);
  return Ctx.IsEquivalent(FD1, FD2);
}

static FriendCountAndPosition getFriendCountAndPosition(ASTImporter &Importer,
                                                        FriendDecl *FD) {
  unsigned int FriendCount = 0;
  UnsignedOrNone FriendPosition = std::nullopt;
  const auto *RD = cast<CXXRecordDecl>(FD->getLexicalDeclContext());

  for (FriendDecl *FoundFriend : RD->friends()) {
    if (FoundFriend == FD) {
      FriendPosition = FriendCount;
      ++FriendCount;
    } else if (IsEquivalentFriend(Importer, FD, FoundFriend)) {
      ++FriendCount;
    }
  }

  assert(FriendPosition && "Friend decl not found in own parent.");

  return {FriendCount, *FriendPosition};
}

ExpectedDecl ASTNodeImporter::VisitFriendDecl(FriendDecl *D) {
  // Import the major distinguishing characteristics of a declaration.
  DeclContext *DC, *LexicalDC;
  if (Error Err = ImportDeclContext(D, DC, LexicalDC))
    return std::move(Err);

  // Determine whether we've already imported this decl.
  // FriendDecl is not a NamedDecl so we cannot use lookup.
  // We try to maintain order and count of redundant friend declarations.
  const auto *RD = cast<CXXRecordDecl>(DC);
  SmallVector<FriendDecl *, 2> ImportedEquivalentFriends;
  for (FriendDecl *ImportedFriend : RD->friends())
    if (IsEquivalentFriend(Importer, D, ImportedFriend))
      ImportedEquivalentFriends.push_back(ImportedFriend);

  FriendCountAndPosition CountAndPosition =
      getFriendCountAndPosition(Importer, D);

  assert(ImportedEquivalentFriends.size() <= CountAndPosition.TotalCount &&
         "Class with non-matching friends is imported, ODR check wrong?");
  if (ImportedEquivalentFriends.size() == CountAndPosition.TotalCount)
    return Importer.MapImported(
        D, ImportedEquivalentFriends[CountAndPosition.IndexOfDecl]);

  // Not found. Create it.
  // The declarations will be put into order later by ImportDeclContext.
  FriendDecl::FriendUnion ToFU;
  if (NamedDecl *FriendD = D->getFriendDecl()) {
    NamedDecl *ToFriendD;
    if (Error Err = importInto(ToFriendD, FriendD))
      return std::move(Err);

    if (FriendD->getFriendObjectKind() != Decl::FOK_None &&
        !(FriendD->isInIdentifierNamespace(Decl::IDNS_NonMemberOperator)))
      ToFriendD->setObjectOfFriendDecl(false);

    ToFU = ToFriendD;
  } else { // The friend is a type, not a decl.
    if (auto TSIOrErr = import(D->getFriendType()))
      ToFU = *TSIOrErr;
    else
      return TSIOrErr.takeError();
  }

  SmallVector<TemplateParameterList *, 1> ToTPLists(D->NumTPLists);
  auto **FromTPLists = D->getTrailingObjects();
  for (unsigned I = 0; I < D->NumTPLists; I++) {
    if (auto ListOrErr = import(FromTPLists[I]))
      ToTPLists[I] = *ListOrErr;
    else
      return ListOrErr.takeError();
  }

  auto LocationOrErr = import(D->getLocation());
  if (!LocationOrErr)
    return LocationOrErr.takeError();
  auto FriendLocOrErr = import(D->getFriendLoc());
  if (!FriendLocOrErr)
    return FriendLocOrErr.takeError();
  auto EllipsisLocOrErr = import(D->getEllipsisLoc());
  if (!EllipsisLocOrErr)
    return EllipsisLocOrErr.takeError();

  FriendDecl *FrD;
  if (GetImportedOrCreateDecl(FrD, D, Importer.getToContext(), DC,
                              *LocationOrErr, ToFU, *FriendLocOrErr,
                              *EllipsisLocOrErr, ToTPLists))
    return FrD;

  FrD->setAccess(D->getAccess());
  FrD->setLexicalDeclContext(LexicalDC);
  LexicalDC->addDeclInternal(FrD);
  return FrD;
}

ExpectedDecl ASTNodeImporter::VisitObjCIvarDecl(ObjCIvarDecl *D) {
  // Import the major distinguishing characteristics of an ivar.
  DeclContext *DC, *LexicalDC;
  DeclarationName Name;
  SourceLocation Loc;
  NamedDecl *ToD;
  if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
    return std::move(Err);
  if (ToD)
    return ToD;

  // Determine whether we've already imported this ivar
  auto FoundDecls = Importer.findDeclsInToCtx(DC, Name);
  for (auto *FoundDecl : FoundDecls) {
    if (ObjCIvarDecl *FoundIvar = dyn_cast<ObjCIvarDecl>(FoundDecl)) {
      if (Importer.IsStructurallyEquivalent(D->getType(),
                                            FoundIvar->getType())) {
        Importer.MapImported(D, FoundIvar);
        return FoundIvar;
      }

      Importer.ToDiag(Loc, diag::warn_odr_ivar_type_inconsistent)
        << Name << D->getType() << FoundIvar->getType();
      Importer.ToDiag(FoundIvar->getLocation(), diag::note_odr_value_here)
        << FoundIvar->getType();

      return make_error<ASTImportError>(ASTImportError::NameConflict);
    }
  }

  Error Err = Error::success();
  auto ToType = importChecked(Err, D->getType());
  auto ToTypeSourceInfo = importChecked(Err, D->getTypeSourceInfo());
  auto ToBitWidth = importChecked(Err, D->getBitWidth());
  auto ToInnerLocStart = importChecked(Err, D->getInnerLocStart());
  if (Err)
    return std::move(Err);

  ObjCIvarDecl *ToIvar;
  if (GetImportedOrCreateDecl(
          ToIvar, D, Importer.getToContext(), cast<ObjCContainerDecl>(DC),
          ToInnerLocStart, Loc, Name.getAsIdentifierInfo(),
          ToType, ToTypeSourceInfo,
          D->getAccessControl(),ToBitWidth, D->getSynthesize()))
    return ToIvar;

  ToIvar->setLexicalDeclContext(LexicalDC);
  LexicalDC->addDeclInternal(ToIvar);
  return ToIvar;
}

ExpectedDecl ASTNodeImporter::VisitVarDecl(VarDecl *D) {

  SmallVector<Decl*, 2> Redecls = getCanonicalForwardRedeclChain(D);
  auto RedeclIt = Redecls.begin();
  // Import the first part of the decl chain. I.e. import all previous
  // declarations starting from the canonical decl.
  for (; RedeclIt != Redecls.end() && *RedeclIt != D; ++RedeclIt) {
    ExpectedDecl RedeclOrErr = import(*RedeclIt);
    if (!RedeclOrErr)
      return RedeclOrErr.takeError();
  }
  assert(*RedeclIt == D);

  // Import the major distinguishing characteristics of a variable.
  DeclContext *DC, *LexicalDC;
  DeclarationName Name;
  SourceLocation Loc;
  NamedDecl *ToD;
  if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
    return std::move(Err);
  if (ToD)
    return ToD;

  // Try to find a variable in our own ("to") context with the same name and
  // in the same context as the variable we're importing.
  VarDecl *FoundByLookup = nullptr;
  if (D->isFileVarDecl()) {
    SmallVector<NamedDecl *, 4> ConflictingDecls;
    unsigned IDNS = Decl::IDNS_Ordinary;
    auto FoundDecls = Importer.findDeclsInToCtx(DC, Name);
    for (auto *FoundDecl : FoundDecls) {
      if (!FoundDecl->isInIdentifierNamespace(IDNS))
        continue;

      if (auto *FoundVar = dyn_cast<VarDecl>(FoundDecl)) {
        if (!hasSameVisibilityContextAndLinkage(FoundVar, D))
          continue;
        if (Importer.IsStructurallyEquivalent(D->getType(),
                                              FoundVar->getType())) {

          // The VarDecl in the "From" context has a definition, but in the
          // "To" context we already have a definition.
          VarDecl *FoundDef = FoundVar->getDefinition();
          if (D->isThisDeclarationADefinition() && FoundDef)
            // FIXME Check for ODR error if the two definitions have
            // different initializers?
            return Importer.MapImported(D, FoundDef);

          // The VarDecl in the "From" context has an initializer, but in the
          // "To" context we already have an initializer.
          const VarDecl *FoundDInit = nullptr;
          if (D->getInit() && FoundVar->getAnyInitializer(FoundDInit))
            // FIXME Diagnose ODR error if the two initializers are different?
            return Importer.MapImported(D, const_cast<VarDecl*>(FoundDInit));

          FoundByLookup = FoundVar;
          break;
        }

        const ArrayType *FoundArray
          = Importer.getToContext().getAsArrayType(FoundVar->getType());
        const ArrayType *TArray
          = Importer.getToContext().getAsArrayType(D->getType());
        if (FoundArray && TArray) {
          if (isa<IncompleteArrayType>(FoundArray) &&
              isa<ConstantArrayType>(TArray)) {
            // Import the type.
            if (auto TyOrErr = import(D->getType()))
              FoundVar->setType(*TyOrErr);
            else
              return TyOrErr.takeError();

            FoundByLookup = FoundVar;
            break;
          } else if (isa<IncompleteArrayType>(TArray) &&
                     isa<ConstantArrayType>(FoundArray)) {
            FoundByLookup = FoundVar;
            break;
          }
        }

        Importer.ToDiag(Loc, diag::warn_odr_variable_type_inconsistent)
          << Name << D->getType() << FoundVar->getType();
        Importer.ToDiag(FoundVar->getLocation(), diag::note_odr_value_here)
          << FoundVar->getType();
        ConflictingDecls.push_back(FoundDecl);
      }
    }

    if (!ConflictingDecls.empty()) {
      ExpectedName NameOrErr = Importer.HandleNameConflict(
          Name, DC, IDNS, ConflictingDecls.data(), ConflictingDecls.size());
      if (NameOrErr)
        Name = NameOrErr.get();
      else
        return NameOrErr.takeError();
    }
  }

  Error Err = Error::success();
  auto ToType = importChecked(Err, D->getType());
  auto ToTypeSourceInfo = importChecked(Err, D->getTypeSourceInfo());
  auto ToInnerLocStart = importChecked(Err, D->getInnerLocStart());
  auto ToQualifierLoc = importChecked(Err, D->getQualifierLoc());
  if (Err)
    return std::move(Err);

  VarDecl *ToVar;
  if (auto *FromDecomp = dyn_cast<DecompositionDecl>(D)) {
    SmallVector<BindingDecl *> Bindings(FromDecomp->bindings().size());
    if (Error Err =
            ImportArrayChecked(FromDecomp->bindings(), Bindings.begin()))
      return std::move(Err);
    DecompositionDecl *ToDecomp;
    if (GetImportedOrCreateDecl(
            ToDecomp, FromDecomp, Importer.getToContext(), DC, ToInnerLocStart,
            Loc, ToType, ToTypeSourceInfo, D->getStorageClass(), Bindings))
      return ToDecomp;
    ToVar = ToDecomp;
  } else {
    // Create the imported variable.
    if (GetImportedOrCreateDecl(ToVar, D, Importer.getToContext(), DC,
                                ToInnerLocStart, Loc,
                                Name.getAsIdentifierInfo(), ToType,
                                ToTypeSourceInfo, D->getStorageClass()))
      return ToVar;
  }

  ToVar->setTSCSpec(D->getTSCSpec());
  ToVar->setQualifierInfo(ToQualifierLoc);
  ToVar->setAccess(D->getAccess());
  ToVar->setLexicalDeclContext(LexicalDC);
  if (D->isInlineSpecified())
    ToVar->setInlineSpecified();
  if (D->isInline())
    ToVar->setImplicitlyInline();

  if (FoundByLookup) {
    auto *Recent = const_cast<VarDecl *>(FoundByLookup->getMostRecentDecl());
    ToVar->setPreviousDecl(Recent);
  }

  // Import the described template, if any.
  if (D->getDescribedVarTemplate()) {
    auto ToVTOrErr = import(D->getDescribedVarTemplate());
    if (!ToVTOrErr)
      return ToVTOrErr.takeError();
  } else if (MemberSpecializationInfo *MSI = D->getMemberSpecializationInfo()) {
    TemplateSpecializationKind SK = MSI->getTemplateSpecializationKind();
    VarDecl *FromInst = D->getInstantiatedFromStaticDataMember();
    if (Expected<VarDecl *> ToInstOrErr = import(FromInst))
      ToVar->setInstantiationOfStaticDataMember(*ToInstOrErr, SK);
    else
      return ToInstOrErr.takeError();
    if (ExpectedSLoc POIOrErr = import(MSI->getPointOfInstantiation()))
      ToVar->getMemberSpecializationInfo()->setPointOfInstantiation(*POIOrErr);
    else
      return POIOrErr.takeError();
  }

  if (Error Err = ImportInitializer(D, ToVar))
    return std::move(Err);

  if (D->isConstexpr())
    ToVar->setConstexpr(true);

  addDeclToContexts(D, ToVar);

  // Import the rest of the chain. I.e. import all subsequent declarations.
  for (++RedeclIt; RedeclIt != Redecls.end(); ++RedeclIt) {
    ExpectedDecl RedeclOrErr = import(*RedeclIt);
    if (!RedeclOrErr)
      return RedeclOrErr.takeError();
  }

  return ToVar;
}

ExpectedDecl ASTNodeImporter::VisitImplicitParamDecl(ImplicitParamDecl *D) {
  // Parameters are created in the translation unit's context, then moved
  // into the function declaration's context afterward.
  DeclContext *DC = Importer.getToContext().getTranslationUnitDecl();

  Error Err = Error::success();
  auto ToDeclName = importChecked(Err, D->getDeclName());
  auto ToLocation = importChecked(Err, D->getLocation());
  auto ToType = importChecked(Err, D->getType());
  if (Err)
    return std::move(Err);

  // Create the imported parameter.
  ImplicitParamDecl *ToParm = nullptr;
  if (GetImportedOrCreateDecl(ToParm, D, Importer.getToContext(), DC,
                              ToLocation, ToDeclName.getAsIdentifierInfo(),
                              ToType, D->getParameterKind()))
    return ToParm;
  return ToParm;
}

Error ASTNodeImporter::ImportDefaultArgOfParmVarDecl(
    const ParmVarDecl *FromParam, ParmVarDecl *ToParam) {

  if (auto LocOrErr = import(FromParam->getExplicitObjectParamThisLoc()))
    ToParam->setExplicitObjectParameterLoc(*LocOrErr);
  else
    return LocOrErr.takeError();

  ToParam->setHasInheritedDefaultArg(FromParam->hasInheritedDefaultArg());
  ToParam->setKNRPromoted(FromParam->isKNRPromoted());

  if (FromParam->hasUninstantiatedDefaultArg()) {
    if (auto ToDefArgOrErr = import(FromParam->getUninstantiatedDefaultArg()))
      ToParam->setUninstantiatedDefaultArg(*ToDefArgOrErr);
    else
      return ToDefArgOrErr.takeError();
  } else if (FromParam->hasUnparsedDefaultArg()) {
    ToParam->setUnparsedDefaultArg();
  } else if (FromParam->hasDefaultArg()) {
    if (auto ToDefArgOrErr = import(FromParam->getDefaultArg()))
      ToParam->setDefaultArg(*ToDefArgOrErr);
    else
      return ToDefArgOrErr.takeError();
  }

  return Error::success();
}

Expected<InheritedConstructor>
ASTNodeImporter::ImportInheritedConstructor(const InheritedConstructor &From) {
  Error Err = Error::success();
  CXXConstructorDecl *ToBaseCtor = importChecked(Err, From.getConstructor());
  ConstructorUsingShadowDecl *ToShadow =
      importChecked(Err, From.getShadowDecl());
  if (Err)
    return std::move(Err);
  return InheritedConstructor(ToShadow, ToBaseCtor);
}

ExpectedDecl ASTNodeImporter::VisitParmVarDecl(ParmVarDecl *D) {
  // Parameters are created in the translation unit's context, then moved
  // into the function declaration's context afterward.
  DeclContext *DC = Importer.getToContext().getTranslationUnitDecl();

  Error Err = Error::success();
  auto ToDeclName = importChecked(Err, D->getDeclName());
  auto ToLocation = importChecked(Err, D->getLocation());
  auto ToInnerLocStart = importChecked(Err, D->getInnerLocStart());
  auto ToType = importChecked(Err, D->getType());
  auto ToTypeSourceInfo = importChecked(Err, D->getTypeSourceInfo());
  if (Err)
    return std::move(Err);

  ParmVarDecl *ToParm;
  if (GetImportedOrCreateDecl(ToParm, D, Importer.getToContext(), DC,
                              ToInnerLocStart, ToLocation,
                              ToDeclName.getAsIdentifierInfo(), ToType,
                              ToTypeSourceInfo, D->getStorageClass(),
                              /*DefaultArg*/ nullptr))
    return ToParm;

  // Set the default argument. It should be no problem if it was already done.
  // Do not import the default expression before GetImportedOrCreateDecl call
  // to avoid possible infinite import loop because circular dependency.
  if (Error Err = ImportDefaultArgOfParmVarDecl(D, ToParm))
    return std::move(Err);

  if (D->isObjCMethodParameter()) {
    ToParm->setObjCMethodScopeInfo(D->getFunctionScopeIndex());
    ToParm->setObjCDeclQualifier(D->getObjCDeclQualifier());
  } else {
    ToParm->setScopeInfo(D->getFunctionScopeDepth(),
                         D->getFunctionScopeIndex());
  }

  return ToParm;
}

ExpectedDecl ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) {
  // Import the major distinguishing characteristics of a method.
  DeclContext *DC, *LexicalDC;
  DeclarationName Name;
  SourceLocation Loc;
  NamedDecl *ToD;
  if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
    return std::move(Err);
  if (ToD)
    return ToD;

  auto FoundDecls = Importer.findDeclsInToCtx(DC, Name);
  for (auto *FoundDecl : FoundDecls) {
    if (auto *FoundMethod = dyn_cast<ObjCMethodDecl>(FoundDecl)) {
      if (FoundMethod->isInstanceMethod() != D->isInstanceMethod())
        continue;

      // Check return types.
      if (!Importer.IsStructurallyEquivalent(D->getReturnType(),
                                             FoundMethod->getReturnType())) {
        Importer.ToDiag(Loc, diag::warn_odr_objc_method_result_type_inconsistent)
            << D->isInstanceMethod() << Name << D->getReturnType()
            << FoundMethod->getReturnType();
        Importer.ToDiag(FoundMethod->getLocation(),
                        diag::note_odr_objc_method_here)
          << D->isInstanceMethod() << Name;

        return make_error<ASTImportError>(ASTImportError::NameConflict);
      }

      // Check the number of parameters.
      if (D->param_size() != FoundMethod->param_size()) {
        Importer.ToDiag(Loc, diag::warn_odr_objc_method_num_params_inconsistent)
          << D->isInstanceMethod() << Name
          << D->param_size() << FoundMethod->param_size();
        Importer.ToDiag(FoundMethod->getLocation(),
                        diag::note_odr_objc_method_here)
          << D->isInstanceMethod() << Name;

        return make_error<ASTImportError>(ASTImportError::NameConflict);
      }

      // Check parameter types.
      for (ObjCMethodDecl::param_iterator P = D->param_begin(),
             PEnd = D->param_end(), FoundP = FoundMethod->param_begin();
           P != PEnd; ++P, ++FoundP) {
        if (!Importer.IsStructurallyEquivalent((*P)->getType(),
                                               (*FoundP)->getType())) {
          Importer.FromDiag((*P)->getLocation(),
                            diag::warn_odr_objc_method_param_type_inconsistent)
            << D->isInstanceMethod() << Name
            << (*P)->getType() << (*FoundP)->getType();
          Importer.ToDiag((*FoundP)->getLocation(), diag::note_odr_value_here)
            << (*FoundP)->getType();

          return make_error<ASTImportError>(ASTImportError::NameConflict);
        }
      }

      // Check variadic/non-variadic.
      // Check the number of parameters.
      if (D->isVariadic() != FoundMethod->isVariadic()) {
        Importer.ToDiag(Loc, diag::warn_odr_objc_method_variadic_inconsistent)
          << D->isInstanceMethod() << Name;
        Importer.ToDiag(FoundMethod->getLocation(),
                        diag::note_odr_objc_method_here)
          << D->isInstanceMethod() << Name;

        return make_error<ASTImportError>(ASTImportError::NameConflict);
      }

      // FIXME: Any other bits we need to merge?
      return Importer.MapImported(D, FoundMethod);
    }
  }

  Error Err = Error::success();
  auto ToEndLoc = importChecked(Err, D->getEndLoc());
  auto ToReturnType = importChecked(Err, D->getReturnType());
  auto ToReturnTypeSourceInfo =
      importChecked(Err, D->getReturnTypeSourceInfo());
  if (Err)
    return std::move(Err);

  ObjCMethodDecl *ToMethod;
  if (GetImportedOrCreateDecl(
          ToMethod, D, Importer.getToContext(), Loc, ToEndLoc,
          Name.getObjCSelector(), ToReturnType, ToReturnTypeSourceInfo, DC,
          D->isInstanceMethod(), D->isVariadic(), D->isPropertyAccessor(),
          D->isSynthesizedAccessorStub(), D->isImplicit(), D->isDefined(),
          D->getImplementationControl(), D->hasRelatedResultType()))
    return ToMethod;

  // FIXME: When we decide to merge method definitions, we'll need to
  // deal with implicit parameters.

  // Import the parameters
  SmallVector<ParmVarDecl *, 5> ToParams;
  for (auto *FromP : D->parameters()) {
    if (Expected<ParmVarDecl *> ToPOrErr = import(FromP))
      ToParams.push_back(*ToPOrErr);
    else
      return ToPOrErr.takeError();
  }

  // Set the parameters.
  for (auto *ToParam : ToParams) {
    ToParam->setOwningFunction(ToMethod);
    ToMethod->addDeclInternal(ToParam);
  }

  SmallVector<SourceLocation, 12> FromSelLocs;
  D->getSelectorLocs(FromSelLocs);
  SmallVector<SourceLocation, 12> ToSelLocs(FromSelLocs.size());
  if (Error Err = ImportContainerChecked(FromSelLocs, ToSelLocs))
    return std::move(Err);

  ToMethod->setMethodParams(Importer.getToContext(), ToParams, ToSelLocs);

  ToMethod->setLexicalDeclContext(LexicalDC);
  LexicalDC->addDeclInternal(ToMethod);

  // Implicit params are declared when Sema encounters the definition but this
  // never happens when the method is imported. Manually declare the implicit
  // params now that the MethodDecl knows its class interface.
  if (D->getSelfDecl())
    ToMethod->createImplicitParams(Importer.getToContext(),
                                   ToMethod->getClassInterface());

  return ToMethod;
}

ExpectedDecl ASTNodeImporter::VisitObjCTypeParamDecl(ObjCTypeParamDecl *D) {
  // Import the major distinguishing characteristics of a category.
  DeclContext *DC, *LexicalDC;
  DeclarationName Name;
  SourceLocation Loc;
  NamedDecl *ToD;
  if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
    return std::move(Err);
  if (ToD)
    return ToD;

  Error Err = Error::success();
  auto ToVarianceLoc = importChecked(Err, D->getVarianceLoc());
  auto ToLocation = importChecked(Err, D->getLocation());
  auto ToColonLoc = importChecked(Err, D->getColonLoc());
  auto ToTypeSourceInfo = importChecked(Err, D->getTypeSourceInfo());
  if (Err)
    return std::move(Err);

  ObjCTypeParamDecl *Result;
  if (GetImportedOrCreateDecl(
          Result, D, Importer.getToContext(), DC, D->getVariance(),
          ToVarianceLoc, D->getIndex(),
          ToLocation, Name.getAsIdentifierInfo(),
          ToColonLoc, ToTypeSourceInfo))
    return Result;

  // Only import 'ObjCTypeParamType' after the decl is created.
  auto ToTypeForDecl = importChecked(Err, D->getTypeForDecl());
  if (Err)
    return std::move(Err);
  Result->setTypeForDecl(ToTypeForDecl);
  Result->setLexicalDeclContext(LexicalDC);
  return Result;
}

ExpectedDecl ASTNodeImporter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) {
  // Import the major distinguishing characteristics of a category.
  DeclContext *DC, *LexicalDC;
  DeclarationName Name;
  SourceLocation Loc;
  NamedDecl *ToD;
  if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
    return std::move(Err);
  if (ToD)
    return ToD;

  ObjCInterfaceDecl *ToInterface;
  if (Error Err = importInto(ToInterface, D->getClassInterface()))
    return std::move(Err);

  // Determine if we've already encountered this category.
  ObjCCategoryDecl *MergeWithCategory
    = ToInterface->FindCategoryDeclaration(Name.getAsIdentifierInfo());
  ObjCCategoryDecl *ToCategory = MergeWithCategory;
  if (!ToCategory) {

    Error Err = Error::success();
    auto ToAtStartLoc = importChecked(Err, D->getAtStartLoc());
    auto ToCategoryNameLoc = importChecked(Err, D->getCategoryNameLoc());
    auto ToIvarLBraceLoc = importChecked(Err, D->getIvarLBraceLoc());
    auto ToIvarRBraceLoc = importChecked(Err, D->getIvarRBraceLoc());
    if (Err)
      return std::move(Err);

    if (GetImportedOrCreateDecl(ToCategory, D, Importer.getToContext(), DC,
                                ToAtStartLoc, Loc,
                                ToCategoryNameLoc,
                                Name.getAsIdentifierInfo(), ToInterface,
                                /*TypeParamList=*/nullptr,
                                ToIvarLBraceLoc,
                                ToIvarRBraceLoc))
      return ToCategory;

    ToCategory->setLexicalDeclContext(LexicalDC);
    LexicalDC->addDeclInternal(ToCategory);
    // Import the type parameter list after MapImported, to avoid
    // loops when bringing in their DeclContext.
    if (auto PListOrErr = ImportObjCTypeParamList(D->getTypeParamList()))
      ToCategory->setTypeParamList(*PListOrErr);
    else
      return PListOrErr.takeError();

    // Import protocols
    SmallVector<ObjCProtocolDecl *, 4> Protocols;
    SmallVector<SourceLocation, 4> ProtocolLocs;
    ObjCCategoryDecl::protocol_loc_iterator FromProtoLoc
      = D->protocol_loc_begin();
    for (ObjCCategoryDecl::protocol_iterator FromProto = D->protocol_begin(),
                                          FromProtoEnd = D->protocol_end();
         FromProto != FromProtoEnd;
         ++FromProto, ++FromProtoLoc) {
      if (Expected<ObjCProtocolDecl *> ToProtoOrErr = import(*FromProto))
        Protocols.push_back(*ToProtoOrErr);
      else
        return ToProtoOrErr.takeError();

      if (ExpectedSLoc ToProtoLocOrErr = import(*FromProtoLoc))
        ProtocolLocs.push_back(*ToProtoLocOrErr);
      else
        return ToProtoLocOrErr.takeError();
    }

    // FIXME: If we're merging, make sure that the protocol list is the same.
    ToCategory->setProtocolList(Protocols.data(), Protocols.size(),
                                ProtocolLocs.data(), Importer.getToContext());

  } else {
    Importer.MapImported(D, ToCategory);
  }

  // Import all of the members of this category.
  if (Error Err = ImportDeclContext(D))
    return std::move(Err);

  // If we have an implementation, import it as well.
  if (D->getImplementation()) {
    if (Expected<ObjCCategoryImplDecl *> ToImplOrErr =
        import(D->getImplementation()))
      ToCategory->setImplementation(*ToImplOrErr);
    else
      return ToImplOrErr.takeError();
  }

  return ToCategory;
}

Error ASTNodeImporter::ImportDefinition(
    ObjCProtocolDecl *From, ObjCProtocolDecl *To, ImportDefinitionKind Kind) {
  if (To->getDefinition()) {
    if (shouldForceImportDeclContext(Kind))
      if (Error Err = ImportDeclContext(From))
        return Err;
    return Error::success();
  }

  // Start the protocol definition
  To->startDefinition();

  // Import protocols
  SmallVector<ObjCProtocolDecl *, 4> Protocols;
  SmallVector<SourceLocation, 4> ProtocolLocs;
  ObjCProtocolDecl::protocol_loc_iterator FromProtoLoc =
      From->protocol_loc_begin();
  for (ObjCProtocolDecl::protocol_iterator FromProto = From->protocol_begin(),
                                        FromProtoEnd = From->protocol_end();
       FromProto != FromProtoEnd;
       ++FromProto, ++FromProtoLoc) {
    if (Expected<ObjCProtocolDecl *> ToProtoOrErr = import(*FromProto))
      Protocols.push_back(*ToProtoOrErr);
    else
      return ToProtoOrErr.takeError();

    if (ExpectedSLoc ToProtoLocOrErr = import(*FromProtoLoc))
      ProtocolLocs.push_back(*ToProtoLocOrErr);
    else
      return ToProtoLocOrErr.takeError();

  }

  // FIXME: If we're merging, make sure that the protocol list is the same.
  To->setProtocolList(Protocols.data(), Protocols.size(),
                      ProtocolLocs.data(), Importer.getToContext());

  if (shouldForceImportDeclContext(Kind)) {
    // Import all of the members of this protocol.
    if (Error Err = ImportDeclContext(From, /*ForceImport=*/true))
      return Err;
  }
  return Error::success();
}

ExpectedDecl ASTNodeImporter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) {
  // If this protocol has a definition in the translation unit we're coming
  // from, but this particular declaration is not that definition, import the
  // definition and map to that.
  ObjCProtocolDecl *Definition = D->getDefinition();
  if (Definition && Definition != D) {
    if (ExpectedDecl ImportedDefOrErr = import(Definition))
      return Importer.MapImported(D, *ImportedDefOrErr);
    else
      return ImportedDefOrErr.takeError();
  }

  // Import the major distinguishing characteristics of a protocol.
  DeclContext *DC, *LexicalDC;
  DeclarationName Name;
  SourceLocation Loc;
  NamedDecl *ToD;
  if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
    return std::move(Err);
  if (ToD)
    return ToD;

  ObjCProtocolDecl *MergeWithProtocol = nullptr;
  auto FoundDecls = Importer.findDeclsInToCtx(DC, Name);
  for (auto *FoundDecl : FoundDecls) {
    if (!FoundDecl->isInIdentifierNamespace(Decl::IDNS_ObjCProtocol))
      continue;

    if ((MergeWithProtocol = dyn_cast<ObjCProtocolDecl>(FoundDecl)))
      break;
  }

  ObjCProtocolDecl *ToProto = MergeWithProtocol;
  if (!ToProto) {
    auto ToAtBeginLocOrErr = import(D->getAtStartLoc());
    if (!ToAtBeginLocOrErr)
      return ToAtBeginLocOrErr.takeError();

    if (GetImportedOrCreateDecl(ToProto, D, Importer.getToContext(), DC,
                                Name.getAsIdentifierInfo(), Loc,
                                *ToAtBeginLocOrErr,
                                /*PrevDecl=*/nullptr))
      return ToProto;
    ToProto->setLexicalDeclContext(LexicalDC);
    LexicalDC->addDeclInternal(ToProto);
  }

  Importer.MapImported(D, ToProto);

  if (D->isThisDeclarationADefinition())
    if (Error Err = ImportDefinition(D, ToProto))
      return std::move(Err);

  return ToProto;
}

ExpectedDecl ASTNodeImporter::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
  DeclContext *DC, *LexicalDC;
  if (Error Err = ImportDeclContext(D, DC, LexicalDC))
    return std::move(Err);

  ExpectedSLoc ExternLocOrErr = import(D->getExternLoc());
  if (!ExternLocOrErr)
    return ExternLocOrErr.takeError();

  ExpectedSLoc LangLocOrErr = import(D->getLocation());
  if (!LangLocOrErr)
    return LangLocOrErr.takeError();

  bool HasBraces = D->hasBraces();

  LinkageSpecDecl *ToLinkageSpec;
  if (GetImportedOrCreateDecl(ToLinkageSpec, D, Importer.getToContext(), DC,
                              *ExternLocOrErr, *LangLocOrErr,
                              D->getLanguage(), HasBraces))
    return ToLinkageSpec;

  if (HasBraces) {
    ExpectedSLoc RBraceLocOrErr = import(D->getRBraceLoc());
    if (!RBraceLocOrErr)
      return RBraceLocOrErr.takeError();
    ToLinkageSpec->setRBraceLoc(*RBraceLocOrErr);
  }

  ToLinkageSpec->setLexicalDeclContext(LexicalDC);
  LexicalDC->addDeclInternal(ToLinkageSpec);

  return ToLinkageSpec;
}

ExpectedDecl ASTNodeImporter::ImportUsingShadowDecls(BaseUsingDecl *D,
                                                     BaseUsingDecl *ToSI) {
  for (UsingShadowDecl *FromShadow : D->shadows()) {
    if (Expected<UsingShadowDecl *> ToShadowOrErr = import(FromShadow))
      ToSI->addShadowDecl(*ToShadowOrErr);
    else
      // FIXME: We return error here but the definition is already created
      // and available with lookups. How to fix this?..
      return ToShadowOrErr.takeError();
  }
  return ToSI;
}

ExpectedDecl ASTNodeImporter::VisitUsingDecl(UsingDecl *D) {
  DeclContext *DC, *LexicalDC;
  DeclarationName Name;
  SourceLocation Loc;
  NamedDecl *ToD = nullptr;
  if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
    return std::move(Err);
  if (ToD)
    return ToD;

  Error Err = Error::success();
  auto ToLoc = importChecked(Err, D->getNameInfo().getLoc());
  auto ToUsingLoc = importChecked(Err, D->getUsingLoc());
  auto ToQualifierLoc = importChecked(Err, D->getQualifierLoc());
  if (Err)
    return std::move(Err);

  DeclarationNameInfo NameInfo(Name, ToLoc);
  if (Error Err = ImportDeclarationNameLoc(D->getNameInfo(), NameInfo))
    return std::move(Err);

  UsingDecl *ToUsing;
  if (GetImportedOrCreateDecl(ToUsing, D, Importer.getToContext(), DC,
                              ToUsingLoc, ToQualifierLoc, NameInfo,
                              D->hasTypename()))
    return ToUsing;

  ToUsing->setLexicalDeclContext(LexicalDC);
  LexicalDC->addDeclInternal(ToUsing);

  if (NamedDecl *FromPattern =
      Importer.getFromContext().getInstantiatedFromUsingDecl(D)) {
    if (Expected<NamedDecl *> ToPatternOrErr = import(FromPattern))
      Importer.getToContext().setInstantiatedFromUsingDecl(
          ToUsing, *ToPatternOrErr);
    else
      return ToPatternOrErr.takeError();
  }

  return ImportUsingShadowDecls(D, ToUsing);
}

ExpectedDecl ASTNodeImporter::VisitUsingEnumDecl(UsingEnumDecl *D) {
  DeclContext *DC, *LexicalDC;
  DeclarationName Name;
  SourceLocation Loc;
  NamedDecl *ToD = nullptr;
  if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
    return std::move(Err);
  if (ToD)
    return ToD;

  Error Err = Error::success();
  auto ToUsingLoc = importChecked(Err, D->getUsingLoc());
  auto ToEnumLoc = importChecked(Err, D->getEnumLoc());
  auto ToNameLoc = importChecked(Err, D->getLocation());
  auto *ToEnumType = importChecked(Err, D->getEnumType());
  if (Err)
    return std::move(Err);

  UsingEnumDecl *ToUsingEnum;
  if (GetImportedOrCreateDecl(ToUsingEnum, D, Importer.getToContext(), DC,
                              ToUsingLoc, ToEnumLoc, ToNameLoc, ToEnumType))
    return ToUsingEnum;

  ToUsingEnum->setLexicalDeclContext(LexicalDC);
  LexicalDC->addDeclInternal(ToUsingEnum);

  if (UsingEnumDecl *FromPattern =
          Importer.getFromContext().getInstantiatedFromUsingEnumDecl(D)) {
    if (Expected<UsingEnumDecl *> ToPatternOrErr = import(FromPattern))
      Importer.getToContext().setInstantiatedFromUsingEnumDecl(ToUsingEnum,
                                                               *ToPatternOrErr);
    else
      return ToPatternOrErr.takeError();
  }

  return ImportUsingShadowDecls(D, ToUsingEnum);
}

ExpectedDecl ASTNodeImporter::VisitUsingShadowDecl(UsingShadowDecl *D) {
  DeclContext *DC, *LexicalDC;
  DeclarationName Name;
  SourceLocation Loc;
  NamedDecl *ToD = nullptr;
  if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
    return std::move(Err);
  if (ToD)
    return ToD;

  Expected<BaseUsingDecl *> ToIntroducerOrErr = import(D->getIntroducer());
  if (!ToIntroducerOrErr)
    return ToIntroducerOrErr.takeError();

  Expected<NamedDecl *> ToTargetOrErr = import(D->getTargetDecl());
  if (!ToTargetOrErr)
    return ToTargetOrErr.takeError();

  UsingShadowDecl *ToShadow;
  if (auto *FromConstructorUsingShadow =
          dyn_cast<ConstructorUsingShadowDecl>(D)) {
    Error Err = Error::success();
    ConstructorUsingShadowDecl *Nominated = importChecked(
        Err, FromConstructorUsingShadow->getNominatedBaseClassShadowDecl());
    if (Err)
      return std::move(Err);
    // The 'Target' parameter of ConstructorUsingShadowDecl constructor
    // is really the "NominatedBaseClassShadowDecl" value if it exists
    // (see code of ConstructorUsingShadowDecl::ConstructorUsingShadowDecl).
    // We should pass the NominatedBaseClassShadowDecl to it (if non-null) to
    // get the correct values.
    if (GetImportedOrCreateDecl<ConstructorUsingShadowDecl>(
            ToShadow, D, Importer.getToContext(), DC, Loc,
            cast<UsingDecl>(*ToIntroducerOrErr),
            Nominated ? Nominated : *ToTargetOrErr,
            FromConstructorUsingShadow->constructsVirtualBase()))
      return ToShadow;
  } else {
    if (GetImportedOrCreateDecl(ToShadow, D, Importer.getToContext(), DC, Loc,
                                Name, *ToIntroducerOrErr, *ToTargetOrErr))
      return ToShadow;
  }

  ToShadow->setLexicalDeclContext(LexicalDC);
  ToShadow->setAccess(D->getAccess());

  if (UsingShadowDecl *FromPattern =
      Importer.getFromContext().getInstantiatedFromUsingShadowDecl(D)) {
    if (Expected<UsingShadowDecl *> ToPatternOrErr = import(FromPattern))
      Importer.getToContext().setInstantiatedFromUsingShadowDecl(
          ToShadow, *ToPatternOrErr);
    else
      // FIXME: We return error here but the definition is already created
      // and available with lookups. How to fix this?..
      return ToPatternOrErr.takeError();
  }

  LexicalDC->addDeclInternal(ToShadow);

  return ToShadow;
}

ExpectedDecl ASTNodeImporter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
  DeclContext *DC, *LexicalDC;
  DeclarationName Name;
  SourceLocation Loc;
  NamedDecl *ToD = nullptr;
  if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
    return std::move(Err);
  if (ToD)
    return ToD;

  auto ToComAncestorOrErr = Importer.ImportContext(D->getCommonAncestor());
  if (!ToComAncestorOrErr)
    return ToComAncestorOrErr.takeError();

  Error Err = Error::success();
  auto ToNominatedNamespace = importChecked(Err, D->getNominatedNamespace());
  auto ToUsingLoc = importChecked(Err, D->getUsingLoc());
  auto ToNamespaceKeyLocation =
      importChecked(Err, D->getNamespaceKeyLocation());
  auto ToQualifierLoc = importChecked(Err, D->getQualifierLoc());
  auto ToIdentLocation = importChecked(Err, D->getIdentLocation());
  if (Err)
    return std::move(Err);

  UsingDirectiveDecl *ToUsingDir;
  if (GetImportedOrCreateDecl(ToUsingDir, D, Importer.getToContext(), DC,
                              ToUsingLoc,
                              ToNamespaceKeyLocation,
                              ToQualifierLoc,
                              ToIdentLocation,
                              ToNominatedNamespace, *ToComAncestorOrErr))
    return ToUsingDir;

  ToUsingDir->setLexicalDeclContext(LexicalDC);
  LexicalDC->addDeclInternal(ToUsingDir);

  return ToUsingDir;
}

ExpectedDecl ASTNodeImporter::VisitUsingPackDecl(UsingPackDecl *D) {
  DeclContext *DC, *LexicalDC;
  DeclarationName Name;
  SourceLocation Loc;
  NamedDecl *ToD = nullptr;
  if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
    return std::move(Err);
  if (ToD)
    return ToD;

  auto ToInstantiatedFromUsingOrErr =
      Importer.Import(D->getInstantiatedFromUsingDecl());
  if (!ToInstantiatedFromUsingOrErr)
    return ToInstantiatedFromUsingOrErr.takeError();
  SmallVector<NamedDecl *, 4> Expansions(D->expansions().size());
  if (Error Err = ImportArrayChecked(D->expansions(), Expansions.begin()))
    return std::move(Err);

  UsingPackDecl *ToUsingPack;
  if (GetImportedOrCreateDecl(ToUsingPack, D, Importer.getToContext(), DC,
                              cast<NamedDecl>(*ToInstantiatedFromUsingOrErr),
                              Expansions))
    return ToUsingPack;

  addDeclToContexts(D, ToUsingPack);

  return ToUsingPack;
}

ExpectedDecl ASTNodeImporter::VisitUnresolvedUsingValueDecl(
    UnresolvedUsingValueDecl *D) {
  DeclContext *DC, *LexicalDC;
  DeclarationName Name;
  SourceLocation Loc;
  NamedDecl *ToD = nullptr;
  if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
    return std::move(Err);
  if (ToD)
    return ToD;

  Error Err = Error::success();
  auto ToLoc = importChecked(Err, D->getNameInfo().getLoc());
  auto ToUsingLoc = importChecked(Err, D->getUsingLoc());
  auto ToQualifierLoc = importChecked(Err, D->getQualifierLoc());
  auto ToEllipsisLoc = importChecked(Err, D->getEllipsisLoc());
  if (Err)
    return std::move(Err);

  DeclarationNameInfo NameInfo(Name, ToLoc);
  if (Error Err = ImportDeclarationNameLoc(D->getNameInfo(), NameInfo))
    return std::move(Err);

  UnresolvedUsingValueDecl *ToUsingValue;
  if (GetImportedOrCreateDecl(ToUsingValue, D, Importer.getToContext(), DC,
                              ToUsingLoc, ToQualifierLoc, NameInfo,
                              ToEllipsisLoc))
    return ToUsingValue;

  ToUsingValue->setAccess(D->getAccess());
  ToUsingValue->setLexicalDeclContext(LexicalDC);
  LexicalDC->addDeclInternal(ToUsingValue);

  return ToUsingValue;
}

ExpectedDecl ASTNodeImporter::VisitUnresolvedUsingTypenameDecl(
    UnresolvedUsingTypenameDecl *D) {
  DeclContext *DC, *LexicalDC;
  DeclarationName Name;
  SourceLocation Loc;
  NamedDecl *ToD = nullptr;
  if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
    return std::move(Err);
  if (ToD)
    return ToD;

  Error Err = Error::success();
  auto ToUsingLoc = importChecked(Err, D->getUsingLoc());
  auto ToTypenameLoc = importChecked(Err, D->getTypenameLoc());
  auto ToQualifierLoc = importChecked(Err, D->getQualifierLoc());
  auto ToEllipsisLoc = importChecked(Err, D->getEllipsisLoc());
  if (Err)
    return std::move(Err);

  UnresolvedUsingTypenameDecl *ToUsing;
  if (GetImportedOrCreateDecl(ToUsing, D, Importer.getToContext(), DC,
                              ToUsingLoc, ToTypenameLoc,
                              ToQualifierLoc, Loc, Name, ToEllipsisLoc))
    return ToUsing;

  ToUsing->setAccess(D->getAccess());
  ToUsing->setLexicalDeclContext(LexicalDC);
  LexicalDC->addDeclInternal(ToUsing);

  return ToUsing;
}

ExpectedDecl ASTNodeImporter::VisitBuiltinTemplateDecl(BuiltinTemplateDecl *D) {
  Decl* ToD = nullptr;
  switch (D->getBuiltinTemplateKind()) {
#define BuiltinTemplate(BTName)                                                \
  case BuiltinTemplateKind::BTK##BTName:                                       \
    ToD = Importer.getToContext().get##BTName##Decl();                         \
    break;
#include "clang/Basic/BuiltinTemplates.inc"
  }
  assert(ToD && "BuiltinTemplateDecl of unsupported kind!");
  Importer.MapImported(D, ToD);
  return ToD;
}

Error ASTNodeImporter::ImportDefinition(
    ObjCInterfaceDecl *From, ObjCInterfaceDecl *To, ImportDefinitionKind Kind) {
  if (To->getDefinition()) {
    // Check consistency of superclass.
    ObjCInterfaceDecl *FromSuper = From->getSuperClass();
    if (FromSuper) {
      if (auto FromSuperOrErr = import(FromSuper))
        FromSuper = *FromSuperOrErr;
      else
        return FromSuperOrErr.takeError();
    }

    ObjCInterfaceDecl *ToSuper = To->getSuperClass();
    if ((bool)FromSuper != (bool)ToSuper ||
        (FromSuper && !declaresSameEntity(FromSuper, ToSuper))) {
      Importer.ToDiag(To->getLocation(),
                      diag::warn_odr_objc_superclass_inconsistent)
        << To->getDeclName();
      if (ToSuper)
        Importer.ToDiag(To->getSuperClassLoc(), diag::note_odr_objc_superclass)
          << To->getSuperClass()->getDeclName();
      else
        Importer.ToDiag(To->getLocation(),
                        diag::note_odr_objc_missing_superclass);
      if (From->getSuperClass())
        Importer.FromDiag(From->getSuperClassLoc(),
                          diag::note_odr_objc_superclass)
        << From->getSuperClass()->getDeclName();
      else
        Importer.FromDiag(From->getLocation(),
                          diag::note_odr_objc_missing_superclass);
    }

    if (shouldForceImportDeclContext(Kind))
      if (Error Err = ImportDeclContext(From))
        return Err;
    return Error::success();
  }

  // Start the definition.
  To->startDefinition();

  // If this class has a superclass, import it.
  if (From->getSuperClass()) {
    if (auto SuperTInfoOrErr = import(From->getSuperClassTInfo()))
      To->setSuperClass(*SuperTInfoOrErr);
    else
      return SuperTInfoOrErr.takeError();
  }

  // Import protocols
  SmallVector<ObjCProtocolDecl *, 4> Protocols;
  SmallVector<SourceLocation, 4> ProtocolLocs;
  ObjCInterfaceDecl::protocol_loc_iterator FromProtoLoc =
      From->protocol_loc_begin();

  for (ObjCInterfaceDecl::protocol_iterator FromProto = From->protocol_begin(),
                                         FromProtoEnd = From->protocol_end();
       FromProto != FromProtoEnd;
       ++FromProto, ++FromProtoLoc) {
    if (Expected<ObjCProtocolDecl *> ToProtoOrErr = import(*FromProto))
      Protocols.push_back(*ToProtoOrErr);
    else
      return ToProtoOrErr.takeError();

    if (ExpectedSLoc ToProtoLocOrErr = import(*FromProtoLoc))
      ProtocolLocs.push_back(*ToProtoLocOrErr);
    else
      return ToProtoLocOrErr.takeError();

  }

  // FIXME: If we're merging, make sure that the protocol list is the same.
  To->setProtocolList(Protocols.data(), Protocols.size(),
                      ProtocolLocs.data(), Importer.getToContext());

  // Import categories. When the categories themselves are imported, they'll
  // hook themselves into this interface.
  for (auto *Cat : From->known_categories()) {
    auto ToCatOrErr = import(Cat);
    if (!ToCatOrErr)
      return ToCatOrErr.takeError();
  }

  // If we have an @implementation, import it as well.
  if (From->getImplementation()) {
    if (Expected<ObjCImplementationDecl *> ToImplOrErr =
        import(From->getImplementation()))
      To->setImplementation(*ToImplOrErr);
    else
      return ToImplOrErr.takeError();
  }

  // Import all of the members of this class.
  if (Error Err = ImportDeclContext(From, /*ForceImport=*/true))
    return Err;

  return Error::success();
}

Expected<ObjCTypeParamList *>
ASTNodeImporter::ImportObjCTypeParamList(ObjCTypeParamList *list) {
  if (!list)
    return nullptr;

  SmallVector<ObjCTypeParamDecl *, 4> toTypeParams;
  for (auto *fromTypeParam : *list) {
    if (auto toTypeParamOrErr = import(fromTypeParam))
      toTypeParams.push_back(*toTypeParamOrErr);
    else
      return toTypeParamOrErr.takeError();
  }

  auto LAngleLocOrErr = import(list->getLAngleLoc());
  if (!LAngleLocOrErr)
    return LAngleLocOrErr.takeError();

  auto RAngleLocOrErr = import(list->getRAngleLoc());
  if (!RAngleLocOrErr)
    return RAngleLocOrErr.takeError();

  return ObjCTypeParamList::create(Importer.getToContext(),
                                   *LAngleLocOrErr,
                                   toTypeParams,
                                   *RAngleLocOrErr);
}

ExpectedDecl ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
  // If this class has a definition in the translation unit we're coming from,
  // but this particular declaration is not that definition, import the
  // definition and map to that.
  ObjCInterfaceDecl *Definition = D->getDefinition();
  if (Definition && Definition != D) {
    if (ExpectedDecl ImportedDefOrErr = import(Definition))
      return Importer.MapImported(D, *ImportedDefOrErr);
    else
      return ImportedDefOrErr.takeError();
  }

  // Import the major distinguishing characteristics of an @interface.
  DeclContext *DC, *LexicalDC;
  DeclarationName Name;
  SourceLocation Loc;
  NamedDecl *ToD;
  if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
    return std::move(Err);
  if (ToD)
    return ToD;

  // Look for an existing interface with the same name.
  ObjCInterfaceDecl *MergeWithIface = nullptr;
  auto FoundDecls = Importer.findDeclsInToCtx(DC, Name);
  for (auto *FoundDecl : FoundDecls) {
    if (!FoundDecl->isInIdentifierNamespace(Decl::IDNS_Ordinary))
      continue;

    if ((MergeWithIface = dyn_cast<ObjCInterfaceDecl>(FoundDecl)))
      break;
  }

  // Create an interface declaration, if one does not already exist.
  ObjCInterfaceDecl *ToIface = MergeWithIface;
  if (!ToIface) {
    ExpectedSLoc AtBeginLocOrErr = import(D->getAtStartLoc());
    if (!AtBeginLocOrErr)
      return AtBeginLocOrErr.takeError();

    if (GetImportedOrCreateDecl(
            ToIface, D, Importer.getToContext(), DC,
            *AtBeginLocOrErr, Name.getAsIdentifierInfo(),
            /*TypeParamList=*/nullptr,
            /*PrevDecl=*/nullptr, Loc, D->isImplicitInterfaceDecl()))
      return ToIface;
    ToIface->setLexicalDeclContext(LexicalDC);
    LexicalDC->addDeclInternal(ToIface);
  }
  Importer.MapImported(D, ToIface);
  // Import the type parameter list after MapImported, to avoid
  // loops when bringing in their DeclContext.
  if (auto ToPListOrErr =
      ImportObjCTypeParamList(D->getTypeParamListAsWritten()))
    ToIface->setTypeParamList(*ToPListOrErr);
  else
    return ToPListOrErr.takeError();

  if (D->isThisDeclarationADefinition())
    if (Error Err = ImportDefinition(D, ToIface))
      return std::move(Err);

  return ToIface;
}

ExpectedDecl
ASTNodeImporter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) {
  ObjCCategoryDecl *Category;
  if (Error Err = importInto(Category, D->getCategoryDecl()))
    return std::move(Err);

  ObjCCategoryImplDecl *ToImpl = Category->getImplementation();
  if (!ToImpl) {
    DeclContext *DC, *LexicalDC;
    if (Error Err = ImportDeclContext(D, DC, LexicalDC))
      return std::move(Err);

    Error Err = Error::success();
    auto ToLocation = importChecked(Err, D->getLocation());
    auto ToAtStartLoc = importChecked(Err, D->getAtStartLoc());
    auto ToCategoryNameLoc = importChecked(Err, D->getCategoryNameLoc());
    if (Err)
      return std::move(Err);

    if (GetImportedOrCreateDecl(
            ToImpl, D, Importer.getToContext(), DC,
            Importer.Import(D->getIdentifier()), Category->getClassInterface(),
            ToLocation, ToAtStartLoc, ToCategoryNameLoc))
      return ToImpl;

    ToImpl->setLexicalDeclContext(LexicalDC);
    LexicalDC->addDeclInternal(ToImpl);
    Category->setImplementation(ToImpl);
  }

  Importer.MapImported(D, ToImpl);
  if (Error Err = ImportDeclContext(D))
    return std::move(Err);

  return ToImpl;
}

ExpectedDecl
ASTNodeImporter::VisitObjCImplementationDecl(ObjCImplementationDecl *D) {
  // Find the corresponding interface.
  ObjCInterfaceDecl *Iface;
  if (Error Err = importInto(Iface, D->getClassInterface()))
    return std::move(Err);

  // Import the superclass, if any.
  ObjCInterfaceDecl *Super;
  if (Error Err = importInto(Super, D->getSuperClass()))
    return std::move(Err);

  ObjCImplementationDecl *Impl = Iface->getImplementation();
  if (!Impl) {
    // We haven't imported an implementation yet. Create a new @implementation
    // now.
    DeclContext *DC, *LexicalDC;
    if (Error Err = ImportDeclContext(D, DC, LexicalDC))
      return std::move(Err);

    Error Err = Error::success();
    auto ToLocation = importChecked(Err, D->getLocation());
    auto ToAtStartLoc = importChecked(Err, D->getAtStartLoc());
    auto ToSuperClassLoc = importChecked(Err, D->getSuperClassLoc());
    auto ToIvarLBraceLoc = importChecked(Err, D->getIvarLBraceLoc());
    auto ToIvarRBraceLoc = importChecked(Err, D->getIvarRBraceLoc());
    if (Err)
      return std::move(Err);

    if (GetImportedOrCreateDecl(Impl, D, Importer.getToContext(),
                                DC, Iface, Super,
                                ToLocation,
                                ToAtStartLoc,
                                ToSuperClassLoc,
                                ToIvarLBraceLoc,
                                ToIvarRBraceLoc))
      return Impl;

    Impl->setLexicalDeclContext(LexicalDC);

    // Associate the implementation with the class it implements.
    Iface->setImplementation(Impl);
    Importer.MapImported(D, Iface->getImplementation());
  } else {
    Importer.MapImported(D, Iface->getImplementation());

    // Verify that the existing @implementation has the same superclass.
    if ((Super && !Impl->getSuperClass()) ||
        (!Super && Impl->getSuperClass()) ||
        (Super && Impl->getSuperClass() &&
         !declaresSameEntity(Super->getCanonicalDecl(),
                             Impl->getSuperClass()))) {
      Importer.ToDiag(Impl->getLocation(),
                      diag::warn_odr_objc_superclass_inconsistent)
        << Iface->getDeclName();
      // FIXME: It would be nice to have the location of the superclass
      // below.
      if (Impl->getSuperClass())
        Importer.ToDiag(Impl->getLocation(),
                        diag::note_odr_objc_superclass)
        << Impl->getSuperClass()->getDeclName();
      else
        Importer.ToDiag(Impl->getLocation(),
                        diag::note_odr_objc_missing_superclass);
      if (D->getSuperClass())
        Importer.FromDiag(D->getLocation(),
                          diag::note_odr_objc_superclass)
        << D->getSuperClass()->getDeclName();
      else
        Importer.FromDiag(D->getLocation(),
                          diag::note_odr_objc_missing_superclass);

      return make_error<ASTImportError>(ASTImportError::NameConflict);
    }
  }

  // Import all of the members of this @implementation.
  if (Error Err = ImportDeclContext(D))
    return std::move(Err);

  return Impl;
}

ExpectedDecl ASTNodeImporter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
  // Import the major distinguishing characteristics of an @property.
  DeclContext *DC, *LexicalDC;
  DeclarationName Name;
  SourceLocation Loc;
  NamedDecl *ToD;
  if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
    return std::move(Err);
  if (ToD)
    return ToD;

  // Check whether we have already imported this property.
  auto FoundDecls = Importer.findDeclsInToCtx(DC, Name);
  for (auto *FoundDecl : FoundDecls) {
    if (auto *FoundProp = dyn_cast<ObjCPropertyDecl>(FoundDecl)) {
      // Instance and class properties can share the same name but are different
      // declarations.
      if (FoundProp->isInstanceProperty() != D->isInstanceProperty())
        continue;

      // Check property types.
      if (!Importer.IsStructurallyEquivalent(D->getType(),
                                             FoundProp->getType())) {
        Importer.ToDiag(Loc, diag::warn_odr_objc_property_type_inconsistent)
          << Name << D->getType() << FoundProp->getType();
        Importer.ToDiag(FoundProp->getLocation(), diag::note_odr_value_here)
          << FoundProp->getType();

        return make_error<ASTImportError>(ASTImportError::NameConflict);
      }

      // FIXME: Check property attributes, getters, setters, etc.?

      // Consider these properties to be equivalent.
      Importer.MapImported(D, FoundProp);
      return FoundProp;
    }
  }

  Error Err = Error::success();
  auto ToType = importChecked(Err, D->getType());
  auto ToTypeSourceInfo = importChecked(Err, D->getTypeSourceInfo());
  auto ToAtLoc = importChecked(Err, D->getAtLoc());
  auto ToLParenLoc = importChecked(Err, D->getLParenLoc());
  if (Err)
    return std::move(Err);

  // Create the new property.
  ObjCPropertyDecl *ToProperty;
  if (GetImportedOrCreateDecl(
          ToProperty, D, Importer.getToContext(), DC, Loc,
          Name.getAsIdentifierInfo(), ToAtLoc,
          ToLParenLoc, ToType,
          ToTypeSourceInfo, D->getPropertyImplementation()))
    return ToProperty;

  auto ToGetterName = importChecked(Err, D->getGetterName());
  auto ToSetterName = importChecked(Err, D->getSetterName());
  auto ToGetterNameLoc = importChecked(Err, D->getGetterNameLoc());
  auto ToSetterNameLoc = importChecked(Err, D->getSetterNameLoc());
  auto ToGetterMethodDecl = importChecked(Err, D->getGetterMethodDecl());
  auto ToSetterMethodDecl = importChecked(Err, D->getSetterMethodDecl());
  auto ToPropertyIvarDecl = importChecked(Err, D->getPropertyIvarDecl());
  if (Err)
    return std::move(Err);

  ToProperty->setLexicalDeclContext(LexicalDC);
  LexicalDC->addDeclInternal(ToProperty);

  ToProperty->setPropertyAttributes(D->getPropertyAttributes());
  ToProperty->setPropertyAttributesAsWritten(
                                      D->getPropertyAttributesAsWritten());
  ToProperty->setGetterName(ToGetterName, ToGetterNameLoc);
  ToProperty->setSetterName(ToSetterName, ToSetterNameLoc);
  ToProperty->setGetterMethodDecl(ToGetterMethodDecl);
  ToProperty->setSetterMethodDecl(ToSetterMethodDecl);
  ToProperty->setPropertyIvarDecl(ToPropertyIvarDecl);
  return ToProperty;
}

ExpectedDecl
ASTNodeImporter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) {
  ObjCPropertyDecl *Property;
  if (Error Err = importInto(Property, D->getPropertyDecl()))
    return std::move(Err);

  DeclContext *DC, *LexicalDC;
  if (Error Err = ImportDeclContext(D, DC, LexicalDC))
    return std::move(Err);

  auto *InImpl = cast<ObjCImplDecl>(LexicalDC);

  // Import the ivar (for an @synthesize).
  ObjCIvarDecl *Ivar = nullptr;
  if (Error Err = importInto(Ivar, D->getPropertyIvarDecl()))
    return std::move(Err);

  ObjCPropertyImplDecl *ToImpl
    = InImpl->FindPropertyImplDecl(Property->getIdentifier(),
                                   Property->getQueryKind());
  if (!ToImpl) {

    Error Err = Error::success();
    auto ToBeginLoc = importChecked(Err, D->getBeginLoc());
    auto ToLocation = importChecked(Err, D->getLocation());
    auto ToPropertyIvarDeclLoc =
        importChecked(Err, D->getPropertyIvarDeclLoc());
    if (Err)
      return std::move(Err);

    if (GetImportedOrCreateDecl(ToImpl, D, Importer.getToContext(), DC,
                                ToBeginLoc,
                                ToLocation, Property,
                                D->getPropertyImplementation(), Ivar,
                                ToPropertyIvarDeclLoc))
      return ToImpl;

    ToImpl->setLexicalDeclContext(LexicalDC);
    LexicalDC->addDeclInternal(ToImpl);
  } else {
    // Check that we have the same kind of property implementation (@synthesize
    // vs. @dynamic).
    if (D->getPropertyImplementation() != ToImpl->getPropertyImplementation()) {
      Importer.ToDiag(ToImpl->getLocation(),
                      diag::warn_odr_objc_property_impl_kind_inconsistent)
        << Property->getDeclName()
        << (ToImpl->getPropertyImplementation()
                                              == ObjCPropertyImplDecl::Dynamic);
      Importer.FromDiag(D->getLocation(),
                        diag::note_odr_objc_property_impl_kind)
        << D->getPropertyDecl()->getDeclName()
        << (D->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic);

      return make_error<ASTImportError>(ASTImportError::NameConflict);
    }

    // For @synthesize, check that we have the same
    if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize &&
        Ivar != ToImpl->getPropertyIvarDecl()) {
      Importer.ToDiag(ToImpl->getPropertyIvarDeclLoc(),
                      diag::warn_odr_objc_synthesize_ivar_inconsistent)
        << Property->getDeclName()
        << ToImpl->getPropertyIvarDecl()->getDeclName()
        << Ivar->getDeclName();
      Importer.FromDiag(D->getPropertyIvarDeclLoc(),
                        diag::note_odr_objc_synthesize_ivar_here)
        << D->getPropertyIvarDecl()->getDeclName();

      return make_error<ASTImportError>(ASTImportError::NameConflict);
    }

    // Merge the existing implementation with the new implementation.
    Importer.MapImported(D, ToImpl);
  }

  return ToImpl;
}

ExpectedDecl
ASTNodeImporter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
  // For template arguments, we adopt the translation unit as our declaration
  // context. This context will be fixed when (during) the actual template
  // declaration is created.

  ExpectedSLoc BeginLocOrErr = import(D->getBeginLoc());
  if (!BeginLocOrErr)
    return BeginLocOrErr.takeError();

  ExpectedSLoc LocationOrErr = import(D->getLocation());
  if (!LocationOrErr)
    return LocationOrErr.takeError();

  TemplateTypeParmDecl *ToD = nullptr;
  if (GetImportedOrCreateDecl(
      ToD, D, Importer.getToContext(),
      Importer.getToContext().getTranslationUnitDecl(),
      *BeginLocOrErr, *LocationOrErr,
      D->getDepth(), D->getIndex(), Importer.Import(D->getIdentifier()),
      D->wasDeclaredWithTypename(), D->isParameterPack(),
      D->hasTypeConstraint()))
    return ToD;

  // Import the type-constraint
  if (const TypeConstraint *TC = D->getTypeConstraint()) {

    Error Err = Error::success();
    auto ToConceptRef = importChecked(Err, TC->getConceptReference());
    auto ToIDC = importChecked(Err, TC->getImmediatelyDeclaredConstraint());
    if (Err)
      return std::move(Err);

    ToD->setTypeConstraint(ToConceptRef, ToIDC, TC->getArgPackSubstIndex());
  }

  if (Error Err = importTemplateParameterDefaultArgument(D, ToD))
    return Err;

  return ToD;
}

ExpectedDecl
ASTNodeImporter::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {

  Error Err = Error::success();
  auto ToDeclName = importChecked(Err, D->getDeclName());
  auto ToLocation = importChecked(Err, D->getLocation());
  auto ToType = importChecked(Err, D->getType());
  auto ToTypeSourceInfo = importChecked(Err, D->getTypeSourceInfo());
  auto ToInnerLocStart = importChecked(Err, D->getInnerLocStart());
  if (Err)
    return std::move(Err);

  NonTypeTemplateParmDecl *ToD = nullptr;
  if (GetImportedOrCreateDecl(ToD, D, Importer.getToContext(),
                              Importer.getToContext().getTranslationUnitDecl(),
                              ToInnerLocStart, ToLocation, D->getDepth(),
                              D->getPosition(),
                              ToDeclName.getAsIdentifierInfo(), ToType,
                              D->isParameterPack(), ToTypeSourceInfo))
    return ToD;

  Err = importTemplateParameterDefaultArgument(D, ToD);
  if (Err)
    return Err;

  return ToD;
}

ExpectedDecl
ASTNodeImporter::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
  bool IsCanonical = false;
  if (auto *CanonD = Importer.getFromContext()
                         .findCanonicalTemplateTemplateParmDeclInternal(D);
      CanonD == D)
    IsCanonical = true;

  // Import the name of this declaration.
  auto NameOrErr = import(D->getDeclName());
  if (!NameOrErr)
    return NameOrErr.takeError();

  // Import the location of this declaration.
  ExpectedSLoc LocationOrErr = import(D->getLocation());
  if (!LocationOrErr)
    return LocationOrErr.takeError();

  // Import template parameters.
  auto TemplateParamsOrErr = import(D->getTemplateParameters());
  if (!TemplateParamsOrErr)
    return TemplateParamsOrErr.takeError();

  TemplateTemplateParmDecl *ToD = nullptr;
  if (GetImportedOrCreateDecl(
          ToD, D, Importer.getToContext(),
          Importer.getToContext().getTranslationUnitDecl(), *LocationOrErr,
          D->getDepth(), D->getPosition(), D->isParameterPack(),
          (*NameOrErr).getAsIdentifierInfo(), D->wasDeclaredWithTypename(),
          *TemplateParamsOrErr))
    return ToD;

  if (Error Err = importTemplateParameterDefaultArgument(D, ToD))
    return Err;

  if (IsCanonical)
    return Importer.getToContext()
        .insertCanonicalTemplateTemplateParmDeclInternal(ToD);

  return ToD;
}

// Returns the definition for a (forward) declaration of a TemplateDecl, if
// it has any definition in the redecl chain.
template <typename T> static auto getTemplateDefinition(T *D) -> T * {
  assert(D->getTemplatedDecl() && "Should be called on templates only");
  auto *ToTemplatedDef = D->getTemplatedDecl()->getDefinition();
  if (!ToTemplatedDef)
    return nullptr;
  auto *TemplateWithDef = ToTemplatedDef->getDescribedTemplate();
  return cast_or_null<T>(TemplateWithDef);
}

ExpectedDecl ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) {

  // Import the major distinguishing characteristics of this class template.
  DeclContext *DC, *LexicalDC;
  DeclarationName Name;
  SourceLocation Loc;
  NamedDecl *ToD;
  if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
    return std::move(Err);
  if (ToD)
    return ToD;

  // Should check if a declaration is friend in a dependent context.
  // Such templates are not linked together in a declaration chain.
  // The ASTImporter strategy is to map existing forward declarations to
  // imported ones only if strictly necessary, otherwise import these as new
  // forward declarations. In case of the "dependent friend" declarations, new
  // declarations are created, but not linked in a declaration chain.
  auto IsDependentFriend = [](ClassTemplateDecl *TD) {
    return TD->getFriendObjectKind() != Decl::FOK_None &&
           TD->getLexicalDeclContext()->isDependentContext();
  };
  bool DependentFriend = IsDependentFriend(D);

  ClassTemplateDecl *FoundByLookup = nullptr;

  // We may already have a template of the same name; try to find and match it.
  if (!DC->isFunctionOrMethod()) {
    SmallVector<NamedDecl *, 4> ConflictingDecls;
    auto FoundDecls = Importer.findDeclsInToCtx(DC, Name);
    for (auto *FoundDecl : FoundDecls) {
      if (!FoundDecl->isInIdentifierNamespace(Decl::IDNS_Ordinary |
                                              Decl::IDNS_TagFriend))
        continue;

      auto *FoundTemplate = dyn_cast<ClassTemplateDecl>(FoundDecl);
      if (FoundTemplate) {
        if (!hasSameVisibilityContextAndLinkage(FoundTemplate, D))
          continue;

        // FIXME: sufficient condition for 'IgnoreTemplateParmDepth'?
        bool IgnoreTemplateParmDepth =
            (FoundTemplate->getFriendObjectKind() != Decl::FOK_None) !=
            (D->getFriendObjectKind() != Decl::FOK_None);
        if (IsStructuralMatch(D, FoundTemplate, /*Complain=*/true,
                              IgnoreTemplateParmDepth)) {
          if (DependentFriend || IsDependentFriend(FoundTemplate))
            continue;

          ClassTemplateDecl *TemplateWithDef =
              getTemplateDefinition(FoundTemplate);
          if (D->isThisDeclarationADefinition() && TemplateWithDef)
            return Importer.MapImported(D, TemplateWithDef);
          if (!FoundByLookup)
            FoundByLookup = FoundTemplate;
          // Search in all matches because there may be multiple decl chains,
          // see ASTTests test ImportExistingFriendClassTemplateDef.
          continue;
        }
        // When importing a friend, it is possible that multiple declarations
        // with same name can co-exist in specific cases (if a template contains
        // a friend template and has a specialization). For this case the
        // declarations should match, except that the "template depth" is
        // different. No linking of previous declaration is needed in this case.
        // FIXME: This condition may need refinement.
        if (D->getFriendObjectKind() != Decl::FOK_None &&
            FoundTemplate->getFriendObjectKind() != Decl::FOK_None &&
            D->getFriendObjectKind() != FoundTemplate->getFriendObjectKind() &&
            IsStructuralMatch(D, FoundTemplate, /*Complain=*/false,
                              /*IgnoreTemplateParmDepth=*/true))
          continue;

        ConflictingDecls.push_back(FoundDecl);
      }
    }

    if (!ConflictingDecls.empty()) {
      ExpectedName NameOrErr = Importer.HandleNameConflict(
          Name, DC, Decl::IDNS_Ordinary, ConflictingDecls.data(),
          ConflictingDecls.size());
      if (NameOrErr)
        Name = NameOrErr.get();
      else
        return NameOrErr.takeError();
    }
  }

  CXXRecordDecl *FromTemplated = D->getTemplatedDecl();

  auto TemplateParamsOrErr = import(D->getTemplateParameters());
  if (!TemplateParamsOrErr)
    return TemplateParamsOrErr.takeError();

  // Create the declaration that is being templated.
  CXXRecordDecl *ToTemplated;
  if (Error Err = importInto(ToTemplated, FromTemplated))
    return std::move(Err);

  // Create the class template declaration itself.
  ClassTemplateDecl *D2;
  if (GetImportedOrCreateDecl(D2, D, Importer.getToContext(), DC, Loc, Name,
                              *TemplateParamsOrErr, ToTemplated))
    return D2;

  ToTemplated->setDescribedClassTemplate(D2);

  D2->setAccess(D->getAccess());
  D2->setLexicalDeclContext(LexicalDC);

  addDeclToContexts(D, D2);
  updateLookupTableForTemplateParameters(**TemplateParamsOrErr);

  if (FoundByLookup) {
    auto *Recent =
        const_cast<ClassTemplateDecl *>(FoundByLookup->getMostRecentDecl());

    // It is possible that during the import of the class template definition
    // we start the import of a fwd friend decl of the very same class template
    // and we add the fwd friend decl to the lookup table. But the ToTemplated
    // had been created earlier and by that time the lookup could not find
    // anything existing, so it has no previous decl. Later, (still during the
    // import of the fwd friend decl) we start to import the definition again
    // and this time the lookup finds the previous fwd friend class template.
    // In this case we must set up the previous decl for the templated decl.
    if (!ToTemplated->getPreviousDecl()) {
      assert(FoundByLookup->getTemplatedDecl() &&
             "Found decl must have its templated decl set");
      CXXRecordDecl *PrevTemplated =
          FoundByLookup->getTemplatedDecl()->getMostRecentDecl();
      if (ToTemplated != PrevTemplated)
        ToTemplated->setPreviousDecl(PrevTemplated);
    }

    D2->setPreviousDecl(Recent);
  }

  return D2;
}

ExpectedDecl ASTNodeImporter::VisitClassTemplateSpecializationDecl(
                                          ClassTemplateSpecializationDecl *D) {
  ClassTemplateDecl *ClassTemplate;
  if (Error Err = importInto(ClassTemplate, D->getSpecializedTemplate()))
    return std::move(Err);

  // Import the context of this declaration.
  DeclContext *DC, *LexicalDC;
  if (Error Err = ImportDeclContext(D, DC, LexicalDC))
    return std::move(Err);

  // Import template arguments.
  SmallVector<TemplateArgument, 2> TemplateArgs;
  if (Error Err =
          ImportTemplateArguments(D->getTemplateArgs().asArray(), TemplateArgs))
    return std::move(Err);
  // Try to find an existing specialization with these template arguments and
  // template parameter list.
  void *InsertPos = nullptr;
  ClassTemplateSpecializationDecl *PrevDecl = nullptr;
  ClassTemplatePartialSpecializationDecl *PartialSpec =
            dyn_cast<ClassTemplatePartialSpecializationDecl>(D);

  // Import template parameters.
  TemplateParameterList *ToTPList = nullptr;

  if (PartialSpec) {
    auto ToTPListOrErr = import(PartialSpec->getTemplateParameters());
    if (!ToTPListOrErr)
      return ToTPListOrErr.takeError();
    ToTPList = *ToTPListOrErr;
    PrevDecl = ClassTemplate->findPartialSpecialization(TemplateArgs,
                                                        *ToTPListOrErr,
                                                        InsertPos);
  } else
    PrevDecl = ClassTemplate->findSpecialization(TemplateArgs, InsertPos);

  if (PrevDecl) {
    if (IsStructuralMatch(D, PrevDecl)) {
      CXXRecordDecl *PrevDefinition = PrevDecl->getDefinition();
      if (D->isThisDeclarationADefinition() && PrevDefinition) {
        Importer.MapImported(D, PrevDefinition);
        // Import those default field initializers which have been
        // instantiated in the "From" context, but not in the "To" context.
        for (auto *FromField : D->fields()) {
          auto ToOrErr = import(FromField);
          if (!ToOrErr)
            return ToOrErr.takeError();
        }

        // Import those methods which have been instantiated in the
        // "From" context, but not in the "To" context.
        for (CXXMethodDecl *FromM : D->methods()) {
          auto ToOrErr = import(FromM);
          if (!ToOrErr)
            return ToOrErr.takeError();
        }

        // TODO Import instantiated default arguments.
        // TODO Import instantiated exception specifications.
        //
        // Generally, ASTCommon.h/DeclUpdateKind enum gives a very good hint
        // what else could be fused during an AST merge.
        return PrevDefinition;
      }
    } else { // ODR violation.
      // FIXME HandleNameConflict
      return make_error<ASTImportError>(ASTImportError::NameConflict);
    }
  }

  // Import the location of this declaration.
  ExpectedSLoc BeginLocOrErr = import(D->getBeginLoc());
  if (!BeginLocOrErr)
    return BeginLocOrErr.takeError();
  ExpectedSLoc IdLocOrErr = import(D->getLocation());
  if (!IdLocOrErr)
    return IdLocOrErr.takeError();

  // Import TemplateArgumentListInfo.
  TemplateArgumentListInfo ToTAInfo;
  if (const auto *ASTTemplateArgs = D->getTemplateArgsAsWritten()) {
    if (Error Err = ImportTemplateArgumentListInfo(*ASTTemplateArgs, ToTAInfo))
      return std::move(Err);
  }

  // Create the specialization.
  ClassTemplateSpecializationDecl *D2 = nullptr;
  if (PartialSpec) {
    QualType CanonInjType;
    if (Error Err = importInto(
        CanonInjType, PartialSpec->getInjectedSpecializationType()))
      return std::move(Err);
    CanonInjType = CanonInjType.getCanonicalType();

    if (GetImportedOrCreateDecl<ClassTemplatePartialSpecializationDecl>(
            D2, D, Importer.getToContext(), D->getTagKind(), DC, *BeginLocOrErr,
            *IdLocOrErr, ToTPList, ClassTemplate, ArrayRef(TemplateArgs),
            CanonInjType,
            cast_or_null<ClassTemplatePartialSpecializationDecl>(PrevDecl)))
      return D2;

    // Update InsertPos, because preceding import calls may have invalidated
    // it by adding new specializations.
    auto *PartSpec2 = cast<ClassTemplatePartialSpecializationDecl>(D2);
    if (!ClassTemplate->findPartialSpecialization(TemplateArgs, ToTPList,
                                                  InsertPos))
      // Add this partial specialization to the class template.
      ClassTemplate->AddPartialSpecialization(PartSpec2, InsertPos);
    if (Expected<ClassTemplatePartialSpecializationDecl *> ToInstOrErr =
            import(PartialSpec->getInstantiatedFromMember()))
      PartSpec2->setInstantiatedFromMember(*ToInstOrErr);
    else
      return ToInstOrErr.takeError();

    updateLookupTableForTemplateParameters(*ToTPList);
  } else { // Not a partial specialization.
    if (GetImportedOrCreateDecl(D2, D, Importer.getToContext(), D->getTagKind(),
                                DC, *BeginLocOrErr, *IdLocOrErr, ClassTemplate,
                                TemplateArgs, D->hasStrictPackMatch(),
                                PrevDecl))
      return D2;

    // Update InsertPos, because preceding import calls may have invalidated
    // it by adding new specializations.
    if (!ClassTemplate->findSpecialization(TemplateArgs, InsertPos))
      // Add this specialization to the class template.
      ClassTemplate->AddSpecialization(D2, InsertPos);
  }

  D2->setSpecializationKind(D->getSpecializationKind());

  // Set the context of this specialization/instantiation.
  D2->setLexicalDeclContext(LexicalDC);

  // Add to the DC only if it was an explicit specialization/instantiation.
  if (D2->isExplicitInstantiationOrSpecialization()) {
    LexicalDC->addDeclInternal(D2);
  }

  if (auto BraceRangeOrErr = import(D->getBraceRange()))
    D2->setBraceRange(*BraceRangeOrErr);
  else
    return BraceRangeOrErr.takeError();

  if (Error Err = ImportTemplateParameterLists(D, D2))
    return std::move(Err);

  // Import the qualifier, if any.
  if (auto LocOrErr = import(D->getQualifierLoc()))
    D2->setQualifierInfo(*LocOrErr);
  else
    return LocOrErr.takeError();

  if (D->getTemplateArgsAsWritten())
    D2->setTemplateArgsAsWritten(ToTAInfo);

  if (auto LocOrErr = import(D->getTemplateKeywordLoc()))
    D2->setTemplateKeywordLoc(*LocOrErr);
  else
    return LocOrErr.takeError();

  if (auto LocOrErr = import(D->getExternKeywordLoc()))
    D2->setExternKeywordLoc(*LocOrErr);
  else
    return LocOrErr.takeError();

  if (D->getPointOfInstantiation().isValid()) {
    if (auto POIOrErr = import(D->getPointOfInstantiation()))
      D2->setPointOfInstantiation(*POIOrErr);
    else
      return POIOrErr.takeError();
  }

  D2->setTemplateSpecializationKind(D->getTemplateSpecializationKind());

  if (auto P = D->getInstantiatedFrom()) {
    if (auto *CTD = dyn_cast<ClassTemplateDecl *>(P)) {
      if (auto CTDorErr = import(CTD))
        D2->setInstantiationOf(*CTDorErr);
    } else {
      auto *CTPSD = cast<ClassTemplatePartialSpecializationDecl *>(P);
      auto CTPSDOrErr = import(CTPSD);
      if (!CTPSDOrErr)
        return CTPSDOrErr.takeError();
      const TemplateArgumentList &DArgs = D->getTemplateInstantiationArgs();
      SmallVector<TemplateArgument, 2> D2ArgsVec(DArgs.size());
      for (unsigned I = 0; I < DArgs.size(); ++I) {
        const TemplateArgument &DArg = DArgs[I];
        if (auto ArgOrErr = import(DArg))
          D2ArgsVec[I] = *ArgOrErr;
        else
          return ArgOrErr.takeError();
      }
      D2->setInstantiationOf(
          *CTPSDOrErr,
          TemplateArgumentList::CreateCopy(Importer.getToContext(), D2ArgsVec));
    }
  }

  if (D->isCompleteDefinition())
    if (Error Err = ImportDefinition(D, D2))
      return std::move(Err);

  return D2;
}

ExpectedDecl ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) {
  // Import the major distinguishing characteristics of this variable template.
  DeclContext *DC, *LexicalDC;
  DeclarationName Name;
  SourceLocation Loc;
  NamedDecl *ToD;
  if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
    return std::move(Err);
  if (ToD)
    return ToD;

  // We may already have a template of the same name; try to find and match it.
  assert(!DC->isFunctionOrMethod() &&
         "Variable templates cannot be declared at function scope");

  SmallVector<NamedDecl *, 4> ConflictingDecls;
  auto FoundDecls = Importer.findDeclsInToCtx(DC, Name);
  VarTemplateDecl *FoundByLookup = nullptr;
  for (auto *FoundDecl : FoundDecls) {
    if (!FoundDecl->isInIdentifierNamespace(Decl::IDNS_Ordinary))
      continue;

    if (VarTemplateDecl *FoundTemplate = dyn_cast<VarTemplateDecl>(FoundDecl)) {
      // Use the templated decl, some linkage flags are set only there.
      if (!hasSameVisibilityContextAndLinkage(FoundTemplate->getTemplatedDecl(),
                                              D->getTemplatedDecl()))
        continue;
      if (IsStructuralMatch(D, FoundTemplate)) {
        // FIXME Check for ODR error if the two definitions have
        // different initializers?
        VarTemplateDecl *FoundDef = getTemplateDefinition(FoundTemplate);
        if (D->getDeclContext()->isRecord()) {
          assert(FoundTemplate->getDeclContext()->isRecord() &&
                 "Member variable template imported as non-member, "
                 "inconsistent imported AST?");
          if (FoundDef)
            return Importer.MapImported(D, FoundDef);
          if (!D->isThisDeclarationADefinition())
            return Importer.MapImported(D, FoundTemplate);
        } else {
          if (FoundDef && D->isThisDeclarationADefinition())
            return Importer.MapImported(D, FoundDef);
        }
        FoundByLookup = FoundTemplate;
        break;
      }
      ConflictingDecls.push_back(FoundDecl);
    }
  }

  if (!ConflictingDecls.empty()) {
    ExpectedName NameOrErr = Importer.HandleNameConflict(
        Name, DC, Decl::IDNS_Ordinary, ConflictingDecls.data(),
        ConflictingDecls.size());
    if (NameOrErr)
      Name = NameOrErr.get();
    else
      return NameOrErr.takeError();
  }

  VarDecl *DTemplated = D->getTemplatedDecl();

  // Import the type.
  // FIXME: Value not used?
  ExpectedType TypeOrErr = import(DTemplated->getType());
  if (!TypeOrErr)
    return TypeOrErr.takeError();

  // Create the declaration that is being templated.
  VarDecl *ToTemplated;
  if (Error Err = importInto(ToTemplated, DTemplated))
    return std::move(Err);

  // Create the variable template declaration itself.
  auto TemplateParamsOrErr = import(D->getTemplateParameters());
  if (!TemplateParamsOrErr)
    return TemplateParamsOrErr.takeError();

  VarTemplateDecl *ToVarTD;
  if (GetImportedOrCreateDecl(ToVarTD, D, Importer.getToContext(), DC, Loc,
                              Name, *TemplateParamsOrErr, ToTemplated))
    return ToVarTD;

  ToTemplated->setDescribedVarTemplate(ToVarTD);

  ToVarTD->setAccess(D->getAccess());
  ToVarTD->setLexicalDeclContext(LexicalDC);
  LexicalDC->addDeclInternal(ToVarTD);
  if (DC != Importer.getToContext().getTranslationUnitDecl())
    updateLookupTableForTemplateParameters(**TemplateParamsOrErr);

  if (FoundByLookup) {
    auto *Recent =
        const_cast<VarTemplateDecl *>(FoundByLookup->getMostRecentDecl());
    if (!ToTemplated->getPreviousDecl()) {
      auto *PrevTemplated =
          FoundByLookup->getTemplatedDecl()->getMostRecentDecl();
      if (ToTemplated != PrevTemplated)
        ToTemplated->setPreviousDecl(PrevTemplated);
    }
    ToVarTD->setPreviousDecl(Recent);
  }

  return ToVarTD;
}

ExpectedDecl ASTNodeImporter::VisitVarTemplateSpecializationDecl(
    VarTemplateSpecializationDecl *D) {
  // A VarTemplateSpecializationDecl inherits from VarDecl, the import is done
  // in an analog way (but specialized for this case).

  SmallVector<Decl *, 2> Redecls = getCanonicalForwardRedeclChain(D);
  auto RedeclIt = Redecls.begin();
  // Import the first part of the decl chain. I.e. import all previous
  // declarations starting from the canonical decl.
  for (; RedeclIt != Redecls.end() && *RedeclIt != D; ++RedeclIt) {
    ExpectedDecl RedeclOrErr = import(*RedeclIt);
    if (!RedeclOrErr)
      return RedeclOrErr.takeError();
  }
  assert(*RedeclIt == D);

  VarTemplateDecl *VarTemplate = nullptr;
  if (Error Err = importInto(VarTemplate, D->getSpecializedTemplate()))
    return std::move(Err);

  // Import the context of this declaration.
  DeclContext *DC, *LexicalDC;
  if (Error Err = ImportDeclContext(D, DC, LexicalDC))
    return std::move(Err);

  // Import the location of this declaration.
  ExpectedSLoc BeginLocOrErr = import(D->getBeginLoc());
  if (!BeginLocOrErr)
    return BeginLocOrErr.takeError();

  auto IdLocOrErr = import(D->getLocation());
  if (!IdLocOrErr)
    return IdLocOrErr.takeError();

  // Import template arguments.
  SmallVector<TemplateArgument, 2> TemplateArgs;
  if (Error Err =
          ImportTemplateArguments(D->getTemplateArgs().asArray(), TemplateArgs))
    return std::move(Err);

  // Try to find an existing specialization with these template arguments.
  void *InsertPos = nullptr;
  VarTemplateSpecializationDecl *FoundSpecialization =
      VarTemplate->findSpecialization(TemplateArgs, InsertPos);
  if (FoundSpecialization) {
    if (IsStructuralMatch(D, FoundSpecialization)) {
      VarDecl *FoundDef = FoundSpecialization->getDefinition();
      if (D->getDeclContext()->isRecord()) {
        // In a record, it is allowed only to have one optional declaration and
        // one definition of the (static or constexpr) variable template.
        assert(
            FoundSpecialization->getDeclContext()->isRecord() &&
            "Member variable template specialization imported as non-member, "
            "inconsistent imported AST?");
        if (FoundDef)
          return Importer.MapImported(D, FoundDef);
        if (!D->isThisDeclarationADefinition())
          return Importer.MapImported(D, FoundSpecialization);
      } else {
        // If definition is imported and there is already one, map to it.
        // Otherwise create a new variable and link it to the existing.
        if (FoundDef && D->isThisDeclarationADefinition())
          return Importer.MapImported(D, FoundDef);
      }
    } else {
      return make_error<ASTImportError>(ASTImportError::NameConflict);
    }
  }

  VarTemplateSpecializationDecl *D2 = nullptr;

  TemplateArgumentListInfo ToTAInfo;
  if (const auto *Args = D->getTemplateArgsAsWritten()) {
    if (Error Err = ImportTemplateArgumentListInfo(*Args, ToTAInfo))
      return std::move(Err);
  }

  using PartVarSpecDecl = VarTemplatePartialSpecializationDecl;
  // Create a new specialization.
  if (auto *FromPartial = dyn_cast<PartVarSpecDecl>(D)) {
    auto ToTPListOrErr = import(FromPartial->getTemplateParameters());
    if (!ToTPListOrErr)
      return ToTPListOrErr.takeError();

    PartVarSpecDecl *ToPartial;
    if (GetImportedOrCreateDecl(ToPartial, D, Importer.getToContext(), DC,
                                *BeginLocOrErr, *IdLocOrErr, *ToTPListOrErr,
                                VarTemplate, QualType(), nullptr,
                                D->getStorageClass(), TemplateArgs))
      return ToPartial;

    if (Expected<PartVarSpecDecl *> ToInstOrErr =
            import(FromPartial->getInstantiatedFromMember()))
      ToPartial->setInstantiatedFromMember(*ToInstOrErr);
    else
      return ToInstOrErr.takeError();

    if (FromPartial->isMemberSpecialization())
      ToPartial->setMemberSpecialization();

    D2 = ToPartial;

    // FIXME: Use this update if VarTemplatePartialSpecializationDecl is fixed
    // to adopt template parameters.
    // updateLookupTableForTemplateParameters(**ToTPListOrErr);
  } else { // Full specialization
    if (GetImportedOrCreateDecl(D2, D, Importer.getToContext(), DC,
                                *BeginLocOrErr, *IdLocOrErr, VarTemplate,
                                QualType(), nullptr, D->getStorageClass(),
                                TemplateArgs))
      return D2;
  }

  // Update InsertPos, because preceding import calls may have invalidated
  // it by adding new specializations.
  if (!VarTemplate->findSpecialization(TemplateArgs, InsertPos))
    VarTemplate->AddSpecialization(D2, InsertPos);

  QualType T;
  if (Error Err = importInto(T, D->getType()))
    return std::move(Err);
  D2->setType(T);

  auto TInfoOrErr = import(D->getTypeSourceInfo());
  if (!TInfoOrErr)
    return TInfoOrErr.takeError();
  D2->setTypeSourceInfo(*TInfoOrErr);

  if (D->getPointOfInstantiation().isValid()) {
    if (ExpectedSLoc POIOrErr = import(D->getPointOfInstantiation()))
      D2->setPointOfInstantiation(*POIOrErr);
    else
      return POIOrErr.takeError();
  }

  D2->setSpecializationKind(D->getSpecializationKind());

  if (D->getTemplateArgsAsWritten())
    D2->setTemplateArgsAsWritten(ToTAInfo);

  if (auto LocOrErr = import(D->getQualifierLoc()))
    D2->setQualifierInfo(*LocOrErr);
  else
    return LocOrErr.takeError();

  if (D->isConstexpr())
    D2->setConstexpr(true);

  D2->setAccess(D->getAccess());

  if (Error Err = ImportInitializer(D, D2))
    return std::move(Err);

  if (FoundSpecialization)
    D2->setPreviousDecl(FoundSpecialization->getMostRecentDecl());

  addDeclToContexts(D, D2);

  // Import the rest of the chain. I.e. import all subsequent declarations.
  for (++RedeclIt; RedeclIt != Redecls.end(); ++RedeclIt) {
    ExpectedDecl RedeclOrErr = import(*RedeclIt);
    if (!RedeclOrErr)
      return RedeclOrErr.takeError();
  }

  return D2;
}

ExpectedDecl
ASTNodeImporter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
  DeclContext *DC, *LexicalDC;
  DeclarationName Name;
  SourceLocation Loc;
  NamedDecl *ToD;

  if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
    return std::move(Err);

  if (ToD)
    return ToD;

  const FunctionTemplateDecl *FoundByLookup = nullptr;

  // Try to find a function in our own ("to") context with the same name, same
  // type, and in the same context as the function we're importing.
  // FIXME Split this into a separate function.
  if (!LexicalDC->isFunctionOrMethod()) {
    unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_OrdinaryFriend;
    auto FoundDecls = Importer.findDeclsInToCtx(DC, Name);
    for (auto *FoundDecl : FoundDecls) {
      if (!FoundDecl->isInIdentifierNamespace(IDNS))
        continue;

      if (auto *FoundTemplate = dyn_cast<FunctionTemplateDecl>(FoundDecl)) {
        if (!hasSameVisibilityContextAndLinkage(FoundTemplate, D))
          continue;
        if (IsStructuralMatch(D, FoundTemplate)) {
          FunctionTemplateDecl *TemplateWithDef =
              getTemplateDefinition(FoundTemplate);
          if (D->isThisDeclarationADefinition() && TemplateWithDef)
            return Importer.MapImported(D, TemplateWithDef);

          FoundByLookup = FoundTemplate;
          break;
          // TODO: handle conflicting names
        }
      }
    }
  }

  auto ParamsOrErr = import(D->getTemplateParameters());
  if (!ParamsOrErr)
    return ParamsOrErr.takeError();
  TemplateParameterList *Params = *ParamsOrErr;

  FunctionDecl *TemplatedFD;
  if (Error Err = importInto(TemplatedFD, D->getTemplatedDecl()))
    return std::move(Err);

  // At creation of the template the template parameters are "adopted"
  // (DeclContext is changed). After this possible change the lookup table
  // must be updated.
  // At deduction guides the DeclContext of the template parameters may be
  // different from what we would expect, it may be the class template, or a
  // probably different CXXDeductionGuideDecl. This may come from the fact that
  // the template parameter objects may be shared between deduction guides or
  // the class template, and at creation of multiple FunctionTemplateDecl
  // objects (for deduction guides) the same parameters are re-used. The
  // "adoption" happens multiple times with different parent, even recursively
  // for TemplateTemplateParmDecl. The same happens at import when the
  // FunctionTemplateDecl objects are created, but in different order.
  // In this way the DeclContext of these template parameters is not necessarily
  // the same as in the "from" context.
  SmallVector<DeclContext *, 2> OldParamDC;
  OldParamDC.reserve(Params->size());
  llvm::transform(*Params, std::back_inserter(OldParamDC),
                  [](NamedDecl *ND) { return ND->getDeclContext(); });

  FunctionTemplateDecl *ToFunc;
  if (GetImportedOrCreateDecl(ToFunc, D, Importer.getToContext(), DC, Loc, Name,
                              Params, TemplatedFD))
    return ToFunc;

  // Fail if TemplatedFD is already part of a template.
  // The template should have been found by structural equivalence check before,
  // or ToFunc should be already imported.
  // If not, there is AST incompatibility that can be caused by previous import
  // errors. (NameConflict is not exact here.)
  if (TemplatedFD->getDescribedTemplate())
    return make_error<ASTImportError>(ASTImportError::NameConflict);

  TemplatedFD->setDescribedFunctionTemplate(ToFunc);

  ToFunc->setAccess(D->getAccess());
  ToFunc->setLexicalDeclContext(LexicalDC);
  addDeclToContexts(D, ToFunc);

  ASTImporterLookupTable *LT = Importer.SharedState->getLookupTable();
  if (LT && !OldParamDC.empty()) {
    for (unsigned int I = 0; I < OldParamDC.size(); ++I)
      LT->updateForced(Params->getParam(I), OldParamDC[I]);
  }

  if (FoundByLookup) {
    auto *Recent =
        const_cast<FunctionTemplateDecl *>(FoundByLookup->getMostRecentDecl());
    if (!TemplatedFD->getPreviousDecl()) {
      assert(FoundByLookup->getTemplatedDecl() &&
             "Found decl must have its templated decl set");
      auto *PrevTemplated =
          FoundByLookup->getTemplatedDecl()->getMostRecentDecl();
      if (TemplatedFD != PrevTemplated)
        TemplatedFD->setPreviousDecl(PrevTemplated);
    }
    ToFunc->setPreviousDecl(Recent);
  }

  return ToFunc;
}

ExpectedDecl ASTNodeImporter::VisitConceptDecl(ConceptDecl *D) {
  DeclContext *DC, *LexicalDC;
  Error Err = ImportDeclContext(D, DC, LexicalDC);
  auto LocationOrErr = importChecked(Err, D->getLocation());
  auto NameDeclOrErr = importChecked(Err, D->getDeclName());
  auto ToTemplateParameters = importChecked(Err, D->getTemplateParameters());
  auto ConstraintExpr = importChecked(Err, D->getConstraintExpr());
  if (Err)
    return std::move(Err);

  ConceptDecl *To;
  if (GetImportedOrCreateDecl(To, D, Importer.getToContext(), DC, LocationOrErr,
                              NameDeclOrErr, ToTemplateParameters,
                              ConstraintExpr))
    return To;
  To->setLexicalDeclContext(LexicalDC);
  LexicalDC->addDeclInternal(To);
  return To;
}

ExpectedDecl
ASTNodeImporter::VisitRequiresExprBodyDecl(RequiresExprBodyDecl *D) {
  DeclContext *DC, *LexicalDC;
  Error Err = ImportDeclContext(D, DC, LexicalDC);
  auto RequiresLoc = importChecked(Err, D->getLocation());
  if (Err)
    return std::move(Err);

  RequiresExprBodyDecl *To;
  if (GetImportedOrCreateDecl(To, D, Importer.getToContext(), DC, RequiresLoc))
    return To;
  To->setLexicalDeclContext(LexicalDC);
  LexicalDC->addDeclInternal(To);
  return To;
}

ExpectedDecl ASTNodeImporter::VisitImplicitConceptSpecializationDecl(
    ImplicitConceptSpecializationDecl *D) {
  DeclContext *DC, *LexicalDC;
  Error Err = ImportDeclContext(D, DC, LexicalDC);
  auto ToSL = importChecked(Err, D->getLocation());
  if (Err)
    return std::move(Err);

  SmallVector<TemplateArgument, 2> ToArgs(D->getTemplateArguments().size());
  if (Error Err = ImportTemplateArguments(D->getTemplateArguments(), ToArgs))
    return std::move(Err);

  ImplicitConceptSpecializationDecl *To;
  if (GetImportedOrCreateDecl(To, D, Importer.getToContext(), DC, ToSL, ToArgs))
    return To;
  To->setLexicalDeclContext(LexicalDC);
  LexicalDC->addDeclInternal(To);
  return To;
}

//----------------------------------------------------------------------------
// Import Statements
//----------------------------------------------------------------------------

ExpectedStmt ASTNodeImporter::VisitStmt(Stmt *S) {
  Importer.FromDiag(S->getBeginLoc(), diag::err_unsupported_ast_node)
      << S->getStmtClassName();
  return make_error<ASTImportError>(ASTImportError::UnsupportedConstruct);
}


ExpectedStmt ASTNodeImporter::VisitGCCAsmStmt(GCCAsmStmt *S) {
  if (Importer.returnWithErrorInTest())
    return make_error<ASTImportError>(ASTImportError::UnsupportedConstruct);
  SmallVector<IdentifierInfo *, 4> Names;
  for (unsigned I = 0, E = S->getNumOutputs(); I != E; I++) {
    IdentifierInfo *ToII = Importer.Import(S->getOutputIdentifier(I));
    // ToII is nullptr when no symbolic name is given for output operand
    // see ParseStmtAsm::ParseAsmOperandsOpt
    Names.push_back(ToII);
  }

  for (unsigned I = 0, E = S->getNumInputs(); I != E; I++) {
    IdentifierInfo *ToII = Importer.Import(S->getInputIdentifier(I));
    // ToII is nullptr when no symbolic name is given for input operand
    // see ParseStmtAsm::ParseAsmOperandsOpt
    Names.push_back(ToII);
  }

  SmallVector<Expr *, 4> Clobbers;
  for (unsigned I = 0, E = S->getNumClobbers(); I != E; I++) {
    if (auto ClobberOrErr = import(S->getClobberExpr(I)))
      Clobbers.push_back(*ClobberOrErr);
    else
      return ClobberOrErr.takeError();

  }

  SmallVector<Expr *, 4> Constraints;
  for (unsigned I = 0, E = S->getNumOutputs(); I != E; I++) {
    if (auto OutputOrErr = import(S->getOutputConstraintExpr(I)))
      Constraints.push_back(*OutputOrErr);
    else
      return OutputOrErr.takeError();
  }

  for (unsigned I = 0, E = S->getNumInputs(); I != E; I++) {
    if (auto InputOrErr = import(S->getInputConstraintExpr(I)))
      Constraints.push_back(*InputOrErr);
    else
      return InputOrErr.takeError();
  }

  SmallVector<Expr *, 4> Exprs(S->getNumOutputs() + S->getNumInputs() +
                               S->getNumLabels());
  if (Error Err = ImportContainerChecked(S->outputs(), Exprs))
    return std::move(Err);

  if (Error Err =
          ImportArrayChecked(S->inputs(), Exprs.begin() + S->getNumOutputs()))
    return std::move(Err);

  if (Error Err = ImportArrayChecked(
          S->labels(), Exprs.begin() + S->getNumOutputs() + S->getNumInputs()))
    return std::move(Err);

  ExpectedSLoc AsmLocOrErr = import(S->getAsmLoc());
  if (!AsmLocOrErr)
    return AsmLocOrErr.takeError();
  auto AsmStrOrErr = import(S->getAsmStringExpr());
  if (!AsmStrOrErr)
    return AsmStrOrErr.takeError();
  ExpectedSLoc RParenLocOrErr = import(S->getRParenLoc());
  if (!RParenLocOrErr)
    return RParenLocOrErr.takeError();

  return new (Importer.getToContext()) GCCAsmStmt(
      Importer.getToContext(),
      *AsmLocOrErr,
      S->isSimple(),
      S->isVolatile(),
      S->getNumOutputs(),
      S->getNumInputs(),
      Names.data(),
      Constraints.data(),
      Exprs.data(),
      *AsmStrOrErr,
      S->getNumClobbers(),
      Clobbers.data(),
      S->getNumLabels(),
      *RParenLocOrErr);
}

ExpectedStmt ASTNodeImporter::VisitDeclStmt(DeclStmt *S) {

  Error Err = Error::success();
  auto ToDG = importChecked(Err, S->getDeclGroup());
  auto ToBeginLoc = importChecked(Err, S->getBeginLoc());
  auto ToEndLoc = importChecked(Err, S->getEndLoc());
  if (Err)
    return std::move(Err);
  return new (Importer.getToContext()) DeclStmt(ToDG, ToBeginLoc, ToEndLoc);
}

ExpectedStmt ASTNodeImporter::VisitNullStmt(NullStmt *S) {
  ExpectedSLoc ToSemiLocOrErr = import(S->getSemiLoc());
  if (!ToSemiLocOrErr)
    return ToSemiLocOrErr.takeError();
  return new (Importer.getToContext()) NullStmt(
      *ToSemiLocOrErr, S->hasLeadingEmptyMacro());
}

ExpectedStmt ASTNodeImporter::VisitCompoundStmt(CompoundStmt *S) {
  SmallVector<Stmt *, 8> ToStmts(S->size());

  if (Error Err = ImportContainerChecked(S->body(), ToStmts))
    return std::move(Err);

  ExpectedSLoc ToLBracLocOrErr = import(S->getLBracLoc());
  if (!ToLBracLocOrErr)
    return ToLBracLocOrErr.takeError();

  ExpectedSLoc ToRBracLocOrErr = import(S->getRBracLoc());
  if (!ToRBracLocOrErr)
    return ToRBracLocOrErr.takeError();

  FPOptionsOverride FPO =
      S->hasStoredFPFeatures() ? S->getStoredFPFeatures() : FPOptionsOverride();
  return CompoundStmt::Create(Importer.getToContext(), ToStmts, FPO,
                              *ToLBracLocOrErr, *ToRBracLocOrErr);
}

ExpectedStmt ASTNodeImporter::VisitCaseStmt(CaseStmt *S) {

  Error Err = Error::success();
  auto ToLHS = importChecked(Err, S->getLHS());
  auto ToRHS = importChecked(Err, S->getRHS());
  auto ToSubStmt = importChecked(Err, S->getSubStmt());
  auto ToCaseLoc = importChecked(Err, S->getCaseLoc());
  auto ToEllipsisLoc = importChecked(Err, S->getEllipsisLoc());
  auto ToColonLoc = importChecked(Err, S->getColonLoc());
  if (Err)
    return std::move(Err);

  auto *ToStmt = CaseStmt::Create(Importer.getToContext(), ToLHS, ToRHS,
                                  ToCaseLoc, ToEllipsisLoc, ToColonLoc);
  ToStmt->setSubStmt(ToSubStmt);

  return ToStmt;
}

ExpectedStmt ASTNodeImporter::VisitDefaultStmt(DefaultStmt *S) {

  Error Err = Error::success();
  auto ToDefaultLoc = importChecked(Err, S->getDefaultLoc());
  auto ToColonLoc = importChecked(Err, S->getColonLoc());
  auto ToSubStmt = importChecked(Err, S->getSubStmt());
  if (Err)
    return std::move(Err);

  return new (Importer.getToContext()) DefaultStmt(
    ToDefaultLoc, ToColonLoc, ToSubStmt);
}

ExpectedStmt ASTNodeImporter::VisitLabelStmt(LabelStmt *S) {

  Error Err = Error::success();
  auto ToIdentLoc = importChecked(Err, S->getIdentLoc());
  auto ToLabelDecl = importChecked(Err, S->getDecl());
  auto ToSubStmt = importChecked(Err, S->getSubStmt());
  if (Err)
    return std::move(Err);

  return new (Importer.getToContext()) LabelStmt(
      ToIdentLoc, ToLabelDecl, ToSubStmt);
}

ExpectedStmt ASTNodeImporter::VisitAttributedStmt(AttributedStmt *S) {
  ExpectedSLoc ToAttrLocOrErr = import(S->getAttrLoc());
  if (!ToAttrLocOrErr)
    return ToAttrLocOrErr.takeError();
  ArrayRef<const Attr*> FromAttrs(S->getAttrs());
  SmallVector<const Attr *, 1> ToAttrs(FromAttrs.size());
  if (Error Err = ImportContainerChecked(FromAttrs, ToAttrs))
    return std::move(Err);
  ExpectedStmt ToSubStmtOrErr = import(S->getSubStmt());
  if (!ToSubStmtOrErr)
    return ToSubStmtOrErr.takeError();

  return AttributedStmt::Create(
      Importer.getToContext(), *ToAttrLocOrErr, ToAttrs, *ToSubStmtOrErr);
}

ExpectedStmt ASTNodeImporter::VisitIfStmt(IfStmt *S) {

  Error Err = Error::success();
  auto ToIfLoc = importChecked(Err, S->getIfLoc());
  auto ToInit = importChecked(Err, S->getInit());
  auto ToConditionVariable = importChecked(Err, S->getConditionVariable());
  auto ToCond = importChecked(Err, S->getCond());
  auto ToLParenLoc = importChecked(Err, S->getLParenLoc());
  auto ToRParenLoc = importChecked(Err, S->getRParenLoc());
  auto ToThen = importChecked(Err, S->getThen());
  auto ToElseLoc = importChecked(Err, S->getElseLoc());
  auto ToElse = importChecked(Err, S->getElse());
  if (Err)
    return std::move(Err);

  return IfStmt::Create(Importer.getToContext(), ToIfLoc, S->getStatementKind(),
                        ToInit, ToConditionVariable, ToCond, ToLParenLoc,
                        ToRParenLoc, ToThen, ToElseLoc, ToElse);
}

ExpectedStmt ASTNodeImporter::VisitSwitchStmt(SwitchStmt *S) {

  Error Err = Error::success();
  auto ToInit = importChecked(Err, S->getInit());
  auto ToConditionVariable = importChecked(Err, S->getConditionVariable());
  auto ToCond = importChecked(Err, S->getCond());
  auto ToLParenLoc = importChecked(Err, S->getLParenLoc());
  auto ToRParenLoc = importChecked(Err, S->getRParenLoc());
  auto ToBody = importChecked(Err, S->getBody());
  auto ToSwitchLoc = importChecked(Err, S->getSwitchLoc());
  if (Err)
    return std::move(Err);

  auto *ToStmt =
      SwitchStmt::Create(Importer.getToContext(), ToInit, ToConditionVariable,
                         ToCond, ToLParenLoc, ToRParenLoc);
  ToStmt->setBody(ToBody);
  ToStmt->setSwitchLoc(ToSwitchLoc);

  // Now we have to re-chain the cases.
  SwitchCase *LastChainedSwitchCase = nullptr;
  for (SwitchCase *SC = S->getSwitchCaseList(); SC != nullptr;
       SC = SC->getNextSwitchCase()) {
    Expected<SwitchCase *> ToSCOrErr = import(SC);
    if (!ToSCOrErr)
      return ToSCOrErr.takeError();
    if (LastChainedSwitchCase)
      LastChainedSwitchCase->setNextSwitchCase(*ToSCOrErr);
    else
      ToStmt->setSwitchCaseList(*ToSCOrErr);
    LastChainedSwitchCase = *ToSCOrErr;
  }

  return ToStmt;
}

ExpectedStmt ASTNodeImporter::VisitWhileStmt(WhileStmt *S) {

  Error Err = Error::success();
  auto ToConditionVariable = importChecked(Err, S->getConditionVariable());
  auto ToCond = importChecked(Err, S->getCond());
  auto ToBody = importChecked(Err, S->getBody());
  auto ToWhileLoc = importChecked(Err, S->getWhileLoc());
  auto ToLParenLoc = importChecked(Err, S->getLParenLoc());
  auto ToRParenLoc = importChecked(Err, S->getRParenLoc());
  if (Err)
    return std::move(Err);

  return WhileStmt::Create(Importer.getToContext(), ToConditionVariable, ToCond,
                           ToBody, ToWhileLoc, ToLParenLoc, ToRParenLoc);
}

ExpectedStmt ASTNodeImporter::VisitDoStmt(DoStmt *S) {

  Error Err = Error::success();
  auto ToBody = importChecked(Err, S->getBody());
  auto ToCond = importChecked(Err, S->getCond());
  auto ToDoLoc = importChecked(Err, S->getDoLoc());
  auto ToWhileLoc = importChecked(Err, S->getWhileLoc());
  auto ToRParenLoc = importChecked(Err, S->getRParenLoc());
  if (Err)
    return std::move(Err);

  return new (Importer.getToContext()) DoStmt(
      ToBody, ToCond, ToDoLoc, ToWhileLoc, ToRParenLoc);
}

ExpectedStmt ASTNodeImporter::VisitForStmt(ForStmt *S) {

  Error Err = Error::success();
  auto ToInit = importChecked(Err, S->getInit());
  auto ToCond = importChecked(Err, S->getCond());
  auto ToConditionVariable = importChecked(Err, S->getConditionVariable());
  auto ToInc = importChecked(Err, S->getInc());
  auto ToBody = importChecked(Err, S->getBody());
  auto ToForLoc = importChecked(Err, S->getForLoc());
  auto ToLParenLoc = importChecked(Err, S->getLParenLoc());
  auto ToRParenLoc = importChecked(Err, S->getRParenLoc());
  if (Err)
    return std::move(Err);

  return new (Importer.getToContext()) ForStmt(
      Importer.getToContext(),
      ToInit, ToCond, ToConditionVariable, ToInc, ToBody, ToForLoc, ToLParenLoc,
      ToRParenLoc);
}

ExpectedStmt ASTNodeImporter::VisitGotoStmt(GotoStmt *S) {

  Error Err = Error::success();
  auto ToLabel = importChecked(Err, S->getLabel());
  auto ToGotoLoc = importChecked(Err, S->getGotoLoc());
  auto ToLabelLoc = importChecked(Err, S->getLabelLoc());
  if (Err)
    return std::move(Err);

  return new (Importer.getToContext()) GotoStmt(
      ToLabel, ToGotoLoc, ToLabelLoc);
}

ExpectedStmt ASTNodeImporter::VisitIndirectGotoStmt(IndirectGotoStmt *S) {

  Error Err = Error::success();
  auto ToGotoLoc = importChecked(Err, S->getGotoLoc());
  auto ToStarLoc = importChecked(Err, S->getStarLoc());
  auto ToTarget = importChecked(Err, S->getTarget());
  if (Err)
    return std::move(Err);

  return new (Importer.getToContext()) IndirectGotoStmt(
      ToGotoLoc, ToStarLoc, ToTarget);
}

ExpectedStmt ASTNodeImporter::VisitContinueStmt(ContinueStmt *S) {
  ExpectedSLoc ToContinueLocOrErr = import(S->getContinueLoc());
  if (!ToContinueLocOrErr)
    return ToContinueLocOrErr.takeError();
  return new (Importer.getToContext()) ContinueStmt(*ToContinueLocOrErr);
}

ExpectedStmt ASTNodeImporter::VisitBreakStmt(BreakStmt *S) {
  auto ToBreakLocOrErr = import(S->getBreakLoc());
  if (!ToBreakLocOrErr)
    return ToBreakLocOrErr.takeError();
  return new (Importer.getToContext()) BreakStmt(*ToBreakLocOrErr);
}

ExpectedStmt ASTNodeImporter::VisitReturnStmt(ReturnStmt *S) {

  Error Err = Error::success();
  auto ToReturnLoc = importChecked(Err, S->getReturnLoc());
  auto ToRetValue = importChecked(Err, S->getRetValue());
  auto ToNRVOCandidate = importChecked(Err, S->getNRVOCandidate());
  if (Err)
    return std::move(Err);

  return ReturnStmt::Create(Importer.getToContext(), ToReturnLoc, ToRetValue,
                            ToNRVOCandidate);
}

ExpectedStmt ASTNodeImporter::VisitCXXCatchStmt(CXXCatchStmt *S) {

  Error Err = Error::success();
  auto ToCatchLoc = importChecked(Err, S->getCatchLoc());
  auto ToExceptionDecl = importChecked(Err, S->getExceptionDecl());
  auto ToHandlerBlock = importChecked(Err, S->getHandlerBlock());
  if (Err)
    return std::move(Err);

  return new (Importer.getToContext()) CXXCatchStmt (
      ToCatchLoc, ToExceptionDecl, ToHandlerBlock);
}

ExpectedStmt ASTNodeImporter::VisitCXXTryStmt(CXXTryStmt *S) {
  ExpectedSLoc ToTryLocOrErr = import(S->getTryLoc());
  if (!ToTryLocOrErr)
    return ToTryLocOrErr.takeError();

  ExpectedStmt ToTryBlockOrErr = import(S->getTryBlock());
  if (!ToTryBlockOrErr)
    return ToTryBlockOrErr.takeError();

  SmallVector<Stmt *, 1> ToHandlers(S->getNumHandlers());
  for (unsigned HI = 0, HE = S->getNumHandlers(); HI != HE; ++HI) {
    CXXCatchStmt *FromHandler = S->getHandler(HI);
    if (auto ToHandlerOrErr = import(FromHandler))
      ToHandlers[HI] = *ToHandlerOrErr;
    else
      return ToHandlerOrErr.takeError();
  }

  return CXXTryStmt::Create(Importer.getToContext(), *ToTryLocOrErr,
                            cast<CompoundStmt>(*ToTryBlockOrErr), ToHandlers);
}

ExpectedStmt ASTNodeImporter::VisitCXXForRangeStmt(CXXForRangeStmt *S) {

  Error Err = Error::success();
  auto ToInit = importChecked(Err, S->getInit());
  auto ToRangeStmt = importChecked(Err, S->getRangeStmt());
  auto ToBeginStmt = importChecked(Err, S->getBeginStmt());
  auto ToEndStmt = importChecked(Err, S->getEndStmt());
  auto ToCond = importChecked(Err, S->getCond());
  auto ToInc = importChecked(Err, S->getInc());
  auto ToLoopVarStmt = importChecked(Err, S->getLoopVarStmt());
  auto ToBody = importChecked(Err, S->getBody());
  auto ToForLoc = importChecked(Err, S->getForLoc());
  auto ToCoawaitLoc = importChecked(Err, S->getCoawaitLoc());
  auto ToColonLoc = importChecked(Err, S->getColonLoc());
  auto ToRParenLoc = importChecked(Err, S->getRParenLoc());
  if (Err)
    return std::move(Err);

  return new (Importer.getToContext()) CXXForRangeStmt(
      ToInit, ToRangeStmt, ToBeginStmt, ToEndStmt, ToCond, ToInc, ToLoopVarStmt,
      ToBody, ToForLoc, ToCoawaitLoc, ToColonLoc, ToRParenLoc);
}

ExpectedStmt
ASTNodeImporter::VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) {
  Error Err = Error::success();
  auto ToElement = importChecked(Err, S->getElement());
  auto ToCollection = importChecked(Err, S->getCollection());
  auto ToBody = importChecked(Err, S->getBody());
  auto ToForLoc = importChecked(Err, S->getForLoc());
  auto ToRParenLoc = importChecked(Err, S->getRParenLoc());
  if (Err)
    return std::move(Err);

  return new (Importer.getToContext()) ObjCForCollectionStmt(ToElement,
                                                             ToCollection,
                                                             ToBody,
                                                             ToForLoc,
                                                             ToRParenLoc);
}

ExpectedStmt ASTNodeImporter::VisitObjCAtCatchStmt(ObjCAtCatchStmt *S) {

  Error Err = Error::success();
  auto ToAtCatchLoc = importChecked(Err, S->getAtCatchLoc());
  auto ToRParenLoc = importChecked(Err, S->getRParenLoc());
  auto ToCatchParamDecl = importChecked(Err, S->getCatchParamDecl());
  auto ToCatchBody = importChecked(Err, S->getCatchBody());
  if (Err)
    return std::move(Err);

  return new (Importer.getToContext()) ObjCAtCatchStmt (
      ToAtCatchLoc, ToRParenLoc, ToCatchParamDecl, ToCatchBody);
}

ExpectedStmt ASTNodeImporter::VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *S) {
  ExpectedSLoc ToAtFinallyLocOrErr = import(S->getAtFinallyLoc());
  if (!ToAtFinallyLocOrErr)
    return ToAtFinallyLocOrErr.takeError();
  ExpectedStmt ToAtFinallyStmtOrErr = import(S->getFinallyBody());
  if (!ToAtFinallyStmtOrErr)
    return ToAtFinallyStmtOrErr.takeError();
  return new (Importer.getToContext()) ObjCAtFinallyStmt(*ToAtFinallyLocOrErr,
                                                         *ToAtFinallyStmtOrErr);
}

ExpectedStmt ASTNodeImporter::VisitObjCAtTryStmt(ObjCAtTryStmt *S) {

  Error Err = Error::success();
  auto ToAtTryLoc = importChecked(Err, S->getAtTryLoc());
  auto ToTryBody = importChecked(Err, S->getTryBody());
  auto ToFinallyStmt = importChecked(Err, S->getFinallyStmt());
  if (Err)
    return std::move(Err);

  SmallVector<Stmt *, 1> ToCatchStmts(S->getNumCatchStmts());
  for (unsigned CI = 0, CE = S->getNumCatchStmts(); CI != CE; ++CI) {
    ObjCAtCatchStmt *FromCatchStmt = S->getCatchStmt(CI);
    if (ExpectedStmt ToCatchStmtOrErr = import(FromCatchStmt))
      ToCatchStmts[CI] = *ToCatchStmtOrErr;
    else
      return ToCatchStmtOrErr.takeError();
  }

  return ObjCAtTryStmt::Create(Importer.getToContext(),
                               ToAtTryLoc, ToTryBody,
                               ToCatchStmts.begin(), ToCatchStmts.size(),
                               ToFinallyStmt);
}

ExpectedStmt
ASTNodeImporter::VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S) {

  Error Err = Error::success();
  auto ToAtSynchronizedLoc = importChecked(Err, S->getAtSynchronizedLoc());
  auto ToSynchExpr = importChecked(Err, S->getSynchExpr());
  auto ToSynchBody = importChecked(Err, S->getSynchBody());
  if (Err)
    return std::move(Err);

  return new (Importer.getToContext()) ObjCAtSynchronizedStmt(
    ToAtSynchronizedLoc, ToSynchExpr, ToSynchBody);
}

ExpectedStmt ASTNodeImporter::VisitObjCAtThrowStmt(ObjCAtThrowStmt *S) {
  ExpectedSLoc ToThrowLocOrErr = import(S->getThrowLoc());
  if (!ToThrowLocOrErr)
    return ToThrowLocOrErr.takeError();
  ExpectedExpr ToThrowExprOrErr = import(S->getThrowExpr());
  if (!ToThrowExprOrErr)
    return ToThrowExprOrErr.takeError();
  return new (Importer.getToContext()) ObjCAtThrowStmt(
      *ToThrowLocOrErr, *ToThrowExprOrErr);
}

ExpectedStmt ASTNodeImporter::VisitObjCAutoreleasePoolStmt(
    ObjCAutoreleasePoolStmt *S) {
  ExpectedSLoc ToAtLocOrErr = import(S->getAtLoc());
  if (!ToAtLocOrErr)
    return ToAtLocOrErr.takeError();
  ExpectedStmt ToSubStmtOrErr = import(S->getSubStmt());
  if (!ToSubStmtOrErr)
    return ToSubStmtOrErr.takeError();
  return new (Importer.getToContext()) ObjCAutoreleasePoolStmt(*ToAtLocOrErr,
                                                               *ToSubStmtOrErr);
}

//----------------------------------------------------------------------------
// Import Expressions
//----------------------------------------------------------------------------
ExpectedStmt ASTNodeImporter::VisitExpr(Expr *E) {
  Importer.FromDiag(E->getBeginLoc(), diag::err_unsupported_ast_node)
      << E->getStmtClassName();
  return make_error<ASTImportError>(ASTImportError::UnsupportedConstruct);
}

ExpectedStmt ASTNodeImporter::VisitSourceLocExpr(SourceLocExpr *E) {
  Error Err = Error::success();
  auto ToType = importChecked(Err, E->getType());
  auto BLoc = importChecked(Err, E->getBeginLoc());
  auto RParenLoc = importChecked(Err, E->getEndLoc());
  if (Err)
    return std::move(Err);
  auto ParentContextOrErr = Importer.ImportContext(E->getParentContext());
  if (!ParentContextOrErr)
    return ParentContextOrErr.takeError();

  return new (Importer.getToContext())
      SourceLocExpr(Importer.getToContext(), E->getIdentKind(), ToType, BLoc,
                    RParenLoc, *ParentContextOrErr);
}

ExpectedStmt ASTNodeImporter::VisitVAArgExpr(VAArgExpr *E) {

  Error Err = Error::success();
  auto ToBuiltinLoc = importChecked(Err, E->getBuiltinLoc());
  auto ToSubExpr = importChecked(Err, E->getSubExpr());
  auto ToWrittenTypeInfo = importChecked(Err, E->getWrittenTypeInfo());
  auto ToRParenLoc = importChecked(Err, E->getRParenLoc());
  auto ToType = importChecked(Err, E->getType());
  if (Err)
    return std::move(Err);

  return new (Importer.getToContext()) VAArgExpr(
      ToBuiltinLoc, ToSubExpr, ToWrittenTypeInfo, ToRParenLoc, ToType,
      E->isMicrosoftABI());
}

ExpectedStmt ASTNodeImporter::VisitChooseExpr(ChooseExpr *E) {

  Error Err = Error::success();
  auto ToCond = importChecked(Err, E->getCond());
  auto ToLHS = importChecked(Err, E->getLHS());
  auto ToRHS = importChecked(Err, E->getRHS());
  auto ToBuiltinLoc = importChecked(Err, E->getBuiltinLoc());
  auto ToRParenLoc = importChecked(Err, E->getRParenLoc());
  auto ToType = importChecked(Err, E->getType());
  if (Err)
    return std::move(Err);

  ExprValueKind VK = E->getValueKind();
  ExprObjectKind OK = E->getObjectKind();

  // The value of CondIsTrue only matters if the value is not
  // condition-dependent.
  bool CondIsTrue = !E->isConditionDependent() && E->isConditionTrue();

  return new (Importer.getToContext())
      ChooseExpr(ToBuiltinLoc, ToCond, ToLHS, ToRHS, ToType, VK, OK,
                 ToRParenLoc, CondIsTrue);
}

ExpectedStmt ASTNodeImporter::VisitConvertVectorExpr(ConvertVectorExpr *E) {
  Error Err = Error::success();
  auto *ToSrcExpr = importChecked(Err, E->getSrcExpr());
  auto ToRParenLoc = importChecked(Err, E->getRParenLoc());
  auto ToBuiltinLoc = importChecked(Err, E->getBuiltinLoc());
  auto ToType = importChecked(Err, E->getType());
  auto *ToTSI = importChecked(Err, E->getTypeSourceInfo());
  if (Err)
    return std::move(Err);

  return ConvertVectorExpr::Create(
      Importer.getToContext(), ToSrcExpr, ToTSI, ToType, E->getValueKind(),
      E->getObjectKind(), ToBuiltinLoc, ToRParenLoc,
      E->getStoredFPFeaturesOrDefault());
}

ExpectedStmt ASTNodeImporter::VisitShuffleVectorExpr(ShuffleVectorExpr *E) {
  Error Err = Error::success();
  auto ToRParenLoc = importChecked(Err, E->getRParenLoc());
  auto ToBeginLoc = importChecked(Err, E->getBeginLoc());
  auto ToType = importChecked(Err, E->getType());
  const unsigned NumSubExprs = E->getNumSubExprs();

  llvm::SmallVector<Expr *, 8> ToSubExprs;
  ArrayRef<Expr *> FromSubExprs(E->getSubExprs(), NumSubExprs);
  ToSubExprs.resize(NumSubExprs);

  if ((Err = ImportContainerChecked(FromSubExprs, ToSubExprs)))
    return std::move(Err);

  return new (Importer.getToContext()) ShuffleVectorExpr(
      Importer.getToContext(), ToSubExprs, ToType, ToBeginLoc, ToRParenLoc);
}

ExpectedStmt ASTNodeImporter::VisitGNUNullExpr(GNUNullExpr *E) {
  ExpectedType TypeOrErr = import(E->getType());
  if (!TypeOrErr)
    return TypeOrErr.takeError();

  ExpectedSLoc BeginLocOrErr = import(E->getBeginLoc());
  if (!BeginLocOrErr)
    return BeginLocOrErr.takeError();

  return new (Importer.getToContext()) GNUNullExpr(*TypeOrErr, *BeginLocOrErr);
}

ExpectedStmt
ASTNodeImporter::VisitGenericSelectionExpr(GenericSelectionExpr *E) {
  Error Err = Error::success();
  auto ToGenericLoc = importChecked(Err, E->getGenericLoc());
  Expr *ToControllingExpr = nullptr;
  TypeSourceInfo *ToControllingType = nullptr;
  if (E->isExprPredicate())
    ToControllingExpr = importChecked(Err, E->getControllingExpr());
  else
    ToControllingType = importChecked(Err, E->getControllingType());
  assert((ToControllingExpr || ToControllingType) &&
         "Either the controlling expr or type must be nonnull");
  auto ToDefaultLoc = importChecked(Err, E->getDefaultLoc());
  auto ToRParenLoc = importChecked(Err, E->getRParenLoc());
  if (Err)
    return std::move(Err);

  ArrayRef<const TypeSourceInfo *> FromAssocTypes(E->getAssocTypeSourceInfos());
  SmallVector<TypeSourceInfo *, 1> ToAssocTypes(FromAssocTypes.size());
  if (Error Err = ImportContainerChecked(FromAssocTypes, ToAssocTypes))
    return std::move(Err);

  ArrayRef<const Expr *> FromAssocExprs(E->getAssocExprs());
  SmallVector<Expr *, 1> ToAssocExprs(FromAssocExprs.size());
  if (Error Err = ImportContainerChecked(FromAssocExprs, ToAssocExprs))
    return std::move(Err);

  const ASTContext &ToCtx = Importer.getToContext();
  if (E->isResultDependent()) {
    if (ToControllingExpr) {
      return GenericSelectionExpr::Create(
          ToCtx, ToGenericLoc, ToControllingExpr, ArrayRef(ToAssocTypes),
          ArrayRef(ToAssocExprs), ToDefaultLoc, ToRParenLoc,
          E->containsUnexpandedParameterPack());
    }
    return GenericSelectionExpr::Create(
        ToCtx, ToGenericLoc, ToControllingType, ArrayRef(ToAssocTypes),
        ArrayRef(ToAssocExprs), ToDefaultLoc, ToRParenLoc,
        E->containsUnexpandedParameterPack());
  }

  if (ToControllingExpr) {
    return GenericSelectionExpr::Create(
        ToCtx, ToGenericLoc, ToControllingExpr, ArrayRef(ToAssocTypes),
        ArrayRef(ToAssocExprs), ToDefaultLoc, ToRParenLoc,
        E->containsUnexpandedParameterPack(), E->getResultIndex());
  }
  return GenericSelectionExpr::Create(
      ToCtx, ToGenericLoc, ToControllingType, ArrayRef(ToAssocTypes),
      ArrayRef(ToAssocExprs), ToDefaultLoc, ToRParenLoc,
      E->containsUnexpandedParameterPack(), E->getResultIndex());
}

ExpectedStmt ASTNodeImporter::VisitPredefinedExpr(PredefinedExpr *E) {

  Error Err = Error::success();
  auto ToBeginLoc = importChecked(Err, E->getBeginLoc());
  auto ToType = importChecked(Err, E->getType());
  auto ToFunctionName = importChecked(Err, E->getFunctionName());
  if (Err)
    return std::move(Err);

  return PredefinedExpr::Create(Importer.getToContext(), ToBeginLoc, ToType,
                                E->getIdentKind(), E->isTransparent(),
                                ToFunctionName);
}

ExpectedStmt ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) {

  Error Err = Error::success();
  auto ToQualifierLoc = importChecked(Err, E->getQualifierLoc());
  auto ToTemplateKeywordLoc = importChecked(Err, E->getTemplateKeywordLoc());
  auto ToDecl = importChecked(Err, E->getDecl());
  auto ToLocation = importChecked(Err, E->getLocation());
  auto ToType = importChecked(Err, E->getType());
  if (Err)
    return std::move(Err);

  NamedDecl *ToFoundD = nullptr;
  if (E->getDecl() != E->getFoundDecl()) {
    auto FoundDOrErr = import(E->getFoundDecl());
    if (!FoundDOrErr)
      return FoundDOrErr.takeError();
    ToFoundD = *FoundDOrErr;
  }

  TemplateArgumentListInfo ToTAInfo;
  TemplateArgumentListInfo *ToResInfo = nullptr;
  if (E->hasExplicitTemplateArgs()) {
    if (Error Err =
            ImportTemplateArgumentListInfo(E->getLAngleLoc(), E->getRAngleLoc(),
                                           E->template_arguments(), ToTAInfo))
      return std::move(Err);
    ToResInfo = &ToTAInfo;
  }

  auto *ToE = DeclRefExpr::Create(
      Importer.getToContext(), ToQualifierLoc, ToTemplateKeywordLoc, ToDecl,
      E->refersToEnclosingVariableOrCapture(), ToLocation, ToType,
      E->getValueKind(), ToFoundD, ToResInfo, E->isNonOdrUse());
  if (E->hadMultipleCandidates())
    ToE->setHadMultipleCandidates(true);
  ToE->setIsImmediateEscalating(E->isImmediateEscalating());
  return ToE;
}

ExpectedStmt ASTNodeImporter::VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) {
  ExpectedType TypeOrErr = import(E->getType());
  if (!TypeOrErr)
    return TypeOrErr.takeError();

  return new (Importer.getToContext()) ImplicitValueInitExpr(*TypeOrErr);
}

ExpectedStmt ASTNodeImporter::VisitDesignatedInitExpr(DesignatedInitExpr *E) {
  ExpectedExpr ToInitOrErr = import(E->getInit());
  if (!ToInitOrErr)
    return ToInitOrErr.takeError();

  ExpectedSLoc ToEqualOrColonLocOrErr = import(E->getEqualOrColonLoc());
  if (!ToEqualOrColonLocOrErr)
    return ToEqualOrColonLocOrErr.takeError();

  SmallVector<Expr *, 4> ToIndexExprs(E->getNumSubExprs() - 1);
  // List elements from the second, the first is Init itself
  for (unsigned I = 1, N = E->getNumSubExprs(); I < N; I++) {
    if (ExpectedExpr ToArgOrErr = import(E->getSubExpr(I)))
      ToIndexExprs[I - 1] = *ToArgOrErr;
    else
      return ToArgOrErr.takeError();
  }

  SmallVector<Designator, 4> ToDesignators(E->size());
  if (Error Err = ImportContainerChecked(E->designators(), ToDesignators))
    return std::move(Err);

  return DesignatedInitExpr::Create(
        Importer.getToContext(), ToDesignators,
        ToIndexExprs, *ToEqualOrColonLocOrErr,
        E->usesGNUSyntax(), *ToInitOrErr);
}

ExpectedStmt
ASTNodeImporter::VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E) {
  ExpectedType ToTypeOrErr = import(E->getType());
  if (!ToTypeOrErr)
    return ToTypeOrErr.takeError();

  ExpectedSLoc ToLocationOrErr = import(E->getLocation());
  if (!ToLocationOrErr)
    return ToLocationOrErr.takeError();

  return new (Importer.getToContext()) CXXNullPtrLiteralExpr(
      *ToTypeOrErr, *ToLocationOrErr);
}

ExpectedStmt ASTNodeImporter::VisitIntegerLiteral(IntegerLiteral *E) {
  ExpectedType ToTypeOrErr = import(E->getType());
  if (!ToTypeOrErr)
    return ToTypeOrErr.takeError();

  ExpectedSLoc ToLocationOrErr = import(E->getLocation());
  if (!ToLocationOrErr)
    return ToLocationOrErr.takeError();

  return IntegerLiteral::Create(
      Importer.getToContext(), E->getValue(), *ToTypeOrErr, *ToLocationOrErr);
}


ExpectedStmt ASTNodeImporter::VisitFloatingLiteral(FloatingLiteral *E) {
  ExpectedType ToTypeOrErr = import(E->getType());
  if (!ToTypeOrErr)
    return ToTypeOrErr.takeError();

  ExpectedSLoc ToLocationOrErr = import(E->getLocation());
  if (!ToLocationOrErr)
    return ToLocationOrErr.takeError();

  return FloatingLiteral::Create(
      Importer.getToContext(), E->getValue(), E->isExact(),
      *ToTypeOrErr, *ToLocationOrErr);
}

ExpectedStmt ASTNodeImporter::VisitImaginaryLiteral(ImaginaryLiteral *E) {
  auto ToTypeOrErr = import(E->getType());
  if (!ToTypeOrErr)
    return ToTypeOrErr.takeError();

  ExpectedExpr ToSubExprOrErr = import(E->getSubExpr());
  if (!ToSubExprOrErr)
    return ToSubExprOrErr.takeError();

  return new (Importer.getToContext()) ImaginaryLiteral(
      *ToSubExprOrErr, *ToTypeOrErr);
}

ExpectedStmt ASTNodeImporter::VisitFixedPointLiteral(FixedPointLiteral *E) {
  auto ToTypeOrErr = import(E->getType());
  if (!ToTypeOrErr)
    return ToTypeOrErr.takeError();

  ExpectedSLoc ToLocationOrErr = import(E->getLocation());
  if (!ToLocationOrErr)
    return ToLocationOrErr.takeError();

  return new (Importer.getToContext()) FixedPointLiteral(
      Importer.getToContext(), E->getValue(), *ToTypeOrErr, *ToLocationOrErr,
      Importer.getToContext().getFixedPointScale(*ToTypeOrErr));
}

ExpectedStmt ASTNodeImporter::VisitCharacterLiteral(CharacterLiteral *E) {
  ExpectedType ToTypeOrErr = import(E->getType());
  if (!ToTypeOrErr)
    return ToTypeOrErr.takeError();

  ExpectedSLoc ToLocationOrErr = import(E->getLocation());
  if (!ToLocationOrErr)
    return ToLocationOrErr.takeError();

  return new (Importer.getToContext()) CharacterLiteral(
      E->getValue(), E->getKind(), *ToTypeOrErr, *ToLocationOrErr);
}

ExpectedStmt ASTNodeImporter::VisitStringLiteral(StringLiteral *E) {
  ExpectedType ToTypeOrErr = import(E->getType());
  if (!ToTypeOrErr)
    return ToTypeOrErr.takeError();

  SmallVector<SourceLocation, 4> ToLocations(E->getNumConcatenated());
  if (Error Err = ImportArrayChecked(
      E->tokloc_begin(), E->tokloc_end(), ToLocations.begin()))
    return std::move(Err);

  return StringLiteral::Create(Importer.getToContext(), E->getBytes(),
                               E->getKind(), E->isPascal(), *ToTypeOrErr,
                               ToLocations);
}

ExpectedStmt ASTNodeImporter::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {

  Error Err = Error::success();
  auto ToLParenLoc = importChecked(Err, E->getLParenLoc());
  auto ToTypeSourceInfo = importChecked(Err, E->getTypeSourceInfo());
  auto ToType = importChecked(Err, E->getType());
  auto ToInitializer = importChecked(Err, E->getInitializer());
  if (Err)
    return std::move(Err);

  return new (Importer.getToContext()) CompoundLiteralExpr(
        ToLParenLoc, ToTypeSourceInfo, ToType, E->getValueKind(),
        ToInitializer, E->isFileScope());
}

ExpectedStmt ASTNodeImporter::VisitAtomicExpr(AtomicExpr *E) {

  Error Err = Error::success();
  auto ToBuiltinLoc = importChecked(Err, E->getBuiltinLoc());
  auto ToType = importChecked(Err, E->getType());
  auto ToRParenLoc = importChecked(Err, E->getRParenLoc());
  if (Err)
    return std::move(Err);

  SmallVector<Expr *, 6> ToExprs(E->getNumSubExprs());
  if (Error Err = ImportArrayChecked(
      E->getSubExprs(), E->getSubExprs() + E->getNumSubExprs(),
      ToExprs.begin()))
    return std::move(Err);

  return new (Importer.getToContext()) AtomicExpr(

      ToBuiltinLoc, ToExprs, ToType, E->getOp(), ToRParenLoc);
}

ExpectedStmt ASTNodeImporter::VisitAddrLabelExpr(AddrLabelExpr *E) {
  Error Err = Error::success();
  auto ToAmpAmpLoc = importChecked(Err, E->getAmpAmpLoc());
  auto ToLabelLoc = importChecked(Err, E->getLabelLoc());
  auto ToLabel = importChecked(Err, E->getLabel());
  auto ToType = importChecked(Err, E->getType());
  if (Err)
    return std::move(Err);

  return new (Importer.getToContext()) AddrLabelExpr(
      ToAmpAmpLoc, ToLabelLoc, ToLabel, ToType);
}
ExpectedStmt ASTNodeImporter::VisitConstantExpr(ConstantExpr *E) {
  Error Err = Error::success();
  auto ToSubExpr = importChecked(Err, E->getSubExpr());
  auto ToResult = importChecked(Err, E->getAPValueResult());
  if (Err)
    return std::move(Err);

  return ConstantExpr::Create(Importer.getToContext(), ToSubExpr, ToResult);
}
ExpectedStmt ASTNodeImporter::VisitParenExpr(ParenExpr *E) {
  Error Err = Error::success();
  auto ToLParen = importChecked(Err, E->getLParen());
  auto ToRParen = importChecked(Err, E->getRParen());
  auto ToSubExpr = importChecked(Err, E->getSubExpr());
  if (Err)
    return std::move(Err);

  return new (Importer.getToContext())
      ParenExpr(ToLParen, ToRParen, ToSubExpr);
}

ExpectedStmt ASTNodeImporter::VisitParenListExpr(ParenListExpr *E) {
  SmallVector<Expr *, 4> ToExprs(E->getNumExprs());
  if (Error Err = ImportContainerChecked(E->exprs(), ToExprs))
    return std::move(Err);

  ExpectedSLoc ToLParenLocOrErr = import(E->getLParenLoc());
  if (!ToLParenLocOrErr)
    return ToLParenLocOrErr.takeError();

  ExpectedSLoc ToRParenLocOrErr = import(E->getRParenLoc());
  if (!ToRParenLocOrErr)
    return ToRParenLocOrErr.takeError();

  return ParenListExpr::Create(Importer.getToContext(), *ToLParenLocOrErr,
                               ToExprs, *ToRParenLocOrErr);
}

ExpectedStmt ASTNodeImporter::VisitStmtExpr(StmtExpr *E) {
  Error Err = Error::success();
  auto ToSubStmt = importChecked(Err, E->getSubStmt());
  auto ToType = importChecked(Err, E->getType());
  auto ToLParenLoc = importChecked(Err, E->getLParenLoc());
  auto ToRParenLoc = importChecked(Err, E->getRParenLoc());
  if (Err)
    return std::move(Err);

  return new (Importer.getToContext())
      StmtExpr(ToSubStmt, ToType, ToLParenLoc, ToRParenLoc,
               E->getTemplateDepth());
}

ExpectedStmt ASTNodeImporter::VisitUnaryOperator(UnaryOperator *E) {
  Error Err = Error::success();
  auto ToSubExpr = importChecked(Err, E->getSubExpr());
  auto ToType = importChecked(Err, E->getType());
  auto ToOperatorLoc = importChecked(Err, E->getOperatorLoc());
  if (Err)
    return std::move(Err);

  auto *UO = UnaryOperator::CreateEmpty(Importer.getToContext(),
                                        E->hasStoredFPFeatures());
  UO->setType(ToType);
  UO->setSubExpr(ToSubExpr);
  UO->setOpcode(E->getOpcode());
  UO->setOperatorLoc(ToOperatorLoc);
  UO->setCanOverflow(E->canOverflow());
  if (E->hasStoredFPFeatures())
    UO->setStoredFPFeatures(E->getStoredFPFeatures());

  return UO;
}

ExpectedStmt

ASTNodeImporter::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E) {
  Error Err = Error::success();
  auto ToType = importChecked(Err, E->getType());
  auto ToOperatorLoc = importChecked(Err, E->getOperatorLoc());
  auto ToRParenLoc = importChecked(Err, E->getRParenLoc());
  if (Err)
    return std::move(Err);

  if (E->isArgumentType()) {
    Expected<TypeSourceInfo *> ToArgumentTypeInfoOrErr =
        import(E->getArgumentTypeInfo());
    if (!ToArgumentTypeInfoOrErr)
      return ToArgumentTypeInfoOrErr.takeError();

    return new (Importer.getToContext()) UnaryExprOrTypeTraitExpr(
        E->getKind(), *ToArgumentTypeInfoOrErr, ToType, ToOperatorLoc,
        ToRParenLoc);
  }

  ExpectedExpr ToArgumentExprOrErr = import(E->getArgumentExpr());
  if (!ToArgumentExprOrErr)
    return ToArgumentExprOrErr.takeError();

  return new (Importer.getToContext()) UnaryExprOrTypeTraitExpr(
      E->getKind(), *ToArgumentExprOrErr, ToType, ToOperatorLoc, ToRParenLoc);
}

ExpectedStmt ASTNodeImporter::VisitBinaryOperator(BinaryOperator *E) {
  Error Err = Error::success();
  auto ToLHS = importChecked(Err, E->getLHS());
  auto ToRHS = importChecked(Err, E->getRHS());
  auto ToType = importChecked(Err, E->getType());
  auto ToOperatorLoc = importChecked(Err, E->getOperatorLoc());
  if (Err)
    return std::move(Err);

  return BinaryOperator::Create(
      Importer.getToContext(), ToLHS, ToRHS, E->getOpcode(), ToType,
      E->getValueKind(), E->getObjectKind(), ToOperatorLoc,
      E->getFPFeatures());
}

ExpectedStmt ASTNodeImporter::VisitConditionalOperator(ConditionalOperator *E) {
  Error Err = Error::success();
  auto ToCond = importChecked(Err, E->getCond());
  auto ToQuestionLoc = importChecked(Err, E->getQuestionLoc());
  auto ToLHS = importChecked(Err, E->getLHS());
  auto ToColonLoc = importChecked(Err, E->getColonLoc());
  auto ToRHS = importChecked(Err, E->getRHS());
  auto ToType = importChecked(Err, E->getType());
  if (Err)
    return std::move(Err);

  return new (Importer.getToContext()) ConditionalOperator(
      ToCond, ToQuestionLoc, ToLHS, ToColonLoc, ToRHS, ToType,
      E->getValueKind(), E->getObjectKind());
}

ExpectedStmt
ASTNodeImporter::VisitBinaryConditionalOperator(BinaryConditionalOperator *E) {
  Error Err = Error::success();
  auto ToCommon = importChecked(Err, E->getCommon());
  auto ToOpaqueValue = importChecked(Err, E->getOpaqueValue());
  auto ToCond = importChecked(Err, E->getCond());
  auto ToTrueExpr = importChecked(Err, E->getTrueExpr());
  auto ToFalseExpr = importChecked(Err, E->getFalseExpr());
  auto ToQuestionLoc = importChecked(Err, E->getQuestionLoc());
  auto ToColonLoc = importChecked(Err, E->getColonLoc());
  auto ToType = importChecked(Err, E->getType());
  if (Err)
    return std::move(Err);

  return new (Importer.getToContext()) BinaryConditionalOperator(
      ToCommon, ToOpaqueValue, ToCond, ToTrueExpr, ToFalseExpr,
      ToQuestionLoc, ToColonLoc, ToType, E->getValueKind(),
      E->getObjectKind());
}

ExpectedStmt ASTNodeImporter::VisitCXXRewrittenBinaryOperator(
    CXXRewrittenBinaryOperator *E) {
  Error Err = Error::success();
  auto ToSemanticForm = importChecked(Err, E->getSemanticForm());
  if (Err)
    return std::move(Err);

  return new (Importer.getToContext())
      CXXRewrittenBinaryOperator(ToSemanticForm, E->isReversed());
}

ExpectedStmt ASTNodeImporter::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E) {
  Error Err = Error::success();
  auto ToBeginLoc = importChecked(Err, E->getBeginLoc());
  auto ToQueriedTypeSourceInfo =
      importChecked(Err, E->getQueriedTypeSourceInfo());
  auto ToDimensionExpression = importChecked(Err, E->getDimensionExpression());
  auto ToEndLoc = importChecked(Err, E->getEndLoc());
  auto ToType = importChecked(Err, E->getType());
  if (Err)
    return std::move(Err);

  return new (Importer.getToContext()) ArrayTypeTraitExpr(
      ToBeginLoc, E->getTrait(), ToQueriedTypeSourceInfo, E->getValue(),
      ToDimensionExpression, ToEndLoc, ToType);
}

ExpectedStmt ASTNodeImporter::VisitExpressionTraitExpr(ExpressionTraitExpr *E) {
  Error Err = Error::success();
  auto ToBeginLoc = importChecked(Err, E->getBeginLoc());
  auto ToQueriedExpression = importChecked(Err, E->getQueriedExpression());
  auto ToEndLoc = importChecked(Err, E->getEndLoc());
  auto ToType = importChecked(Err, E->getType());
  if (Err)
    return std::move(Err);

  return new (Importer.getToContext()) ExpressionTraitExpr(
      ToBeginLoc, E->getTrait(), ToQueriedExpression, E->getValue(),
      ToEndLoc, ToType);
}

ExpectedStmt ASTNodeImporter::VisitOpaqueValueExpr(OpaqueValueExpr *E) {
  Error Err = Error::success();
  auto ToLocation = importChecked(Err, E->getLocation());
  auto ToType = importChecked(Err, E->getType());
  auto ToSourceExpr = importChecked(Err, E->getSourceExpr());
  if (Err)
    return std::move(Err);

  return new (Importer.getToContext()) OpaqueValueExpr(
      ToLocation, ToType, E->getValueKind(), E->getObjectKind(), ToSourceExpr);
}

ExpectedStmt ASTNodeImporter::VisitArraySubscriptExpr(ArraySubscriptExpr *E) {
  Error Err = Error::success();
  auto ToLHS = importChecked(Err, E->getLHS());
  auto ToRHS = importChecked(Err, E->getRHS());
  auto ToType = importChecked(Err, E->getType());
  auto ToRBracketLoc = importChecked(Err, E->getRBracketLoc());
  if (Err)
    return std::move(Err);

  return new (Importer.getToContext()) ArraySubscriptExpr(
      ToLHS, ToRHS, ToType, E->getValueKind(), E->getObjectKind(),
      ToRBracketLoc);
}

ExpectedStmt
ASTNodeImporter::VisitCompoundAssignOperator(CompoundAssignOperator *E) {
  Error Err = Error::success();
  auto ToLHS = importChecked(Err, E->getLHS());
  auto ToRHS = importChecked(Err, E->getRHS());
  auto ToType = importChecked(Err, E->getType());
  auto ToComputationLHSType = importChecked(Err, E->getComputationLHSType());
  auto ToComputationResultType =
      importChecked(Err, E->getComputationResultType());
  auto ToOperatorLoc = importChecked(Err, E->getOperatorLoc());
  if (Err)
    return std::move(Err);

  return CompoundAssignOperator::Create(
      Importer.getToContext(), ToLHS, ToRHS, E->getOpcode(), ToType,
      E->getValueKind(), E->getObjectKind(), ToOperatorLoc,
      E->getFPFeatures(),
      ToComputationLHSType, ToComputationResultType);
}

Expected<CXXCastPath>
ASTNodeImporter::ImportCastPath(CastExpr *CE) {
  CXXCastPath Path;
  for (auto I = CE->path_begin(), E = CE->path_end(); I != E; ++I) {
    if (auto SpecOrErr = import(*I))
      Path.push_back(*SpecOrErr);
    else
      return SpecOrErr.takeError();
  }
  return Path;
}

ExpectedStmt ASTNodeImporter::VisitImplicitCastExpr(ImplicitCastExpr *E) {
  ExpectedType ToTypeOrErr = import(E->getType());
  if (!ToTypeOrErr)
    return ToTypeOrErr.takeError();

  ExpectedExpr ToSubExprOrErr = import(E->getSubExpr());
  if (!ToSubExprOrErr)
    return ToSubExprOrErr.takeError();

  Expected<CXXCastPath> ToBasePathOrErr = ImportCastPath(E);
  if (!ToBasePathOrErr)
    return ToBasePathOrErr.takeError();

  return ImplicitCastExpr::Create(
      Importer.getToContext(), *ToTypeOrErr, E->getCastKind(), *ToSubExprOrErr,
      &(*ToBasePathOrErr), E->getValueKind(), E->getFPFeatures());
}

ExpectedStmt ASTNodeImporter::VisitExplicitCastExpr(ExplicitCastExpr *E) {
  Error Err = Error::success();
  auto ToType = importChecked(Err, E->getType());
  auto ToSubExpr = importChecked(Err, E->getSubExpr());
  auto ToTypeInfoAsWritten = importChecked(Err, E->getTypeInfoAsWritten());
  if (Err)
    return std::move(Err);

  Expected<CXXCastPath> ToBasePathOrErr = ImportCastPath(E);
  if (!ToBasePathOrErr)
    return ToBasePathOrErr.takeError();
  CXXCastPath *ToBasePath = &(*ToBasePathOrErr);

  switch (E->getStmtClass()) {
  case Stmt::CStyleCastExprClass: {
    auto *CCE = cast<CStyleCastExpr>(E);
    ExpectedSLoc ToLParenLocOrErr = import(CCE->getLParenLoc());
    if (!ToLParenLocOrErr)
      return ToLParenLocOrErr.takeError();
    ExpectedSLoc ToRParenLocOrErr = import(CCE->getRParenLoc());
    if (!ToRParenLocOrErr)
      return ToRParenLocOrErr.takeError();
    return CStyleCastExpr::Create(
        Importer.getToContext(), ToType, E->getValueKind(), E->getCastKind(),
        ToSubExpr, ToBasePath, CCE->getFPFeatures(), ToTypeInfoAsWritten,
        *ToLParenLocOrErr, *ToRParenLocOrErr);
  }

  case Stmt::CXXFunctionalCastExprClass: {
    auto *FCE = cast<CXXFunctionalCastExpr>(E);
    ExpectedSLoc ToLParenLocOrErr = import(FCE->getLParenLoc());
    if (!ToLParenLocOrErr)
      return ToLParenLocOrErr.takeError();
    ExpectedSLoc ToRParenLocOrErr = import(FCE->getRParenLoc());
    if (!ToRParenLocOrErr)
      return ToRParenLocOrErr.takeError();
    return CXXFunctionalCastExpr::Create(
        Importer.getToContext(), ToType, E->getValueKind(), ToTypeInfoAsWritten,
        E->getCastKind(), ToSubExpr, ToBasePath, FCE->getFPFeatures(),
        *ToLParenLocOrErr, *ToRParenLocOrErr);
  }

  case Stmt::ObjCBridgedCastExprClass: {
    auto *OCE = cast<ObjCBridgedCastExpr>(E);
    ExpectedSLoc ToLParenLocOrErr = import(OCE->getLParenLoc());
    if (!ToLParenLocOrErr)
      return ToLParenLocOrErr.takeError();
    ExpectedSLoc ToBridgeKeywordLocOrErr = import(OCE->getBridgeKeywordLoc());
    if (!ToBridgeKeywordLocOrErr)
      return ToBridgeKeywordLocOrErr.takeError();
    return new (Importer.getToContext()) ObjCBridgedCastExpr(
        *ToLParenLocOrErr, OCE->getBridgeKind(), E->getCastKind(),
        *ToBridgeKeywordLocOrErr, ToTypeInfoAsWritten, ToSubExpr);
  }
  case Stmt::BuiltinBitCastExprClass: {
    auto *BBC = cast<BuiltinBitCastExpr>(E);
    ExpectedSLoc ToKWLocOrErr = import(BBC->getBeginLoc());
    if (!ToKWLocOrErr)
      return ToKWLocOrErr.takeError();
    ExpectedSLoc ToRParenLocOrErr = import(BBC->getEndLoc());
    if (!ToRParenLocOrErr)
      return ToRParenLocOrErr.takeError();
    return new (Importer.getToContext()) BuiltinBitCastExpr(
        ToType, E->getValueKind(), E->getCastKind(), ToSubExpr,
        ToTypeInfoAsWritten, *ToKWLocOrErr, *ToRParenLocOrErr);
  }
  default:
    llvm_unreachable("Cast expression of unsupported type!");
    return make_error<ASTImportError>(ASTImportError::UnsupportedConstruct);
  }
}

ExpectedStmt ASTNodeImporter::VisitOffsetOfExpr(OffsetOfExpr *E) {
  SmallVector<OffsetOfNode, 4> ToNodes;
  for (int I = 0, N = E->getNumComponents(); I < N; ++I) {
    const OffsetOfNode &FromNode = E->getComponent(I);

    SourceLocation ToBeginLoc, ToEndLoc;

    if (FromNode.getKind() != OffsetOfNode::Base) {
      Error Err = Error::success();
      ToBeginLoc = importChecked(Err, FromNode.getBeginLoc());
      ToEndLoc = importChecked(Err, FromNode.getEndLoc());
      if (Err)
        return std::move(Err);
    }

    switch (FromNode.getKind()) {
    case OffsetOfNode::Array:
      ToNodes.push_back(
          OffsetOfNode(ToBeginLoc, FromNode.getArrayExprIndex(), ToEndLoc));
      break;
    case OffsetOfNode::Base: {
      auto ToBSOrErr = import(FromNode.getBase());
      if (!ToBSOrErr)
        return ToBSOrErr.takeError();
      ToNodes.push_back(OffsetOfNode(*ToBSOrErr));
      break;
    }
    case OffsetOfNode::Field: {
      auto ToFieldOrErr = import(FromNode.getField());
      if (!ToFieldOrErr)
        return ToFieldOrErr.takeError();
      ToNodes.push_back(OffsetOfNode(ToBeginLoc, *ToFieldOrErr, ToEndLoc));
      break;
    }
    case OffsetOfNode::Identifier: {
      IdentifierInfo *ToII = Importer.Import(FromNode.getFieldName());
      ToNodes.push_back(OffsetOfNode(ToBeginLoc, ToII, ToEndLoc));
      break;
    }
    }
  }

  SmallVector<Expr *, 4> ToExprs(E->getNumExpressions());
  for (int I = 0, N = E->getNumExpressions(); I < N; ++I) {
    ExpectedExpr ToIndexExprOrErr = import(E->getIndexExpr(I));
    if (!ToIndexExprOrErr)
      return ToIndexExprOrErr.takeError();
    ToExprs[I] = *ToIndexExprOrErr;
  }

  Error Err = Error::success();
  auto ToType = importChecked(Err, E->getType());
  auto ToTypeSourceInfo = importChecked(Err, E->getTypeSourceInfo());
  auto ToOperatorLoc = importChecked(Err, E->getOperatorLoc());
  auto ToRParenLoc = importChecked(Err, E->getRParenLoc());
  if (Err)
    return std::move(Err);

  return OffsetOfExpr::Create(
      Importer.getToContext(), ToType, ToOperatorLoc, ToTypeSourceInfo, ToNodes,
      ToExprs, ToRParenLoc);
}

ExpectedStmt ASTNodeImporter::VisitCXXNoexceptExpr(CXXNoexceptExpr *E) {
  Error Err = Error::success();
  auto ToType = importChecked(Err, E->getType());
  auto ToOperand = importChecked(Err, E->getOperand());
  auto ToBeginLoc = importChecked(Err, E->getBeginLoc());
  auto ToEndLoc = importChecked(Err, E->getEndLoc());
  if (Err)
    return std::move(Err);

  CanThrowResult ToCanThrow;
  if (E->isValueDependent())
    ToCanThrow = CT_Dependent;
  else
    ToCanThrow = E->getValue() ? CT_Can : CT_Cannot;

  return new (Importer.getToContext()) CXXNoexceptExpr(
      ToType, ToOperand, ToCanThrow, ToBeginLoc, ToEndLoc);
}

ExpectedStmt ASTNodeImporter::VisitCXXThrowExpr(CXXThrowExpr *E) {
  Error Err = Error::success();
  auto ToSubExpr = importChecked(Err, E->getSubExpr());
  auto ToType = importChecked(Err, E->getType());
  auto ToThrowLoc = importChecked(Err, E->getThrowLoc());
  if (Err)
    return std::move(Err);

  return new (Importer.getToContext()) CXXThrowExpr(
      ToSubExpr, ToType, ToThrowLoc, E->isThrownVariableInScope());
}

ExpectedStmt ASTNodeImporter::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) {
  ExpectedSLoc ToUsedLocOrErr = import(E->getUsedLocation());
  if (!ToUsedLocOrErr)
    return ToUsedLocOrErr.takeError();

  auto ToParamOrErr = import(E->getParam());
  if (!ToParamOrErr)
    return ToParamOrErr.takeError();

  auto UsedContextOrErr = Importer.ImportContext(E->getUsedContext());
  if (!UsedContextOrErr)
    return UsedContextOrErr.takeError();

  // Import the default arg if it was not imported yet.
  // This is needed because it can happen that during the import of the
  // default expression (from VisitParmVarDecl) the same ParmVarDecl is
  // encountered here. The default argument for a ParmVarDecl is set in the
  // ParmVarDecl only after it is imported (set in VisitParmVarDecl if not here,
  // see VisitParmVarDecl).
  ParmVarDecl *ToParam = *ToParamOrErr;
  if (!ToParam->getDefaultArg()) {
    std::optional<ParmVarDecl *> FromParam =
        Importer.getImportedFromDecl(ToParam);
    assert(FromParam && "ParmVarDecl was not imported?");

    if (Error Err = ImportDefaultArgOfParmVarDecl(*FromParam, ToParam))
      return std::move(Err);
  }
  Expr *RewrittenInit = nullptr;
  if (E->hasRewrittenInit()) {
    ExpectedExpr ExprOrErr = import(E->getRewrittenExpr());
    if (!ExprOrErr)
      return ExprOrErr.takeError();
    RewrittenInit = ExprOrErr.get();
  }
  return CXXDefaultArgExpr::Create(Importer.getToContext(), *ToUsedLocOrErr,
                                   *ToParamOrErr, RewrittenInit,
                                   *UsedContextOrErr);
}

ExpectedStmt
ASTNodeImporter::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) {
  Error Err = Error::success();
  auto ToType = importChecked(Err, E->getType());
  auto ToTypeSourceInfo = importChecked(Err, E->getTypeSourceInfo());
  auto ToRParenLoc = importChecked(Err, E->getRParenLoc());
  if (Err)
    return std::move(Err);

  return new (Importer.getToContext()) CXXScalarValueInitExpr(
      ToType, ToTypeSourceInfo, ToRParenLoc);
}

ExpectedStmt
ASTNodeImporter::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) {
  ExpectedExpr ToSubExprOrErr = import(E->getSubExpr());
  if (!ToSubExprOrErr)
    return ToSubExprOrErr.takeError();

  auto ToDtorOrErr = import(E->getTemporary()->getDestructor());
  if (!ToDtorOrErr)
    return ToDtorOrErr.takeError();

  ASTContext &ToCtx = Importer.getToContext();
  CXXTemporary *Temp = CXXTemporary::Create(ToCtx, *ToDtorOrErr);
  return CXXBindTemporaryExpr::Create(ToCtx, Temp, *ToSubExprOrErr);
}

ExpectedStmt

ASTNodeImporter::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E) {
  Error Err = Error::success();
  auto ToConstructor = importChecked(Err, E->getConstructor());
  auto ToType = importChecked(Err, E->getType());
  auto ToTypeSourceInfo = importChecked(Err, E->getTypeSourceInfo());
  auto ToParenOrBraceRange = importChecked(Err, E->getParenOrBraceRange());
  if (Err)
    return std::move(Err);

  SmallVector<Expr *, 8> ToArgs(E->getNumArgs());
  if (Error Err = ImportContainerChecked(E->arguments(), ToArgs))
    return std::move(Err);

  return CXXTemporaryObjectExpr::Create(
      Importer.getToContext(), ToConstructor, ToType, ToTypeSourceInfo, ToArgs,
      ToParenOrBraceRange, E->hadMultipleCandidates(),
      E->isListInitialization(), E->isStdInitListInitialization(),
      E->requiresZeroInitialization());
}

ExpectedDecl ASTNodeImporter::VisitLifetimeExtendedTemporaryDecl(
    LifetimeExtendedTemporaryDecl *D) {
  DeclContext *DC, *LexicalDC;
  if (Error Err = ImportDeclContext(D, DC, LexicalDC))
    return std::move(Err);

  Error Err = Error::success();
  auto Temporary = importChecked(Err, D->getTemporaryExpr());
  auto ExtendingDecl = importChecked(Err, D->getExtendingDecl());
  if (Err)
    return std::move(Err);
  // FIXME: Should ManglingNumber get numbers associated with 'to' context?

  LifetimeExtendedTemporaryDecl *To;
  if (GetImportedOrCreateDecl(To, D, Temporary, ExtendingDecl,
                              D->getManglingNumber()))
    return To;

  To->setLexicalDeclContext(LexicalDC);
  LexicalDC->addDeclInternal(To);
  return To;
}

ExpectedStmt
ASTNodeImporter::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E) {
  Error Err = Error::success();
  auto ToType = importChecked(Err, E->getType());
  Expr *ToTemporaryExpr = importChecked(
      Err, E->getLifetimeExtendedTemporaryDecl() ? nullptr : E->getSubExpr());
  auto ToMaterializedDecl =
      importChecked(Err, E->getLifetimeExtendedTemporaryDecl());
  if (Err)
    return std::move(Err);

  if (!ToTemporaryExpr)
    ToTemporaryExpr = cast<Expr>(ToMaterializedDecl->getTemporaryExpr());

  auto *ToMTE = new (Importer.getToContext()) MaterializeTemporaryExpr(
      ToType, ToTemporaryExpr, E->isBoundToLvalueReference(),
      ToMaterializedDecl);

  return ToMTE;
}

ExpectedStmt ASTNodeImporter::VisitPackExpansionExpr(PackExpansionExpr *E) {
  Error Err = Error::success();
  auto *ToPattern = importChecked(Err, E->getPattern());
  auto ToEllipsisLoc = importChecked(Err, E->getEllipsisLoc());
  if (Err)
    return std::move(Err);

  return new (Importer.getToContext())
      PackExpansionExpr(ToPattern, ToEllipsisLoc, E->getNumExpansions());
}

ExpectedStmt ASTNodeImporter::VisitSizeOfPackExpr(SizeOfPackExpr *E) {
  Error Err = Error::success();
  auto ToOperatorLoc = importChecked(Err, E->getOperatorLoc());
  auto ToPack = importChecked(Err, E->getPack());
  auto ToPackLoc = importChecked(Err, E->getPackLoc());
  auto ToRParenLoc = importChecked(Err, E->getRParenLoc());
  if (Err)
    return std::move(Err);

  UnsignedOrNone Length = std::nullopt;
  if (!E->isValueDependent())
    Length = E->getPackLength();

  SmallVector<TemplateArgument, 8> ToPartialArguments;
  if (E->isPartiallySubstituted()) {
    if (Error Err = ImportTemplateArguments(E->getPartialArguments(),
                                            ToPartialArguments))
      return std::move(Err);
  }

  return SizeOfPackExpr::Create(
      Importer.getToContext(), ToOperatorLoc, ToPack, ToPackLoc, ToRParenLoc,
      Length, ToPartialArguments);
}


ExpectedStmt ASTNodeImporter::VisitCXXNewExpr(CXXNewExpr *E) {
  Error Err = Error::success();
  auto ToOperatorNew = importChecked(Err, E->getOperatorNew());
  auto ToOperatorDelete = importChecked(Err, E->getOperatorDelete());
  auto ToTypeIdParens = importChecked(Err, E->getTypeIdParens());
  auto ToArraySize = importChecked(Err, E->getArraySize());
  auto ToInitializer = importChecked(Err, E->getInitializer());
  auto ToType = importChecked(Err, E->getType());
  auto ToAllocatedTypeSourceInfo =
      importChecked(Err, E->getAllocatedTypeSourceInfo());
  auto ToSourceRange = importChecked(Err, E->getSourceRange());
  auto ToDirectInitRange = importChecked(Err, E->getDirectInitRange());
  if (Err)
    return std::move(Err);

  SmallVector<Expr *, 4> ToPlacementArgs(E->getNumPlacementArgs());
  if (Error Err =
      ImportContainerChecked(E->placement_arguments(), ToPlacementArgs))
    return std::move(Err);

  return CXXNewExpr::Create(
      Importer.getToContext(), E->isGlobalNew(), ToOperatorNew,
      ToOperatorDelete, E->implicitAllocationParameters(),
      E->doesUsualArrayDeleteWantSize(), ToPlacementArgs, ToTypeIdParens,
      ToArraySize, E->getInitializationStyle(), ToInitializer, ToType,
      ToAllocatedTypeSourceInfo, ToSourceRange, ToDirectInitRange);
}

ExpectedStmt ASTNodeImporter::VisitCXXDeleteExpr(CXXDeleteExpr *E) {
  Error Err = Error::success();
  auto ToType = importChecked(Err, E->getType());
  auto ToOperatorDelete = importChecked(Err, E->getOperatorDelete());
  auto ToArgument = importChecked(Err, E->getArgument());
  auto ToBeginLoc = importChecked(Err, E->getBeginLoc());
  if (Err)
    return std::move(Err);

  return new (Importer.getToContext()) CXXDeleteExpr(
      ToType, E->isGlobalDelete(), E->isArrayForm(), E->isArrayFormAsWritten(),
      E->doesUsualArrayDeleteWantSize(), ToOperatorDelete, ToArgument,
      ToBeginLoc);
}

ExpectedStmt ASTNodeImporter::VisitCXXConstructExpr(CXXConstructExpr *E) {
  Error Err = Error::success();
  auto ToType = importChecked(Err, E->getType());
  auto ToLocation = importChecked(Err, E->getLocation());
  auto ToConstructor = importChecked(Err, E->getConstructor());
  auto ToParenOrBraceRange = importChecked(Err, E->getParenOrBraceRange());
  if (Err)
    return std::move(Err);

  SmallVector<Expr *, 6> ToArgs(E->getNumArgs());
  if (Error Err = ImportContainerChecked(E->arguments(), ToArgs))
    return std::move(Err);

  CXXConstructExpr *ToE = CXXConstructExpr::Create(
      Importer.getToContext(), ToType, ToLocation, ToConstructor,
      E->isElidable(), ToArgs, E->hadMultipleCandidates(),
      E->isListInitialization(), E->isStdInitListInitialization(),
      E->requiresZeroInitialization(), E->getConstructionKind(),
      ToParenOrBraceRange);
  ToE->setIsImmediateEscalating(E->isImmediateEscalating());
  return ToE;
}

ExpectedStmt ASTNodeImporter::VisitExprWithCleanups(ExprWithCleanups *E) {
  ExpectedExpr ToSubExprOrErr = import(E->getSubExpr());
  if (!ToSubExprOrErr)
    return ToSubExprOrErr.takeError();

  SmallVector<ExprWithCleanups::CleanupObject, 8> ToObjects(E->getNumObjects());
  if (Error Err = ImportContainerChecked(E->getObjects(), ToObjects))
    return std::move(Err);

  return ExprWithCleanups::Create(
      Importer.getToContext(), *ToSubExprOrErr, E->cleanupsHaveSideEffects(),
      ToObjects);
}

ExpectedStmt ASTNodeImporter::VisitCXXMemberCallExpr(CXXMemberCallExpr *E) {
  Error Err = Error::success();
  auto ToCallee = importChecked(Err, E->getCallee());
  auto ToType = importChecked(Err, E->getType());
  auto ToRParenLoc = importChecked(Err, E->getRParenLoc());
  if (Err)
    return std::move(Err);

  SmallVector<Expr *, 4> ToArgs(E->getNumArgs());
  if (Error Err = ImportContainerChecked(E->arguments(), ToArgs))
    return std::move(Err);

  return CXXMemberCallExpr::Create(Importer.getToContext(), ToCallee, ToArgs,
                                   ToType, E->getValueKind(), ToRParenLoc,
                                   E->getFPFeatures());
}

ExpectedStmt ASTNodeImporter::VisitCXXThisExpr(CXXThisExpr *E) {
  ExpectedType ToTypeOrErr = import(E->getType());
  if (!ToTypeOrErr)
    return ToTypeOrErr.takeError();

  ExpectedSLoc ToLocationOrErr = import(E->getLocation());
  if (!ToLocationOrErr)
    return ToLocationOrErr.takeError();

  return CXXThisExpr::Create(Importer.getToContext(), *ToLocationOrErr,
                             *ToTypeOrErr, E->isImplicit());
}

ExpectedStmt ASTNodeImporter::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) {
  ExpectedType ToTypeOrErr = import(E->getType());
  if (!ToTypeOrErr)
    return ToTypeOrErr.takeError();

  ExpectedSLoc ToLocationOrErr = import(E->getLocation());
  if (!ToLocationOrErr)
    return ToLocationOrErr.takeError();

  return CXXBoolLiteralExpr::Create(Importer.getToContext(), E->getValue(),
                                    *ToTypeOrErr, *ToLocationOrErr);
}

ExpectedStmt ASTNodeImporter::VisitMemberExpr(MemberExpr *E) {
  Error Err = Error::success();
  auto ToBase = importChecked(Err, E->getBase());
  auto ToOperatorLoc = importChecked(Err, E->getOperatorLoc());
  auto ToQualifierLoc = importChecked(Err, E->getQualifierLoc());
  auto ToTemplateKeywordLoc = importChecked(Err, E->getTemplateKeywordLoc());
  auto ToMemberDecl = importChecked(Err, E->getMemberDecl());
  auto ToType = importChecked(Err, E->getType());
  auto ToDecl = importChecked(Err, E->getFoundDecl().getDecl());
  auto ToName = importChecked(Err, E->getMemberNameInfo().getName());
  auto ToLoc = importChecked(Err, E->getMemberNameInfo().getLoc());
  if (Err)
    return std::move(Err);

  DeclAccessPair ToFoundDecl =
      DeclAccessPair::make(ToDecl, E->getFoundDecl().getAccess());

  DeclarationNameInfo ToMemberNameInfo(ToName, ToLoc);

  TemplateArgumentListInfo ToTAInfo, *ResInfo = nullptr;
  if (E->hasExplicitTemplateArgs()) {
    if (Error Err =
            ImportTemplateArgumentListInfo(E->getLAngleLoc(), E->getRAngleLoc(),
                                           E->template_arguments(), ToTAInfo))
      return std::move(Err);
    ResInfo = &ToTAInfo;
  }

  return MemberExpr::Create(Importer.getToContext(), ToBase, E->isArrow(),
                            ToOperatorLoc, ToQualifierLoc, ToTemplateKeywordLoc,
                            ToMemberDecl, ToFoundDecl, ToMemberNameInfo,
                            ResInfo, ToType, E->getValueKind(),
                            E->getObjectKind(), E->isNonOdrUse());
}

ExpectedStmt
ASTNodeImporter::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) {
  Error Err = Error::success();
  auto ToBase = importChecked(Err, E->getBase());
  auto ToOperatorLoc = importChecked(Err, E->getOperatorLoc());
  auto ToQualifierLoc = importChecked(Err, E->getQualifierLoc());
  auto ToScopeTypeInfo = importChecked(Err, E->getScopeTypeInfo());
  auto ToColonColonLoc = importChecked(Err, E->getColonColonLoc());
  auto ToTildeLoc = importChecked(Err, E->getTildeLoc());
  if (Err)
    return std::move(Err);

  PseudoDestructorTypeStorage Storage;
  if (const IdentifierInfo *FromII = E->getDestroyedTypeIdentifier()) {
    const IdentifierInfo *ToII = Importer.Import(FromII);
    ExpectedSLoc ToDestroyedTypeLocOrErr = import(E->getDestroyedTypeLoc());
    if (!ToDestroyedTypeLocOrErr)
      return ToDestroyedTypeLocOrErr.takeError();
    Storage = PseudoDestructorTypeStorage(ToII, *ToDestroyedTypeLocOrErr);
  } else {
    if (auto ToTIOrErr = import(E->getDestroyedTypeInfo()))
      Storage = PseudoDestructorTypeStorage(*ToTIOrErr);
    else
      return ToTIOrErr.takeError();
  }

  return new (Importer.getToContext()) CXXPseudoDestructorExpr(
      Importer.getToContext(), ToBase, E->isArrow(), ToOperatorLoc,
      ToQualifierLoc, ToScopeTypeInfo, ToColonColonLoc, ToTildeLoc, Storage);
}

ExpectedStmt ASTNodeImporter::VisitCXXDependentScopeMemberExpr(
    CXXDependentScopeMemberExpr *E) {
  Error Err = Error::success();
  auto ToType = importChecked(Err, E->getType());
  auto ToOperatorLoc = importChecked(Err, E->getOperatorLoc());
  auto ToQualifierLoc = importChecked(Err, E->getQualifierLoc());
  auto ToTemplateKeywordLoc = importChecked(Err, E->getTemplateKeywordLoc());
  auto ToFirstQualifierFoundInScope =
      importChecked(Err, E->getFirstQualifierFoundInScope());
  if (Err)
    return std::move(Err);

  Expr *ToBase = nullptr;
  if (!E->isImplicitAccess()) {
    if (ExpectedExpr ToBaseOrErr = import(E->getBase()))
      ToBase = *ToBaseOrErr;
    else
      return ToBaseOrErr.takeError();
  }

  TemplateArgumentListInfo ToTAInfo, *ResInfo = nullptr;

  if (E->hasExplicitTemplateArgs()) {
    if (Error Err =
            ImportTemplateArgumentListInfo(E->getLAngleLoc(), E->getRAngleLoc(),
                                           E->template_arguments(), ToTAInfo))
      return std::move(Err);
    ResInfo = &ToTAInfo;
  }
  auto ToMember = importChecked(Err, E->getMember());
  auto ToMemberLoc = importChecked(Err, E->getMemberLoc());
  if (Err)
    return std::move(Err);
  DeclarationNameInfo ToMemberNameInfo(ToMember, ToMemberLoc);

  // Import additional name location/type info.
  if (Error Err =
          ImportDeclarationNameLoc(E->getMemberNameInfo(), ToMemberNameInfo))
    return std::move(Err);

  return CXXDependentScopeMemberExpr::Create(
      Importer.getToContext(), ToBase, ToType, E->isArrow(), ToOperatorLoc,
      ToQualifierLoc, ToTemplateKeywordLoc, ToFirstQualifierFoundInScope,
      ToMemberNameInfo, ResInfo);
}

ExpectedStmt
ASTNodeImporter::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) {
  Error Err = Error::success();
  auto ToQualifierLoc = importChecked(Err, E->getQualifierLoc());
  auto ToTemplateKeywordLoc = importChecked(Err, E->getTemplateKeywordLoc());
  auto ToDeclName = importChecked(Err, E->getDeclName());
  auto ToNameLoc = importChecked(Err, E->getNameInfo().getLoc());
  auto ToLAngleLoc = importChecked(Err, E->getLAngleLoc());
  auto ToRAngleLoc = importChecked(Err, E->getRAngleLoc());
  if (Err)
    return std::move(Err);

  DeclarationNameInfo ToNameInfo(ToDeclName, ToNameLoc);
  if (Error Err = ImportDeclarationNameLoc(E->getNameInfo(), ToNameInfo))
    return std::move(Err);

  TemplateArgumentListInfo ToTAInfo(ToLAngleLoc, ToRAngleLoc);
  TemplateArgumentListInfo *ResInfo = nullptr;
  if (E->hasExplicitTemplateArgs()) {
    if (Error Err =
        ImportTemplateArgumentListInfo(E->template_arguments(), ToTAInfo))
      return std::move(Err);
    ResInfo = &ToTAInfo;
  }

  return DependentScopeDeclRefExpr::Create(
      Importer.getToContext(), ToQualifierLoc, ToTemplateKeywordLoc,
      ToNameInfo, ResInfo);
}

ExpectedStmt ASTNodeImporter::VisitCXXUnresolvedConstructExpr(
    CXXUnresolvedConstructExpr *E) {
  Error Err = Error::success();
  auto ToLParenLoc = importChecked(Err, E->getLParenLoc());
  auto ToRParenLoc = importChecked(Err, E->getRParenLoc());
  auto ToType = importChecked(Err, E->getType());
  auto ToTypeSourceInfo = importChecked(Err, E->getTypeSourceInfo());
  if (Err)
    return std::move(Err);

  SmallVector<Expr *, 8> ToArgs(E->getNumArgs());
  if (Error Err =
      ImportArrayChecked(E->arg_begin(), E->arg_end(), ToArgs.begin()))
    return std::move(Err);

  return CXXUnresolvedConstructExpr::Create(
      Importer.getToContext(), ToType, ToTypeSourceInfo, ToLParenLoc,
      ArrayRef(ToArgs), ToRParenLoc, E->isListInitialization());
}

ExpectedStmt
ASTNodeImporter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) {
  Expected<CXXRecordDecl *> ToNamingClassOrErr = import(E->getNamingClass());
  if (!ToNamingClassOrErr)
    return ToNamingClassOrErr.takeError();

  auto ToQualifierLocOrErr = import(E->getQualifierLoc());
  if (!ToQualifierLocOrErr)
    return ToQualifierLocOrErr.takeError();

  Error Err = Error::success();
  auto ToName = importChecked(Err, E->getName());
  auto ToNameLoc = importChecked(Err, E->getNameLoc());
  if (Err)
    return std::move(Err);
  DeclarationNameInfo ToNameInfo(ToName, ToNameLoc);

  // Import additional name location/type info.
  if (Error Err = ImportDeclarationNameLoc(E->getNameInfo(), ToNameInfo))
    return std::move(Err);

  UnresolvedSet<8> ToDecls;
  for (auto *D : E->decls())
    if (auto ToDOrErr = import(D))
      ToDecls.addDecl(cast<NamedDecl>(*ToDOrErr));
    else
      return ToDOrErr.takeError();

  if (E->hasExplicitTemplateArgs()) {
    TemplateArgumentListInfo ToTAInfo;
    if (Error Err = ImportTemplateArgumentListInfo(
        E->getLAngleLoc(), E->getRAngleLoc(), E->template_arguments(),
        ToTAInfo))
      return std::move(Err);

    ExpectedSLoc ToTemplateKeywordLocOrErr = import(E->getTemplateKeywordLoc());
    if (!ToTemplateKeywordLocOrErr)
      return ToTemplateKeywordLocOrErr.takeError();

    const bool KnownDependent =
        (E->getDependence() & ExprDependence::TypeValue) ==
        ExprDependence::TypeValue;
    return UnresolvedLookupExpr::Create(
        Importer.getToContext(), *ToNamingClassOrErr, *ToQualifierLocOrErr,
        *ToTemplateKeywordLocOrErr, ToNameInfo, E->requiresADL(), &ToTAInfo,
        ToDecls.begin(), ToDecls.end(), KnownDependent,
        /*KnownInstantiationDependent=*/E->isInstantiationDependent());
  }

  return UnresolvedLookupExpr::Create(
      Importer.getToContext(), *ToNamingClassOrErr, *ToQualifierLocOrErr,
      ToNameInfo, E->requiresADL(), ToDecls.begin(), ToDecls.end(),
      /*KnownDependent=*/E->isTypeDependent(),
      /*KnownInstantiationDependent=*/E->isInstantiationDependent());
}

ExpectedStmt
ASTNodeImporter::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E) {
  Error Err = Error::success();
  auto ToType = importChecked(Err, E->getType());
  auto ToOperatorLoc = importChecked(Err, E->getOperatorLoc());
  auto ToQualifierLoc = importChecked(Err, E->getQualifierLoc());
  auto ToTemplateKeywordLoc = importChecked(Err, E->getTemplateKeywordLoc());
  auto ToName = importChecked(Err, E->getName());
  auto ToNameLoc = importChecked(Err, E->getNameLoc());
  if (Err)
    return std::move(Err);

  DeclarationNameInfo ToNameInfo(ToName, ToNameLoc);
  // Import additional name location/type info.
  if (Error Err = ImportDeclarationNameLoc(E->getNameInfo(), ToNameInfo))
    return std::move(Err);

  UnresolvedSet<8> ToDecls;
  for (Decl *D : E->decls())
    if (auto ToDOrErr = import(D))
      ToDecls.addDecl(cast<NamedDecl>(*ToDOrErr));
    else
      return ToDOrErr.takeError();

  TemplateArgumentListInfo ToTAInfo;
  TemplateArgumentListInfo *ResInfo = nullptr;
  if (E->hasExplicitTemplateArgs()) {
    TemplateArgumentListInfo FromTAInfo;
    E->copyTemplateArgumentsInto(FromTAInfo);
    if (Error Err = ImportTemplateArgumentListInfo(FromTAInfo, ToTAInfo))
      return std::move(Err);
    ResInfo = &ToTAInfo;
  }

  Expr *ToBase = nullptr;
  if (!E->isImplicitAccess()) {
    if (ExpectedExpr ToBaseOrErr = import(E->getBase()))
      ToBase = *ToBaseOrErr;
    else
      return ToBaseOrErr.takeError();
  }

  return UnresolvedMemberExpr::Create(
      Importer.getToContext(), E->hasUnresolvedUsing(), ToBase, ToType,
      E->isArrow(), ToOperatorLoc, ToQualifierLoc, ToTemplateKeywordLoc,
      ToNameInfo, ResInfo, ToDecls.begin(), ToDecls.end());
}

ExpectedStmt ASTNodeImporter::VisitCallExpr(CallExpr *E) {
  Error Err = Error::success();
  auto ToCallee = importChecked(Err, E->getCallee());
  auto ToType = importChecked(Err, E->getType());
  auto ToRParenLoc = importChecked(Err, E->getRParenLoc());
  if (Err)
    return std::move(Err);

  unsigned NumArgs = E->getNumArgs();
  llvm::SmallVector<Expr *, 2> ToArgs(NumArgs);
  if (Error Err = ImportContainerChecked(E->arguments(), ToArgs))
     return std::move(Err);

  if (const auto *OCE = dyn_cast<CXXOperatorCallExpr>(E)) {
    return CXXOperatorCallExpr::Create(
        Importer.getToContext(), OCE->getOperator(), ToCallee, ToArgs, ToType,
        OCE->getValueKind(), ToRParenLoc, OCE->getFPFeatures(),
        OCE->getADLCallKind());
  }

  return CallExpr::Create(Importer.getToContext(), ToCallee, ToArgs, ToType,
                          E->getValueKind(), ToRParenLoc, E->getFPFeatures(),
                          /*MinNumArgs=*/0, E->getADLCallKind());
}

ExpectedStmt ASTNodeImporter::VisitLambdaExpr(LambdaExpr *E) {
  CXXRecordDecl *FromClass = E->getLambdaClass();
  auto ToClassOrErr = import(FromClass);
  if (!ToClassOrErr)
    return ToClassOrErr.takeError();
  CXXRecordDecl *ToClass = *ToClassOrErr;

  auto ToCallOpOrErr = import(E->getCallOperator());
  if (!ToCallOpOrErr)
    return ToCallOpOrErr.takeError();

  SmallVector<Expr *, 8> ToCaptureInits(E->capture_size());
  if (Error Err = ImportContainerChecked(E->capture_inits(), ToCaptureInits))
    return std::move(Err);

  Error Err = Error::success();
  auto ToIntroducerRange = importChecked(Err, E->getIntroducerRange());
  auto ToCaptureDefaultLoc = importChecked(Err, E->getCaptureDefaultLoc());
  auto ToEndLoc = importChecked(Err, E->getEndLoc());
  if (Err)
    return std::move(Err);

  return LambdaExpr::Create(Importer.getToContext(), ToClass, ToIntroducerRange,
                            E->getCaptureDefault(), ToCaptureDefaultLoc,
                            E->hasExplicitParameters(),
                            E->hasExplicitResultType(), ToCaptureInits,
                            ToEndLoc, E->containsUnexpandedParameterPack());
}


ExpectedStmt ASTNodeImporter::VisitInitListExpr(InitListExpr *E) {
  Error Err = Error::success();
  auto ToLBraceLoc = importChecked(Err, E->getLBraceLoc());
  auto ToRBraceLoc = importChecked(Err, E->getRBraceLoc());
  auto ToType = importChecked(Err, E->getType());
  if (Err)
    return std::move(Err);

  SmallVector<Expr *, 4> ToExprs(E->getNumInits());
  if (Error Err = ImportContainerChecked(E->inits(), ToExprs))
    return std::move(Err);

  ASTContext &ToCtx = Importer.getToContext();
  InitListExpr *To = new (ToCtx) InitListExpr(
      ToCtx, ToLBraceLoc, ToExprs, ToRBraceLoc);
  To->setType(ToType);

  if (E->hasArrayFiller()) {
    if (ExpectedExpr ToFillerOrErr = import(E->getArrayFiller()))
      To->setArrayFiller(*ToFillerOrErr);
    else
      return ToFillerOrErr.takeError();
  }

  if (FieldDecl *FromFD = E->getInitializedFieldInUnion()) {
    if (auto ToFDOrErr = import(FromFD))
      To->setInitializedFieldInUnion(*ToFDOrErr);
    else
      return ToFDOrErr.takeError();
  }

  if (InitListExpr *SyntForm = E->getSyntacticForm()) {
    if (auto ToSyntFormOrErr = import(SyntForm))
      To->setSyntacticForm(*ToSyntFormOrErr);
    else
      return ToSyntFormOrErr.takeError();
  }

  // Copy InitListExprBitfields, which are not handled in the ctor of
  // InitListExpr.
  To->sawArrayRangeDesignator(E->hadArrayRangeDesignator());

  return To;
}

ExpectedStmt ASTNodeImporter::VisitCXXStdInitializerListExpr(
    CXXStdInitializerListExpr *E) {
  ExpectedType ToTypeOrErr = import(E->getType());
  if (!ToTypeOrErr)
    return ToTypeOrErr.takeError();

  ExpectedExpr ToSubExprOrErr = import(E->getSubExpr());
  if (!ToSubExprOrErr)
    return ToSubExprOrErr.takeError();

  return new (Importer.getToContext()) CXXStdInitializerListExpr(
      *ToTypeOrErr, *ToSubExprOrErr);
}

ExpectedStmt ASTNodeImporter::VisitCXXInheritedCtorInitExpr(
    CXXInheritedCtorInitExpr *E) {
  Error Err = Error::success();
  auto ToLocation = importChecked(Err, E->getLocation());
  auto ToType = importChecked(Err, E->getType());
  auto ToConstructor = importChecked(Err, E->getConstructor());
  if (Err)
    return std::move(Err);

  return new (Importer.getToContext()) CXXInheritedCtorInitExpr(
      ToLocation, ToType, ToConstructor, E->constructsVBase(),
      E->inheritedFromVBase());
}

ExpectedStmt ASTNodeImporter::VisitArrayInitLoopExpr(ArrayInitLoopExpr *E) {
  Error Err = Error::success();
  auto ToType = importChecked(Err, E->getType());
  auto ToCommonExpr = importChecked(Err, E->getCommonExpr());
  auto ToSubExpr = importChecked(Err, E->getSubExpr());
  if (Err)
    return std::move(Err);

  return new (Importer.getToContext()) ArrayInitLoopExpr(
      ToType, ToCommonExpr, ToSubExpr);
}

ExpectedStmt ASTNodeImporter::VisitArrayInitIndexExpr(ArrayInitIndexExpr *E) {
  ExpectedType ToTypeOrErr = import(E->getType());
  if (!ToTypeOrErr)
    return ToTypeOrErr.takeError();
  return new (Importer.getToContext()) ArrayInitIndexExpr(*ToTypeOrErr);
}

ExpectedStmt ASTNodeImporter::VisitCXXDefaultInitExpr(CXXDefaultInitExpr *E) {
  ExpectedSLoc ToBeginLocOrErr = import(E->getBeginLoc());
  if (!ToBeginLocOrErr)
    return ToBeginLocOrErr.takeError();

  auto ToFieldOrErr = import(E->getField());
  if (!ToFieldOrErr)
    return ToFieldOrErr.takeError();

  auto UsedContextOrErr = Importer.ImportContext(E->getUsedContext());
  if (!UsedContextOrErr)
    return UsedContextOrErr.takeError();

  FieldDecl *ToField = *ToFieldOrErr;
  assert(ToField->hasInClassInitializer() &&
         "Field should have in-class initializer if there is a default init "
         "expression that uses it.");
  if (!ToField->getInClassInitializer()) {
    // The in-class initializer may be not yet set in "To" AST even if the
    // field is already there. This must be set here to make construction of
    // CXXDefaultInitExpr work.
    auto ToInClassInitializerOrErr =
        import(E->getField()->getInClassInitializer());
    if (!ToInClassInitializerOrErr)
      return ToInClassInitializerOrErr.takeError();
    ToField->setInClassInitializer(*ToInClassInitializerOrErr);
  }

  Expr *RewrittenInit = nullptr;
  if (E->hasRewrittenInit()) {
    ExpectedExpr ExprOrErr = import(E->getRewrittenExpr());
    if (!ExprOrErr)
      return ExprOrErr.takeError();
    RewrittenInit = ExprOrErr.get();
  }

  return CXXDefaultInitExpr::Create(Importer.getToContext(), *ToBeginLocOrErr,
                                    ToField, *UsedContextOrErr, RewrittenInit);
}

ExpectedStmt ASTNodeImporter::VisitCXXNamedCastExpr(CXXNamedCastExpr *E) {
  Error Err = Error::success();
  auto ToType = importChecked(Err, E->getType());
  auto ToSubExpr = importChecked(Err, E->getSubExpr());
  auto ToTypeInfoAsWritten = importChecked(Err, E->getTypeInfoAsWritten());
  auto ToOperatorLoc = importChecked(Err, E->getOperatorLoc());
  auto ToRParenLoc = importChecked(Err, E->getRParenLoc());
  auto ToAngleBrackets = importChecked(Err, E->getAngleBrackets());
  if (Err)
    return std::move(Err);

  ExprValueKind VK = E->getValueKind();
  CastKind CK = E->getCastKind();
  auto ToBasePathOrErr = ImportCastPath(E);
  if (!ToBasePathOrErr)
    return ToBasePathOrErr.takeError();

  if (auto CCE = dyn_cast<CXXStaticCastExpr>(E)) {
    return CXXStaticCastExpr::Create(
        Importer.getToContext(), ToType, VK, CK, ToSubExpr, &(*ToBasePathOrErr),
        ToTypeInfoAsWritten, CCE->getFPFeatures(), ToOperatorLoc, ToRParenLoc,
        ToAngleBrackets);
  } else if (isa<CXXDynamicCastExpr>(E)) {
    return CXXDynamicCastExpr::Create(
        Importer.getToContext(), ToType, VK, CK, ToSubExpr, &(*ToBasePathOrErr),
        ToTypeInfoAsWritten, ToOperatorLoc, ToRParenLoc, ToAngleBrackets);
  } else if (isa<CXXReinterpretCastExpr>(E)) {
    return CXXReinterpretCastExpr::Create(
        Importer.getToContext(), ToType, VK, CK, ToSubExpr, &(*ToBasePathOrErr),
        ToTypeInfoAsWritten, ToOperatorLoc, ToRParenLoc, ToAngleBrackets);
  } else if (isa<CXXConstCastExpr>(E)) {
    return CXXConstCastExpr::Create(
        Importer.getToContext(), ToType, VK, ToSubExpr, ToTypeInfoAsWritten,
        ToOperatorLoc, ToRParenLoc, ToAngleBrackets);
  } else {
    llvm_unreachable("Unknown cast type");
    return make_error<ASTImportError>();
  }
}

ExpectedStmt ASTNodeImporter::VisitSubstNonTypeTemplateParmExpr(
    SubstNonTypeTemplateParmExpr *E) {
  Error Err = Error::success();
  auto ToType = importChecked(Err, E->getType());
  auto ToNameLoc = importChecked(Err, E->getNameLoc());
  auto ToAssociatedDecl = importChecked(Err, E->getAssociatedDecl());
  auto ToReplacement = importChecked(Err, E->getReplacement());
  if (Err)
    return std::move(Err);

  return new (Importer.getToContext()) SubstNonTypeTemplateParmExpr(
      ToType, E->getValueKind(), ToNameLoc, ToReplacement, ToAssociatedDecl,
      E->getIndex(), E->getPackIndex(), E->isReferenceParameter(),
      E->getFinal());
}

ExpectedStmt ASTNodeImporter::VisitTypeTraitExpr(TypeTraitExpr *E) {
  Error Err = Error::success();
  auto ToType = importChecked(Err, E->getType());
  auto ToBeginLoc = importChecked(Err, E->getBeginLoc());
  auto ToEndLoc = importChecked(Err, E->getEndLoc());
  if (Err)
    return std::move(Err);

  SmallVector<TypeSourceInfo *, 4> ToArgs(E->getNumArgs());
  if (Error Err = ImportContainerChecked(E->getArgs(), ToArgs))
    return std::move(Err);

  if (E->isStoredAsBoolean()) {
    // According to Sema::BuildTypeTrait(), if E is value-dependent,
    // Value is always false.
    bool ToValue = (E->isValueDependent() ? false : E->getBoolValue());
    return TypeTraitExpr::Create(Importer.getToContext(), ToType, ToBeginLoc,
                                 E->getTrait(), ToArgs, ToEndLoc, ToValue);
  }
  return TypeTraitExpr::Create(Importer.getToContext(), ToType, ToBeginLoc,
                               E->getTrait(), ToArgs, ToEndLoc,
                               E->getAPValue());
}

ExpectedStmt ASTNodeImporter::VisitCXXTypeidExpr(CXXTypeidExpr *E) {
  ExpectedType ToTypeOrErr = import(E->getType());
  if (!ToTypeOrErr)
    return ToTypeOrErr.takeError();

  auto ToSourceRangeOrErr = import(E->getSourceRange());
  if (!ToSourceRangeOrErr)
    return ToSourceRangeOrErr.takeError();

  if (E->isTypeOperand()) {
    if (auto ToTSIOrErr = import(E->getTypeOperandSourceInfo()))
      return new (Importer.getToContext()) CXXTypeidExpr(
          *ToTypeOrErr, *ToTSIOrErr, *ToSourceRangeOrErr);
    else
      return ToTSIOrErr.takeError();
  }

  ExpectedExpr ToExprOperandOrErr = import(E->getExprOperand());
  if (!ToExprOperandOrErr)
    return ToExprOperandOrErr.takeError();

  return new (Importer.getToContext()) CXXTypeidExpr(
      *ToTypeOrErr, *ToExprOperandOrErr, *ToSourceRangeOrErr);
}

ExpectedStmt ASTNodeImporter::VisitCXXFoldExpr(CXXFoldExpr *E) {
  Error Err = Error::success();

  QualType ToType = importChecked(Err, E->getType());
  UnresolvedLookupExpr *ToCallee = importChecked(Err, E->getCallee());
  SourceLocation ToLParenLoc = importChecked(Err, E->getLParenLoc());
  Expr *ToLHS = importChecked(Err, E->getLHS());
  SourceLocation ToEllipsisLoc = importChecked(Err, E->getEllipsisLoc());
  Expr *ToRHS = importChecked(Err, E->getRHS());
  SourceLocation ToRParenLoc = importChecked(Err, E->getRParenLoc());

  if (Err)
    return std::move(Err);

  return new (Importer.getToContext())
      CXXFoldExpr(ToType, ToCallee, ToLParenLoc, ToLHS, E->getOperator(),
                  ToEllipsisLoc, ToRHS, ToRParenLoc, E->getNumExpansions());
}

ExpectedStmt ASTNodeImporter::VisitRequiresExpr(RequiresExpr *E) {
  Error Err = Error::success();
  auto RequiresKWLoc = importChecked(Err, E->getRequiresKWLoc());
  auto RParenLoc = importChecked(Err, E->getRParenLoc());
  auto RBraceLoc = importChecked(Err, E->getRBraceLoc());

  auto Body = importChecked(Err, E->getBody());
  auto LParenLoc = importChecked(Err, E->getLParenLoc());
  if (Err)
    return std::move(Err);
  SmallVector<ParmVarDecl *, 4> LocalParameters(E->getLocalParameters().size());
  if (Error Err =
          ImportArrayChecked(E->getLocalParameters(), LocalParameters.begin()))
    return std::move(Err);
  SmallVector<concepts::Requirement *, 4> Requirements(
      E->getRequirements().size());
  if (Error Err =
          ImportArrayChecked(E->getRequirements(), Requirements.begin()))
    return std::move(Err);
  return RequiresExpr::Create(Importer.getToContext(), RequiresKWLoc, Body,
                              LParenLoc, LocalParameters, RParenLoc,
                              Requirements, RBraceLoc);
}

ExpectedStmt
ASTNodeImporter::VisitConceptSpecializationExpr(ConceptSpecializationExpr *E) {
  Error Err = Error::success();
  auto CL = importChecked(Err, E->getConceptReference());
  auto CSD = importChecked(Err, E->getSpecializationDecl());
  if (Err)
    return std::move(Err);
  if (E->isValueDependent())
    return ConceptSpecializationExpr::Create(
        Importer.getToContext(), CL,
        const_cast<ImplicitConceptSpecializationDecl *>(CSD), nullptr);
  ConstraintSatisfaction Satisfaction;
  if (Error Err =
          ImportConstraintSatisfaction(E->getSatisfaction(), Satisfaction))
    return std::move(Err);
  return ConceptSpecializationExpr::Create(
      Importer.getToContext(), CL,
      const_cast<ImplicitConceptSpecializationDecl *>(CSD), &Satisfaction);
}

Error ASTNodeImporter::ImportOverriddenMethods(CXXMethodDecl *ToMethod,
                                               CXXMethodDecl *FromMethod) {
  Error ImportErrors = Error::success();
  for (auto *FromOverriddenMethod : FromMethod->overridden_methods()) {
    if (auto ImportedOrErr = import(FromOverriddenMethod))
      ToMethod->getCanonicalDecl()->addOverriddenMethod(cast<CXXMethodDecl>(
          (*ImportedOrErr)->getCanonicalDecl()));
    else
      ImportErrors =
          joinErrors(std::move(ImportErrors), ImportedOrErr.takeError());
  }
  return ImportErrors;
}

ASTImporter::ASTImporter(ASTContext &ToContext, FileManager &ToFileManager,
                         ASTContext &FromContext, FileManager &FromFileManager,
                         bool MinimalImport,
                         std::shared_ptr<ASTImporterSharedState> SharedState)
    : SharedState(SharedState), ToContext(ToContext), FromContext(FromContext),
      ToFileManager(ToFileManager), FromFileManager(FromFileManager),
      Minimal(MinimalImport), ODRHandling(ODRHandlingType::Conservative) {

  // Create a default state without the lookup table: LLDB case.
  if (!SharedState) {
    this->SharedState = std::make_shared<ASTImporterSharedState>();
  }

  ImportedDecls[FromContext.getTranslationUnitDecl()] =
      ToContext.getTranslationUnitDecl();
}

ASTImporter::~ASTImporter() = default;

UnsignedOrNone ASTImporter::getFieldIndex(Decl *F) {
  assert(F && (isa<FieldDecl>(*F) || isa<IndirectFieldDecl>(*F)) &&
      "Try to get field index for non-field.");

  auto *Owner = dyn_cast<RecordDecl>(F->getDeclContext());
  if (!Owner)
    return std::nullopt;

  unsigned Index = 0;
  for (const auto *D : Owner->decls()) {
    if (D == F)
      return Index;

    if (isa<FieldDecl>(*D) || isa<IndirectFieldDecl>(*D))
      ++Index;
  }

  llvm_unreachable("Field was not found in its parent context.");

  return std::nullopt;
}

ASTImporter::FoundDeclsTy
ASTImporter::findDeclsInToCtx(DeclContext *DC, DeclarationName Name) {
  // We search in the redecl context because of transparent contexts.
  // E.g. a simple C language enum is a transparent context:
  //   enum E { A, B };
  // Now if we had a global variable in the TU
  //   int A;
  // then the enum constant 'A' and the variable 'A' violates ODR.
  // We can diagnose this only if we search in the redecl context.
  DeclContext *ReDC = DC->getRedeclContext();
  if (SharedState->getLookupTable()) {
    if (ReDC->isNamespace()) {
      // Namespaces can be reopened.
      // Lookup table does not handle this, we must search here in all linked
      // namespaces.
      FoundDeclsTy Result;
      SmallVector<Decl *, 2> NSChain =
          getCanonicalForwardRedeclChain<NamespaceDecl>(
              dyn_cast<NamespaceDecl>(ReDC));
      for (auto *D : NSChain) {
        ASTImporterLookupTable::LookupResult LookupResult =
            SharedState->getLookupTable()->lookup(dyn_cast<NamespaceDecl>(D),
                                                  Name);
        Result.append(LookupResult.begin(), LookupResult.end());
      }
      return Result;
    } else {
      ASTImporterLookupTable::LookupResult LookupResult =
          SharedState->getLookupTable()->lookup(ReDC, Name);
      return FoundDeclsTy(LookupResult.begin(), LookupResult.end());
    }
  } else {
    DeclContext::lookup_result NoloadLookupResult = ReDC->noload_lookup(Name);
    FoundDeclsTy Result(NoloadLookupResult.begin(), NoloadLookupResult.end());
    // We must search by the slow case of localUncachedLookup because that is
    // working even if there is no LookupPtr for the DC. We could use
    // DC::buildLookup() to create the LookupPtr, but that would load external
    // decls again, we must avoid that case.
    // Also, even if we had the LookupPtr, we must find Decls which are not
    // in the LookupPtr, so we need the slow case.
    // These cases are handled in ASTImporterLookupTable, but we cannot use
    // that with LLDB since that traverses through the AST which initiates the
    // load of external decls again via DC::decls().  And again, we must avoid
    // loading external decls during the import.
    if (Result.empty())
      ReDC->localUncachedLookup(Name, Result);
    return Result;
  }
}

void ASTImporter::AddToLookupTable(Decl *ToD) {
  SharedState->addDeclToLookup(ToD);
}

Expected<Decl *> ASTImporter::ImportImpl(Decl *FromD) {
  // Import the decl using ASTNodeImporter.
  ASTNodeImporter Importer(*this);
  return Importer.Visit(FromD);
}

void ASTImporter::RegisterImportedDecl(Decl *FromD, Decl *ToD) {
  MapImported(FromD, ToD);
}

llvm::Expected<ExprWithCleanups::CleanupObject>
ASTImporter::Import(ExprWithCleanups::CleanupObject From) {
  if (auto *CLE = From.dyn_cast<CompoundLiteralExpr *>()) {
    if (Expected<Expr *> R = Import(CLE))
      return ExprWithCleanups::CleanupObject(cast<CompoundLiteralExpr>(*R));
  }

  // FIXME: Handle BlockDecl when we implement importing BlockExpr in
  //        ASTNodeImporter.
  return make_error<ASTImportError>(ASTImportError::UnsupportedConstruct);
}

ExpectedTypePtr ASTImporter::Import(const Type *FromT) {
  if (!FromT)
    return FromT;

  // Check whether we've already imported this type.
  llvm::DenseMap<const Type *, const Type *>::iterator Pos =
      ImportedTypes.find(FromT);
  if (Pos != ImportedTypes.end())
    return Pos->second;

  // Import the type.
  ASTNodeImporter Importer(*this);
  ExpectedType ToTOrErr = Importer.Visit(FromT);
  if (!ToTOrErr)
    return ToTOrErr.takeError();

  // Record the imported type.
  ImportedTypes[FromT] = ToTOrErr->getTypePtr();

  return ToTOrErr->getTypePtr();
}

Expected<QualType> ASTImporter::Import(QualType FromT) {
  if (FromT.isNull())
    return QualType{};

  ExpectedTypePtr ToTyOrErr = Import(FromT.getTypePtr());
  if (!ToTyOrErr)
    return ToTyOrErr.takeError();

  return ToContext.getQualifiedType(*ToTyOrErr, FromT.getLocalQualifiers());
}

Expected<TypeSourceInfo *> ASTImporter::Import(TypeSourceInfo *FromTSI) {
  if (!FromTSI)
    return FromTSI;

  // FIXME: For now we just create a "trivial" type source info based
  // on the type and a single location. Implement a real version of this.
  ExpectedType TOrErr = Import(FromTSI->getType());
  if (!TOrErr)
    return TOrErr.takeError();
  ExpectedSLoc BeginLocOrErr = Import(FromTSI->getTypeLoc().getBeginLoc());
  if (!BeginLocOrErr)
    return BeginLocOrErr.takeError();

  return ToContext.getTrivialTypeSourceInfo(*TOrErr, *BeginLocOrErr);
}

namespace {
// To use this object, it should be created before the new attribute is created,
// and destructed after it is created. The construction already performs the
// import of the data.
template <typename T> struct AttrArgImporter {
  AttrArgImporter(const AttrArgImporter<T> &) = delete;
  AttrArgImporter(AttrArgImporter<T> &&) = default;
  AttrArgImporter<T> &operator=(const AttrArgImporter<T> &) = delete;
  AttrArgImporter<T> &operator=(AttrArgImporter<T> &&) = default;

  AttrArgImporter(ASTNodeImporter &I, Error &Err, const T &From)
      : To(I.importChecked(Err, From)) {}

  const T &value() { return To; }

private:
  T To;
};

// To use this object, it should be created before the new attribute is created,
// and destructed after it is created. The construction already performs the
// import of the data. The array data is accessible in a pointer form, this form
// is used by the attribute classes. This object should be created once for the
// array data to be imported (the array size is not imported, just copied).
template <typename T> struct AttrArgArrayImporter {
  AttrArgArrayImporter(const AttrArgArrayImporter<T> &) = delete;
  AttrArgArrayImporter(AttrArgArrayImporter<T> &&) = default;
  AttrArgArrayImporter<T> &operator=(const AttrArgArrayImporter<T> &) = delete;
  AttrArgArrayImporter<T> &operator=(AttrArgArrayImporter<T> &&) = default;

  AttrArgArrayImporter(ASTNodeImporter &I, Error &Err,
                       const llvm::iterator_range<T *> &From,
                       unsigned ArraySize) {
    if (Err)
      return;
    To.reserve(ArraySize);
    Err = I.ImportContainerChecked(From, To);
  }

  T *value() { return To.data(); }

private:
  llvm::SmallVector<T, 2> To;
};

class AttrImporter {
  Error Err{Error::success()};
  Attr *ToAttr = nullptr;
  ASTImporter &Importer;
  ASTNodeImporter NImporter;

public:
  AttrImporter(ASTImporter &I) : Importer(I), NImporter(I) {}

  // Useful for accessing the imported attribute.
  template <typename T> T *castAttrAs() { return cast<T>(ToAttr); }
  template <typename T> const T *castAttrAs() const { return cast<T>(ToAttr); }

  // Create an "importer" for an attribute parameter.
  // Result of the 'value()' of that object is to be passed to the function
  // 'importAttr', in the order that is expected by the attribute class.
  template <class T> AttrArgImporter<T> importArg(const T &From) {
    return AttrArgImporter<T>(NImporter, Err, From);
  }

  // Create an "importer" for an attribute parameter that has array type.
  // Result of the 'value()' of that object is to be passed to the function
  // 'importAttr', then the size of the array as next argument.
  template <typename T>
  AttrArgArrayImporter<T> importArrayArg(const llvm::iterator_range<T *> &From,
                                         unsigned ArraySize) {
    return AttrArgArrayImporter<T>(NImporter, Err, From, ArraySize);
  }

  // Create an attribute object with the specified arguments.
  // The 'FromAttr' is the original (not imported) attribute, the 'ImportedArg'
  // should be values that are passed to the 'Create' function of the attribute.
  // (The 'Create' with 'ASTContext' first and 'AttributeCommonInfo' last is
  // used here.) As much data is copied or imported from the old attribute
  // as possible. The passed arguments should be already imported.
  // If an import error happens, the internal error is set to it, and any
  // further import attempt is ignored.
  template <typename T, typename... Arg>
  void importAttr(const T *FromAttr, Arg &&...ImportedArg) {
    static_assert(std::is_base_of<Attr, T>::value,
                  "T should be subclass of Attr.");
    assert(!ToAttr && "Use one AttrImporter to import one Attribute object.");

    const IdentifierInfo *ToAttrName = Importer.Import(FromAttr->getAttrName());
    const IdentifierInfo *ToScopeName =
        Importer.Import(FromAttr->getScopeName());
    SourceRange ToAttrRange =
        NImporter.importChecked(Err, FromAttr->getRange());
    SourceLocation ToScopeLoc =
        NImporter.importChecked(Err, FromAttr->getScopeLoc());

    if (Err)
      return;

    AttributeCommonInfo ToI(
        ToAttrName, AttributeScopeInfo(ToScopeName, ToScopeLoc), ToAttrRange,
        FromAttr->getParsedKind(), FromAttr->getForm());
    // The "SemanticSpelling" is not needed to be passed to the constructor.
    // That value is recalculated from the SpellingListIndex if needed.
    ToAttr = T::Create(Importer.getToContext(),
                       std::forward<Arg>(ImportedArg)..., ToI);

    ToAttr->setImplicit(FromAttr->isImplicit());
    ToAttr->setPackExpansion(FromAttr->isPackExpansion());
    if (auto *ToInheritableAttr = dyn_cast<InheritableAttr>(ToAttr))
      ToInheritableAttr->setInherited(FromAttr->isInherited());
  }

  // Create a clone of the 'FromAttr' and import its source range only.
  // This causes objects with invalid references to be created if the 'FromAttr'
  // contains other data that should be imported.
  void cloneAttr(const Attr *FromAttr) {
    assert(!ToAttr && "Use one AttrImporter to import one Attribute object.");

    SourceRange ToRange = NImporter.importChecked(Err, FromAttr->getRange());
    if (Err)
      return;

    ToAttr = FromAttr->clone(Importer.getToContext());
    ToAttr->setRange(ToRange);
    ToAttr->setAttrName(Importer.Import(FromAttr->getAttrName()));
  }

  // Get the result of the previous import attempt (can be used only once).
  llvm::Expected<Attr *> getResult() && {
    if (Err)
      return std::move(Err);
    assert(ToAttr && "Attribute should be created.");
    return ToAttr;
  }
};
} // namespace

Expected<Attr *> ASTImporter::Import(const Attr *FromAttr) {
  AttrImporter AI(*this);

  // FIXME: Is there some kind of AttrVisitor to use here?
  switch (FromAttr->getKind()) {
  case attr::Aligned: {
    auto *From = cast<AlignedAttr>(FromAttr);
    if (From->isAlignmentExpr())
      AI.importAttr(From, true, AI.importArg(From->getAlignmentExpr()).value());
    else
      AI.importAttr(From, false,
                    AI.importArg(From->getAlignmentType()).value());
    break;
  }

  case attr::AlignValue: {
    auto *From = cast<AlignValueAttr>(FromAttr);
    AI.importAttr(From, AI.importArg(From->getAlignment()).value());
    break;
  }

  case attr::Format: {
    const auto *From = cast<FormatAttr>(FromAttr);
    AI.importAttr(From, Import(From->getType()), From->getFormatIdx(),
                  From->getFirstArg());
    break;
  }

  case attr::EnableIf: {
    const auto *From = cast<EnableIfAttr>(FromAttr);
    AI.importAttr(From, AI.importArg(From->getCond()).value(),
                  From->getMessage());
    break;
  }

  case attr::AssertCapability: {
    const auto *From = cast<AssertCapabilityAttr>(FromAttr);
    AI.importAttr(From,
                  AI.importArrayArg(From->args(), From->args_size()).value(),
                  From->args_size());
    break;
  }
  case attr::AcquireCapability: {
    const auto *From = cast<AcquireCapabilityAttr>(FromAttr);
    AI.importAttr(From,
                  AI.importArrayArg(From->args(), From->args_size()).value(),
                  From->args_size());
    break;
  }
  case attr::TryAcquireCapability: {
    const auto *From = cast<TryAcquireCapabilityAttr>(FromAttr);
    AI.importAttr(From, AI.importArg(From->getSuccessValue()).value(),
                  AI.importArrayArg(From->args(), From->args_size()).value(),
                  From->args_size());
    break;
  }
  case attr::ReleaseCapability: {
    const auto *From = cast<ReleaseCapabilityAttr>(FromAttr);
    AI.importAttr(From,
                  AI.importArrayArg(From->args(), From->args_size()).value(),
                  From->args_size());
    break;
  }
  case attr::RequiresCapability: {
    const auto *From = cast<RequiresCapabilityAttr>(FromAttr);
    AI.importAttr(From,
                  AI.importArrayArg(From->args(), From->args_size()).value(),
                  From->args_size());
    break;
  }
  case attr::GuardedBy: {
    const auto *From = cast<GuardedByAttr>(FromAttr);
    AI.importAttr(From, AI.importArg(From->getArg()).value());
    break;
  }
  case attr::PtGuardedBy: {
    const auto *From = cast<PtGuardedByAttr>(FromAttr);
    AI.importAttr(From, AI.importArg(From->getArg()).value());
    break;
  }
  case attr::AcquiredAfter: {
    const auto *From = cast<AcquiredAfterAttr>(FromAttr);
    AI.importAttr(From,
                  AI.importArrayArg(From->args(), From->args_size()).value(),
                  From->args_size());
    break;
  }
  case attr::AcquiredBefore: {
    const auto *From = cast<AcquiredBeforeAttr>(FromAttr);
    AI.importAttr(From,
                  AI.importArrayArg(From->args(), From->args_size()).value(),
                  From->args_size());
    break;
  }
  case attr::LockReturned: {
    const auto *From = cast<LockReturnedAttr>(FromAttr);
    AI.importAttr(From, AI.importArg(From->getArg()).value());
    break;
  }
  case attr::LocksExcluded: {
    const auto *From = cast<LocksExcludedAttr>(FromAttr);
    AI.importAttr(From,
                  AI.importArrayArg(From->args(), From->args_size()).value(),
                  From->args_size());
    break;
  }
  default: {
    // The default branch works for attributes that have no arguments to import.
    // FIXME: Handle every attribute type that has arguments of type to import
    // (most often Expr* or Decl* or type) in the switch above.
    AI.cloneAttr(FromAttr);
    break;
  }
  }

  return std::move(AI).getResult();
}

Decl *ASTImporter::GetAlreadyImportedOrNull(const Decl *FromD) const {
  return ImportedDecls.lookup(FromD);
}

TranslationUnitDecl *ASTImporter::GetFromTU(Decl *ToD) {
  auto FromDPos = ImportedFromDecls.find(ToD);
  if (FromDPos == ImportedFromDecls.end())
    return nullptr;
  return FromDPos->second->getTranslationUnitDecl();
}

Expected<Decl *> ASTImporter::Import(Decl *FromD) {
  if (!FromD)
    return nullptr;

  // Push FromD to the stack, and remove that when we return.
  ImportPath.push(FromD);
  auto ImportPathBuilder =
      llvm::make_scope_exit([this]() { ImportPath.pop(); });

  // Check whether there was a previous failed import.
  // If yes return the existing error.
  if (auto Error = getImportDeclErrorIfAny(FromD))
    return make_error<ASTImportError>(*Error);

  // Check whether we've already imported this declaration.
  Decl *ToD = GetAlreadyImportedOrNull(FromD);
  if (ToD) {
    // Already imported (possibly from another TU) and with an error.
    if (auto Error = SharedState->getImportDeclErrorIfAny(ToD)) {
      setImportDeclError(FromD, *Error);
      return make_error<ASTImportError>(*Error);
    }

    // If FromD has some updated flags after last import, apply it.
    updateFlags(FromD, ToD);
    // If we encounter a cycle during an import then we save the relevant part
    // of the import path associated to the Decl.
    if (ImportPath.hasCycleAtBack())
      SavedImportPaths[FromD].push_back(ImportPath.copyCycleAtBack());
    return ToD;
  }

  // Import the declaration.
  ExpectedDecl ToDOrErr = ImportImpl(FromD);
  if (!ToDOrErr) {
    // Failed to import.

    auto Pos = ImportedDecls.find(FromD);
    if (Pos != ImportedDecls.end()) {
      // Import failed after the object was created.
      // Remove all references to it.
      auto *ToD = Pos->second;
      ImportedDecls.erase(Pos);

      // ImportedDecls and ImportedFromDecls are not symmetric.  It may happen
      // (e.g. with namespaces) that several decls from the 'from' context are
      // mapped to the same decl in the 'to' context.  If we removed entries
      // from the LookupTable here then we may end up removing them multiple
      // times.

      // The Lookuptable contains decls only which are in the 'to' context.
      // Remove from the Lookuptable only if it is *imported* into the 'to'
      // context (and do not remove it if it was added during the initial
      // traverse of the 'to' context).
      auto PosF = ImportedFromDecls.find(ToD);
      if (PosF != ImportedFromDecls.end()) {
        // In the case of TypedefNameDecl we create the Decl first and only
        // then we import and set its DeclContext. So, the DC might not be set
        // when we reach here.
        if (ToD->getDeclContext())
          SharedState->removeDeclFromLookup(ToD);
        ImportedFromDecls.erase(PosF);
      }

      // FIXME: AST may contain remaining references to the failed object.
      // However, the ImportDeclErrors in the shared state contains all the
      // failed objects together with their error.
    }

    // Error encountered for the first time.
    // After takeError the error is not usable any more in ToDOrErr.
    // Get a copy of the error object (any more simple solution for this?).
    ASTImportError ErrOut;
    handleAllErrors(ToDOrErr.takeError(),
                    [&ErrOut](const ASTImportError &E) { ErrOut = E; });
    setImportDeclError(FromD, ErrOut);
    // Set the error for the mapped to Decl, which is in the "to" context.
    if (Pos != ImportedDecls.end())
      SharedState->setImportDeclError(Pos->second, ErrOut);

    // Set the error for all nodes which have been created before we
    // recognized the error.
    for (const auto &Path : SavedImportPaths[FromD]) {
      // The import path contains import-dependency nodes first.
      // Save the node that was imported as dependency of the current node.
      Decl *PrevFromDi = FromD;
      for (Decl *FromDi : Path) {
        // Begin and end of the path equals 'FromD', skip it.
        if (FromDi == FromD)
          continue;
        // We should not set import error on a node and all following nodes in
        // the path if child import errors are ignored.
        if (ChildErrorHandlingStrategy(FromDi).ignoreChildErrorOnParent(
                PrevFromDi))
          break;
        PrevFromDi = FromDi;
        setImportDeclError(FromDi, ErrOut);
        //FIXME Should we remove these Decls from ImportedDecls?
        // Set the error for the mapped to Decl, which is in the "to" context.
        auto Ii = ImportedDecls.find(FromDi);
        if (Ii != ImportedDecls.end())
          SharedState->setImportDeclError(Ii->second, ErrOut);
          // FIXME Should we remove these Decls from the LookupTable,
          // and from ImportedFromDecls?
      }
    }
    SavedImportPaths.erase(FromD);

    // Do not return ToDOrErr, error was taken out of it.
    return make_error<ASTImportError>(ErrOut);
  }

  ToD = *ToDOrErr;

  // FIXME: Handle the "already imported with error" case. We can get here
  // nullptr only if GetImportedOrCreateDecl returned nullptr (after a
  // previously failed create was requested).
  // Later GetImportedOrCreateDecl can be updated to return the error.
  if (!ToD) {
    auto Err = getImportDeclErrorIfAny(FromD);
    assert(Err);
    return make_error<ASTImportError>(*Err);
  }

  // We could import from the current TU without error.  But previously we
  // already had imported a Decl as `ToD` from another TU (with another
  // ASTImporter object) and with an error.
  if (auto Error = SharedState->getImportDeclErrorIfAny(ToD)) {
    setImportDeclError(FromD, *Error);
    return make_error<ASTImportError>(*Error);
  }
  // Make sure that ImportImpl registered the imported decl.
  assert(ImportedDecls.count(FromD) != 0 && "Missing call to MapImported?");

  if (FromD->hasAttrs())
    for (const Attr *FromAttr : FromD->getAttrs()) {
      auto ToAttrOrErr = Import(FromAttr);
      if (ToAttrOrErr)
        ToD->addAttr(*ToAttrOrErr);
      else
        return ToAttrOrErr.takeError();
    }

  // Notify subclasses.
  Imported(FromD, ToD);

  updateFlags(FromD, ToD);
  SavedImportPaths.erase(FromD);
  return ToDOrErr;
}

llvm::Expected<InheritedConstructor>
ASTImporter::Import(const InheritedConstructor &From) {
  return ASTNodeImporter(*this).ImportInheritedConstructor(From);
}

Expected<DeclContext *> ASTImporter::ImportContext(DeclContext *FromDC) {
  if (!FromDC)
    return FromDC;

  ExpectedDecl ToDCOrErr = Import(cast<Decl>(FromDC));
  if (!ToDCOrErr)
    return ToDCOrErr.takeError();
  auto *ToDC = cast<DeclContext>(*ToDCOrErr);

  // When we're using a record/enum/Objective-C class/protocol as a context, we
  // need it to have a definition.
  if (auto *ToRecord = dyn_cast<RecordDecl>(ToDC)) {
    auto *FromRecord = cast<RecordDecl>(FromDC);
    if (ToRecord->isCompleteDefinition())
      return ToDC;

    // If FromRecord is not defined we need to force it to be.
    // Simply calling CompleteDecl(...) for a RecordDecl will break some cases
    // it will start the definition but we never finish it.
    // If there are base classes they won't be imported and we will
    // be missing anything that we inherit from those bases.
    if (FromRecord->getASTContext().getExternalSource() &&
        !FromRecord->isCompleteDefinition())
      FromRecord->getASTContext().getExternalSource()->CompleteType(FromRecord);

    if (FromRecord->isCompleteDefinition())
      if (Error Err = ASTNodeImporter(*this).ImportDefinition(
          FromRecord, ToRecord, ASTNodeImporter::IDK_Basic))
        return std::move(Err);
  } else if (auto *ToEnum = dyn_cast<EnumDecl>(ToDC)) {
    auto *FromEnum = cast<EnumDecl>(FromDC);
    if (ToEnum->isCompleteDefinition()) {
      // Do nothing.
    } else if (FromEnum->isCompleteDefinition()) {
      if (Error Err = ASTNodeImporter(*this).ImportDefinition(
          FromEnum, ToEnum, ASTNodeImporter::IDK_Basic))
        return std::move(Err);
    } else {
      CompleteDecl(ToEnum);
    }
  } else if (auto *ToClass = dyn_cast<ObjCInterfaceDecl>(ToDC)) {
    auto *FromClass = cast<ObjCInterfaceDecl>(FromDC);
    if (ToClass->getDefinition()) {
      // Do nothing.
    } else if (ObjCInterfaceDecl *FromDef = FromClass->getDefinition()) {
      if (Error Err = ASTNodeImporter(*this).ImportDefinition(
          FromDef, ToClass, ASTNodeImporter::IDK_Basic))
        return std::move(Err);
    } else {
      CompleteDecl(ToClass);
    }
  } else if (auto *ToProto = dyn_cast<ObjCProtocolDecl>(ToDC)) {
    auto *FromProto = cast<ObjCProtocolDecl>(FromDC);
    if (ToProto->getDefinition()) {
      // Do nothing.
    } else if (ObjCProtocolDecl *FromDef = FromProto->getDefinition()) {
      if (Error Err = ASTNodeImporter(*this).ImportDefinition(
          FromDef, ToProto, ASTNodeImporter::IDK_Basic))
        return std::move(Err);
    } else {
      CompleteDecl(ToProto);
    }
  }

  return ToDC;
}

Expected<Expr *> ASTImporter::Import(Expr *FromE) {
  if (ExpectedStmt ToSOrErr = Import(cast_or_null<Stmt>(FromE)))
    return cast_or_null<Expr>(*ToSOrErr);
  else
    return ToSOrErr.takeError();
}

Expected<Stmt *> ASTImporter::Import(Stmt *FromS) {
  if (!FromS)
    return nullptr;

  // Check whether we've already imported this statement.
  llvm::DenseMap<Stmt *, Stmt *>::iterator Pos = ImportedStmts.find(FromS);
  if (Pos != ImportedStmts.end())
    return Pos->second;

  // Import the statement.
  ASTNodeImporter Importer(*this);
  ExpectedStmt ToSOrErr = Importer.Visit(FromS);
  if (!ToSOrErr)
    return ToSOrErr;

  if (auto *ToE = dyn_cast<Expr>(*ToSOrErr)) {
    auto *FromE = cast<Expr>(FromS);
    // Copy ExprBitfields, which may not be handled in Expr subclasses
    // constructors.
    ToE->setValueKind(FromE->getValueKind());
    ToE->setObjectKind(FromE->getObjectKind());
    ToE->setDependence(FromE->getDependence());
  }

  // Record the imported statement object.
  ImportedStmts[FromS] = *ToSOrErr;
  return ToSOrErr;
}

Expected<NestedNameSpecifier *>
ASTImporter::Import(NestedNameSpecifier *FromNNS) {
  if (!FromNNS)
    return nullptr;

  NestedNameSpecifier *Prefix = nullptr;
  if (Error Err = importInto(Prefix, FromNNS->getPrefix()))
    return std::move(Err);

  switch (FromNNS->getKind()) {
  case NestedNameSpecifier::Identifier:
    assert(FromNNS->getAsIdentifier() && "NNS should contain identifier.");
    return NestedNameSpecifier::Create(ToContext, Prefix,
                                       Import(FromNNS->getAsIdentifier()));

  case NestedNameSpecifier::Namespace:
    if (ExpectedDecl NSOrErr = Import(FromNNS->getAsNamespace())) {
      return NestedNameSpecifier::Create(ToContext, Prefix,
                                         cast<NamespaceBaseDecl>(*NSOrErr));
    } else
      return NSOrErr.takeError();

  case NestedNameSpecifier::Global:
    return NestedNameSpecifier::GlobalSpecifier(ToContext);

  case NestedNameSpecifier::Super:
    if (ExpectedDecl RDOrErr = Import(FromNNS->getAsRecordDecl()))
      return NestedNameSpecifier::SuperSpecifier(ToContext,
                                                 cast<CXXRecordDecl>(*RDOrErr));
    else
      return RDOrErr.takeError();

  case NestedNameSpecifier::TypeSpec:
    if (ExpectedTypePtr TyOrErr = Import(FromNNS->getAsType())) {
      return NestedNameSpecifier::Create(ToContext, Prefix, *TyOrErr);
    } else {
      return TyOrErr.takeError();
    }
  }

  llvm_unreachable("Invalid nested name specifier kind");
}

Expected<NestedNameSpecifierLoc>
ASTImporter::Import(NestedNameSpecifierLoc FromNNS) {
  // Copied from NestedNameSpecifier mostly.
  SmallVector<NestedNameSpecifierLoc , 8> NestedNames;
  NestedNameSpecifierLoc NNS = FromNNS;

  // Push each of the nested-name-specifiers's onto a stack for
  // serialization in reverse order.
  while (NNS) {
    NestedNames.push_back(NNS);
    NNS = NNS.getPrefix();
  }

  NestedNameSpecifierLocBuilder Builder;

  while (!NestedNames.empty()) {
    NNS = NestedNames.pop_back_val();
    NestedNameSpecifier *Spec = nullptr;
    if (Error Err = importInto(Spec, NNS.getNestedNameSpecifier()))
      return std::move(Err);

    NestedNameSpecifier::SpecifierKind Kind = Spec->getKind();

    SourceLocation ToLocalBeginLoc, ToLocalEndLoc;
    if (Kind != NestedNameSpecifier::Super) {
      if (Error Err = importInto(ToLocalBeginLoc, NNS.getLocalBeginLoc()))
        return std::move(Err);

      if (Kind != NestedNameSpecifier::Global)
        if (Error Err = importInto(ToLocalEndLoc, NNS.getLocalEndLoc()))
          return std::move(Err);
    }

    switch (Kind) {
    case NestedNameSpecifier::Identifier:
      Builder.Extend(getToContext(), Spec->getAsIdentifier(), ToLocalBeginLoc,
                     ToLocalEndLoc);
      break;

    case NestedNameSpecifier::Namespace:
      Builder.Extend(getToContext(), Spec->getAsNamespace(), ToLocalBeginLoc,
                     ToLocalEndLoc);
      break;

    case NestedNameSpecifier::TypeSpec: {
      SourceLocation ToTLoc;
      if (Error Err = importInto(ToTLoc, NNS.getTypeLoc().getBeginLoc()))
        return std::move(Err);
      TypeSourceInfo *TSI = getToContext().getTrivialTypeSourceInfo(
          QualType(Spec->getAsType(), 0), ToTLoc);
      Builder.Extend(getToContext(), TSI->getTypeLoc(), ToLocalEndLoc);
      break;
    }

    case NestedNameSpecifier::Global:
      Builder.MakeGlobal(getToContext(), ToLocalBeginLoc);
      break;

    case NestedNameSpecifier::Super: {
      auto ToSourceRangeOrErr = Import(NNS.getSourceRange());
      if (!ToSourceRangeOrErr)
        return ToSourceRangeOrErr.takeError();

      Builder.MakeSuper(getToContext(), Spec->getAsRecordDecl(),
                        ToSourceRangeOrErr->getBegin(),
                        ToSourceRangeOrErr->getEnd());
    }
  }
  }

  return Builder.getWithLocInContext(getToContext());
}

Expected<TemplateName> ASTImporter::Import(TemplateName From) {
  switch (From.getKind()) {
  case TemplateName::Template:
    if (ExpectedDecl ToTemplateOrErr = Import(From.getAsTemplateDecl()))
      return TemplateName(cast<TemplateDecl>((*ToTemplateOrErr)->getCanonicalDecl()));
    else
      return ToTemplateOrErr.takeError();

  case TemplateName::OverloadedTemplate: {
    OverloadedTemplateStorage *FromStorage = From.getAsOverloadedTemplate();
    UnresolvedSet<2> ToTemplates;
    for (auto *I : *FromStorage) {
      if (auto ToOrErr = Import(I))
        ToTemplates.addDecl(cast<NamedDecl>(*ToOrErr));
      else
        return ToOrErr.takeError();
    }
    return ToContext.getOverloadedTemplateName(ToTemplates.begin(),
                                               ToTemplates.end());
  }

  case TemplateName::AssumedTemplate: {
    AssumedTemplateStorage *FromStorage = From.getAsAssumedTemplateName();
    auto DeclNameOrErr = Import(FromStorage->getDeclName());
    if (!DeclNameOrErr)
      return DeclNameOrErr.takeError();
    return ToContext.getAssumedTemplateName(*DeclNameOrErr);
  }

  case TemplateName::QualifiedTemplate: {
    QualifiedTemplateName *QTN = From.getAsQualifiedTemplateName();
    auto QualifierOrErr = Import(QTN->getQualifier());
    if (!QualifierOrErr)
      return QualifierOrErr.takeError();
    auto TNOrErr = Import(QTN->getUnderlyingTemplate());
    if (!TNOrErr)
      return TNOrErr.takeError();
    return ToContext.getQualifiedTemplateName(
        *QualifierOrErr, QTN->hasTemplateKeyword(), *TNOrErr);
  }

  case TemplateName::DependentTemplate: {
    DependentTemplateName *DTN = From.getAsDependentTemplateName();
    auto QualifierOrErr = Import(DTN->getQualifier());
    if (!QualifierOrErr)
      return QualifierOrErr.takeError();
    return ToContext.getDependentTemplateName(
        {*QualifierOrErr, Import(DTN->getName()), DTN->hasTemplateKeyword()});
  }

  case TemplateName::SubstTemplateTemplateParm: {
    SubstTemplateTemplateParmStorage *Subst =
        From.getAsSubstTemplateTemplateParm();
    auto ReplacementOrErr = Import(Subst->getReplacement());
    if (!ReplacementOrErr)
      return ReplacementOrErr.takeError();

    auto AssociatedDeclOrErr = Import(Subst->getAssociatedDecl());
    if (!AssociatedDeclOrErr)
      return AssociatedDeclOrErr.takeError();

    return ToContext.getSubstTemplateTemplateParm(
        *ReplacementOrErr, *AssociatedDeclOrErr, Subst->getIndex(),
        Subst->getPackIndex(), Subst->getFinal());
  }

  case TemplateName::SubstTemplateTemplateParmPack: {
    SubstTemplateTemplateParmPackStorage *SubstPack =
        From.getAsSubstTemplateTemplateParmPack();
    ASTNodeImporter Importer(*this);
    auto ArgPackOrErr =
        Importer.ImportTemplateArgument(SubstPack->getArgumentPack());
    if (!ArgPackOrErr)
      return ArgPackOrErr.takeError();

    auto AssociatedDeclOrErr = Import(SubstPack->getAssociatedDecl());
    if (!AssociatedDeclOrErr)
      return AssociatedDeclOrErr.takeError();

    return ToContext.getSubstTemplateTemplateParmPack(
        *ArgPackOrErr, *AssociatedDeclOrErr, SubstPack->getIndex(),
        SubstPack->getFinal());
  }
  case TemplateName::UsingTemplate: {
    auto UsingOrError = Import(From.getAsUsingShadowDecl());
    if (!UsingOrError)
      return UsingOrError.takeError();
    return TemplateName(cast<UsingShadowDecl>(*UsingOrError));
  }
  case TemplateName::DeducedTemplate:
    llvm_unreachable("Unexpected DeducedTemplate");
  }

  llvm_unreachable("Invalid template name kind");
}

Expected<SourceLocation> ASTImporter::Import(SourceLocation FromLoc) {
  if (FromLoc.isInvalid())
    return SourceLocation{};

  SourceManager &FromSM = FromContext.getSourceManager();
  bool IsBuiltin = FromSM.isWrittenInBuiltinFile(FromLoc);

  FileIDAndOffset Decomposed = FromSM.getDecomposedLoc(FromLoc);
  Expected<FileID> ToFileIDOrErr = Import(Decomposed.first, IsBuiltin);
  if (!ToFileIDOrErr)
    return ToFileIDOrErr.takeError();
  SourceManager &ToSM = ToContext.getSourceManager();
  return ToSM.getComposedLoc(*ToFileIDOrErr, Decomposed.second);
}

Expected<SourceRange> ASTImporter::Import(SourceRange FromRange) {
  SourceLocation ToBegin, ToEnd;
  if (Error Err = importInto(ToBegin, FromRange.getBegin()))
    return std::move(Err);
  if (Error Err = importInto(ToEnd, FromRange.getEnd()))
    return std::move(Err);

  return SourceRange(ToBegin, ToEnd);
}

Expected<FileID> ASTImporter::Import(FileID FromID, bool IsBuiltin) {
  llvm::DenseMap<FileID, FileID>::iterator Pos = ImportedFileIDs.find(FromID);
  if (Pos != ImportedFileIDs.end())
    return Pos->second;

  SourceManager &FromSM = FromContext.getSourceManager();
  SourceManager &ToSM = ToContext.getSourceManager();
  const SrcMgr::SLocEntry &FromSLoc = FromSM.getSLocEntry(FromID);

  // Map the FromID to the "to" source manager.
  FileID ToID;
  if (FromSLoc.isExpansion()) {
    const SrcMgr::ExpansionInfo &FromEx = FromSLoc.getExpansion();
    ExpectedSLoc ToSpLoc = Import(FromEx.getSpellingLoc());
    if (!ToSpLoc)
      return ToSpLoc.takeError();
    ExpectedSLoc ToExLocS = Import(FromEx.getExpansionLocStart());
    if (!ToExLocS)
      return ToExLocS.takeError();
    unsigned ExLength = FromSM.getFileIDSize(FromID);
    SourceLocation MLoc;
    if (FromEx.isMacroArgExpansion()) {
      MLoc = ToSM.createMacroArgExpansionLoc(*ToSpLoc, *ToExLocS, ExLength);
    } else {
      if (ExpectedSLoc ToExLocE = Import(FromEx.getExpansionLocEnd()))
        MLoc = ToSM.createExpansionLoc(*ToSpLoc, *ToExLocS, *ToExLocE, ExLength,
                                       FromEx.isExpansionTokenRange());
      else
        return ToExLocE.takeError();
    }
    ToID = ToSM.getFileID(MLoc);
  } else {
    const SrcMgr::ContentCache *Cache = &FromSLoc.getFile().getContentCache();

    if (!IsBuiltin && !Cache->BufferOverridden) {
      // Include location of this file.
      ExpectedSLoc ToIncludeLoc = Import(FromSLoc.getFile().getIncludeLoc());
      if (!ToIncludeLoc)
        return ToIncludeLoc.takeError();

      // Every FileID that is not the main FileID needs to have a valid include
      // location so that the include chain points to the main FileID. When
      // importing the main FileID (which has no include location), we need to
      // create a fake include location in the main file to keep this property
      // intact.
      SourceLocation ToIncludeLocOrFakeLoc = *ToIncludeLoc;
      if (FromID == FromSM.getMainFileID())
        ToIncludeLocOrFakeLoc = ToSM.getLocForStartOfFile(ToSM.getMainFileID());

      if (Cache->OrigEntry && Cache->OrigEntry->getDir()) {
        // FIXME: We probably want to use getVirtualFileRef(), so we don't hit
        // the disk again
        // FIXME: We definitely want to re-use the existing MemoryBuffer, rather
        // than mmap the files several times.
        auto Entry =
            ToFileManager.getOptionalFileRef(Cache->OrigEntry->getName());
        // FIXME: The filename may be a virtual name that does probably not
        // point to a valid file and we get no Entry here. In this case try with
        // the memory buffer below.
        if (Entry)
          ToID = ToSM.createFileID(*Entry, ToIncludeLocOrFakeLoc,
                                   FromSLoc.getFile().getFileCharacteristic());
      }
    }

    if (ToID.isInvalid() || IsBuiltin) {
      // FIXME: We want to re-use the existing MemoryBuffer!
      std::optional<llvm::MemoryBufferRef> FromBuf =
          Cache->getBufferOrNone(FromContext.getDiagnostics(),
                                 FromSM.getFileManager(), SourceLocation{});
      if (!FromBuf)
        return llvm::make_error<ASTImportError>(ASTImportError::Unknown);

      std::unique_ptr<llvm::MemoryBuffer> ToBuf =
          llvm::MemoryBuffer::getMemBufferCopy(FromBuf->getBuffer(),
                                               FromBuf->getBufferIdentifier());
      ToID = ToSM.createFileID(std::move(ToBuf),
                               FromSLoc.getFile().getFileCharacteristic());
    }
  }

  assert(ToID.isValid() && "Unexpected invalid fileID was created.");

  ImportedFileIDs[FromID] = ToID;
  return ToID;
}

Expected<CXXCtorInitializer *> ASTImporter::Import(CXXCtorInitializer *From) {
  ExpectedExpr ToExprOrErr = Import(From->getInit());
  if (!ToExprOrErr)
    return ToExprOrErr.takeError();

  auto LParenLocOrErr = Import(From->getLParenLoc());
  if (!LParenLocOrErr)
    return LParenLocOrErr.takeError();

  auto RParenLocOrErr = Import(From->getRParenLoc());
  if (!RParenLocOrErr)
    return RParenLocOrErr.takeError();

  if (From->isBaseInitializer()) {
    auto ToTInfoOrErr = Import(From->getTypeSourceInfo());
    if (!ToTInfoOrErr)
      return ToTInfoOrErr.takeError();

    SourceLocation EllipsisLoc;
    if (From->isPackExpansion())
      if (Error Err = importInto(EllipsisLoc, From->getEllipsisLoc()))
        return std::move(Err);

    return new (ToContext) CXXCtorInitializer(
        ToContext, *ToTInfoOrErr, From->isBaseVirtual(), *LParenLocOrErr,
        *ToExprOrErr, *RParenLocOrErr, EllipsisLoc);
  } else if (From->isMemberInitializer()) {
    ExpectedDecl ToFieldOrErr = Import(From->getMember());
    if (!ToFieldOrErr)
      return ToFieldOrErr.takeError();

    auto MemberLocOrErr = Import(From->getMemberLocation());
    if (!MemberLocOrErr)
      return MemberLocOrErr.takeError();

    return new (ToContext) CXXCtorInitializer(
        ToContext, cast_or_null<FieldDecl>(*ToFieldOrErr), *MemberLocOrErr,
        *LParenLocOrErr, *ToExprOrErr, *RParenLocOrErr);
  } else if (From->isIndirectMemberInitializer()) {
    ExpectedDecl ToIFieldOrErr = Import(From->getIndirectMember());
    if (!ToIFieldOrErr)
      return ToIFieldOrErr.takeError();

    auto MemberLocOrErr = Import(From->getMemberLocation());
    if (!MemberLocOrErr)
      return MemberLocOrErr.takeError();

    return new (ToContext) CXXCtorInitializer(
        ToContext, cast_or_null<IndirectFieldDecl>(*ToIFieldOrErr),
        *MemberLocOrErr, *LParenLocOrErr, *ToExprOrErr, *RParenLocOrErr);
  } else if (From->isDelegatingInitializer()) {
    auto ToTInfoOrErr = Import(From->getTypeSourceInfo());
    if (!ToTInfoOrErr)
      return ToTInfoOrErr.takeError();

    return new (ToContext)
        CXXCtorInitializer(ToContext, *ToTInfoOrErr, *LParenLocOrErr,
                           *ToExprOrErr, *RParenLocOrErr);
  } else {
    // FIXME: assert?
    return make_error<ASTImportError>();
  }
}

Expected<CXXBaseSpecifier *>
ASTImporter::Import(const CXXBaseSpecifier *BaseSpec) {
  auto Pos = ImportedCXXBaseSpecifiers.find(BaseSpec);
  if (Pos != ImportedCXXBaseSpecifiers.end())
    return Pos->second;

  Expected<SourceRange> ToSourceRange = Import(BaseSpec->getSourceRange());
  if (!ToSourceRange)
    return ToSourceRange.takeError();
  Expected<TypeSourceInfo *> ToTSI = Import(BaseSpec->getTypeSourceInfo());
  if (!ToTSI)
    return ToTSI.takeError();
  ExpectedSLoc ToEllipsisLoc = Import(BaseSpec->getEllipsisLoc());
  if (!ToEllipsisLoc)
    return ToEllipsisLoc.takeError();
  CXXBaseSpecifier *Imported = new (ToContext) CXXBaseSpecifier(
      *ToSourceRange, BaseSpec->isVirtual(), BaseSpec->isBaseOfClass(),
      BaseSpec->getAccessSpecifierAsWritten(), *ToTSI, *ToEllipsisLoc);
  ImportedCXXBaseSpecifiers[BaseSpec] = Imported;
  return Imported;
}

llvm::Expected<APValue> ASTImporter::Import(const APValue &FromValue) {
  ASTNodeImporter Importer(*this);
  return Importer.ImportAPValue(FromValue);
}

Error ASTImporter::ImportDefinition(Decl *From) {
  ExpectedDecl ToOrErr = Import(From);
  if (!ToOrErr)
    return ToOrErr.takeError();
  Decl *To = *ToOrErr;

  auto *FromDC = cast<DeclContext>(From);
  ASTNodeImporter Importer(*this);

  if (auto *ToRecord = dyn_cast<RecordDecl>(To)) {
    if (!ToRecord->getDefinition()) {
      return Importer.ImportDefinition(
          cast<RecordDecl>(FromDC), ToRecord,
          ASTNodeImporter::IDK_Everything);
    }
  }

  if (auto *ToEnum = dyn_cast<EnumDecl>(To)) {
    if (!ToEnum->getDefinition()) {
      return Importer.ImportDefinition(
          cast<EnumDecl>(FromDC), ToEnum, ASTNodeImporter::IDK_Everything);
    }
  }

  if (auto *ToIFace = dyn_cast<ObjCInterfaceDecl>(To)) {
    if (!ToIFace->getDefinition()) {
      return Importer.ImportDefinition(
          cast<ObjCInterfaceDecl>(FromDC), ToIFace,
          ASTNodeImporter::IDK_Everything);
    }
  }

  if (auto *ToProto = dyn_cast<ObjCProtocolDecl>(To)) {
    if (!ToProto->getDefinition()) {
      return Importer.ImportDefinition(
          cast<ObjCProtocolDecl>(FromDC), ToProto,
          ASTNodeImporter::IDK_Everything);
    }
  }

  return Importer.ImportDeclContext(FromDC, true);
}

Expected<DeclarationName> ASTImporter::Import(DeclarationName FromName) {
  if (!FromName)
    return DeclarationName{};

  switch (FromName.getNameKind()) {
  case DeclarationName::Identifier:
    return DeclarationName(Import(FromName.getAsIdentifierInfo()));

  case DeclarationName::ObjCZeroArgSelector:
  case DeclarationName::ObjCOneArgSelector:
  case DeclarationName::ObjCMultiArgSelector:
    if (auto ToSelOrErr = Import(FromName.getObjCSelector()))
      return DeclarationName(*ToSelOrErr);
    else
      return ToSelOrErr.takeError();

  case DeclarationName::CXXConstructorName: {
    if (auto ToTyOrErr = Import(FromName.getCXXNameType()))
      return ToContext.DeclarationNames.getCXXConstructorName(
          ToContext.getCanonicalType(*ToTyOrErr));
    else
      return ToTyOrErr.takeError();
  }

  case DeclarationName::CXXDestructorName: {
    if (auto ToTyOrErr = Import(FromName.getCXXNameType()))
      return ToContext.DeclarationNames.getCXXDestructorName(
          ToContext.getCanonicalType(*ToTyOrErr));
    else
      return ToTyOrErr.takeError();
  }

  case DeclarationName::CXXDeductionGuideName: {
    if (auto ToTemplateOrErr = Import(FromName.getCXXDeductionGuideTemplate()))
      return ToContext.DeclarationNames.getCXXDeductionGuideName(
          cast<TemplateDecl>(*ToTemplateOrErr));
    else
      return ToTemplateOrErr.takeError();
  }

  case DeclarationName::CXXConversionFunctionName: {
    if (auto ToTyOrErr = Import(FromName.getCXXNameType()))
      return ToContext.DeclarationNames.getCXXConversionFunctionName(
          ToContext.getCanonicalType(*ToTyOrErr));
    else
      return ToTyOrErr.takeError();
  }

  case DeclarationName::CXXOperatorName:
    return ToContext.DeclarationNames.getCXXOperatorName(
                                          FromName.getCXXOverloadedOperator());

  case DeclarationName::CXXLiteralOperatorName:
    return ToContext.DeclarationNames.getCXXLiteralOperatorName(
        Import(FromName.getCXXLiteralIdentifier()));

  case DeclarationName::CXXUsingDirective:
    // FIXME: STATICS!
    return DeclarationName::getUsingDirectiveName();
  }

  llvm_unreachable("Invalid DeclarationName Kind!");
}

IdentifierInfo *ASTImporter::Import(const IdentifierInfo *FromId) {
  if (!FromId)
    return nullptr;

  IdentifierInfo *ToId = &ToContext.Idents.get(FromId->getName());

  if (!ToId->getBuiltinID() && FromId->getBuiltinID())
    ToId->setBuiltinID(FromId->getBuiltinID());

  return ToId;
}

IdentifierOrOverloadedOperator
ASTImporter::Import(IdentifierOrOverloadedOperator FromIO) {
  if (const IdentifierInfo *FromII = FromIO.getIdentifier())
    return Import(FromII);
  return FromIO.getOperator();
}

Expected<Selector> ASTImporter::Import(Selector FromSel) {
  if (FromSel.isNull())
    return Selector{};

  SmallVector<const IdentifierInfo *, 4> Idents;
  Idents.push_back(Import(FromSel.getIdentifierInfoForSlot(0)));
  for (unsigned I = 1, N = FromSel.getNumArgs(); I < N; ++I)
    Idents.push_back(Import(FromSel.getIdentifierInfoForSlot(I)));
  return ToContext.Selectors.getSelector(FromSel.getNumArgs(), Idents.data());
}

llvm::Expected<APValue>
ASTNodeImporter::ImportAPValue(const APValue &FromValue) {
  APValue Result;
  llvm::Error Err = llvm::Error::success();
  auto ImportLoop = [&](const APValue *From, APValue *To, unsigned Size) {
    for (unsigned Idx = 0; Idx < Size; Idx++) {
      APValue Tmp = importChecked(Err, From[Idx]);
      To[Idx] = Tmp;
    }
  };
  switch (FromValue.getKind()) {
  case APValue::None:
  case APValue::Indeterminate:
  case APValue::Int:
  case APValue::Float:
  case APValue::FixedPoint:
  case APValue::ComplexInt:
  case APValue::ComplexFloat:
    Result = FromValue;
    break;
  case APValue::Vector: {
    Result.MakeVector();
    MutableArrayRef<APValue> Elts =
        Result.setVectorUninit(FromValue.getVectorLength());
    ImportLoop(((const APValue::Vec *)(const char *)&FromValue.Data)->Elts,
               Elts.data(), FromValue.getVectorLength());
    break;
  }
  case APValue::Array:
    Result.MakeArray(FromValue.getArrayInitializedElts(),
                     FromValue.getArraySize());
    ImportLoop(((const APValue::Arr *)(const char *)&FromValue.Data)->Elts,
               ((const APValue::Arr *)(const char *)&Result.Data)->Elts,
               FromValue.getArrayInitializedElts());
    break;
  case APValue::Struct:
    Result.MakeStruct(FromValue.getStructNumBases(),
                      FromValue.getStructNumFields());
    ImportLoop(
        ((const APValue::StructData *)(const char *)&FromValue.Data)->Elts,
        ((const APValue::StructData *)(const char *)&Result.Data)->Elts,
        FromValue.getStructNumBases() + FromValue.getStructNumFields());
    break;
  case APValue::Union: {
    Result.MakeUnion();
    const Decl *ImpFDecl = importChecked(Err, FromValue.getUnionField());
    APValue ImpValue = importChecked(Err, FromValue.getUnionValue());
    if (Err)
      return std::move(Err);
    Result.setUnion(cast<FieldDecl>(ImpFDecl), ImpValue);
    break;
  }
  case APValue::AddrLabelDiff: {
    Result.MakeAddrLabelDiff();
    const Expr *ImpLHS = importChecked(Err, FromValue.getAddrLabelDiffLHS());
    const Expr *ImpRHS = importChecked(Err, FromValue.getAddrLabelDiffRHS());
    if (Err)
      return std::move(Err);
    Result.setAddrLabelDiff(cast<AddrLabelExpr>(ImpLHS),
                            cast<AddrLabelExpr>(ImpRHS));
    break;
  }
  case APValue::MemberPointer: {
    const Decl *ImpMemPtrDecl =
        importChecked(Err, FromValue.getMemberPointerDecl());
    if (Err)
      return std::move(Err);
    MutableArrayRef<const CXXRecordDecl *> ToPath =
        Result.setMemberPointerUninit(
            cast<const ValueDecl>(ImpMemPtrDecl),
            FromValue.isMemberPointerToDerivedMember(),
            FromValue.getMemberPointerPath().size());
    ArrayRef<const CXXRecordDecl *> FromPath = Result.getMemberPointerPath();
    for (unsigned Idx = 0; Idx < FromValue.getMemberPointerPath().size();
         Idx++) {
      const Decl *ImpDecl = importChecked(Err, FromPath[Idx]);
      if (Err)
        return std::move(Err);
      ToPath[Idx] = cast<const CXXRecordDecl>(ImpDecl->getCanonicalDecl());
    }
    break;
  }
  case APValue::LValue:
    APValue::LValueBase Base;
    QualType FromElemTy;
    if (FromValue.getLValueBase()) {
      assert(!FromValue.getLValueBase().is<DynamicAllocLValue>() &&
             "in C++20 dynamic allocation are transient so they shouldn't "
             "appear in the AST");
      if (!FromValue.getLValueBase().is<TypeInfoLValue>()) {
        if (const auto *E =
                FromValue.getLValueBase().dyn_cast<const Expr *>()) {
          FromElemTy = E->getType();
          const Expr *ImpExpr = importChecked(Err, E);
          if (Err)
            return std::move(Err);
          Base = APValue::LValueBase(ImpExpr,
                                     FromValue.getLValueBase().getCallIndex(),
                                     FromValue.getLValueBase().getVersion());
        } else {
          FromElemTy =
              FromValue.getLValueBase().get<const ValueDecl *>()->getType();
          const Decl *ImpDecl = importChecked(
              Err, FromValue.getLValueBase().get<const ValueDecl *>());
          if (Err)
            return std::move(Err);
          Base = APValue::LValueBase(cast<ValueDecl>(ImpDecl),
                                     FromValue.getLValueBase().getCallIndex(),
                                     FromValue.getLValueBase().getVersion());
        }
      } else {
        FromElemTy = FromValue.getLValueBase().getTypeInfoType();
        const Type *ImpTypeInfo = importChecked(
            Err, FromValue.getLValueBase().get<TypeInfoLValue>().getType());
        QualType ImpType =
            importChecked(Err, FromValue.getLValueBase().getTypeInfoType());
        if (Err)
          return std::move(Err);
        Base = APValue::LValueBase::getTypeInfo(TypeInfoLValue(ImpTypeInfo),
                                                ImpType);
      }
    }
    CharUnits Offset = FromValue.getLValueOffset();
    unsigned PathLength = FromValue.getLValuePath().size();
    Result.MakeLValue();
    if (FromValue.hasLValuePath()) {
      MutableArrayRef<APValue::LValuePathEntry> ToPath = Result.setLValueUninit(
          Base, Offset, PathLength, FromValue.isLValueOnePastTheEnd(),
          FromValue.isNullPointer());
      ArrayRef<APValue::LValuePathEntry> FromPath = FromValue.getLValuePath();
      for (unsigned LoopIdx = 0; LoopIdx < PathLength; LoopIdx++) {
        if (FromElemTy->isRecordType()) {
          const Decl *FromDecl =
              FromPath[LoopIdx].getAsBaseOrMember().getPointer();
          const Decl *ImpDecl = importChecked(Err, FromDecl);
          if (Err)
            return std::move(Err);
          if (auto *RD = dyn_cast<CXXRecordDecl>(FromDecl))
            FromElemTy = Importer.FromContext.getRecordType(RD);
          else
            FromElemTy = cast<ValueDecl>(FromDecl)->getType();
          ToPath[LoopIdx] = APValue::LValuePathEntry(APValue::BaseOrMemberType(
              ImpDecl, FromPath[LoopIdx].getAsBaseOrMember().getInt()));
        } else {
          FromElemTy =
              Importer.FromContext.getAsArrayType(FromElemTy)->getElementType();
          ToPath[LoopIdx] = APValue::LValuePathEntry::ArrayIndex(
              FromPath[LoopIdx].getAsArrayIndex());
        }
      }
    } else
      Result.setLValue(Base, Offset, APValue::NoLValuePath{},
                       FromValue.isNullPointer());
  }
  if (Err)
    return std::move(Err);
  return Result;
}

Expected<DeclarationName> ASTImporter::HandleNameConflict(DeclarationName Name,
                                                          DeclContext *DC,
                                                          unsigned IDNS,
                                                          NamedDecl **Decls,
                                                          unsigned NumDecls) {
  if (ODRHandling == ODRHandlingType::Conservative)
    // Report error at any name conflict.
    return make_error<ASTImportError>(ASTImportError::NameConflict);
  else
    // Allow to create the new Decl with the same name.
    return Name;
}

DiagnosticBuilder ASTImporter::ToDiag(SourceLocation Loc, unsigned DiagID) {
  if (LastDiagFromFrom)
    ToContext.getDiagnostics().notePriorDiagnosticFrom(
      FromContext.getDiagnostics());
  LastDiagFromFrom = false;
  return ToContext.getDiagnostics().Report(Loc, DiagID);
}

DiagnosticBuilder ASTImporter::FromDiag(SourceLocation Loc, unsigned DiagID) {
  if (!LastDiagFromFrom)
    FromContext.getDiagnostics().notePriorDiagnosticFrom(
      ToContext.getDiagnostics());
  LastDiagFromFrom = true;
  return FromContext.getDiagnostics().Report(Loc, DiagID);
}

void ASTImporter::CompleteDecl (Decl *D) {
  if (auto *ID = dyn_cast<ObjCInterfaceDecl>(D)) {
    if (!ID->getDefinition())
      ID->startDefinition();
  }
  else if (auto *PD = dyn_cast<ObjCProtocolDecl>(D)) {
    if (!PD->getDefinition())
      PD->startDefinition();
  }
  else if (auto *TD = dyn_cast<TagDecl>(D)) {
    if (!TD->getDefinition() && !TD->isBeingDefined()) {
      TD->startDefinition();
      TD->setCompleteDefinition(true);
    }
  }
  else {
    assert(0 && "CompleteDecl called on a Decl that can't be completed");
  }
}

Decl *ASTImporter::MapImported(Decl *From, Decl *To) {
  auto [Pos, Inserted] = ImportedDecls.try_emplace(From, To);
  assert((Inserted || Pos->second == To) &&
         "Try to import an already imported Decl");
  if (!Inserted)
    return Pos->second;
  // This mapping should be maintained only in this function. Therefore do not
  // check for additional consistency.
  ImportedFromDecls[To] = From;
  // In the case of TypedefNameDecl we create the Decl first and only then we
  // import and set its DeclContext. So, the DC is still not set when we reach
  // here from GetImportedOrCreateDecl.
  if (To->getDeclContext())
    AddToLookupTable(To);
  return To;
}

std::optional<ASTImportError>
ASTImporter::getImportDeclErrorIfAny(Decl *FromD) const {
  auto Pos = ImportDeclErrors.find(FromD);
  if (Pos != ImportDeclErrors.end())
    return Pos->second;
  else
    return std::nullopt;
}

void ASTImporter::setImportDeclError(Decl *From, ASTImportError Error) {
  auto InsertRes = ImportDeclErrors.insert({From, Error});
  (void)InsertRes;
  // Either we set the error for the first time, or we already had set one and
  // now we want to set the same error.
  assert(InsertRes.second || InsertRes.first->second.Error == Error.Error);
}

bool ASTImporter::IsStructurallyEquivalent(QualType From, QualType To,
                                           bool Complain) {
  llvm::DenseMap<const Type *, const Type *>::iterator Pos =
      ImportedTypes.find(From.getTypePtr());
  if (Pos != ImportedTypes.end()) {
    if (ExpectedType ToFromOrErr = Import(From)) {
      if (ToContext.hasSameType(*ToFromOrErr, To))
        return true;
    } else {
      llvm::consumeError(ToFromOrErr.takeError());
    }
  }

  StructuralEquivalenceContext Ctx(
      getToContext().getLangOpts(), FromContext, ToContext, NonEquivalentDecls,
      getStructuralEquivalenceKind(*this), false, Complain);
  return Ctx.IsEquivalent(From, To);
}
