diff options
Diffstat (limited to 'clang/lib/AST/ASTImporter.cpp')
| -rw-r--r-- | clang/lib/AST/ASTImporter.cpp | 8809 |
1 files changed, 8809 insertions, 0 deletions
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp new file mode 100644 index 000000000000..54acca7dc62c --- /dev/null +++ b/clang/lib/AST/ASTImporter.cpp @@ -0,0 +1,8809 @@ +//===- 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/ASTImporterSharedState.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/ASTDiagnostic.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/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/APSInt.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/None.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/ScopeExit.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MemoryBuffer.h" +#include <algorithm> +#include <cassert> +#include <cstddef> +#include <memory> +#include <type_traits> +#include <utility> + +namespace clang { + + using llvm::make_error; + using llvm::Error; + using llvm::Expected; + 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 ImportError::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 ImportError::log(raw_ostream &OS) const { + OS << toString(); + } + + std::error_code ImportError::convertToErrorCode() const { + llvm_unreachable("Function not implemented."); + } + + char ImportError::ID; + + template <class T> + 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"); + } + + 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(); + } + + 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> + LLVM_NODISCARD Error importInto(ImportT &To, const ImportT &From) { + return Importer.importInto(To, From); + } + + // Use this to import pointers of specific type. + template <typename ImportT> + LLVM_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> + Expected<T *> import(T *From) { + auto ToOrErr = Importer.Import(From); + if (!ToOrErr) + return ToOrErr.takeError(); + return cast_or_null<T>(*ToOrErr); + } + + template <typename T> + Expected<T *> 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 Optional<T> by importing the contained T, if any. + template<typename T> + Expected<Optional<T>> import(Optional<T> From) { + if (!From) + return Optional<T>(); + return import(*From); + } + + template <class T> + Expected<std::tuple<T>> + importSeq(const T &From) { + Expected<T> ToOrErr = import(From); + if (!ToOrErr) + return ToOrErr.takeError(); + return std::make_tuple<T>(std::move(*ToOrErr)); + } + + // Import multiple objects with a single function call. + // This should work for every type for which a variant of `import` exists. + // The arguments are processed from left to right and import is stopped on + // first error. + template <class THead, class... TTail> + Expected<std::tuple<THead, TTail...>> + importSeq(const THead &FromHead, const TTail &...FromTail) { + Expected<std::tuple<THead>> ToHeadOrErr = importSeq(FromHead); + if (!ToHeadOrErr) + return ToHeadOrErr.takeError(); + Expected<std::tuple<TTail...>> ToTailOrErr = importSeq(FromTail...); + if (!ToTailOrErr) + return ToTailOrErr.takeError(); + return std::tuple_cat(*ToHeadOrErr, *ToTailOrErr); + } + +// Wrapper for an overload set. + template <typename ToDeclT> struct CallOverloadedCreateFun { + template <typename... Args> + auto operator()(Args &&... args) + -> decltype(ToDeclT::Create(std::forward<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> + LLVM_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> + LLVM_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> + LLVM_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); + InitializeImportedDecl(FromD, ToD); + return false; // A new Decl is created. + } + + void InitializeImportedDecl(Decl *FromD, Decl *ToD) { + ToD->IdentifierNamespace = FromD->IdentifierNamespace; + if (FromD->hasAttrs()) + for (const Attr *FromAttr : FromD->getAttrs()) { + // FIXME: Return of the error here is not possible until store of + // import errors is implemented. + auto ToAttrOrErr = import(FromAttr); + if (ToAttrOrErr) + ToD->addAttr(*ToAttrOrErr); + else + llvm::consumeError(ToAttrOrErr.takeError()); + } + 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; + } + + 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); + ExpectedType VisitAtomicType(const AtomicType *T); + ExpectedType VisitBuiltinType(const BuiltinType *T); + ExpectedType VisitDecayedType(const DecayedType *T); + ExpectedType VisitComplexType(const ComplexType *T); + ExpectedType VisitPointerType(const PointerType *T); + ExpectedType VisitBlockPointerType(const BlockPointerType *T); + ExpectedType VisitLValueReferenceType(const LValueReferenceType *T); + ExpectedType VisitRValueReferenceType(const RValueReferenceType *T); + ExpectedType VisitMemberPointerType(const MemberPointerType *T); + ExpectedType VisitConstantArrayType(const ConstantArrayType *T); + ExpectedType VisitIncompleteArrayType(const IncompleteArrayType *T); + ExpectedType VisitVariableArrayType(const VariableArrayType *T); + ExpectedType VisitDependentSizedArrayType(const DependentSizedArrayType *T); + // FIXME: DependentSizedExtVectorType + ExpectedType VisitVectorType(const VectorType *T); + ExpectedType VisitExtVectorType(const ExtVectorType *T); + ExpectedType VisitFunctionNoProtoType(const FunctionNoProtoType *T); + ExpectedType VisitFunctionProtoType(const FunctionProtoType *T); + ExpectedType VisitUnresolvedUsingType(const UnresolvedUsingType *T); + ExpectedType VisitParenType(const ParenType *T); + ExpectedType VisitTypedefType(const TypedefType *T); + ExpectedType VisitTypeOfExprType(const TypeOfExprType *T); + // FIXME: DependentTypeOfExprType + ExpectedType VisitTypeOfType(const TypeOfType *T); + ExpectedType VisitDecltypeType(const DecltypeType *T); + ExpectedType VisitUnaryTransformType(const UnaryTransformType *T); + ExpectedType VisitAutoType(const AutoType *T); + ExpectedType VisitInjectedClassNameType(const InjectedClassNameType *T); + // FIXME: DependentDecltypeType + ExpectedType VisitRecordType(const RecordType *T); + ExpectedType VisitEnumType(const EnumType *T); + ExpectedType VisitAttributedType(const AttributedType *T); + ExpectedType VisitTemplateTypeParmType(const TemplateTypeParmType *T); + ExpectedType VisitSubstTemplateTypeParmType( + const SubstTemplateTypeParmType *T); + ExpectedType VisitTemplateSpecializationType( + const TemplateSpecializationType *T); + ExpectedType VisitElaboratedType(const ElaboratedType *T); + ExpectedType VisitDependentNameType(const DependentNameType *T); + ExpectedType VisitPackExpansionType(const PackExpansionType *T); + ExpectedType VisitDependentTemplateSpecializationType( + const DependentTemplateSpecializationType *T); + ExpectedType VisitObjCInterfaceType(const ObjCInterfaceType *T); + ExpectedType VisitObjCObjectType(const ObjCObjectType *T); + ExpectedType VisitObjCObjectPointerType(const ObjCObjectPointerType *T); + + // Importing declarations + 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); + + Expected<CXXCastPath> ImportCastPath(CastExpr *E); + + 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( + const TemplateArgument *FromArgs, unsigned NumFromArgs, + 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); + Error ImportTemplateParameterLists(const DeclaratorDecl *FromD, + DeclaratorDecl *ToD); + + Error ImportTemplateInformation(FunctionDecl *FromFD, FunctionDecl *ToFD); + + Error ImportFunctionDeclBody(FunctionDecl *FromFD, FunctionDecl *ToFD); + + Error ImportDefaultArgOfParmVarDecl(const ParmVarDecl *FromParam, + ParmVarDecl *ToParam); + + template <typename T> + bool hasSameVisibilityContext(T *Found, T *From); + + bool IsStructuralMatch(Decl *From, Decl *To, bool Complain); + bool IsStructuralMatch(RecordDecl *FromRecord, RecordDecl *ToRecord, + bool Complain = true); + bool IsStructuralMatch(VarDecl *FromVar, VarDecl *ToVar, + bool Complain = true); + bool IsStructuralMatch(EnumDecl *FromEnum, EnumDecl *ToRecord); + bool IsStructuralMatch(EnumConstantDecl *FromEC, EnumConstantDecl *ToEC); + bool IsStructuralMatch(FunctionTemplateDecl *From, + FunctionTemplateDecl *To); + bool IsStructuralMatch(FunctionDecl *From, FunctionDecl *To); + bool IsStructuralMatch(ClassTemplateDecl *From, ClassTemplateDecl *To); + bool IsStructuralMatch(VarTemplateDecl *From, VarTemplateDecl *To); + 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 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 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 VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D); + ExpectedDecl VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *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); + + // 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 VisitVAArgExpr(VAArgExpr *E); + ExpectedStmt VisitChooseExpr(ChooseExpr *E); + ExpectedStmt VisitGNUNullExpr(GNUNullExpr *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 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 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); + + template<typename IIter, typename OIter> + Error ImportArrayChecked(IIter Ibegin, IIter Iend, OIter Obegin) { + using ItemT = typename std::remove_reference<decltype(*Obegin)>::type; + 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); + }; + +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. + auto TemplArgs = FTSInfo->TemplateArguments->asArray(); + if (Error Err = ImportTemplateArguments(TemplArgs.data(), TemplArgs.size(), + 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); + } + + 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(*ToOrErr, *ToTypeOrErr); + } + + case TemplateArgument::NullPtr: { + ExpectedType ToTypeOrErr = import(From.getNullPtrType()); + if (!ToTypeOrErr) + return ToTypeOrErr.takeError(); + return TemplateArgument(*ToTypeOrErr, /*isNullPtr*/true); + } + + case TemplateArgument::Template: { + Expected<TemplateName> ToTemplateOrErr = import(From.getAsTemplate()); + if (!ToTemplateOrErr) + return ToTemplateOrErr.takeError(); + + return TemplateArgument(*ToTemplateOrErr); + } + + case TemplateArgument::TemplateExpansion: { + Expected<TemplateName> ToTemplateOrErr = + import(From.getAsTemplateOrTemplatePattern()); + if (!ToTemplateOrErr) + return ToTemplateOrErr.takeError(); + + return TemplateArgument( + *ToTemplateOrErr, From.getNumTemplateExpansions()); + } + + case TemplateArgument::Expression: + if (ExpectedExpr ToExpr = import(From.getAsExpr())) + return TemplateArgument(*ToExpr); + else + return ToExpr.takeError(); + + case TemplateArgument::Pack: { + SmallVector<TemplateArgument, 2> ToPack; + ToPack.reserve(From.pack_size()); + if (Error Err = ImportTemplateArguments( + From.pack_begin(), From.pack_size(), ToPack)) + return std::move(Err); + + return TemplateArgument( + llvm::makeArrayRef(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( + *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 Designator(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(D.getFirstExprIndex(), + *ToLBracketLocOrErr, *ToRBracketLocOrErr); + + ExpectedSLoc ToEllipsisLocOrErr = import(D.getEllipsisLoc()); + if (!ToEllipsisLocOrErr) + return ToEllipsisLocOrErr.takeError(); + + assert(D.isArrayRangeDesignator()); + return Designator( + D.getFirstExprIndex(), *ToLBracketLocOrErr, *ToEllipsisLocOrErr, + *ToRBracketLocOrErr); +} + +template <> +Expected<LambdaCapture> ASTNodeImporter::import(const LambdaCapture &From) { + VarDecl *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::hasSameVisibilityContext(T *Found, T *From) { + 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::hasSameVisibilityContext(TypedefNameDecl *Found, + TypedefNameDecl *From) { + 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<ImportError>(ImportError::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/AArch64SVEACLETypes.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(); + + ExpectedType ClassTypeOrErr = import(QualType(T->getClass(), 0)); + if (!ClassTypeOrErr) + return ClassTypeOrErr.takeError(); + + return Importer.getToContext().getMemberPointerType( + *ToPointeeTypeOrErr, (*ClassTypeOrErr).getTypePtr()); +} + +ExpectedType +ASTNodeImporter::VisitConstantArrayType(const ConstantArrayType *T) { + QualType ToElementType; + const Expr *ToSizeExpr; + if (auto Imp = importSeq(T->getElementType(), T->getSizeExpr())) + std::tie(ToElementType, ToSizeExpr) = *Imp; + else + return Imp.takeError(); + + return Importer.getToContext().getConstantArrayType( + ToElementType, T->getSize(), ToSizeExpr, T->getSizeModifier(), + T->getIndexTypeCVRQualifiers()); +} + +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) { + QualType ToElementType; + Expr *ToSizeExpr; + SourceRange ToBracketsRange; + if (auto Imp = importSeq( + T->getElementType(), T->getSizeExpr(), T->getBracketsRange())) + std::tie(ToElementType, ToSizeExpr, ToBracketsRange) = *Imp; + else + return Imp.takeError(); + + return Importer.getToContext().getVariableArrayType( + ToElementType, ToSizeExpr, T->getSizeModifier(), + T->getIndexTypeCVRQualifiers(), ToBracketsRange); +} + +ExpectedType ASTNodeImporter::VisitDependentSizedArrayType( + const DependentSizedArrayType *T) { + QualType ToElementType; + Expr *ToSizeExpr; + SourceRange ToBracketsRange; + if (auto Imp = importSeq( + T->getElementType(), T->getSizeExpr(), T->getBracketsRange())) + std::tie(ToElementType, ToSizeExpr, ToBracketsRange) = *Imp; + else + return Imp.takeError(); + // SizeExpr may be null if size is not specified directly. + // For example, 'int a[]'. + + return Importer.getToContext().getDependentSizedArrayType( + ToElementType, ToSizeExpr, T->getSizeModifier(), + T->getIndexTypeCVRQualifiers(), ToBracketsRange); +} + +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(); + FunctionProtoType::ExtProtoInfo ToEPI; + + auto Imp = importSeq( + FromEPI.ExceptionSpec.NoexceptExpr, + FromEPI.ExceptionSpec.SourceDecl, + FromEPI.ExceptionSpec.SourceTemplate); + if (!Imp) + return Imp.takeError(); + + 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.Exceptions = ExceptionTypes; + std::tie( + ToEPI.ExceptionSpec.NoexceptExpr, + ToEPI.ExceptionSpec.SourceDecl, + ToEPI.ExceptionSpec.SourceTemplate) = *Imp; + + return Importer.getToContext().getFunctionType( + *ToReturnTypeOrErr, ArgTypes, ToEPI); +} + +ExpectedType ASTNodeImporter::VisitUnresolvedUsingType( + const UnresolvedUsingType *T) { + UnresolvedUsingTypenameDecl *ToD; + Decl *ToPrevD; + if (auto Imp = importSeq(T->getDecl(), T->getDecl()->getPreviousDecl())) + std::tie(ToD, ToPrevD) = *Imp; + else + return Imp.takeError(); + + 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::VisitTypedefType(const TypedefType *T) { + Expected<TypedefNameDecl *> ToDeclOrErr = import(T->getDecl()); + if (!ToDeclOrErr) + return ToDeclOrErr.takeError(); + + return Importer.getToContext().getTypeDeclType(*ToDeclOrErr); +} + +ExpectedType ASTNodeImporter::VisitTypeOfExprType(const TypeOfExprType *T) { + ExpectedExpr ToExprOrErr = import(T->getUnderlyingExpr()); + if (!ToExprOrErr) + return ToExprOrErr.takeError(); + + return Importer.getToContext().getTypeOfExprType(*ToExprOrErr); +} + +ExpectedType ASTNodeImporter::VisitTypeOfType(const TypeOfType *T) { + ExpectedType ToUnderlyingTypeOrErr = import(T->getUnderlyingType()); + if (!ToUnderlyingTypeOrErr) + return ToUnderlyingTypeOrErr.takeError(); + + return Importer.getToContext().getTypeOfType(*ToUnderlyingTypeOrErr); +} + +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(); + + return Importer.getToContext().getAutoType(*ToDeducedTypeOrErr, + T->getKeyword(), + /*IsDependent*/false); +} + +ExpectedType ASTNodeImporter::VisitInjectedClassNameType( + const InjectedClassNameType *T) { + Expected<CXXRecordDecl *> ToDeclOrErr = import(T->getDecl()); + if (!ToDeclOrErr) + return ToDeclOrErr.takeError(); + + ExpectedType ToInjTypeOrErr = import(T->getInjectedSpecializationType()); + if (!ToInjTypeOrErr) + return ToInjTypeOrErr.takeError(); + + // FIXME: ASTContext::getInjectedClassNameType is not suitable for AST reading + // See comments in InjectedClassNameType definition for details + // return Importer.getToContext().getInjectedClassNameType(D, InjType); + enum { + TypeAlignmentInBits = 4, + TypeAlignment = 1 << TypeAlignmentInBits + }; + + return QualType(new (Importer.getToContext(), TypeAlignment) + InjectedClassNameType(*ToDeclOrErr, *ToInjTypeOrErr), 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); +} + +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) { + ExpectedType ReplacedOrErr = import(QualType(T->getReplacedParameter(), 0)); + if (!ReplacedOrErr) + return ReplacedOrErr.takeError(); + const TemplateTypeParmType *Replaced = + cast<TemplateTypeParmType>((*ReplacedOrErr).getTypePtr()); + + ExpectedType ToReplacementTypeOrErr = import(T->getReplacementType()); + if (!ToReplacementTypeOrErr) + return ToReplacementTypeOrErr.takeError(); + + return Importer.getToContext().getSubstTemplateTypeParmType( + Replaced, (*ToReplacementTypeOrErr).getCanonicalType()); +} + +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->getArgs(), T->getNumArgs(), ToTemplateArgs)) + return std::move(Err); + + QualType ToCanonType; + if (!QualType(T, 0).isCanonical()) { + QualType FromCanonType + = Importer.getFromContext().getCanonicalType(QualType(T, 0)); + if (ExpectedType TyOrErr = import(FromCanonType)) + ToCanonType = *TyOrErr; + else + return TyOrErr.takeError(); + } + return Importer.getToContext().getTemplateSpecializationType(*ToTemplateOrErr, + ToTemplateArgs, + ToCanonType); +} + +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()); +} + +ExpectedType ASTNodeImporter::VisitDependentTemplateSpecializationType( + const DependentTemplateSpecializationType *T) { + auto ToQualifierOrErr = import(T->getQualifier()); + if (!ToQualifierOrErr) + return ToQualifierOrErr.takeError(); + + IdentifierInfo *ToName = Importer.Import(T->getIdentifier()); + + SmallVector<TemplateArgument, 2> ToPack; + ToPack.reserve(T->getNumArgs()); + if (Error Err = ImportTemplateArguments( + T->getArgs(), T->getNumArgs(), ToPack)) + return std::move(Err); + + return Importer.getToContext().getDependentTemplateSpecializationType( + T->getKeyword(), *ToQualifierOrErr, ToName, ToPack); +} + +ExpectedType +ASTNodeImporter::VisitDependentNameType(const DependentNameType *T) { + auto ToQualifierOrErr = import(T->getQualifier()); + if (!ToQualifierOrErr) + return ToQualifierOrErr.takeError(); + + IdentifierInfo *Name = Importer.Import(T->getIdentifier()); + + QualType Canon; + if (T != T->getCanonicalTypeInternal().getTypePtr()) { + if (ExpectedType TyOrErr = import(T->getCanonicalTypeInternal())) + Canon = (*TyOrErr).getCanonicalType(); + else + return TyOrErr.takeError(); + } + + return Importer.getToContext().getDependentNameType(T->getKeyword(), + *ToQualifierOrErr, + Name, Canon); +} + +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); +} + +//---------------------------------------------------------------------------- +// 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); + 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<ImportError>(ImportError::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::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. + bool AccumulateChildErrors = isa<TagDecl>(FromDC); + + Error ChildErrors = Error::success(); + for (auto *From : FromDC->decls()) { + ExpectedDecl ImportedOrErr = import(From); + if (!ImportedOrErr) { + if (AccumulateChildErrors) + ChildErrors = + joinErrors(std::move(ChildErrors), ImportedOrErr.takeError()); + else + consumeError(ImportedOrErr.takeError()); + } + } + + // 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 apper 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. + const auto *FromRD = dyn_cast<RecordDecl>(FromDC); + if (!FromRD) + return ChildErrors; + + auto ToDCOrErr = Importer.ImportContext(FromDC); + if (!ToDCOrErr) { + consumeError(std::move(ChildErrors)); + return ToDCOrErr.takeError(); + } + + 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 (isa<FieldDecl>(D) || isa<IndirectFieldDecl>(D) || isa<FriendDecl>(D)) { + assert(D && "DC contains a null decl"); + Decl *ToD = Importer.GetAlreadyImportedOrNull(D); + // Remove only the decls which we successfully imported. + if (ToD) { + 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); + } + } + } + + return ChildErrors; +} + +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))) { + 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(); + // 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 (From->isInitKnownICE()) { + EvaluatedStmt *Eval = To->ensureEvaluatedStmt(); + Eval->CheckedICE = true; + Eval->IsICE = From->isInitICE(); + } + + // 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( + const TemplateArgument *FromArgs, unsigned NumFromArgs, + SmallVectorImpl<TemplateArgument> &ToArgs) { + for (unsigned I = 0; I != NumFromArgs; ++I) { + if (auto ToOrErr = import(FromArgs[I])) + 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) { + StructuralEquivalenceContext Ctx( + Importer.getFromContext(), Importer.getToContext(), + Importer.getNonEquivalentDecls(), getStructuralEquivalenceKind(Importer), + false, Complain); + return Ctx.IsEquivalent(From, To); +} + +bool ASTNodeImporter::IsStructuralMatch(RecordDecl *FromRecord, + RecordDecl *ToRecord, bool Complain) { + // Eliminate a potential failure point where we attempt to re-import + // something we're trying to import while completing ToRecord. + Decl *ToOrigin = Importer.GetOriginalDecl(ToRecord); + if (ToOrigin) { + auto *ToOriginRecord = dyn_cast<RecordDecl>(ToOrigin); + if (ToOriginRecord) + ToRecord = ToOriginRecord; + } + + StructuralEquivalenceContext Ctx(Importer.getFromContext(), + ToRecord->getASTContext(), + Importer.getNonEquivalentDecls(), + getStructuralEquivalenceKind(Importer), + false, Complain); + return Ctx.IsEquivalent(FromRecord, ToRecord); +} + +bool ASTNodeImporter::IsStructuralMatch(VarDecl *FromVar, VarDecl *ToVar, + bool Complain) { + StructuralEquivalenceContext Ctx( + Importer.getFromContext(), Importer.getToContext(), + Importer.getNonEquivalentDecls(), getStructuralEquivalenceKind(Importer), + false, Complain); + return Ctx.IsEquivalent(FromVar, ToVar); +} + +bool ASTNodeImporter::IsStructuralMatch(EnumDecl *FromEnum, EnumDecl *ToEnum) { + // Eliminate a potential failure point where we attempt to re-import + // something we're trying to import while completing ToEnum. + if (Decl *ToOrigin = Importer.GetOriginalDecl(ToEnum)) + if (auto *ToOriginEnum = dyn_cast<EnumDecl>(ToOrigin)) + ToEnum = ToOriginEnum; + + StructuralEquivalenceContext Ctx( + Importer.getFromContext(), Importer.getToContext(), + Importer.getNonEquivalentDecls(), getStructuralEquivalenceKind(Importer)); + return Ctx.IsEquivalent(FromEnum, ToEnum); +} + +bool ASTNodeImporter::IsStructuralMatch(FunctionTemplateDecl *From, + FunctionTemplateDecl *To) { + StructuralEquivalenceContext Ctx( + Importer.getFromContext(), Importer.getToContext(), + Importer.getNonEquivalentDecls(), getStructuralEquivalenceKind(Importer), + false, false); + return Ctx.IsEquivalent(From, To); +} + +bool ASTNodeImporter::IsStructuralMatch(FunctionDecl *From, FunctionDecl *To) { + StructuralEquivalenceContext Ctx( + Importer.getFromContext(), Importer.getToContext(), + Importer.getNonEquivalentDecls(), getStructuralEquivalenceKind(Importer), + false, false); + return Ctx.IsEquivalent(From, To); +} + +bool ASTNodeImporter::IsStructuralMatch(EnumConstantDecl *FromEC, + EnumConstantDecl *ToEC) { + const llvm::APSInt &FromVal = FromEC->getInitVal(); + const llvm::APSInt &ToVal = ToEC->getInitVal(); + + return FromVal.isSigned() == ToVal.isSigned() && + FromVal.getBitWidth() == ToVal.getBitWidth() && + FromVal == ToVal; +} + +bool ASTNodeImporter::IsStructuralMatch(ClassTemplateDecl *From, + ClassTemplateDecl *To) { + StructuralEquivalenceContext Ctx(Importer.getFromContext(), + Importer.getToContext(), + Importer.getNonEquivalentDecls(), + getStructuralEquivalenceKind(Importer)); + return Ctx.IsEquivalent(From, To); +} + +bool ASTNodeImporter::IsStructuralMatch(VarTemplateDecl *From, + VarTemplateDecl *To) { + StructuralEquivalenceContext Ctx(Importer.getFromContext(), + Importer.getToContext(), + Importer.getNonEquivalentDecls(), + getStructuralEquivalenceKind(Importer)); + return Ctx.IsEquivalent(From, To); +} + +ExpectedDecl ASTNodeImporter::VisitDecl(Decl *D) { + Importer.FromDiag(D->getLocation(), diag::err_unsupported_ast_node) + << D->getDeclKindName(); + return make_error<ImportError>(ImportError::UnsupportedConstruct); +} + +ExpectedDecl ASTNodeImporter::VisitImportDecl(ImportDecl *D) { + Importer.FromDiag(D->getLocation(), diag::err_unsupported_ast_node) + << D->getDeclKindName(); + return make_error<ImportError>(ImportError::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::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; + + SourceLocation ToLocation, ToRParenLoc; + Expr *ToAssertExpr; + StringLiteral *ToMessage; + if (auto Imp = importSeq( + D->getLocation(), D->getAssertExpr(), D->getMessage(), D->getRParenLoc())) + std::tie(ToLocation, ToAssertExpr, ToMessage, ToRParenLoc) = *Imp; + else + return Imp.takeError(); + + 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. + // FIXME: Not testable. + if (auto *TU = dyn_cast<TranslationUnitDecl>(DC)) + MergeWithNamespace = TU->getAnonymousNamespace(); + else + MergeWithNamespace = cast<NamespaceDecl>(DC)->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(); + + // 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)) + return ToNamespace; + 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. + + SourceLocation ToNamespaceLoc, ToAliasLoc, ToTargetNameLoc; + NestedNameSpecifierLoc ToQualifierLoc; + NamespaceDecl *ToNamespace; + if (auto Imp = importSeq( + D->getNamespaceLoc(), D->getAliasLoc(), D->getQualifierLoc(), + D->getTargetNameLoc(), D->getNamespace())) + std::tie( + ToNamespaceLoc, ToAliasLoc, ToQualifierLoc, ToTargetNameLoc, + ToNamespace) = *Imp; + else + return Imp.takeError(); + 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. + 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; + + // 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->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 (!hasSameVisibilityContext(FoundTypedef, D)) + continue; + + QualType FromUT = D->getUnderlyingType(); + QualType FoundUT = FoundTypedef->getUnderlyingType(); + if (Importer.IsStructurallyEquivalent(FromUT, FoundUT)) { + // 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(); + } + } + + QualType ToUnderlyingType; + TypeSourceInfo *ToTypeSourceInfo; + SourceLocation ToBeginLoc; + if (auto Imp = importSeq( + D->getUnderlyingType(), D->getTypeSourceInfo(), D->getBeginLoc())) + std::tie(ToUnderlyingType, ToTypeSourceInfo, ToBeginLoc) = *Imp; + else + return Imp.takeError(); + + // Create the new typedef node. + // FIXME: ToUnderlyingType is not used. + 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; + + ToTypedef->setAccess(D->getAccess()); + ToTypedef->setLexicalDeclContext(LexicalDC); + + // 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)) + 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(); + } + } + + TemplateParameterList *ToTemplateParameters; + TypeAliasDecl *ToTemplatedDecl; + if (auto Imp = importSeq(D->getTemplateParameters(), D->getTemplatedDecl())) + std::tie(ToTemplateParameters, ToTemplatedDecl) = *Imp; + else + return Imp.takeError(); + + 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); + 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. + if (!DC->isFunctionOrMethod() && SearchName) { + 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 (!hasSameVisibilityContext(FoundEnum, D)) + continue; + if (IsStructuralMatch(D, FoundEnum)) + return Importer.MapImported(D, FoundEnum); + ConflictingDecls.push_back(FoundDecl); + } + } + + if (!ConflictingDecls.empty()) { + ExpectedName NameOrErr = Importer.HandleNameConflict( + SearchName, DC, IDNS, ConflictingDecls.data(), + ConflictingDecls.size()); + if (NameOrErr) + Name = NameOrErr.get(); + else + return NameOrErr.takeError(); + } + } + + SourceLocation ToBeginLoc; + NestedNameSpecifierLoc ToQualifierLoc; + QualType ToIntegerType; + if (auto Imp = importSeq( + D->getBeginLoc(), D->getQualifierLoc(), D->getIntegerType())) + std::tie(ToBeginLoc, ToQualifierLoc, ToIntegerType) = *Imp; + else + return Imp.takeError(); + + // Create the enum declaration. + EnumDecl *D2; + if (GetImportedOrCreateDecl( + D2, D, Importer.getToContext(), DC, ToBeginLoc, + Loc, Name.getAsIdentifierInfo(), nullptr, D->isScoped(), + D->isScopedUsingClassTag(), D->isFixed())) + return D2; + + D2->setQualifierInfo(ToQualifierLoc); + D2->setIntegerType(ToIntegerType); + D2->setAccess(D->getAccess()); + D2->setLexicalDeclContext(LexicalDC); + LexicalDC->addDeclInternal(D2); + + // 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; + + // We may already have a record of the same name; try to find and match it. + RecordDecl *PrevDecl = nullptr; + if (!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 (!hasSameVisibilityContext(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); + } + } + 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->isDependentLambda(), + DCXX->isGenericLambda(), DCXX->getLambdaCaptureDefault())) + return D2CXX; + ExpectedDecl CDeclOrErr = import(DCXX->getLambdaContextDecl()); + if (!CDeclOrErr) + return CDeclOrErr.takeError(); + D2CXX->setLambdaMangling(DCXX->getLambdaManglingNumber(), *CDeclOrErr, + DCXX->hasKnownLambdaInternalLinkage()); + } 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); + if (!DCXX->getDescribedClassTemplate() || DCXX->isImplicit()) + LexicalDC->addDeclInternal(D2); + + if (LexicalDC != DC && D->isInIdentifierNamespace(Decl::IDNS_TagFriend)) + DC->makeDeclVisibleInContext(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). + // FIXME: The previous type is cleared but not removed from + // ASTContext's internal storage. + 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. + SmallVector<Decl *, 2> Redecls = + getCanonicalForwardRedeclChain(D2CXX); + for (auto *R : Redecls) { + auto *RI = cast<CXXRecordDecl>(R); + RI->setTypeForDecl(nullptr); + // Below we create a new injected type and assign that to the + // canonical decl, subsequent declarations in the chain will reuse + // that type. + Importer.getToContext().getInjectedClassNameType( + RI, ToDescribed->getInjectedClassNameSpecialization()); + } + // Set the new type for the previous injected decl too. + if (Injected) { + Injected->setTypeForDecl(nullptr); + 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); + LexicalDC->addDeclInternal(D2); + } + + 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; +} + +Error ASTNodeImporter::ImportTemplateParameterLists(const DeclaratorDecl *FromD, + DeclaratorDecl *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_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> TemplDecls; + unsigned NumTemplates = FromInfo->getNumTemplates(); + for (unsigned I = 0; I < NumTemplates; I++) { + if (Expected<FunctionTemplateDecl *> ToFTDOrErr = + import(FromInfo->getTemplate(I))) + TemplDecls.addDecl(*ToFTDOrErr); + else + return ToFTDOrErr.takeError(); + } + + // Import TemplateArgumentListInfo. + TemplateArgumentListInfo ToTAInfo; + if (Error Err = ImportTemplateArgumentListInfo( + FromInfo->getLAngleLoc(), FromInfo->getRAngleLoc(), + llvm::makeArrayRef( + FromInfo->getTemplateArgs(), FromInfo->getNumTemplateArgs()), + ToTAInfo)) + return Err; + + ToFD->setDependentTemplateSpecialization(Importer.getToContext(), + TemplDecls, ToTAInfo); + 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(); +} + +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 (!hasSameVisibilityContext(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(); + bool usedDifferentExceptionSpec = false; + + if (const auto *FromFPT = D->getType()->getAs<FunctionProtoType>()) { + 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 and update it afterwards. + if (FromEPI.ExceptionSpec.SourceDecl || + FromEPI.ExceptionSpec.SourceTemplate || + FromEPI.ExceptionSpec.NoexceptExpr) { + FunctionProtoType::ExtProtoInfo DefaultEPI; + FromTy = Importer.getFromContext().getFunctionType( + FromFPT->getReturnType(), FromFPT->getParamTypes(), DefaultEPI); + usedDifferentExceptionSpec = true; + } + } + + QualType T; + TypeSourceInfo *TInfo; + SourceLocation ToInnerLocStart, ToEndLoc; + NestedNameSpecifierLoc ToQualifierLoc; + if (auto Imp = importSeq( + FromTy, D->getTypeSourceInfo(), D->getInnerLocStart(), + D->getQualifierLoc(), D->getEndLoc())) + std::tie(T, TInfo, ToInnerLocStart, ToQualifierLoc, ToEndLoc) = *Imp; + else + return Imp.takeError(); + + // 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)) { + Expr *ExplicitExpr = nullptr; + if (FromConstructor->getExplicitSpecifier().getExpr()) { + auto Imp = importSeq(FromConstructor->getExplicitSpecifier().getExpr()); + if (!Imp) + return Imp.takeError(); + std::tie(ExplicitExpr) = *Imp; + } + if (GetImportedOrCreateDecl<CXXConstructorDecl>( + ToFunction, D, Importer.getToContext(), cast<CXXRecordDecl>(DC), + ToInnerLocStart, NameInfo, T, TInfo, + ExplicitSpecifier( + ExplicitExpr, + FromConstructor->getExplicitSpecifier().getKind()), + D->isInlineSpecified(), D->isImplicit(), D->getConstexprKind())) + return ToFunction; + } else if (CXXDestructorDecl *FromDtor = dyn_cast<CXXDestructorDecl>(D)) { + + auto Imp = + importSeq(const_cast<FunctionDecl *>(FromDtor->getOperatorDelete()), + FromDtor->getOperatorDeleteThisArg()); + + if (!Imp) + return Imp.takeError(); + + FunctionDecl *ToOperatorDelete; + Expr *ToThisArg; + std::tie(ToOperatorDelete, ToThisArg) = *Imp; + + if (GetImportedOrCreateDecl<CXXDestructorDecl>( + ToFunction, D, Importer.getToContext(), cast<CXXRecordDecl>(DC), + ToInnerLocStart, NameInfo, T, TInfo, D->isInlineSpecified(), + D->isImplicit(), D->getConstexprKind())) + return ToFunction; + + CXXDestructorDecl *ToDtor = cast<CXXDestructorDecl>(ToFunction); + + ToDtor->setOperatorDelete(ToOperatorDelete, ToThisArg); + } else if (CXXConversionDecl *FromConversion = + dyn_cast<CXXConversionDecl>(D)) { + Expr *ExplicitExpr = nullptr; + if (FromConversion->getExplicitSpecifier().getExpr()) { + auto Imp = importSeq(FromConversion->getExplicitSpecifier().getExpr()); + if (!Imp) + return Imp.takeError(); + std::tie(ExplicitExpr) = *Imp; + } + if (GetImportedOrCreateDecl<CXXConversionDecl>( + ToFunction, D, Importer.getToContext(), cast<CXXRecordDecl>(DC), + ToInnerLocStart, NameInfo, T, TInfo, D->isInlineSpecified(), + ExplicitSpecifier(ExplicitExpr, + FromConversion->getExplicitSpecifier().getKind()), + D->getConstexprKind(), SourceLocation())) + 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->isInlineSpecified(), D->getConstexprKind(), + SourceLocation())) + return ToFunction; + } else { + if (GetImportedOrCreateDecl( + ToFunction, D, Importer.getToContext(), DC, ToInnerLocStart, + NameInfo, T, TInfo, D->getStorageClass(), D->isInlineSpecified(), + D->hasWrittenPrototype(), D->getConstexprKind())) + 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. + } + + ToFunction->setQualifierInfo(ToQualifierLoc); + ToFunction->setAccess(D->getAccess()); + ToFunction->setLexicalDeclContext(LexicalDC); + ToFunction->setVirtualAsWritten(D->isVirtualAsWritten()); + ToFunction->setTrivial(D->isTrivial()); + ToFunction->setPure(D->isPure()); + ToFunction->setDefaulted(D->isDefaulted()); + ToFunction->setExplicitlyDefaulted(D->isExplicitlyDefaulted()); + ToFunction->setDeletedAsWritten(D->isDeletedAsWritten()); + ToFunction->setRangeEnd(ToEndLoc); + + // Set the parameters. + for (auto *Param : Parameters) { + Param->setOwningFunction(ToFunction); + ToFunction->addDeclInternal(Param); + } + 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]); + } + } + + if (usedDifferentExceptionSpec) { + // Update FunctionProtoType::ExtProtoInfo. + if (ExpectedType TyOrErr = import(D->getType())) + ToFunction->setType(*TyOrErr); + else + return TyOrErr.takeError(); + } + + // 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]; + std::copy(CtorInitializers.begin(), CtorInitializers.end(), Memory); + auto *ToCtor = cast<CXXConstructorDecl>(ToFunction); + ToCtor->setCtorInitializers(Memory); + ToCtor->setNumCtorInitializers(NumInitializers); + } + } + + if (D->doesThisDeclarationHaveABody()) { + Error Err = ImportFunctionDeclBody(D, ToFunction); + + if (Err) + return std::move(Err); + } + + // FIXME: Other bits to merge? + + // If it is a template, import all related things. + if (Error Err = ImportTemplateInformation(D, ToFunction)) + return std::move(Err); + + bool IsFriend = D->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend); + + // TODO Can we generalize this approach to other AST nodes as well? + if (D->getDeclContext()->containsDeclAndLoad(D)) + DC->addDeclInternal(ToFunction); + if (DC != LexicalDC && D->getLexicalDeclContext()->containsDeclAndLoad(D)) + LexicalDC->addDeclInternal(ToFunction); + + // Friend declaration's lexical context is the befriending class, but the + // semantic context is the enclosing scope of the befriending class. + // We want the friend functions to be found in the semantic context by lookup. + // FIXME should we handle this generically in VisitFriendDecl? + // In Other cases when LexicalDC != DC we don't want it to be added, + // e.g out-of-class definitions like void B::f() {} . + if (LexicalDC != DC && IsFriend) { + DC->makeDeclVisibleInContext(ToFunction); + } + + if (auto *FromCXXMethod = dyn_cast<CXXMethodDecl>(D)) + if (Error Err = ImportOverriddenMethods(cast<CXXMethodDecl>(ToFunction), + FromCXXMethod)) + return std::move(Err); + + // 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::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. + if (Expr *FromInitializer = D->getInClassInitializer()) { + // We don't have yet the initializer set. + if (FoundField->hasInClassInitializer() && + !FoundField->getInClassInitializer()) { + if (ExpectedExpr ToInitializerOrErr = import(FromInitializer)) + FoundField->setInClassInitializer(*ToInitializerOrErr); + else { + // We can't return error here, + // since we already mapped D as imported. + // FIXME: warning message? + consumeError(ToInitializerOrErr.takeError()); + return FoundField; + } + } + } + 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<ImportError>(ImportError::NameConflict); + } + } + + QualType ToType; + TypeSourceInfo *ToTInfo; + Expr *ToBitWidth; + SourceLocation ToInnerLocStart; + Expr *ToInitializer; + if (auto Imp = importSeq( + D->getType(), D->getTypeSourceInfo(), D->getBitWidth(), + D->getInnerLocStart(), D->getInClassInitializer())) + std::tie( + ToType, ToTInfo, ToBitWidth, ToInnerLocStart, ToInitializer) = *Imp; + else + return Imp.takeError(); + + 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); + if (ToInitializer) + ToField->setInClassInitializer(ToInitializer); + ToField->setImplicit(D->isImplicit()); + LexicalDC->addDeclInternal(ToField); + 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<ImportError>(ImportError::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(); + + llvm::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; +} + +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. + auto *RD = cast<CXXRecordDecl>(DC); + FriendDecl *ImportedFriend = RD->getFirstFriend(); + + while (ImportedFriend) { + if (D->getFriendDecl() && ImportedFriend->getFriendDecl()) { + if (IsStructuralMatch(D->getFriendDecl(), ImportedFriend->getFriendDecl(), + /*Complain=*/false)) + return Importer.MapImported(D, ImportedFriend); + + } else if (D->getFriendType() && ImportedFriend->getFriendType()) { + if (Importer.IsStructurallyEquivalent( + D->getFriendType()->getType(), + ImportedFriend->getFriendType()->getType(), true)) + return Importer.MapImported(D, ImportedFriend); + } + ImportedFriend = ImportedFriend->getNextFriend(); + } + + // Not found. Create it. + 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<TemplateParameterList *>(); + 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(); + + FriendDecl *FrD; + if (GetImportedOrCreateDecl(FrD, D, Importer.getToContext(), DC, + *LocationOrErr, ToFU, + *FriendLocOrErr, 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<ImportError>(ImportError::NameConflict); + } + } + + QualType ToType; + TypeSourceInfo *ToTypeSourceInfo; + Expr *ToBitWidth; + SourceLocation ToInnerLocStart; + if (auto Imp = importSeq( + D->getType(), D->getTypeSourceInfo(), D->getBitWidth(), D->getInnerLocStart())) + std::tie(ToType, ToTypeSourceInfo, ToBitWidth, ToInnerLocStart) = *Imp; + else + return Imp.takeError(); + + 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 (!hasSameVisibilityContext(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(); + } + } + + QualType ToType; + TypeSourceInfo *ToTypeSourceInfo; + SourceLocation ToInnerLocStart; + NestedNameSpecifierLoc ToQualifierLoc; + if (auto Imp = importSeq( + D->getType(), D->getTypeSourceInfo(), D->getInnerLocStart(), + D->getQualifierLoc())) + std::tie(ToType, ToTypeSourceInfo, ToInnerLocStart, ToQualifierLoc) = *Imp; + else + return Imp.takeError(); + + // Create the imported variable. + VarDecl *ToVar; + if (GetImportedOrCreateDecl(ToVar, D, Importer.getToContext(), DC, + ToInnerLocStart, Loc, + Name.getAsIdentifierInfo(), + ToType, ToTypeSourceInfo, + D->getStorageClass())) + return ToVar; + + ToVar->setQualifierInfo(ToQualifierLoc); + ToVar->setAccess(D->getAccess()); + ToVar->setLexicalDeclContext(LexicalDC); + + if (FoundByLookup) { + auto *Recent = const_cast<VarDecl *>(FoundByLookup->getMostRecentDecl()); + ToVar->setPreviousDecl(Recent); + } + + if (Error Err = ImportInitializer(D, ToVar)) + return std::move(Err); + + if (D->isConstexpr()) + ToVar->setConstexpr(true); + + if (D->getDeclContext()->containsDeclAndLoad(D)) + DC->addDeclInternal(ToVar); + if (DC != LexicalDC && D->getLexicalDeclContext()->containsDeclAndLoad(D)) + LexicalDC->addDeclInternal(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(); + + DeclarationName ToDeclName; + SourceLocation ToLocation; + QualType ToType; + if (auto Imp = importSeq(D->getDeclName(), D->getLocation(), D->getType())) + std::tie(ToDeclName, ToLocation, ToType) = *Imp; + else + return Imp.takeError(); + + // 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) { + 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(); +} + +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(); + + DeclarationName ToDeclName; + SourceLocation ToLocation, ToInnerLocStart; + QualType ToType; + TypeSourceInfo *ToTypeSourceInfo; + if (auto Imp = importSeq( + D->getDeclName(), D->getLocation(), D->getType(), D->getInnerLocStart(), + D->getTypeSourceInfo())) + std::tie( + ToDeclName, ToLocation, ToType, ToInnerLocStart, + ToTypeSourceInfo) = *Imp; + else + return Imp.takeError(); + + 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<ImportError>(ImportError::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<ImportError>(ImportError::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<ImportError>(ImportError::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<ImportError>(ImportError::NameConflict); + } + + // FIXME: Any other bits we need to merge? + return Importer.MapImported(D, FoundMethod); + } + } + + SourceLocation ToEndLoc; + QualType ToReturnType; + TypeSourceInfo *ToReturnTypeSourceInfo; + if (auto Imp = importSeq( + D->getEndLoc(), D->getReturnType(), D->getReturnTypeSourceInfo())) + std::tie(ToEndLoc, ToReturnType, ToReturnTypeSourceInfo) = *Imp; + else + return Imp.takeError(); + + ObjCMethodDecl *ToMethod; + if (GetImportedOrCreateDecl( + ToMethod, D, Importer.getToContext(), Loc, + ToEndLoc, Name.getObjCSelector(), ToReturnType, + ToReturnTypeSourceInfo, DC, D->isInstanceMethod(), D->isVariadic(), + D->isPropertyAccessor(), 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); + 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; + + SourceLocation ToVarianceLoc, ToLocation, ToColonLoc; + TypeSourceInfo *ToTypeSourceInfo; + if (auto Imp = importSeq( + D->getVarianceLoc(), D->getLocation(), D->getColonLoc(), + D->getTypeSourceInfo())) + std::tie(ToVarianceLoc, ToLocation, ToColonLoc, ToTypeSourceInfo) = *Imp; + else + return Imp.takeError(); + + ObjCTypeParamDecl *Result; + if (GetImportedOrCreateDecl( + Result, D, Importer.getToContext(), DC, D->getVariance(), + ToVarianceLoc, D->getIndex(), + ToLocation, Name.getAsIdentifierInfo(), + ToColonLoc, ToTypeSourceInfo)) + return Result; + + 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) { + SourceLocation ToAtStartLoc, ToCategoryNameLoc; + SourceLocation ToIvarLBraceLoc, ToIvarRBraceLoc; + if (auto Imp = importSeq( + D->getAtStartLoc(), D->getCategoryNameLoc(), + D->getIvarLBraceLoc(), D->getIvarRBraceLoc())) + std::tie( + ToAtStartLoc, ToCategoryNameLoc, + ToIvarLBraceLoc, ToIvarRBraceLoc) = *Imp; + else + return Imp.takeError(); + + 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::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; + + SourceLocation ToLoc, ToUsingLoc; + NestedNameSpecifierLoc ToQualifierLoc; + if (auto Imp = importSeq( + D->getNameInfo().getLoc(), D->getUsingLoc(), D->getQualifierLoc())) + std::tie(ToLoc, ToUsingLoc, ToQualifierLoc) = *Imp; + else + return Imp.takeError(); + + 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(); + } + + for (UsingShadowDecl *FromShadow : D->shadows()) { + if (Expected<UsingShadowDecl *> ToShadowOrErr = import(FromShadow)) + ToUsing->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 ToUsing; +} + +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<UsingDecl *> ToUsingOrErr = import(D->getUsingDecl()); + if (!ToUsingOrErr) + return ToUsingOrErr.takeError(); + + Expected<NamedDecl *> ToTargetOrErr = import(D->getTargetDecl()); + if (!ToTargetOrErr) + return ToTargetOrErr.takeError(); + + UsingShadowDecl *ToShadow; + if (GetImportedOrCreateDecl(ToShadow, D, Importer.getToContext(), DC, Loc, + *ToUsingOrErr, *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(); + + NamespaceDecl *ToNominatedNamespace; + SourceLocation ToUsingLoc, ToNamespaceKeyLocation, ToIdentLocation; + NestedNameSpecifierLoc ToQualifierLoc; + if (auto Imp = importSeq( + D->getNominatedNamespace(), D->getUsingLoc(), + D->getNamespaceKeyLocation(), D->getQualifierLoc(), + D->getIdentLocation())) + std::tie( + ToNominatedNamespace, ToUsingLoc, ToNamespaceKeyLocation, + ToQualifierLoc, ToIdentLocation) = *Imp; + else + return Imp.takeError(); + + 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::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; + + SourceLocation ToLoc, ToUsingLoc, ToEllipsisLoc; + NestedNameSpecifierLoc ToQualifierLoc; + if (auto Imp = importSeq( + D->getNameInfo().getLoc(), D->getUsingLoc(), D->getQualifierLoc(), + D->getEllipsisLoc())) + std::tie(ToLoc, ToUsingLoc, ToQualifierLoc, ToEllipsisLoc) = *Imp; + else + return Imp.takeError(); + + 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; + + SourceLocation ToUsingLoc, ToTypenameLoc, ToEllipsisLoc; + NestedNameSpecifierLoc ToQualifierLoc; + if (auto Imp = importSeq( + D->getUsingLoc(), D->getTypenameLoc(), D->getQualifierLoc(), + D->getEllipsisLoc())) + std::tie(ToUsingLoc, ToTypenameLoc, ToQualifierLoc, ToEllipsisLoc) = *Imp; + else + return Imp.takeError(); + + 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; +} + + +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(); + } + + if (shouldForceImportDeclContext(Kind)) { + // 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); + + SourceLocation ToLocation, ToAtStartLoc, ToCategoryNameLoc; + if (auto Imp = importSeq( + D->getLocation(), D->getAtStartLoc(), D->getCategoryNameLoc())) + std::tie(ToLocation, ToAtStartLoc, ToCategoryNameLoc) = *Imp; + else + return Imp.takeError(); + + 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); + + SourceLocation ToLocation, ToAtStartLoc, ToSuperClassLoc; + SourceLocation ToIvarLBraceLoc, ToIvarRBraceLoc; + if (auto Imp = importSeq( + D->getLocation(), D->getAtStartLoc(), D->getSuperClassLoc(), + D->getIvarLBraceLoc(), D->getIvarRBraceLoc())) + std::tie( + ToLocation, ToAtStartLoc, ToSuperClassLoc, + ToIvarLBraceLoc, ToIvarRBraceLoc) = *Imp; + else + return Imp.takeError(); + + 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<ImportError>(ImportError::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)) { + // 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<ImportError>(ImportError::NameConflict); + } + + // FIXME: Check property attributes, getters, setters, etc.? + + // Consider these properties to be equivalent. + Importer.MapImported(D, FoundProp); + return FoundProp; + } + } + + QualType ToType; + TypeSourceInfo *ToTypeSourceInfo; + SourceLocation ToAtLoc, ToLParenLoc; + if (auto Imp = importSeq( + D->getType(), D->getTypeSourceInfo(), D->getAtLoc(), D->getLParenLoc())) + std::tie(ToType, ToTypeSourceInfo, ToAtLoc, ToLParenLoc) = *Imp; + else + return Imp.takeError(); + + // Create the new property. + ObjCPropertyDecl *ToProperty; + if (GetImportedOrCreateDecl( + ToProperty, D, Importer.getToContext(), DC, Loc, + Name.getAsIdentifierInfo(), ToAtLoc, + ToLParenLoc, ToType, + ToTypeSourceInfo, D->getPropertyImplementation())) + return ToProperty; + + Selector ToGetterName, ToSetterName; + SourceLocation ToGetterNameLoc, ToSetterNameLoc; + ObjCMethodDecl *ToGetterMethodDecl, *ToSetterMethodDecl; + ObjCIvarDecl *ToPropertyIvarDecl; + if (auto Imp = importSeq( + D->getGetterName(), D->getSetterName(), + D->getGetterNameLoc(), D->getSetterNameLoc(), + D->getGetterMethodDecl(), D->getSetterMethodDecl(), + D->getPropertyIvarDecl())) + std::tie( + ToGetterName, ToSetterName, + ToGetterNameLoc, ToSetterNameLoc, + ToGetterMethodDecl, ToSetterMethodDecl, + ToPropertyIvarDecl) = *Imp; + else + return Imp.takeError(); + + 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) { + SourceLocation ToBeginLoc, ToLocation, ToPropertyIvarDeclLoc; + if (auto Imp = importSeq( + D->getBeginLoc(), D->getLocation(), D->getPropertyIvarDeclLoc())) + std::tie(ToBeginLoc, ToLocation, ToPropertyIvarDeclLoc) = *Imp; + else + return Imp.takeError(); + + 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<ImportError>(ImportError::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<ImportError>(ImportError::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 the actual template declaration + // is created. + + // FIXME: Import default argument. + + ExpectedSLoc BeginLocOrErr = import(D->getBeginLoc()); + if (!BeginLocOrErr) + return BeginLocOrErr.takeError(); + + ExpectedSLoc LocationOrErr = import(D->getLocation()); + if (!LocationOrErr) + return LocationOrErr.takeError(); + + TemplateTypeParmDecl *ToD = nullptr; + (void)GetImportedOrCreateDecl( + ToD, D, Importer.getToContext(), + Importer.getToContext().getTranslationUnitDecl(), + *BeginLocOrErr, *LocationOrErr, + D->getDepth(), D->getIndex(), Importer.Import(D->getIdentifier()), + D->wasDeclaredWithTypename(), D->isParameterPack()); + return ToD; +} + +ExpectedDecl +ASTNodeImporter::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) { + DeclarationName ToDeclName; + SourceLocation ToLocation, ToInnerLocStart; + QualType ToType; + TypeSourceInfo *ToTypeSourceInfo; + if (auto Imp = importSeq( + D->getDeclName(), D->getLocation(), D->getType(), D->getTypeSourceInfo(), + D->getInnerLocStart())) + std::tie( + ToDeclName, ToLocation, ToType, ToTypeSourceInfo, + ToInnerLocStart) = *Imp; + else + return Imp.takeError(); + + // FIXME: Import default argument. + + NonTypeTemplateParmDecl *ToD = nullptr; + (void)GetImportedOrCreateDecl( + ToD, D, Importer.getToContext(), + Importer.getToContext().getTranslationUnitDecl(), + ToInnerLocStart, ToLocation, D->getDepth(), + D->getPosition(), ToDeclName.getAsIdentifierInfo(), ToType, + D->isParameterPack(), ToTypeSourceInfo); + return ToD; +} + +ExpectedDecl +ASTNodeImporter::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) { + // 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(); + + // FIXME: Import default argument. + + TemplateTemplateParmDecl *ToD = nullptr; + (void)GetImportedOrCreateDecl( + ToD, D, Importer.getToContext(), + Importer.getToContext().getTranslationUnitDecl(), *LocationOrErr, + D->getDepth(), D->getPosition(), D->isParameterPack(), + (*NameOrErr).getAsIdentifierInfo(), + *TemplateParamsOrErr); + 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) { + bool IsFriend = D->getFriendObjectKind() != Decl::FOK_None; + + // 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; + + 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; + + Decl *Found = FoundDecl; + auto *FoundTemplate = dyn_cast<ClassTemplateDecl>(Found); + if (FoundTemplate) { + + if (IsStructuralMatch(D, FoundTemplate)) { + 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; + } + 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(); + + // 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. + auto TemplateParamsOrErr = import(D->getTemplateParameters()); + if (!TemplateParamsOrErr) + return TemplateParamsOrErr.takeError(); + + 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); + + if (D->getDeclContext()->containsDeclAndLoad(D)) + DC->addDeclInternal(D2); + if (DC != LexicalDC && D->getLexicalDeclContext()->containsDeclAndLoad(D)) + LexicalDC->addDeclInternal(D2); + + 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); + } + + if (LexicalDC != DC && IsFriend) + DC->makeDeclVisibleInContext(D2); + + if (FromTemplated->isCompleteDefinition() && + !ToTemplated->isCompleteDefinition()) { + // FIXME: Import definition! + } + + 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().data(), D->getTemplateArgs().size(), TemplateArgs)) + return std::move(Err); + + // Try to find an existing specialization with these template arguments. + void *InsertPos = nullptr; + ClassTemplateSpecializationDecl *PrevDecl = nullptr; + ClassTemplatePartialSpecializationDecl *PartialSpec = + dyn_cast<ClassTemplatePartialSpecializationDecl>(D); + if (PartialSpec) + PrevDecl = + ClassTemplate->findPartialSpecialization(TemplateArgs, InsertPos); + else + PrevDecl = ClassTemplate->findSpecialization(TemplateArgs, InsertPos); + + if (PrevDecl) { + if (IsStructuralMatch(D, PrevDecl)) { + if (D->isThisDeclarationADefinition() && PrevDecl->getDefinition()) { + Importer.MapImported(D, PrevDecl->getDefinition()); + // 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 PrevDecl; + } + } else { // ODR violation. + // FIXME HandleNameConflict + return make_error<ImportError>(ImportError::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(); + + // Create the specialization. + ClassTemplateSpecializationDecl *D2 = nullptr; + if (PartialSpec) { + // Import TemplateArgumentListInfo. + TemplateArgumentListInfo ToTAInfo; + const auto &ASTTemplateArgs = *PartialSpec->getTemplateArgsAsWritten(); + if (Error Err = ImportTemplateArgumentListInfo(ASTTemplateArgs, ToTAInfo)) + return std::move(Err); + + QualType CanonInjType; + if (Error Err = importInto( + CanonInjType, PartialSpec->getInjectedSpecializationType())) + return std::move(Err); + CanonInjType = CanonInjType.getCanonicalType(); + + auto ToTPListOrErr = import(PartialSpec->getTemplateParameters()); + if (!ToTPListOrErr) + return ToTPListOrErr.takeError(); + + if (GetImportedOrCreateDecl<ClassTemplatePartialSpecializationDecl>( + D2, D, Importer.getToContext(), D->getTagKind(), DC, + *BeginLocOrErr, *IdLocOrErr, *ToTPListOrErr, ClassTemplate, + llvm::makeArrayRef(TemplateArgs.data(), TemplateArgs.size()), + ToTAInfo, CanonInjType, + cast_or_null<ClassTemplatePartialSpecializationDecl>(PrevDecl))) + return D2; + + // Update InsertPos, because preceding import calls may have invalidated + // it by adding new specializations. + if (!ClassTemplate->findPartialSpecialization(TemplateArgs, InsertPos)) + // Add this partial specialization to the class template. + ClassTemplate->AddPartialSpecialization( + cast<ClassTemplatePartialSpecializationDecl>(D2), InsertPos); + + } else { // Not a partial specialization. + if (GetImportedOrCreateDecl( + D2, D, Importer.getToContext(), D->getTagKind(), DC, + *BeginLocOrErr, *IdLocOrErr, ClassTemplate, TemplateArgs, + 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); + } + + // Import the qualifier, if any. + if (auto LocOrErr = import(D->getQualifierLoc())) + D2->setQualifierInfo(*LocOrErr); + else + return LocOrErr.takeError(); + + if (auto *TSI = D->getTypeAsWritten()) { + if (auto TInfoOrErr = import(TSI)) + D2->setTypeAsWritten(*TInfoOrErr); + else + return TInfoOrErr.takeError(); + + if (auto LocOrErr = import(D->getTemplateKeywordLoc())) + D2->setTemplateKeywordLoc(*LocOrErr); + else + return LocOrErr.takeError(); + + if (auto LocOrErr = import(D->getExternLoc())) + D2->setExternLoc(*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 (D->isCompleteDefinition()) + if (Error Err = ImportDefinition(D, D2)) + return std::move(Err); + + return D2; +} + +ExpectedDecl ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) { + // If this variable 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. + auto *Definition = + cast_or_null<VarDecl>(D->getTemplatedDecl()->getDefinition()); + if (Definition && Definition != D->getTemplatedDecl()) { + if (ExpectedDecl ImportedDefOrErr = import( + Definition->getDescribedVarTemplate())) + return Importer.MapImported(D, *ImportedDefOrErr); + else + return ImportedDefOrErr.takeError(); + } + + // 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); + for (auto *FoundDecl : FoundDecls) { + if (!FoundDecl->isInIdentifierNamespace(Decl::IDNS_Ordinary)) + continue; + + Decl *Found = FoundDecl; + if (VarTemplateDecl *FoundTemplate = dyn_cast<VarTemplateDecl>(Found)) { + if (IsStructuralMatch(D, FoundTemplate)) { + // The variable templates structurally match; call it the same template. + Importer.MapImported(D->getTemplatedDecl(), + FoundTemplate->getTemplatedDecl()); + return Importer.MapImported(D, FoundTemplate); + } + 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 (DTemplated->isThisDeclarationADefinition() && + !ToTemplated->isThisDeclarationADefinition()) { + // FIXME: Import definition! + } + + return ToVarTD; +} + +ExpectedDecl ASTNodeImporter::VisitVarTemplateSpecializationDecl( + VarTemplateSpecializationDecl *D) { + // If this record 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. + VarDecl *Definition = D->getDefinition(); + if (Definition && Definition != D) { + if (ExpectedDecl ImportedDefOrErr = import(Definition)) + return Importer.MapImported(D, *ImportedDefOrErr); + else + return ImportedDefOrErr.takeError(); + } + + 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().data(), D->getTemplateArgs().size(), TemplateArgs)) + return std::move(Err); + + // Try to find an existing specialization with these template arguments. + void *InsertPos = nullptr; + VarTemplateSpecializationDecl *D2 = VarTemplate->findSpecialization( + TemplateArgs, InsertPos); + if (D2) { + // We already have a variable template specialization with these template + // arguments. + + // FIXME: Check for specialization vs. instantiation errors. + + if (VarDecl *FoundDef = D2->getDefinition()) { + if (!D->isThisDeclarationADefinition() || + IsStructuralMatch(D, FoundDef)) { + // The record types structurally match, or the "from" translation + // unit only had a forward declaration anyway; call it the same + // variable. + return Importer.MapImported(D, FoundDef); + } + } + } else { + // Import the type. + QualType T; + if (Error Err = importInto(T, D->getType())) + return std::move(Err); + + auto TInfoOrErr = import(D->getTypeSourceInfo()); + if (!TInfoOrErr) + return TInfoOrErr.takeError(); + + TemplateArgumentListInfo ToTAInfo; + if (Error Err = ImportTemplateArgumentListInfo( + D->getTemplateArgsInfo(), ToTAInfo)) + return std::move(Err); + + using PartVarSpecDecl = VarTemplatePartialSpecializationDecl; + // Create a new specialization. + if (auto *FromPartial = dyn_cast<PartVarSpecDecl>(D)) { + // Import TemplateArgumentListInfo + TemplateArgumentListInfo ArgInfos; + const auto *FromTAArgsAsWritten = FromPartial->getTemplateArgsAsWritten(); + // NOTE: FromTAArgsAsWritten and template parameter list are non-null. + if (Error Err = ImportTemplateArgumentListInfo( + *FromTAArgsAsWritten, ArgInfos)) + return std::move(Err); + + auto ToTPListOrErr = import(FromPartial->getTemplateParameters()); + if (!ToTPListOrErr) + return ToTPListOrErr.takeError(); + + PartVarSpecDecl *ToPartial; + if (GetImportedOrCreateDecl(ToPartial, D, Importer.getToContext(), DC, + *BeginLocOrErr, *IdLocOrErr, *ToTPListOrErr, + VarTemplate, T, *TInfoOrErr, + D->getStorageClass(), TemplateArgs, ArgInfos)) + return ToPartial; + + if (Expected<PartVarSpecDecl *> ToInstOrErr = import( + FromPartial->getInstantiatedFromMember())) + ToPartial->setInstantiatedFromMember(*ToInstOrErr); + else + return ToInstOrErr.takeError(); + + if (FromPartial->isMemberSpecialization()) + ToPartial->setMemberSpecialization(); + + D2 = ToPartial; + + } else { // Full specialization + if (GetImportedOrCreateDecl(D2, D, Importer.getToContext(), DC, + *BeginLocOrErr, *IdLocOrErr, VarTemplate, + T, *TInfoOrErr, + D->getStorageClass(), TemplateArgs)) + return D2; + } + + if (D->getPointOfInstantiation().isValid()) { + if (ExpectedSLoc POIOrErr = import(D->getPointOfInstantiation())) + D2->setPointOfInstantiation(*POIOrErr); + else + return POIOrErr.takeError(); + } + + D2->setSpecializationKind(D->getSpecializationKind()); + D2->setTemplateArgsInfo(ToTAInfo); + + // Add this specialization to the class template. + VarTemplate->AddSpecialization(D2, InsertPos); + + // Import the qualifier, if any. + if (auto LocOrErr = import(D->getQualifierLoc())) + D2->setQualifierInfo(*LocOrErr); + else + return LocOrErr.takeError(); + + if (D->isConstexpr()) + D2->setConstexpr(true); + + // Add the specialization to this context. + D2->setLexicalDeclContext(LexicalDC); + LexicalDC->addDeclInternal(D2); + + D2->setAccess(D->getAccess()); + } + + if (Error Err = ImportInitializer(D, D2)) + return std::move(Err); + + 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 (!hasSameVisibilityContext(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(); + + FunctionDecl *TemplatedFD; + if (Error Err = importInto(TemplatedFD, D->getTemplatedDecl())) + return std::move(Err); + + FunctionTemplateDecl *ToFunc; + if (GetImportedOrCreateDecl(ToFunc, D, Importer.getToContext(), DC, Loc, Name, + *ParamsOrErr, TemplatedFD)) + return ToFunc; + + TemplatedFD->setDescribedFunctionTemplate(ToFunc); + + ToFunc->setAccess(D->getAccess()); + ToFunc->setLexicalDeclContext(LexicalDC); + LexicalDC->addDeclInternal(ToFunc); + + 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; +} + +//---------------------------------------------------------------------------- +// Import Statements +//---------------------------------------------------------------------------- + +ExpectedStmt ASTNodeImporter::VisitStmt(Stmt *S) { + Importer.FromDiag(S->getBeginLoc(), diag::err_unsupported_ast_node) + << S->getStmtClassName(); + return make_error<ImportError>(ImportError::UnsupportedConstruct); +} + + +ExpectedStmt ASTNodeImporter::VisitGCCAsmStmt(GCCAsmStmt *S) { + if (Importer.returnWithErrorInTest()) + return make_error<ImportError>(ImportError::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<StringLiteral *, 4> Clobbers; + for (unsigned I = 0, E = S->getNumClobbers(); I != E; I++) { + if (auto ClobberOrErr = import(S->getClobberStringLiteral(I))) + Clobbers.push_back(*ClobberOrErr); + else + return ClobberOrErr.takeError(); + + } + + SmallVector<StringLiteral *, 4> Constraints; + for (unsigned I = 0, E = S->getNumOutputs(); I != E; I++) { + if (auto OutputOrErr = import(S->getOutputConstraintLiteral(I))) + Constraints.push_back(*OutputOrErr); + else + return OutputOrErr.takeError(); + } + + for (unsigned I = 0, E = S->getNumInputs(); I != E; I++) { + if (auto InputOrErr = import(S->getInputConstraintLiteral(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->getAsmString()); + 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) { + auto Imp = importSeq(S->getDeclGroup(), S->getBeginLoc(), S->getEndLoc()); + if (!Imp) + return Imp.takeError(); + + DeclGroupRef ToDG; + SourceLocation ToBeginLoc, ToEndLoc; + std::tie(ToDG, ToBeginLoc, ToEndLoc) = *Imp; + + 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(); + + return CompoundStmt::Create( + Importer.getToContext(), ToStmts, + *ToLBracLocOrErr, *ToRBracLocOrErr); +} + +ExpectedStmt ASTNodeImporter::VisitCaseStmt(CaseStmt *S) { + auto Imp = importSeq( + S->getLHS(), S->getRHS(), S->getSubStmt(), S->getCaseLoc(), + S->getEllipsisLoc(), S->getColonLoc()); + if (!Imp) + return Imp.takeError(); + + Expr *ToLHS, *ToRHS; + Stmt *ToSubStmt; + SourceLocation ToCaseLoc, ToEllipsisLoc, ToColonLoc; + std::tie(ToLHS, ToRHS, ToSubStmt, ToCaseLoc, ToEllipsisLoc, ToColonLoc) = + *Imp; + + auto *ToStmt = CaseStmt::Create(Importer.getToContext(), ToLHS, ToRHS, + ToCaseLoc, ToEllipsisLoc, ToColonLoc); + ToStmt->setSubStmt(ToSubStmt); + + return ToStmt; +} + +ExpectedStmt ASTNodeImporter::VisitDefaultStmt(DefaultStmt *S) { + auto Imp = importSeq(S->getDefaultLoc(), S->getColonLoc(), S->getSubStmt()); + if (!Imp) + return Imp.takeError(); + + SourceLocation ToDefaultLoc, ToColonLoc; + Stmt *ToSubStmt; + std::tie(ToDefaultLoc, ToColonLoc, ToSubStmt) = *Imp; + + return new (Importer.getToContext()) DefaultStmt( + ToDefaultLoc, ToColonLoc, ToSubStmt); +} + +ExpectedStmt ASTNodeImporter::VisitLabelStmt(LabelStmt *S) { + auto Imp = importSeq(S->getIdentLoc(), S->getDecl(), S->getSubStmt()); + if (!Imp) + return Imp.takeError(); + + SourceLocation ToIdentLoc; + LabelDecl *ToLabelDecl; + Stmt *ToSubStmt; + std::tie(ToIdentLoc, ToLabelDecl, ToSubStmt) = *Imp; + + 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) { + auto Imp = importSeq( + S->getIfLoc(), S->getInit(), S->getConditionVariable(), S->getCond(), + S->getThen(), S->getElseLoc(), S->getElse()); + if (!Imp) + return Imp.takeError(); + + SourceLocation ToIfLoc, ToElseLoc; + Stmt *ToInit, *ToThen, *ToElse; + VarDecl *ToConditionVariable; + Expr *ToCond; + std::tie( + ToIfLoc, ToInit, ToConditionVariable, ToCond, ToThen, ToElseLoc, ToElse) = + *Imp; + + return IfStmt::Create(Importer.getToContext(), ToIfLoc, S->isConstexpr(), + ToInit, ToConditionVariable, ToCond, ToThen, ToElseLoc, + ToElse); +} + +ExpectedStmt ASTNodeImporter::VisitSwitchStmt(SwitchStmt *S) { + auto Imp = importSeq( + S->getInit(), S->getConditionVariable(), S->getCond(), + S->getBody(), S->getSwitchLoc()); + if (!Imp) + return Imp.takeError(); + + Stmt *ToInit, *ToBody; + VarDecl *ToConditionVariable; + Expr *ToCond; + SourceLocation ToSwitchLoc; + std::tie(ToInit, ToConditionVariable, ToCond, ToBody, ToSwitchLoc) = *Imp; + + auto *ToStmt = SwitchStmt::Create(Importer.getToContext(), ToInit, + ToConditionVariable, ToCond); + 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) { + auto Imp = importSeq( + S->getConditionVariable(), S->getCond(), S->getBody(), S->getWhileLoc()); + if (!Imp) + return Imp.takeError(); + + VarDecl *ToConditionVariable; + Expr *ToCond; + Stmt *ToBody; + SourceLocation ToWhileLoc; + std::tie(ToConditionVariable, ToCond, ToBody, ToWhileLoc) = *Imp; + + return WhileStmt::Create(Importer.getToContext(), ToConditionVariable, ToCond, + ToBody, ToWhileLoc); +} + +ExpectedStmt ASTNodeImporter::VisitDoStmt(DoStmt *S) { + auto Imp = importSeq( + S->getBody(), S->getCond(), S->getDoLoc(), S->getWhileLoc(), + S->getRParenLoc()); + if (!Imp) + return Imp.takeError(); + + Stmt *ToBody; + Expr *ToCond; + SourceLocation ToDoLoc, ToWhileLoc, ToRParenLoc; + std::tie(ToBody, ToCond, ToDoLoc, ToWhileLoc, ToRParenLoc) = *Imp; + + return new (Importer.getToContext()) DoStmt( + ToBody, ToCond, ToDoLoc, ToWhileLoc, ToRParenLoc); +} + +ExpectedStmt ASTNodeImporter::VisitForStmt(ForStmt *S) { + auto Imp = importSeq( + S->getInit(), S->getCond(), S->getConditionVariable(), S->getInc(), + S->getBody(), S->getForLoc(), S->getLParenLoc(), S->getRParenLoc()); + if (!Imp) + return Imp.takeError(); + + Stmt *ToInit; + Expr *ToCond, *ToInc; + VarDecl *ToConditionVariable; + Stmt *ToBody; + SourceLocation ToForLoc, ToLParenLoc, ToRParenLoc; + std::tie( + ToInit, ToCond, ToConditionVariable, ToInc, ToBody, ToForLoc, + ToLParenLoc, ToRParenLoc) = *Imp; + + return new (Importer.getToContext()) ForStmt( + Importer.getToContext(), + ToInit, ToCond, ToConditionVariable, ToInc, ToBody, ToForLoc, ToLParenLoc, + ToRParenLoc); +} + +ExpectedStmt ASTNodeImporter::VisitGotoStmt(GotoStmt *S) { + auto Imp = importSeq(S->getLabel(), S->getGotoLoc(), S->getLabelLoc()); + if (!Imp) + return Imp.takeError(); + + LabelDecl *ToLabel; + SourceLocation ToGotoLoc, ToLabelLoc; + std::tie(ToLabel, ToGotoLoc, ToLabelLoc) = *Imp; + + return new (Importer.getToContext()) GotoStmt( + ToLabel, ToGotoLoc, ToLabelLoc); +} + +ExpectedStmt ASTNodeImporter::VisitIndirectGotoStmt(IndirectGotoStmt *S) { + auto Imp = importSeq(S->getGotoLoc(), S->getStarLoc(), S->getTarget()); + if (!Imp) + return Imp.takeError(); + + SourceLocation ToGotoLoc, ToStarLoc; + Expr *ToTarget; + std::tie(ToGotoLoc, ToStarLoc, ToTarget) = *Imp; + + 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) { + auto Imp = importSeq( + S->getReturnLoc(), S->getRetValue(), S->getNRVOCandidate()); + if (!Imp) + return Imp.takeError(); + + SourceLocation ToReturnLoc; + Expr *ToRetValue; + const VarDecl *ToNRVOCandidate; + std::tie(ToReturnLoc, ToRetValue, ToNRVOCandidate) = *Imp; + + return ReturnStmt::Create(Importer.getToContext(), ToReturnLoc, ToRetValue, + ToNRVOCandidate); +} + +ExpectedStmt ASTNodeImporter::VisitCXXCatchStmt(CXXCatchStmt *S) { + auto Imp = importSeq( + S->getCatchLoc(), S->getExceptionDecl(), S->getHandlerBlock()); + if (!Imp) + return Imp.takeError(); + + SourceLocation ToCatchLoc; + VarDecl *ToExceptionDecl; + Stmt *ToHandlerBlock; + std::tie(ToCatchLoc, ToExceptionDecl, ToHandlerBlock) = *Imp; + + 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,*ToTryBlockOrErr, ToHandlers); +} + +ExpectedStmt ASTNodeImporter::VisitCXXForRangeStmt(CXXForRangeStmt *S) { + auto Imp1 = importSeq( + S->getInit(), S->getRangeStmt(), S->getBeginStmt(), S->getEndStmt(), + S->getCond(), S->getInc(), S->getLoopVarStmt(), S->getBody()); + if (!Imp1) + return Imp1.takeError(); + auto Imp2 = importSeq( + S->getForLoc(), S->getCoawaitLoc(), S->getColonLoc(), S->getRParenLoc()); + if (!Imp2) + return Imp2.takeError(); + + DeclStmt *ToRangeStmt, *ToBeginStmt, *ToEndStmt, *ToLoopVarStmt; + Expr *ToCond, *ToInc; + Stmt *ToInit, *ToBody; + std::tie( + ToInit, ToRangeStmt, ToBeginStmt, ToEndStmt, ToCond, ToInc, ToLoopVarStmt, + ToBody) = *Imp1; + SourceLocation ToForLoc, ToCoawaitLoc, ToColonLoc, ToRParenLoc; + std::tie(ToForLoc, ToCoawaitLoc, ToColonLoc, ToRParenLoc) = *Imp2; + + return new (Importer.getToContext()) CXXForRangeStmt( + ToInit, ToRangeStmt, ToBeginStmt, ToEndStmt, ToCond, ToInc, ToLoopVarStmt, + ToBody, ToForLoc, ToCoawaitLoc, ToColonLoc, ToRParenLoc); +} + +ExpectedStmt +ASTNodeImporter::VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) { + auto Imp = importSeq( + S->getElement(), S->getCollection(), S->getBody(), + S->getForLoc(), S->getRParenLoc()); + if (!Imp) + return Imp.takeError(); + + Stmt *ToElement, *ToBody; + Expr *ToCollection; + SourceLocation ToForLoc, ToRParenLoc; + std::tie(ToElement, ToCollection, ToBody, ToForLoc, ToRParenLoc) = *Imp; + + return new (Importer.getToContext()) ObjCForCollectionStmt(ToElement, + ToCollection, + ToBody, + ToForLoc, + ToRParenLoc); +} + +ExpectedStmt ASTNodeImporter::VisitObjCAtCatchStmt(ObjCAtCatchStmt *S) { + auto Imp = importSeq( + S->getAtCatchLoc(), S->getRParenLoc(), S->getCatchParamDecl(), + S->getCatchBody()); + if (!Imp) + return Imp.takeError(); + + SourceLocation ToAtCatchLoc, ToRParenLoc; + VarDecl *ToCatchParamDecl; + Stmt *ToCatchBody; + std::tie(ToAtCatchLoc, ToRParenLoc, ToCatchParamDecl, ToCatchBody) = *Imp; + + 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) { + auto Imp = importSeq( + S->getAtTryLoc(), S->getTryBody(), S->getFinallyStmt()); + if (!Imp) + return Imp.takeError(); + + SourceLocation ToAtTryLoc; + Stmt *ToTryBody, *ToFinallyStmt; + std::tie(ToAtTryLoc, ToTryBody, ToFinallyStmt) = *Imp; + + 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) { + auto Imp = importSeq( + S->getAtSynchronizedLoc(), S->getSynchExpr(), S->getSynchBody()); + if (!Imp) + return Imp.takeError(); + + SourceLocation ToAtSynchronizedLoc; + Expr *ToSynchExpr; + Stmt *ToSynchBody; + std::tie(ToAtSynchronizedLoc, ToSynchExpr, ToSynchBody) = *Imp; + + 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<ImportError>(ImportError::UnsupportedConstruct); +} + +ExpectedStmt ASTNodeImporter::VisitVAArgExpr(VAArgExpr *E) { + auto Imp = importSeq( + E->getBuiltinLoc(), E->getSubExpr(), E->getWrittenTypeInfo(), + E->getRParenLoc(), E->getType()); + if (!Imp) + return Imp.takeError(); + + SourceLocation ToBuiltinLoc, ToRParenLoc; + Expr *ToSubExpr; + TypeSourceInfo *ToWrittenTypeInfo; + QualType ToType; + std::tie(ToBuiltinLoc, ToSubExpr, ToWrittenTypeInfo, ToRParenLoc, ToType) = + *Imp; + + return new (Importer.getToContext()) VAArgExpr( + ToBuiltinLoc, ToSubExpr, ToWrittenTypeInfo, ToRParenLoc, ToType, + E->isMicrosoftABI()); +} + +ExpectedStmt ASTNodeImporter::VisitChooseExpr(ChooseExpr *E) { + auto Imp = importSeq(E->getCond(), E->getLHS(), E->getRHS(), + E->getBuiltinLoc(), E->getRParenLoc(), E->getType()); + if (!Imp) + return Imp.takeError(); + + Expr *ToCond; + Expr *ToLHS; + Expr *ToRHS; + SourceLocation ToBuiltinLoc, ToRParenLoc; + QualType ToType; + std::tie(ToCond, ToLHS, ToRHS, ToBuiltinLoc, ToRParenLoc, ToType) = *Imp; + + ExprValueKind VK = E->getValueKind(); + ExprObjectKind OK = E->getObjectKind(); + + bool TypeDependent = ToCond->isTypeDependent(); + bool ValueDependent = ToCond->isValueDependent(); + + // 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, TypeDependent, ValueDependent); +} + +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::VisitPredefinedExpr(PredefinedExpr *E) { + auto Imp = importSeq( + E->getBeginLoc(), E->getType(), E->getFunctionName()); + if (!Imp) + return Imp.takeError(); + + SourceLocation ToBeginLoc; + QualType ToType; + StringLiteral *ToFunctionName; + std::tie(ToBeginLoc, ToType, ToFunctionName) = *Imp; + + return PredefinedExpr::Create(Importer.getToContext(), ToBeginLoc, ToType, + E->getIdentKind(), ToFunctionName); +} + +ExpectedStmt ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) { + auto Imp = importSeq( + E->getQualifierLoc(), E->getTemplateKeywordLoc(), E->getDecl(), + E->getLocation(), E->getType()); + if (!Imp) + return Imp.takeError(); + + NestedNameSpecifierLoc ToQualifierLoc; + SourceLocation ToTemplateKeywordLoc, ToLocation; + ValueDecl *ToDecl; + QualType ToType; + std::tie(ToQualifierLoc, ToTemplateKeywordLoc, ToDecl, ToLocation, ToType) = + *Imp; + + 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->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); + 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::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.data(), ToLocations.size()); +} + +ExpectedStmt ASTNodeImporter::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) { + auto Imp = importSeq( + E->getLParenLoc(), E->getTypeSourceInfo(), E->getType(), + E->getInitializer()); + if (!Imp) + return Imp.takeError(); + + SourceLocation ToLParenLoc; + TypeSourceInfo *ToTypeSourceInfo; + QualType ToType; + Expr *ToInitializer; + std::tie(ToLParenLoc, ToTypeSourceInfo, ToType, ToInitializer) = *Imp; + + return new (Importer.getToContext()) CompoundLiteralExpr( + ToLParenLoc, ToTypeSourceInfo, ToType, E->getValueKind(), + ToInitializer, E->isFileScope()); +} + +ExpectedStmt ASTNodeImporter::VisitAtomicExpr(AtomicExpr *E) { + auto Imp = importSeq( + E->getBuiltinLoc(), E->getType(), E->getRParenLoc()); + if (!Imp) + return Imp.takeError(); + + SourceLocation ToBuiltinLoc, ToRParenLoc; + QualType ToType; + std::tie(ToBuiltinLoc, ToType, ToRParenLoc) = *Imp; + + 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) { + auto Imp = importSeq( + E->getAmpAmpLoc(), E->getLabelLoc(), E->getLabel(), E->getType()); + if (!Imp) + return Imp.takeError(); + + SourceLocation ToAmpAmpLoc, ToLabelLoc; + LabelDecl *ToLabel; + QualType ToType; + std::tie(ToAmpAmpLoc, ToLabelLoc, ToLabel, ToType) = *Imp; + + return new (Importer.getToContext()) AddrLabelExpr( + ToAmpAmpLoc, ToLabelLoc, ToLabel, ToType); +} + +ExpectedStmt ASTNodeImporter::VisitConstantExpr(ConstantExpr *E) { + auto Imp = importSeq(E->getSubExpr()); + if (!Imp) + return Imp.takeError(); + + Expr *ToSubExpr; + std::tie(ToSubExpr) = *Imp; + + // TODO : Handle APValue::ValueKind that require importing. + APValue::ValueKind Kind = E->getResultAPValueKind(); + if (Kind == APValue::Int || Kind == APValue::Float || + Kind == APValue::FixedPoint || Kind == APValue::ComplexFloat || + Kind == APValue::ComplexInt) + return ConstantExpr::Create(Importer.getToContext(), ToSubExpr, + E->getAPValueResult()); + return ConstantExpr::Create(Importer.getToContext(), ToSubExpr); +} + +ExpectedStmt ASTNodeImporter::VisitParenExpr(ParenExpr *E) { + auto Imp = importSeq(E->getLParen(), E->getRParen(), E->getSubExpr()); + if (!Imp) + return Imp.takeError(); + + SourceLocation ToLParen, ToRParen; + Expr *ToSubExpr; + std::tie(ToLParen, ToRParen, ToSubExpr) = *Imp; + + 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) { + auto Imp = importSeq( + E->getSubStmt(), E->getType(), E->getLParenLoc(), E->getRParenLoc()); + if (!Imp) + return Imp.takeError(); + + CompoundStmt *ToSubStmt; + QualType ToType; + SourceLocation ToLParenLoc, ToRParenLoc; + std::tie(ToSubStmt, ToType, ToLParenLoc, ToRParenLoc) = *Imp; + + return new (Importer.getToContext()) StmtExpr( + ToSubStmt, ToType, ToLParenLoc, ToRParenLoc); +} + +ExpectedStmt ASTNodeImporter::VisitUnaryOperator(UnaryOperator *E) { + auto Imp = importSeq( + E->getSubExpr(), E->getType(), E->getOperatorLoc()); + if (!Imp) + return Imp.takeError(); + + Expr *ToSubExpr; + QualType ToType; + SourceLocation ToOperatorLoc; + std::tie(ToSubExpr, ToType, ToOperatorLoc) = *Imp; + + return new (Importer.getToContext()) UnaryOperator( + ToSubExpr, E->getOpcode(), ToType, E->getValueKind(), E->getObjectKind(), + ToOperatorLoc, E->canOverflow()); +} + +ExpectedStmt +ASTNodeImporter::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E) { + auto Imp = importSeq(E->getType(), E->getOperatorLoc(), E->getRParenLoc()); + if (!Imp) + return Imp.takeError(); + + QualType ToType; + SourceLocation ToOperatorLoc, ToRParenLoc; + std::tie(ToType, ToOperatorLoc, ToRParenLoc) = *Imp; + + 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) { + auto Imp = importSeq( + E->getLHS(), E->getRHS(), E->getType(), E->getOperatorLoc()); + if (!Imp) + return Imp.takeError(); + + Expr *ToLHS, *ToRHS; + QualType ToType; + SourceLocation ToOperatorLoc; + std::tie(ToLHS, ToRHS, ToType, ToOperatorLoc) = *Imp; + + return new (Importer.getToContext()) BinaryOperator( + ToLHS, ToRHS, E->getOpcode(), ToType, E->getValueKind(), + E->getObjectKind(), ToOperatorLoc, E->getFPFeatures()); +} + +ExpectedStmt ASTNodeImporter::VisitConditionalOperator(ConditionalOperator *E) { + auto Imp = importSeq( + E->getCond(), E->getQuestionLoc(), E->getLHS(), E->getColonLoc(), + E->getRHS(), E->getType()); + if (!Imp) + return Imp.takeError(); + + Expr *ToCond, *ToLHS, *ToRHS; + SourceLocation ToQuestionLoc, ToColonLoc; + QualType ToType; + std::tie(ToCond, ToQuestionLoc, ToLHS, ToColonLoc, ToRHS, ToType) = *Imp; + + return new (Importer.getToContext()) ConditionalOperator( + ToCond, ToQuestionLoc, ToLHS, ToColonLoc, ToRHS, ToType, + E->getValueKind(), E->getObjectKind()); +} + +ExpectedStmt ASTNodeImporter::VisitBinaryConditionalOperator( + BinaryConditionalOperator *E) { + auto Imp = importSeq( + E->getCommon(), E->getOpaqueValue(), E->getCond(), E->getTrueExpr(), + E->getFalseExpr(), E->getQuestionLoc(), E->getColonLoc(), E->getType()); + if (!Imp) + return Imp.takeError(); + + Expr *ToCommon, *ToCond, *ToTrueExpr, *ToFalseExpr; + OpaqueValueExpr *ToOpaqueValue; + SourceLocation ToQuestionLoc, ToColonLoc; + QualType ToType; + std::tie( + ToCommon, ToOpaqueValue, ToCond, ToTrueExpr, ToFalseExpr, ToQuestionLoc, + ToColonLoc, ToType) = *Imp; + + return new (Importer.getToContext()) BinaryConditionalOperator( + ToCommon, ToOpaqueValue, ToCond, ToTrueExpr, ToFalseExpr, + ToQuestionLoc, ToColonLoc, ToType, E->getValueKind(), + E->getObjectKind()); +} + +ExpectedStmt ASTNodeImporter::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E) { + auto Imp = importSeq( + E->getBeginLoc(), E->getQueriedTypeSourceInfo(), + E->getDimensionExpression(), E->getEndLoc(), E->getType()); + if (!Imp) + return Imp.takeError(); + + SourceLocation ToBeginLoc, ToEndLoc; + TypeSourceInfo *ToQueriedTypeSourceInfo; + Expr *ToDimensionExpression; + QualType ToType; + std::tie( + ToBeginLoc, ToQueriedTypeSourceInfo, ToDimensionExpression, ToEndLoc, + ToType) = *Imp; + + return new (Importer.getToContext()) ArrayTypeTraitExpr( + ToBeginLoc, E->getTrait(), ToQueriedTypeSourceInfo, E->getValue(), + ToDimensionExpression, ToEndLoc, ToType); +} + +ExpectedStmt ASTNodeImporter::VisitExpressionTraitExpr(ExpressionTraitExpr *E) { + auto Imp = importSeq( + E->getBeginLoc(), E->getQueriedExpression(), E->getEndLoc(), E->getType()); + if (!Imp) + return Imp.takeError(); + + SourceLocation ToBeginLoc, ToEndLoc; + Expr *ToQueriedExpression; + QualType ToType; + std::tie(ToBeginLoc, ToQueriedExpression, ToEndLoc, ToType) = *Imp; + + return new (Importer.getToContext()) ExpressionTraitExpr( + ToBeginLoc, E->getTrait(), ToQueriedExpression, E->getValue(), + ToEndLoc, ToType); +} + +ExpectedStmt ASTNodeImporter::VisitOpaqueValueExpr(OpaqueValueExpr *E) { + auto Imp = importSeq( + E->getLocation(), E->getType(), E->getSourceExpr()); + if (!Imp) + return Imp.takeError(); + + SourceLocation ToLocation; + QualType ToType; + Expr *ToSourceExpr; + std::tie(ToLocation, ToType, ToSourceExpr) = *Imp; + + return new (Importer.getToContext()) OpaqueValueExpr( + ToLocation, ToType, E->getValueKind(), E->getObjectKind(), ToSourceExpr); +} + +ExpectedStmt ASTNodeImporter::VisitArraySubscriptExpr(ArraySubscriptExpr *E) { + auto Imp = importSeq( + E->getLHS(), E->getRHS(), E->getType(), E->getRBracketLoc()); + if (!Imp) + return Imp.takeError(); + + Expr *ToLHS, *ToRHS; + SourceLocation ToRBracketLoc; + QualType ToType; + std::tie(ToLHS, ToRHS, ToType, ToRBracketLoc) = *Imp; + + return new (Importer.getToContext()) ArraySubscriptExpr( + ToLHS, ToRHS, ToType, E->getValueKind(), E->getObjectKind(), + ToRBracketLoc); +} + +ExpectedStmt +ASTNodeImporter::VisitCompoundAssignOperator(CompoundAssignOperator *E) { + auto Imp = importSeq( + E->getLHS(), E->getRHS(), E->getType(), E->getComputationLHSType(), + E->getComputationResultType(), E->getOperatorLoc()); + if (!Imp) + return Imp.takeError(); + + Expr *ToLHS, *ToRHS; + QualType ToType, ToComputationLHSType, ToComputationResultType; + SourceLocation ToOperatorLoc; + std::tie(ToLHS, ToRHS, ToType, ToComputationLHSType, ToComputationResultType, + ToOperatorLoc) = *Imp; + + return new (Importer.getToContext()) CompoundAssignOperator( + ToLHS, ToRHS, E->getOpcode(), ToType, E->getValueKind(), + E->getObjectKind(), ToComputationLHSType, ToComputationResultType, + ToOperatorLoc, E->getFPFeatures()); +} + +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()); +} + +ExpectedStmt ASTNodeImporter::VisitExplicitCastExpr(ExplicitCastExpr *E) { + auto Imp1 = importSeq( + E->getType(), E->getSubExpr(), E->getTypeInfoAsWritten()); + if (!Imp1) + return Imp1.takeError(); + + QualType ToType; + Expr *ToSubExpr; + TypeSourceInfo *ToTypeInfoAsWritten; + std::tie(ToType, ToSubExpr, ToTypeInfoAsWritten) = *Imp1; + + 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, 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, *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); + } + default: + llvm_unreachable("Cast expression of unsupported type!"); + return make_error<ImportError>(ImportError::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) { + auto Imp = importSeq(FromNode.getBeginLoc(), FromNode.getEndLoc()); + if (!Imp) + return Imp.takeError(); + std::tie(ToBeginLoc, ToEndLoc) = *Imp; + } + + 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; + } + + auto Imp = importSeq( + E->getType(), E->getTypeSourceInfo(), E->getOperatorLoc(), + E->getRParenLoc()); + if (!Imp) + return Imp.takeError(); + + QualType ToType; + TypeSourceInfo *ToTypeSourceInfo; + SourceLocation ToOperatorLoc, ToRParenLoc; + std::tie(ToType, ToTypeSourceInfo, ToOperatorLoc, ToRParenLoc) = *Imp; + + return OffsetOfExpr::Create( + Importer.getToContext(), ToType, ToOperatorLoc, ToTypeSourceInfo, ToNodes, + ToExprs, ToRParenLoc); +} + +ExpectedStmt ASTNodeImporter::VisitCXXNoexceptExpr(CXXNoexceptExpr *E) { + auto Imp = importSeq( + E->getType(), E->getOperand(), E->getBeginLoc(), E->getEndLoc()); + if (!Imp) + return Imp.takeError(); + + QualType ToType; + Expr *ToOperand; + SourceLocation ToBeginLoc, ToEndLoc; + std::tie(ToType, ToOperand, ToBeginLoc, ToEndLoc) = *Imp; + + 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) { + auto Imp = importSeq(E->getSubExpr(), E->getType(), E->getThrowLoc()); + if (!Imp) + return Imp.takeError(); + + Expr *ToSubExpr; + QualType ToType; + SourceLocation ToThrowLoc; + std::tie(ToSubExpr, ToType, ToThrowLoc) = *Imp; + + 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()) { + Optional<ParmVarDecl *> FromParam = Importer.getImportedFromDecl(ToParam); + assert(FromParam && "ParmVarDecl was not imported?"); + + if (Error Err = ImportDefaultArgOfParmVarDecl(*FromParam, ToParam)) + return std::move(Err); + } + + return CXXDefaultArgExpr::Create(Importer.getToContext(), *ToUsedLocOrErr, + *ToParamOrErr, *UsedContextOrErr); +} + +ExpectedStmt +ASTNodeImporter::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) { + auto Imp = importSeq( + E->getType(), E->getTypeSourceInfo(), E->getRParenLoc()); + if (!Imp) + return Imp.takeError(); + + QualType ToType; + TypeSourceInfo *ToTypeSourceInfo; + SourceLocation ToRParenLoc; + std::tie(ToType, ToTypeSourceInfo, ToRParenLoc) = *Imp; + + 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) { + auto Imp = importSeq( + E->getConstructor(), E->getType(), E->getTypeSourceInfo(), + E->getParenOrBraceRange()); + if (!Imp) + return Imp.takeError(); + + CXXConstructorDecl *ToConstructor; + QualType ToType; + TypeSourceInfo *ToTypeSourceInfo; + SourceRange ToParenOrBraceRange; + std::tie(ToConstructor, ToType, ToTypeSourceInfo, ToParenOrBraceRange) = *Imp; + + 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()); +} + +ExpectedStmt +ASTNodeImporter::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E) { + auto Imp = importSeq( + E->getType(), E->GetTemporaryExpr(), E->getExtendingDecl()); + if (!Imp) + return Imp.takeError(); + + QualType ToType; + Expr *ToTemporaryExpr; + const ValueDecl *ToExtendingDecl; + std::tie(ToType, ToTemporaryExpr, ToExtendingDecl) = *Imp; + + auto *ToMTE = new (Importer.getToContext()) MaterializeTemporaryExpr( + ToType, ToTemporaryExpr, E->isBoundToLvalueReference()); + + // FIXME: Should ManglingNumber get numbers associated with 'to' context? + ToMTE->setExtendingDecl(ToExtendingDecl, E->getManglingNumber()); + return ToMTE; +} + +ExpectedStmt ASTNodeImporter::VisitPackExpansionExpr(PackExpansionExpr *E) { + auto Imp = importSeq( + E->getType(), E->getPattern(), E->getEllipsisLoc()); + if (!Imp) + return Imp.takeError(); + + QualType ToType; + Expr *ToPattern; + SourceLocation ToEllipsisLoc; + std::tie(ToType, ToPattern, ToEllipsisLoc) = *Imp; + + return new (Importer.getToContext()) PackExpansionExpr( + ToType, ToPattern, ToEllipsisLoc, E->getNumExpansions()); +} + +ExpectedStmt ASTNodeImporter::VisitSizeOfPackExpr(SizeOfPackExpr *E) { + auto Imp = importSeq( + E->getOperatorLoc(), E->getPack(), E->getPackLoc(), E->getRParenLoc()); + if (!Imp) + return Imp.takeError(); + + SourceLocation ToOperatorLoc, ToPackLoc, ToRParenLoc; + NamedDecl *ToPack; + std::tie(ToOperatorLoc, ToPack, ToPackLoc, ToRParenLoc) = *Imp; + + Optional<unsigned> Length; + if (!E->isValueDependent()) + Length = E->getPackLength(); + + SmallVector<TemplateArgument, 8> ToPartialArguments; + if (E->isPartiallySubstituted()) { + if (Error Err = ImportTemplateArguments( + E->getPartialArguments().data(), + E->getPartialArguments().size(), + ToPartialArguments)) + return std::move(Err); + } + + return SizeOfPackExpr::Create( + Importer.getToContext(), ToOperatorLoc, ToPack, ToPackLoc, ToRParenLoc, + Length, ToPartialArguments); +} + + +ExpectedStmt ASTNodeImporter::VisitCXXNewExpr(CXXNewExpr *E) { + auto Imp = importSeq( + E->getOperatorNew(), E->getOperatorDelete(), E->getTypeIdParens(), + E->getArraySize(), E->getInitializer(), E->getType(), + E->getAllocatedTypeSourceInfo(), E->getSourceRange(), + E->getDirectInitRange()); + if (!Imp) + return Imp.takeError(); + + FunctionDecl *ToOperatorNew, *ToOperatorDelete; + SourceRange ToTypeIdParens, ToSourceRange, ToDirectInitRange; + Optional<Expr *> ToArraySize; + Expr *ToInitializer; + QualType ToType; + TypeSourceInfo *ToAllocatedTypeSourceInfo; + std::tie( + ToOperatorNew, ToOperatorDelete, ToTypeIdParens, ToArraySize, ToInitializer, + ToType, ToAllocatedTypeSourceInfo, ToSourceRange, ToDirectInitRange) = *Imp; + + 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->passAlignment(), E->doesUsualArrayDeleteWantSize(), + ToPlacementArgs, ToTypeIdParens, ToArraySize, E->getInitializationStyle(), + ToInitializer, ToType, ToAllocatedTypeSourceInfo, ToSourceRange, + ToDirectInitRange); +} + +ExpectedStmt ASTNodeImporter::VisitCXXDeleteExpr(CXXDeleteExpr *E) { + auto Imp = importSeq( + E->getType(), E->getOperatorDelete(), E->getArgument(), E->getBeginLoc()); + if (!Imp) + return Imp.takeError(); + + QualType ToType; + FunctionDecl *ToOperatorDelete; + Expr *ToArgument; + SourceLocation ToBeginLoc; + std::tie(ToType, ToOperatorDelete, ToArgument, ToBeginLoc) = *Imp; + + return new (Importer.getToContext()) CXXDeleteExpr( + ToType, E->isGlobalDelete(), E->isArrayForm(), E->isArrayFormAsWritten(), + E->doesUsualArrayDeleteWantSize(), ToOperatorDelete, ToArgument, + ToBeginLoc); +} + +ExpectedStmt ASTNodeImporter::VisitCXXConstructExpr(CXXConstructExpr *E) { + auto Imp = importSeq( + E->getType(), E->getLocation(), E->getConstructor(), + E->getParenOrBraceRange()); + if (!Imp) + return Imp.takeError(); + + QualType ToType; + SourceLocation ToLocation; + CXXConstructorDecl *ToConstructor; + SourceRange ToParenOrBraceRange; + std::tie(ToType, ToLocation, ToConstructor, ToParenOrBraceRange) = *Imp; + + SmallVector<Expr *, 6> ToArgs(E->getNumArgs()); + if (Error Err = ImportContainerChecked(E->arguments(), ToArgs)) + return std::move(Err); + + return CXXConstructExpr::Create( + Importer.getToContext(), ToType, ToLocation, ToConstructor, + E->isElidable(), ToArgs, E->hadMultipleCandidates(), + E->isListInitialization(), E->isStdInitListInitialization(), + E->requiresZeroInitialization(), E->getConstructionKind(), + ToParenOrBraceRange); +} + +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) { + auto Imp = importSeq( + E->getCallee(), E->getType(), E->getRParenLoc()); + if (!Imp) + return Imp.takeError(); + + Expr *ToCallee; + QualType ToType; + SourceLocation ToRParenLoc; + std::tie(ToCallee, ToType, ToRParenLoc) = *Imp; + + 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); +} + +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 new (Importer.getToContext()) CXXThisExpr( + *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 new (Importer.getToContext()) CXXBoolLiteralExpr( + E->getValue(), *ToTypeOrErr, *ToLocationOrErr); +} + +ExpectedStmt ASTNodeImporter::VisitMemberExpr(MemberExpr *E) { + auto Imp1 = importSeq( + E->getBase(), E->getOperatorLoc(), E->getQualifierLoc(), + E->getTemplateKeywordLoc(), E->getMemberDecl(), E->getType()); + if (!Imp1) + return Imp1.takeError(); + + Expr *ToBase; + SourceLocation ToOperatorLoc, ToTemplateKeywordLoc; + NestedNameSpecifierLoc ToQualifierLoc; + ValueDecl *ToMemberDecl; + QualType ToType; + std::tie( + ToBase, ToOperatorLoc, ToQualifierLoc, ToTemplateKeywordLoc, ToMemberDecl, + ToType) = *Imp1; + + auto Imp2 = importSeq( + E->getFoundDecl().getDecl(), E->getMemberNameInfo().getName(), + E->getMemberNameInfo().getLoc(), E->getLAngleLoc(), E->getRAngleLoc()); + if (!Imp2) + return Imp2.takeError(); + NamedDecl *ToDecl; + DeclarationName ToName; + SourceLocation ToLoc, ToLAngleLoc, ToRAngleLoc; + std::tie(ToDecl, ToName, ToLoc, ToLAngleLoc, ToRAngleLoc) = *Imp2; + + 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) { + auto Imp = importSeq( + E->getBase(), E->getOperatorLoc(), E->getQualifierLoc(), + E->getScopeTypeInfo(), E->getColonColonLoc(), E->getTildeLoc()); + if (!Imp) + return Imp.takeError(); + + Expr *ToBase; + SourceLocation ToOperatorLoc, ToColonColonLoc, ToTildeLoc; + NestedNameSpecifierLoc ToQualifierLoc; + TypeSourceInfo *ToScopeTypeInfo; + std::tie( + ToBase, ToOperatorLoc, ToQualifierLoc, ToScopeTypeInfo, ToColonColonLoc, + ToTildeLoc) = *Imp; + + PseudoDestructorTypeStorage Storage; + if (IdentifierInfo *FromII = E->getDestroyedTypeIdentifier()) { + 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) { + auto Imp = importSeq( + E->getType(), E->getOperatorLoc(), E->getQualifierLoc(), + E->getTemplateKeywordLoc(), E->getFirstQualifierFoundInScope()); + if (!Imp) + return Imp.takeError(); + + QualType ToType; + SourceLocation ToOperatorLoc, ToTemplateKeywordLoc; + NestedNameSpecifierLoc ToQualifierLoc; + NamedDecl *ToFirstQualifierFoundInScope; + std::tie( + ToType, ToOperatorLoc, ToQualifierLoc, ToTemplateKeywordLoc, + ToFirstQualifierFoundInScope) = *Imp; + + 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 ToMemberNameInfoOrErr = importSeq(E->getMember(), E->getMemberLoc()); + if (!ToMemberNameInfoOrErr) + return ToMemberNameInfoOrErr.takeError(); + DeclarationNameInfo ToMemberNameInfo( + std::get<0>(*ToMemberNameInfoOrErr), std::get<1>(*ToMemberNameInfoOrErr)); + // 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) { + auto Imp = importSeq( + E->getQualifierLoc(), E->getTemplateKeywordLoc(), E->getDeclName(), + E->getExprLoc(), E->getLAngleLoc(), E->getRAngleLoc()); + if (!Imp) + return Imp.takeError(); + + NestedNameSpecifierLoc ToQualifierLoc; + SourceLocation ToTemplateKeywordLoc, ToExprLoc, ToLAngleLoc, ToRAngleLoc; + DeclarationName ToDeclName; + std::tie( + ToQualifierLoc, ToTemplateKeywordLoc, ToDeclName, ToExprLoc, + ToLAngleLoc, ToRAngleLoc) = *Imp; + + DeclarationNameInfo ToNameInfo(ToDeclName, ToExprLoc); + 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) { + auto Imp = importSeq( + E->getLParenLoc(), E->getRParenLoc(), E->getTypeSourceInfo()); + if (!Imp) + return Imp.takeError(); + + SourceLocation ToLParenLoc, ToRParenLoc; + TypeSourceInfo *ToTypeSourceInfo; + std::tie(ToLParenLoc, ToRParenLoc, ToTypeSourceInfo) = *Imp; + + SmallVector<Expr *, 8> ToArgs(E->arg_size()); + if (Error Err = + ImportArrayChecked(E->arg_begin(), E->arg_end(), ToArgs.begin())) + return std::move(Err); + + return CXXUnresolvedConstructExpr::Create( + Importer.getToContext(), ToTypeSourceInfo, ToLParenLoc, + llvm::makeArrayRef(ToArgs), ToRParenLoc); +} + +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(); + + auto ToNameInfoOrErr = importSeq(E->getName(), E->getNameLoc()); + if (!ToNameInfoOrErr) + return ToNameInfoOrErr.takeError(); + DeclarationNameInfo ToNameInfo( + std::get<0>(*ToNameInfoOrErr), std::get<1>(*ToNameInfoOrErr)); + // 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() && E->getTemplateKeywordLoc().isValid()) { + 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(); + + return UnresolvedLookupExpr::Create( + Importer.getToContext(), *ToNamingClassOrErr, *ToQualifierLocOrErr, + *ToTemplateKeywordLocOrErr, ToNameInfo, E->requiresADL(), &ToTAInfo, + ToDecls.begin(), ToDecls.end()); + } + + return UnresolvedLookupExpr::Create( + Importer.getToContext(), *ToNamingClassOrErr, *ToQualifierLocOrErr, + ToNameInfo, E->requiresADL(), E->isOverloaded(), ToDecls.begin(), + ToDecls.end()); +} + +ExpectedStmt +ASTNodeImporter::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E) { + auto Imp1 = importSeq( + E->getType(), E->getOperatorLoc(), E->getQualifierLoc(), + E->getTemplateKeywordLoc()); + if (!Imp1) + return Imp1.takeError(); + + QualType ToType; + SourceLocation ToOperatorLoc, ToTemplateKeywordLoc; + NestedNameSpecifierLoc ToQualifierLoc; + std::tie(ToType, ToOperatorLoc, ToQualifierLoc, ToTemplateKeywordLoc) = *Imp1; + + auto Imp2 = importSeq(E->getName(), E->getNameLoc()); + if (!Imp2) + return Imp2.takeError(); + DeclarationNameInfo ToNameInfo(std::get<0>(*Imp2), std::get<1>(*Imp2)); + // 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()) { + if (Error Err = + ImportTemplateArgumentListInfo(E->template_arguments(), 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) { + auto Imp = importSeq(E->getCallee(), E->getType(), E->getRParenLoc()); + if (!Imp) + return Imp.takeError(); + + Expr *ToCallee; + QualType ToType; + SourceLocation ToRParenLoc; + std::tie(ToCallee, ToType, ToRParenLoc) = *Imp; + + 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, /*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<LambdaCapture, 8> ToCaptures; + ToCaptures.reserve(E->capture_size()); + for (const auto &FromCapture : E->captures()) { + if (auto ToCaptureOrErr = import(FromCapture)) + ToCaptures.push_back(*ToCaptureOrErr); + else + return ToCaptureOrErr.takeError(); + } + + SmallVector<Expr *, 8> ToCaptureInits(E->capture_size()); + if (Error Err = ImportContainerChecked(E->capture_inits(), ToCaptureInits)) + return std::move(Err); + + auto Imp = importSeq( + E->getIntroducerRange(), E->getCaptureDefaultLoc(), E->getEndLoc()); + if (!Imp) + return Imp.takeError(); + + SourceRange ToIntroducerRange; + SourceLocation ToCaptureDefaultLoc, ToEndLoc; + std::tie(ToIntroducerRange, ToCaptureDefaultLoc, ToEndLoc) = *Imp; + + return LambdaExpr::Create( + Importer.getToContext(), ToClass, ToIntroducerRange, + E->getCaptureDefault(), ToCaptureDefaultLoc, ToCaptures, + E->hasExplicitParameters(), E->hasExplicitResultType(), ToCaptureInits, + ToEndLoc, E->containsUnexpandedParameterPack()); +} + + +ExpectedStmt ASTNodeImporter::VisitInitListExpr(InitListExpr *E) { + auto Imp = importSeq(E->getLBraceLoc(), E->getRBraceLoc(), E->getType()); + if (!Imp) + return Imp.takeError(); + + SourceLocation ToLBraceLoc, ToRBraceLoc; + QualType ToType; + std::tie(ToLBraceLoc, ToRBraceLoc, ToType) = *Imp; + + 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) { + auto Imp = importSeq(E->getLocation(), E->getType(), E->getConstructor()); + if (!Imp) + return Imp.takeError(); + + SourceLocation ToLocation; + QualType ToType; + CXXConstructorDecl *ToConstructor; + std::tie(ToLocation, ToType, ToConstructor) = *Imp; + + return new (Importer.getToContext()) CXXInheritedCtorInitExpr( + ToLocation, ToType, ToConstructor, E->constructsVBase(), + E->inheritedFromVBase()); +} + +ExpectedStmt ASTNodeImporter::VisitArrayInitLoopExpr(ArrayInitLoopExpr *E) { + auto Imp = importSeq(E->getType(), E->getCommonExpr(), E->getSubExpr()); + if (!Imp) + return Imp.takeError(); + + QualType ToType; + Expr *ToCommonExpr, *ToSubExpr; + std::tie(ToType, ToCommonExpr, ToSubExpr) = *Imp; + + 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(); + + return CXXDefaultInitExpr::Create( + Importer.getToContext(), *ToBeginLocOrErr, *ToFieldOrErr, *UsedContextOrErr); +} + +ExpectedStmt ASTNodeImporter::VisitCXXNamedCastExpr(CXXNamedCastExpr *E) { + auto Imp = importSeq( + E->getType(), E->getSubExpr(), E->getTypeInfoAsWritten(), + E->getOperatorLoc(), E->getRParenLoc(), E->getAngleBrackets()); + if (!Imp) + return Imp.takeError(); + + QualType ToType; + Expr *ToSubExpr; + TypeSourceInfo *ToTypeInfoAsWritten; + SourceLocation ToOperatorLoc, ToRParenLoc; + SourceRange ToAngleBrackets; + std::tie( + ToType, ToSubExpr, ToTypeInfoAsWritten, ToOperatorLoc, ToRParenLoc, + ToAngleBrackets) = *Imp; + + ExprValueKind VK = E->getValueKind(); + CastKind CK = E->getCastKind(); + auto ToBasePathOrErr = ImportCastPath(E); + if (!ToBasePathOrErr) + return ToBasePathOrErr.takeError(); + + if (isa<CXXStaticCastExpr>(E)) { + return CXXStaticCastExpr::Create( + Importer.getToContext(), ToType, VK, CK, ToSubExpr, &(*ToBasePathOrErr), + ToTypeInfoAsWritten, 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<ImportError>(); + } +} + +ExpectedStmt ASTNodeImporter::VisitSubstNonTypeTemplateParmExpr( + SubstNonTypeTemplateParmExpr *E) { + auto Imp = importSeq( + E->getType(), E->getExprLoc(), E->getParameter(), E->getReplacement()); + if (!Imp) + return Imp.takeError(); + + QualType ToType; + SourceLocation ToExprLoc; + NonTypeTemplateParmDecl *ToParameter; + Expr *ToReplacement; + std::tie(ToType, ToExprLoc, ToParameter, ToReplacement) = *Imp; + + return new (Importer.getToContext()) SubstNonTypeTemplateParmExpr( + ToType, E->getValueKind(), ToExprLoc, ToParameter, ToReplacement); +} + +ExpectedStmt ASTNodeImporter::VisitTypeTraitExpr(TypeTraitExpr *E) { + auto Imp = importSeq( + E->getType(), E->getBeginLoc(), E->getEndLoc()); + if (!Imp) + return Imp.takeError(); + + QualType ToType; + SourceLocation ToBeginLoc, ToEndLoc; + std::tie(ToType, ToBeginLoc, ToEndLoc) = *Imp; + + SmallVector<TypeSourceInfo *, 4> ToArgs(E->getNumArgs()); + if (Error Err = ImportContainerChecked(E->getArgs(), ToArgs)) + return std::move(Err); + + // According to Sema::BuildTypeTrait(), if E is value-dependent, + // Value is always false. + bool ToValue = (E->isValueDependent() ? false : E->getValue()); + + return TypeTraitExpr::Create( + Importer.getToContext(), ToType, ToBeginLoc, E->getTrait(), ToArgs, + ToEndLoc, ToValue); +} + +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); +} + +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; + +Optional<unsigned> 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 None; + + 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 None; +} + +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()) { + 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); +} + +Expected<QualType> ASTImporter::Import(QualType FromT) { + if (FromT.isNull()) + return QualType{}; + + const Type *FromTy = FromT.getTypePtr(); + + // Check whether we've already imported this type. + llvm::DenseMap<const Type *, const Type *>::iterator Pos + = ImportedTypes.find(FromTy); + if (Pos != ImportedTypes.end()) + return ToContext.getQualifiedType(Pos->second, FromT.getLocalQualifiers()); + + // Import the type + ASTNodeImporter Importer(*this); + ExpectedType ToTOrErr = Importer.Visit(FromTy); + if (!ToTOrErr) + return ToTOrErr.takeError(); + + // Record the imported type. + ImportedTypes[FromTy] = (*ToTOrErr).getTypePtr(); + + return ToContext.getQualifiedType(*ToTOrErr, 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); +} + +Expected<Attr *> ASTImporter::Import(const Attr *FromAttr) { + Attr *ToAttr = FromAttr->clone(ToContext); + if (auto ToRangeOrErr = Import(FromAttr->getRange())) + ToAttr->setRange(*ToRangeOrErr); + else + return ToRangeOrErr.takeError(); + + return ToAttr; +} + +Decl *ASTImporter::GetAlreadyImportedOrNull(const Decl *FromD) const { + auto Pos = ImportedDecls.find(FromD); + if (Pos != ImportedDecls.end()) + return Pos->second; + else + return nullptr; +} + +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<ImportError>(*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<ImportError>(*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()) { + 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?). + ImportError ErrOut; + handleAllErrors(ToDOrErr.takeError(), + [&ErrOut](const ImportError &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]) + for (Decl *FromDi : Path) { + 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[FromD].clear(); + + // Do not return ToDOrErr, error was taken out of it. + return make_error<ImportError>(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<ImportError>(*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<ImportError>(*Error); + } + + // Make sure that ImportImpl registered the imported decl. + assert(ImportedDecls.count(FromD) != 0 && "Missing call to MapImported?"); + + // Notify subclasses. + Imported(FromD, ToD); + + updateFlags(FromD, ToD); + SavedImportPaths[FromD].clear(); + return ToDOrErr; +} + +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()) { + // Do nothing. + } else if (FromRecord->isCompleteDefinition()) { + if (Error Err = ASTNodeImporter(*this).ImportDefinition( + FromRecord, ToRecord, ASTNodeImporter::IDK_Basic)) + return std::move(Err); + } else { + CompleteDecl(ToRecord); + } + } 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->setTypeDependent(FromE->isTypeDependent()); + ToE->setValueDependent(FromE->isValueDependent()); + ToE->setInstantiationDependent(FromE->isInstantiationDependent()); + ToE->setContainsUnexpandedParameterPack( + FromE->containsUnexpandedParameterPack()); + } + + // 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<NamespaceDecl>(*NSOrErr)); + } else + return NSOrErr.takeError(); + + case NestedNameSpecifier::NamespaceAlias: + if (ExpectedDecl NSADOrErr = Import(FromNNS->getAsNamespaceAlias())) + return NestedNameSpecifier::Create(ToContext, Prefix, + cast<NamespaceAliasDecl>(*NSADOrErr)); + else + return NSADOrErr.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: + case NestedNameSpecifier::TypeSpecWithTemplate: + if (Expected<QualType> TyOrErr = + Import(QualType(FromNNS->getAsType(), 0u))) { + bool TSTemplate = + FromNNS->getKind() == NestedNameSpecifier::TypeSpecWithTemplate; + return NestedNameSpecifier::Create(ToContext, Prefix, TSTemplate, + TyOrErr->getTypePtr()); + } 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::NamespaceAlias: + Builder.Extend(getToContext(), Spec->getAsNamespaceAlias(), + ToLocalBeginLoc, ToLocalEndLoc); + break; + + case NestedNameSpecifier::TypeSpec: + case NestedNameSpecifier::TypeSpecWithTemplate: { + 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(), ToLocalBeginLoc, 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)); + 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(); + + if (ExpectedDecl ToTemplateOrErr = Import(From.getAsTemplateDecl())) + return ToContext.getQualifiedTemplateName( + *QualifierOrErr, QTN->hasTemplateKeyword(), + cast<TemplateDecl>(*ToTemplateOrErr)); + else + return ToTemplateOrErr.takeError(); + } + + case TemplateName::DependentTemplate: { + DependentTemplateName *DTN = From.getAsDependentTemplateName(); + auto QualifierOrErr = Import(DTN->getQualifier()); + if (!QualifierOrErr) + return QualifierOrErr.takeError(); + + if (DTN->isIdentifier()) { + return ToContext.getDependentTemplateName(*QualifierOrErr, + Import(DTN->getIdentifier())); + } + + return ToContext.getDependentTemplateName(*QualifierOrErr, + DTN->getOperator()); + } + + case TemplateName::SubstTemplateTemplateParm: { + SubstTemplateTemplateParmStorage *Subst = + From.getAsSubstTemplateTemplateParm(); + ExpectedDecl ParamOrErr = Import(Subst->getParameter()); + if (!ParamOrErr) + return ParamOrErr.takeError(); + + auto ReplacementOrErr = Import(Subst->getReplacement()); + if (!ReplacementOrErr) + return ReplacementOrErr.takeError(); + + return ToContext.getSubstTemplateTemplateParm( + cast<TemplateTemplateParmDecl>(*ParamOrErr), *ReplacementOrErr); + } + + case TemplateName::SubstTemplateTemplateParmPack: { + SubstTemplateTemplateParmPackStorage *SubstPack + = From.getAsSubstTemplateTemplateParmPack(); + ExpectedDecl ParamOrErr = Import(SubstPack->getParameterPack()); + if (!ParamOrErr) + return ParamOrErr.takeError(); + + ASTNodeImporter Importer(*this); + auto ArgPackOrErr = + Importer.ImportTemplateArgument(SubstPack->getArgumentPack()); + if (!ArgPackOrErr) + return ArgPackOrErr.takeError(); + + return ToContext.getSubstTemplateTemplateParmPack( + cast<TemplateTemplateParmDecl>(*ParamOrErr), *ArgPackOrErr); + } + } + + 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); + + std::pair<FileID, unsigned> 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 TokenLen = FromSM.getFileIDSize(FromID); + SourceLocation MLoc; + if (FromEx.isMacroArgExpansion()) { + MLoc = ToSM.createMacroArgExpansionLoc(*ToSpLoc, *ToExLocS, TokenLen); + } else { + if (ExpectedSLoc ToExLocE = Import(FromEx.getExpansionLocEnd())) + MLoc = ToSM.createExpansionLoc(*ToSpLoc, *ToExLocS, *ToExLocE, TokenLen, + FromEx.isExpansionTokenRange()); + else + return ToExLocE.takeError(); + } + ToID = ToSM.getFileID(MLoc); + } else { + const SrcMgr::ContentCache *Cache = FromSLoc.getFile().getContentCache(); + + if (!IsBuiltin) { + // Include location of this file. + ExpectedSLoc ToIncludeLoc = Import(FromSLoc.getFile().getIncludeLoc()); + if (!ToIncludeLoc) + return ToIncludeLoc.takeError(); + + if (Cache->OrigEntry && Cache->OrigEntry->getDir()) { + // FIXME: We probably want to use getVirtualFile(), 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.getFile(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, *ToIncludeLoc, + FromSLoc.getFile().getFileCharacteristic()); + } + } + + if (ToID.isInvalid() || IsBuiltin) { + // FIXME: We want to re-use the existing MemoryBuffer! + bool Invalid = true; + const llvm::MemoryBuffer *FromBuf = + Cache->getBuffer(FromContext.getDiagnostics(), + FromSM.getFileManager(), SourceLocation{}, &Invalid); + if (!FromBuf || Invalid) + // FIXME: Use a new error kind? + return llvm::make_error<ImportError>(ImportError::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; + + if (FileIDImportHandler) + FileIDImportHandler(ToID, FromID); + + 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<ImportError>(); + } +} + +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; +} + +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; +} + +Expected<Selector> ASTImporter::Import(Selector FromSel) { + if (FromSel.isNull()) + return Selector{}; + + SmallVector<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()); +} + +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<ImportError>(ImportError::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) { + llvm::DenseMap<Decl *, Decl *>::iterator Pos = ImportedDecls.find(From); + assert((Pos == ImportedDecls.end() || Pos->second == To) && + "Try to import an already imported Decl"); + if (Pos != ImportedDecls.end()) + return Pos->second; + ImportedDecls[From] = To; + // This mapping should be maintained only in this function. Therefore do not + // check for additional consistency. + ImportedFromDecls[To] = From; + AddToLookupTable(To); + return To; +} + +llvm::Optional<ImportError> +ASTImporter::getImportDeclErrorIfAny(Decl *FromD) const { + auto Pos = ImportDeclErrors.find(FromD); + if (Pos != ImportDeclErrors.end()) + return Pos->second; + else + return Optional<ImportError>(); +} + +void ASTImporter::setImportDeclError(Decl *From, ImportError 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(FromContext, ToContext, NonEquivalentDecls, + getStructuralEquivalenceKind(*this), false, + Complain); + return Ctx.IsEquivalent(From, To); +} |
