//===- 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 #include #include #include #include #include namespace clang { using llvm::make_error; using llvm::Error; using llvm::Expected; using ExpectedType = llvm::Expected; using ExpectedStmt = llvm::Expected; using ExpectedExpr = llvm::Expected; using ExpectedDecl = llvm::Expected; using ExpectedSLoc = llvm::Expected; using ExpectedName = llvm::Expected; 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 SmallVector getCanonicalForwardRedeclChain(Redeclarable* D) { SmallVector 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 getCanonicalForwardRedeclChain(Decl* D) { if (auto *FD = dyn_cast(D)) return getCanonicalForwardRedeclChain(FD); if (auto *VD = dyn_cast(D)) return getCanonicalForwardRedeclChain(VD); if (auto *TD = dyn_cast(D)) return getCanonicalForwardRedeclChain(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, public DeclVisitor, public StmtVisitor { ASTImporter &Importer; // Use this instead of Importer.importInto . template LLVM_NODISCARD Error importInto(ImportT &To, const ImportT &From) { return Importer.importInto(To, From); } // Use this to import pointers of specific type. template LLVM_NODISCARD Error importInto(ImportT *&To, ImportT *From) { auto ToOrErr = Importer.Import(From); if (ToOrErr) To = cast_or_null(*ToOrErr); return ToOrErr.takeError(); } // Call the import function of ASTImporter for a baseclass of type `T` and // cast the return value to `T`. template Expected import(T *From) { auto ToOrErr = Importer.Import(From); if (!ToOrErr) return ToOrErr.takeError(); return cast_or_null(*ToOrErr); } template Expected import(const T *From) { return import(const_cast(From)); } // Call the import function of ASTImporter for type `T`. template Expected import(const T &From) { return Importer.Import(From); } // Import an Optional by importing the contained T, if any. template Expected> import(Optional From) { if (!From) return Optional(); return import(*From); } template Expected> importSeq(const T &From) { Expected ToOrErr = import(From); if (!ToOrErr) return ToOrErr.takeError(); return std::make_tuple(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 Expected> importSeq(const THead &FromHead, const TTail &...FromTail) { Expected> ToHeadOrErr = importSeq(FromHead); if (!ToHeadOrErr) return ToHeadOrErr.takeError(); Expected> ToTailOrErr = importSeq(FromTail...); if (!ToTailOrErr) return ToTailOrErr.takeError(); return std::tuple_cat(*ToHeadOrErr, *ToTailOrErr); } // Wrapper for an overload set. template struct CallOverloadedCreateFun { template auto operator()(Args &&... args) -> decltype(ToDeclT::Create(std::forward(args)...)) { return ToDeclT::Create(std::forward(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 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 OC; return GetImportedOrCreateSpecialDecl(ToD, OC, FromD, std::forward(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(ToTypedef, FromD, ...); template LLVM_NODISCARD bool GetImportedOrCreateDecl(ToDeclT *&ToD, FromDeclT *FromD, Args &&... args) { CallOverloadedCreateFun OC; return GetImportedOrCreateSpecialDecl(ToD, OC, FromD, std::forward(args)...); } // Use this version if a special create function must be // used, e.g. CXXRecordDecl::CreateLambda . template 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(Importer.GetAlreadyImportedOrNull(FromD)); if (ToD) return true; // Already imported. ToD = CreateFun(std::forward(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(Definition)); return nullptr; } public: explicit ASTNodeImporter(ASTImporter &Importer) : Importer(Importer) {} using TypeVisitor::Visit; using DeclVisitor::Visit; using StmtVisitor::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 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 &ToArgs); Expected ImportTemplateArgument(const TemplateArgument &From); template Error ImportTemplateArgumentListInfo( const InContainerTy &Container, TemplateArgumentListInfo &ToTAInfo); template Error ImportTemplateArgumentListInfo( SourceLocation FromLAngleLoc, SourceLocation FromRAngleLoc, const InContainerTy &Container, TemplateArgumentListInfo &Result); using TemplateArgsTy = SmallVector; using FunctionTemplateAndArgsTy = std::tuple; Expected 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 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 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 Error ImportArrayChecked(IIter Ibegin, IIter Iend, OIter Obegin) { using ItemT = typename std::remove_reference::type; for (; Ibegin != Iend; ++Ibegin, ++Obegin) { Expected 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 Error ImportContainerChecked( const InContainerTy &InContainer, OutContainerTy &OutContainer) { return ImportArrayChecked( InContainer.begin(), InContainer.end(), OutContainer.begin()); } template Error ImportArrayChecked(const InContainerTy &InContainer, OIter Obegin) { return ImportArrayChecked(InContainer.begin(), InContainer.end(), Obegin); } Error ImportOverriddenMethods(CXXMethodDecl *ToMethod, CXXMethodDecl *FromMethod); Expected FindFunctionTemplateSpecialization( FunctionDecl *FromFD); }; template 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( 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::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 ASTNodeImporter::import(TemplateParameterList *From) { SmallVector 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 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 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 ToTemplateOrErr = import(From.getAsTemplate()); if (!ToTemplateOrErr) return ToTemplateOrErr.takeError(); return TemplateArgument(*ToTemplateOrErr); } case TemplateArgument::TemplateExpansion: { Expected 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 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 ASTNodeImporter::import(const TemplateArgumentLoc &TALoc) { Expected 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 ASTNodeImporter::import(const DeclGroupRef &DG) { if (DG.isNull()) return DeclGroupRef::Create(Importer.getToContext(), nullptr, 0); size_t NumDecls = DG.end() - DG.begin(); SmallVector 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::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 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 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::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) { ExpectedType ToElementTypeOrErr = import(T->getElementType()); if (!ToElementTypeOrErr) return ToElementTypeOrErr.takeError(); return Importer.getToContext().getConstantArrayType(*ToElementTypeOrErr, T->getSize(), 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 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 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(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 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 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 ToDeclOrErr = import(T->getDecl()); if (!ToDeclOrErr) return ToDeclOrErr.takeError(); return Importer.getToContext().getTagDeclType(*ToDeclOrErr); } ExpectedType ASTNodeImporter::VisitEnumType(const EnumType *T) { Expected 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 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((*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 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 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 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 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 TypeArgs; for (auto TypeArg : T->getTypeArgsAsWritten()) { if (ExpectedType TyOrErr = import(TypeArg)) TypeArgs.push_back(*TyOrErr); else return TyOrErr.takeError(); } SmallVector Protocols; for (auto *P : T->quals()) { if (Expected 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(D) && (FunDecl = dyn_cast(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(LeafT); if (RT && RT->getDecl() == D) { Importer.FromDiag(D->getLocation(), diag::err_unsupported_ast_node) << D->getDeclKindName(); return make_error(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(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(FromD)) { if (RecordDecl *ToRecord = cast(ToD)) { if (FromRecord->getDefinition() && FromRecord->isCompleteDefinition() && !ToRecord->getDefinition()) { if (Error Err = ImportDefinition(FromRecord, ToRecord)) return Err; } } return Error::success(); } if (EnumDecl *FromEnum = dyn_cast(FromD)) { if (EnumDecl *ToEnum = cast(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(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(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(D) || isa(D) || isa(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 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(*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(To); auto *FromCXX = dyn_cast(From); if (ToCXX && FromCXX && ToCXX->dataPtr() && FromCXX->dataPtr()) { struct CXXRecordDecl::DefinitionData &ToData = ToCXX->data(); struct CXXRecordDecl::DefinitionData &FromData = FromCXX->data(); ToData.UserDeclaredConstructor = FromData.UserDeclaredConstructor; ToData.UserDeclaredSpecialMembers = FromData.UserDeclaredSpecialMembers; ToData.Aggregate = FromData.Aggregate; ToData.PlainOldData = FromData.PlainOldData; ToData.Empty = FromData.Empty; ToData.Polymorphic = FromData.Polymorphic; ToData.Abstract = FromData.Abstract; ToData.IsStandardLayout = FromData.IsStandardLayout; ToData.IsCXX11StandardLayout = FromData.IsCXX11StandardLayout; ToData.HasBasesWithFields = FromData.HasBasesWithFields; ToData.HasBasesWithNonStaticDataMembers = FromData.HasBasesWithNonStaticDataMembers; ToData.HasPrivateFields = FromData.HasPrivateFields; ToData.HasProtectedFields = FromData.HasProtectedFields; ToData.HasPublicFields = FromData.HasPublicFields; ToData.HasMutableFields = FromData.HasMutableFields; ToData.HasVariantMembers = FromData.HasVariantMembers; ToData.HasOnlyCMembers = FromData.HasOnlyCMembers; ToData.HasInClassInitializer = FromData.HasInClassInitializer; ToData.HasUninitializedReferenceMember = FromData.HasUninitializedReferenceMember; ToData.HasUninitializedFields = FromData.HasUninitializedFields; ToData.HasInheritedConstructor = FromData.HasInheritedConstructor; ToData.HasInheritedAssignment = FromData.HasInheritedAssignment; ToData.NeedOverloadResolutionForCopyConstructor = FromData.NeedOverloadResolutionForCopyConstructor; ToData.NeedOverloadResolutionForMoveConstructor = FromData.NeedOverloadResolutionForMoveConstructor; ToData.NeedOverloadResolutionForMoveAssignment = FromData.NeedOverloadResolutionForMoveAssignment; ToData.NeedOverloadResolutionForDestructor = FromData.NeedOverloadResolutionForDestructor; ToData.DefaultedCopyConstructorIsDeleted = FromData.DefaultedCopyConstructorIsDeleted; ToData.DefaultedMoveConstructorIsDeleted = FromData.DefaultedMoveConstructorIsDeleted; ToData.DefaultedMoveAssignmentIsDeleted = FromData.DefaultedMoveAssignmentIsDeleted; ToData.DefaultedDestructorIsDeleted = FromData.DefaultedDestructorIsDeleted; ToData.HasTrivialSpecialMembers = FromData.HasTrivialSpecialMembers; ToData.HasIrrelevantDestructor = FromData.HasIrrelevantDestructor; ToData.HasConstexprNonCopyMoveConstructor = FromData.HasConstexprNonCopyMoveConstructor; ToData.HasDefaultedDefaultConstructor = FromData.HasDefaultedDefaultConstructor; ToData.DefaultedDefaultConstructorIsConstexpr = FromData.DefaultedDefaultConstructorIsConstexpr; ToData.HasConstexprDefaultConstructor = FromData.HasConstexprDefaultConstructor; ToData.HasNonLiteralTypeFieldsOrBases = FromData.HasNonLiteralTypeFieldsOrBases; // ComputedVisibleConversions not imported. ToData.UserProvidedDefaultConstructor = FromData.UserProvidedDefaultConstructor; ToData.DeclaredSpecialMembers = FromData.DeclaredSpecialMembers; ToData.ImplicitCopyConstructorCanHaveConstParamForVBase = FromData.ImplicitCopyConstructorCanHaveConstParamForVBase; ToData.ImplicitCopyConstructorCanHaveConstParamForNonVBase = FromData.ImplicitCopyConstructorCanHaveConstParamForNonVBase; ToData.ImplicitCopyAssignmentHasConstParam = FromData.ImplicitCopyAssignmentHasConstParam; ToData.HasDeclaredCopyConstructorWithConstParam = FromData.HasDeclaredCopyConstructorWithConstParam; ToData.HasDeclaredCopyAssignmentWithConstParam = FromData.HasDeclaredCopyAssignmentWithConstParam; // Copy over the data stored in RecordDeclBits ToCXX->setArgPassingRestrictions(FromCXX->getArgPassingRestrictions()); SmallVector 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 &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 ASTNodeImporter::ImportTemplateArgument(const TemplateArgument &From) { return import(From); } template 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(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(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::UnsupportedConstruct); } ExpectedDecl ASTNodeImporter::VisitImportDecl(ImportDecl *D) { Importer.FromDiag(D->getLocation(), diag::err_unsupported_ast_node) << D->getDeclKindName(); return make_error(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(DC)) MergeWithNamespace = TU->getAnonymousNamespace(); else MergeWithNamespace = cast(DC)->getAnonymousNamespace(); } else { SmallVector ConflictingDecls; auto FoundDecls = Importer.findDeclsInToCtx(DC, Name); for (auto *FoundDecl : FoundDecls) { if (!FoundDecl->isInIdentifierNamespace(Decl::IDNS_Namespace)) continue; if (auto *FoundNS = dyn_cast(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(DC)) TU->setAnonymousNamespace(ToNamespace); else cast(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 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(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( ToTypedef, D, Importer.getToContext(), DC, ToBeginLoc, Loc, Name.getAsIdentifierInfo(), ToTypeSourceInfo)) return ToTypedef; } else if (GetImportedOrCreateDecl( 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(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 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(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 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 ConflictingDecls; auto FoundDecls = Importer.findDeclsInToCtx(DC, SearchName); for (auto *FoundDecl : FoundDecls) { if (!FoundDecl->isInIdentifierNamespace(IDNS)) continue; if (auto *Typedef = dyn_cast(FoundDecl)) { if (const auto *Tag = Typedef->getUnderlyingType()->getAs()) FoundDecl = Tag->getDecl(); } if (auto *FoundEnum = dyn_cast(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(D)) { IsFriendTemplate = DCXX->getDescribedClassTemplate() && DCXX->getDescribedClassTemplate()->getFriendObjectKind() != Decl::FOK_None; } // Import the major distinguishing characteristics of this record. 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 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 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(Found)) { if (const auto *Tag = Typedef->getUnderlyingType()->getAs()) Found = Tag->getDecl(); } if (auto *FoundRecord = dyn_cast(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(D)) { auto *FoundCXX = dyn_cast(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(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); } 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(PrevDecl), DelayTypeCreation)) return D2CXX; Importer.getToContext().getTypeDeclType( D2CXX, dyn_cast(DC)); } else { if (GetImportedOrCreateDecl(D2CXX, D, Importer.getToContext(), D->getTagKind(), DC, *BeginLocOrErr, Loc, Name.getAsIdentifierInfo(), cast_or_null(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(Found); if (Record && Record->isInjectedClassName()) { Injected = Record; break; } } // Create an injected type for the whole redecl chain. SmallVector Redecls = getCanonicalForwardRedeclChain(D2CXX); for (auto *R : Redecls) { auto *RI = cast(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 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 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(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(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 ToTPLists(Num); for (unsigned int I = 0; I < Num; ++I) if (Expected 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 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 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 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 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 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(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(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::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 Parameters; for (auto P : D->parameters()) { if (Expected ToPOrErr = import(P)) Parameters.push_back(*ToPOrErr); else return ToPOrErr.takeError(); } // Create the imported function. FunctionDecl *ToFunction = nullptr; if (auto *FromConstructor = dyn_cast(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( ToFunction, D, Importer.getToContext(), cast(DC), ToInnerLocStart, NameInfo, T, TInfo, ExplicitSpecifier( ExplicitExpr, FromConstructor->getExplicitSpecifier().getKind()), D->isInlineSpecified(), D->isImplicit(), D->getConstexprKind())) return ToFunction; } else if (CXXDestructorDecl *FromDtor = dyn_cast(D)) { auto Imp = importSeq(const_cast(FromDtor->getOperatorDelete()), FromDtor->getOperatorDeleteThisArg()); if (!Imp) return Imp.takeError(); FunctionDecl *ToOperatorDelete; Expr *ToThisArg; std::tie(ToOperatorDelete, ToThisArg) = *Imp; if (GetImportedOrCreateDecl( ToFunction, D, Importer.getToContext(), cast(DC), ToInnerLocStart, NameInfo, T, TInfo, D->isInlineSpecified(), D->isImplicit())) return ToFunction; CXXDestructorDecl *ToDtor = cast(ToFunction); ToDtor->setOperatorDelete(ToOperatorDelete, ToThisArg); } else if (CXXConversionDecl *FromConversion = dyn_cast(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( ToFunction, D, Importer.getToContext(), cast(DC), ToInnerLocStart, NameInfo, T, TInfo, D->isInlineSpecified(), ExplicitSpecifier(ExplicitExpr, FromConversion->getExplicitSpecifier().getKind()), D->getConstexprKind(), SourceLocation())) return ToFunction; } else if (auto *Method = dyn_cast(D)) { if (GetImportedOrCreateDecl( ToFunction, D, Importer.getToContext(), cast(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( 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()) { 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(D)) { if (unsigned NumInitializers = FromConstructor->getNumCtorInitializers()) { SmallVector 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(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(D)) if (Error Err = ImportOverriddenMethods(cast(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(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::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(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::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 ToD = import(PI)) NamedChain[i++] = *ToD; else return ToD.takeError(); llvm::MutableArrayRef 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(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 ToTPLists(D->NumTPLists); auto **FromTPLists = D->getTrailingObjects(); for (unsigned I = 0; I < D->NumTPLists; I++) { if (auto ListOrErr = import(FromTPLists[I])) ToTPLists[I] = *ListOrErr; else return ListOrErr.takeError(); } auto LocationOrErr = import(D->getLocation()); if (!LocationOrErr) return LocationOrErr.takeError(); auto FriendLocOrErr = import(D->getFriendLoc()); if (!FriendLocOrErr) return FriendLocOrErr.takeError(); 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(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::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(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 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 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(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(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(FoundArray) && isa(TArray)) { // Import the type. if (auto TyOrErr = import(D->getType())) FoundVar->setType(*TyOrErr); else return TyOrErr.takeError(); FoundByLookup = FoundVar; break; } else if (isa(TArray) && isa(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(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(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::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::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::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::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 ToParams; for (auto *FromP : D->parameters()) { if (Expected 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 FromSelLocs; D->getSelectorLocs(FromSelLocs); SmallVector 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 Protocols; SmallVector 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 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 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 Protocols; SmallVector 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 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(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 ToPatternOrErr = import(FromPattern)) Importer.getToContext().setInstantiatedFromUsingDecl( ToUsing, *ToPatternOrErr); else return ToPatternOrErr.takeError(); } for (UsingShadowDecl *FromShadow : D->shadows()) { if (Expected 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 ToUsingOrErr = import(D->getUsingDecl()); if (!ToUsingOrErr) return ToUsingOrErr.takeError(); Expected 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 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 Protocols; SmallVector 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 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 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 ASTNodeImporter::ImportObjCTypeParamList(ObjCTypeParamList *list) { if (!list) return nullptr; SmallVector 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(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::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(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::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(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::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::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 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(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 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(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(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 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(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::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( D2, D, Importer.getToContext(), D->getTagKind(), DC, *BeginLocOrErr, *IdLocOrErr, *ToTPListOrErr, ClassTemplate, llvm::makeArrayRef(TemplateArgs.data(), TemplateArgs.size()), ToTAInfo, CanonInjType, cast_or_null(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(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(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 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(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 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(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 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(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(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::UnsupportedConstruct); } ExpectedStmt ASTNodeImporter::VisitGCCAsmStmt(GCCAsmStmt *S) { if (Importer.returnWithErrorInTest()) return make_error(ImportError::UnsupportedConstruct); SmallVector 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 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 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 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 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 FromAttrs(S->getAttrs()); SmallVector 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 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 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 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::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 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 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 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 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 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 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 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 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 ToBasePathOrErr = ImportCastPath(E); if (!ToBasePathOrErr) return ToBasePathOrErr.takeError(); CXXCastPath *ToBasePath = &(*ToBasePathOrErr); switch (E->getStmtClass()) { case Stmt::CStyleCastExprClass: { auto *CCE = cast(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(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(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::UnsupportedConstruct); } } ExpectedStmt ASTNodeImporter::VisitOffsetOfExpr(OffsetOfExpr *E) { SmallVector 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 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 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 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 Length; if (!E->isValueDependent()) Length = E->getPackLength(); SmallVector 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 ToArraySize; Expr *ToInitializer; QualType ToType; TypeSourceInfo *ToAllocatedTypeSourceInfo; std::tie( ToOperatorNew, ToOperatorDelete, ToTypeIdParens, ToArraySize, ToInitializer, ToType, ToAllocatedTypeSourceInfo, ToSourceRange, ToDirectInitRange) = *Imp; SmallVector 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 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 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 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 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 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(*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(*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 ToArgs(NumArgs); if (Error Err = ImportContainerChecked(E->arguments(), ToArgs)) return std::move(Err); if (const auto *OCE = dyn_cast(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 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 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 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(E)) { return CXXStaticCastExpr::Create( Importer.getToContext(), ToType, VK, CK, ToSubExpr, &(*ToBasePathOrErr), ToTypeInfoAsWritten, ToOperatorLoc, ToRParenLoc, ToAngleBrackets); } else if (isa(E)) { return CXXDynamicCastExpr::Create( Importer.getToContext(), ToType, VK, CK, ToSubExpr, &(*ToBasePathOrErr), ToTypeInfoAsWritten, ToOperatorLoc, ToRParenLoc, ToAngleBrackets); } else if (isa(E)) { return CXXReinterpretCastExpr::Create( Importer.getToContext(), ToType, VK, CK, ToSubExpr, &(*ToBasePathOrErr), ToTypeInfoAsWritten, ToOperatorLoc, ToRParenLoc, ToAngleBrackets); } else if (isa(E)) { return CXXConstCastExpr::Create( Importer.getToContext(), ToType, VK, ToSubExpr, ToTypeInfoAsWritten, ToOperatorLoc, ToRParenLoc, ToAngleBrackets); } else { llvm_unreachable("Unknown cast type"); return make_error(); } } 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 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( (*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 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(); } ImportedDecls[FromContext.getTranslationUnitDecl()] = ToContext.getTranslationUnitDecl(); } ASTImporter::~ASTImporter() = default; Optional ASTImporter::getFieldIndex(Decl *F) { assert(F && (isa(*F) || isa(*F)) && "Try to get field index for non-field."); auto *Owner = dyn_cast(F->getDeclContext()); if (!Owner) return None; unsigned Index = 0; for (const auto *D : Owner->decls()) { if (D == F) return Index; if (isa(*D) || isa(*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 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 ASTImporter::Import(QualType FromT) { if (FromT.isNull()) return QualType{}; const Type *FromTy = FromT.getTypePtr(); // Check whether we've already imported this type. llvm::DenseMap::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 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 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 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(*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(*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(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(*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(*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 ASTImporter::ImportContext(DeclContext *FromDC) { if (!FromDC) return FromDC; ExpectedDecl ToDCOrErr = Import(cast(FromDC)); if (!ToDCOrErr) return ToDCOrErr.takeError(); auto *ToDC = cast(*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(ToDC)) { auto *FromRecord = cast(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(ToDC)) { auto *FromEnum = cast(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(ToDC)) { auto *FromClass = cast(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(ToDC)) { auto *FromProto = cast(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 ASTImporter::Import(Expr *FromE) { if (ExpectedStmt ToSOrErr = Import(cast_or_null(FromE))) return cast_or_null(*ToSOrErr); else return ToSOrErr.takeError(); } Expected ASTImporter::Import(Stmt *FromS) { if (!FromS) return nullptr; // Check whether we've already imported this statement. llvm::DenseMap::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(*ToSOrErr)) { auto *FromE = cast(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 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(*NSOrErr)); } else return NSOrErr.takeError(); case NestedNameSpecifier::NamespaceAlias: if (ExpectedDecl NSADOrErr = Import(FromNNS->getAsNamespaceAlias())) return NestedNameSpecifier::Create(ToContext, Prefix, cast(*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(*RDOrErr)); else return RDOrErr.takeError(); case NestedNameSpecifier::TypeSpec: case NestedNameSpecifier::TypeSpecWithTemplate: if (Expected 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 ASTImporter::Import(NestedNameSpecifierLoc FromNNS) { // Copied from NestedNameSpecifier mostly. SmallVector 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 ASTImporter::Import(TemplateName From) { switch (From.getKind()) { case TemplateName::Template: if (ExpectedDecl ToTemplateOrErr = Import(From.getAsTemplateDecl())) return TemplateName(cast(*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(*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(*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(*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(*ParamOrErr), *ArgPackOrErr); } } llvm_unreachable("Invalid template name kind"); } Expected ASTImporter::Import(SourceLocation FromLoc) { if (FromLoc.isInvalid()) return SourceLocation{}; SourceManager &FromSM = FromContext.getSourceManager(); bool IsBuiltin = FromSM.isWrittenInBuiltinFile(FromLoc); std::pair Decomposed = FromSM.getDecomposedLoc(FromLoc); Expected ToFileIDOrErr = Import(Decomposed.first, IsBuiltin); if (!ToFileIDOrErr) return ToFileIDOrErr.takeError(); SourceManager &ToSM = ToContext.getSourceManager(); return ToSM.getComposedLoc(*ToFileIDOrErr, Decomposed.second); } Expected 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 ASTImporter::Import(FileID FromID, bool IsBuiltin) { llvm::DenseMap::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::Unknown); std::unique_ptr 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 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(*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(*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(); } } Expected ASTImporter::Import(const CXXBaseSpecifier *BaseSpec) { auto Pos = ImportedCXXBaseSpecifiers.find(BaseSpec); if (Pos != ImportedCXXBaseSpecifiers.end()) return Pos->second; Expected ToSourceRange = Import(BaseSpec->getSourceRange()); if (!ToSourceRange) return ToSourceRange.takeError(); Expected 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(From); ASTNodeImporter Importer(*this); if (auto *ToRecord = dyn_cast(To)) { if (!ToRecord->getDefinition()) { return Importer.ImportDefinition( cast(FromDC), ToRecord, ASTNodeImporter::IDK_Everything); } } if (auto *ToEnum = dyn_cast(To)) { if (!ToEnum->getDefinition()) { return Importer.ImportDefinition( cast(FromDC), ToEnum, ASTNodeImporter::IDK_Everything); } } if (auto *ToIFace = dyn_cast(To)) { if (!ToIFace->getDefinition()) { return Importer.ImportDefinition( cast(FromDC), ToIFace, ASTNodeImporter::IDK_Everything); } } if (auto *ToProto = dyn_cast(To)) { if (!ToProto->getDefinition()) { return Importer.ImportDefinition( cast(FromDC), ToProto, ASTNodeImporter::IDK_Everything); } } return Importer.ImportDeclContext(FromDC, true); } Expected 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(*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 ASTImporter::Import(Selector FromSel) { if (FromSel.isNull()) return Selector{}; SmallVector 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 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::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(D)) { if (!ID->getDefinition()) ID->startDefinition(); } else if (auto *PD = dyn_cast(D)) { if (!PD->getDefinition()) PD->startDefinition(); } else if (auto *TD = dyn_cast(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::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 ASTImporter::getImportDeclErrorIfAny(Decl *FromD) const { auto Pos = ImportDeclErrors.find(FromD); if (Pos != ImportDeclErrors.end()) return Pos->second; else return Optional(); } 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::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); }