//===- ASTImporter.cpp - Importing ASTs from other Contexts ---------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file defines the ASTImporter class which imports AST nodes from one // context into another context. // //===----------------------------------------------------------------------===// #include "clang/AST/ASTImporter.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ASTDiagnostic.h" #include "clang/AST/ASTImporterSharedState.h" #include "clang/AST/ASTStructuralEquivalence.h" #include "clang/AST/Attr.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclAccessPair.h" #include "clang/AST/DeclBase.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclFriend.h" #include "clang/AST/DeclGroup.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/DeclVisitor.h" #include "clang/AST/DeclarationName.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/ExternalASTSource.h" #include "clang/AST/LambdaCapture.h" #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/OperationKinds.h" #include "clang/AST/Stmt.h" #include "clang/AST/StmtCXX.h" #include "clang/AST/StmtObjC.h" #include "clang/AST/StmtVisitor.h" #include "clang/AST/TemplateBase.h" #include "clang/AST/TemplateName.h" #include "clang/AST/Type.h" #include "clang/AST/TypeLoc.h" #include "clang/AST/TypeVisitor.h" #include "clang/AST/UnresolvedSet.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/ExceptionSpecificationType.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/LangOptions.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/Specifiers.h" #include "llvm/ADT/APSInt.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/ScopeExit.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MemoryBuffer.h" #include #include #include #include #include #include #include namespace clang { using llvm::make_error; using llvm::Error; using llvm::Expected; using ExpectedTypePtr = 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 ASTImportError::toString() const { // FIXME: Improve error texts. switch (Error) { case NameConflict: return "NameConflict"; case UnsupportedConstruct: return "UnsupportedConstruct"; case Unknown: return "Unknown error"; } llvm_unreachable("Invalid error code."); return "Invalid error code."; } void ASTImportError::log(raw_ostream &OS) const { OS << toString(); } std::error_code ASTImportError::convertToErrorCode() const { llvm_unreachable("Function not implemented."); } char ASTImportError::ID; template 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(); } /// How to handle import errors that occur when import of a child declaration /// of a DeclContext fails. class ChildErrorHandlingStrategy { /// This context is imported (in the 'from' domain). /// It is nullptr if a non-DeclContext is imported. const DeclContext *const FromDC; /// Ignore import errors of the children. /// If true, the context can be imported successfully if a child /// of it failed to import. Otherwise the import errors of the child nodes /// are accumulated (joined) into the import error object of the parent. /// (Import of a parent can fail in other ways.) bool const IgnoreChildErrors; public: ChildErrorHandlingStrategy(const DeclContext *FromDC) : FromDC(FromDC), IgnoreChildErrors(!isa(FromDC)) {} ChildErrorHandlingStrategy(const Decl *FromD) : FromDC(dyn_cast(FromD)), IgnoreChildErrors(!isa(FromD)) {} /// Process the import result of a child (of the current declaration). /// \param ResultErr The import error that can be used as result of /// importing the parent. This may be changed by the function. /// \param ChildErr Result of importing a child. Can be success or error. void handleChildImportResult(Error &ResultErr, Error &&ChildErr) { if (ChildErr && !IgnoreChildErrors) ResultErr = joinErrors(std::move(ResultErr), std::move(ChildErr)); else consumeError(std::move(ChildErr)); } /// Determine if import failure of a child does not cause import failure of /// its parent. bool ignoreChildErrorOnParent(Decl *FromChildD) const { if (!IgnoreChildErrors || !FromDC) return false; return FromDC->containsDecl(FromChildD); } }; class ASTNodeImporter : public TypeVisitor, public DeclVisitor, public StmtVisitor { ASTImporter &Importer; // Use this instead of Importer.importInto . template [[nodiscard]] Error importInto(ImportT &To, const ImportT &From) { return Importer.importInto(To, From); } // Use this to import pointers of specific type. template [[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 auto import(T *From) -> std::conditional_t, Expected, Expected> { auto ToOrErr = Importer.Import(From); if (!ToOrErr) return ToOrErr.takeError(); return cast_or_null(*ToOrErr); } template auto 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 std::optional by importing the contained T, if any. template Expected> import(std::optional From) { if (!From) return std::nullopt; return import(*From); } ExplicitSpecifier importExplicitSpecifier(Error &Err, ExplicitSpecifier ESpec); // Wrapper for an overload set. template struct CallOverloadedCreateFun { template decltype(auto) operator()(Args &&... 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 [[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 [[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 [[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); Importer.SharedState->markAsNewDecl(ToD); InitializeImportedDecl(FromD, ToD); return false; // A new Decl is created. } void InitializeImportedDecl(Decl *FromD, Decl *ToD) { ToD->IdentifierNamespace = FromD->IdentifierNamespace; if (FromD->isUsed()) ToD->setIsUsed(); if (FromD->isImplicit()) ToD->setImplicit(); } // Check if we have found an existing definition. Returns with that // definition if yes, otherwise returns null. Decl *FindAndMapDefinition(FunctionDecl *D, FunctionDecl *FoundFunction) { const FunctionDecl *Definition = nullptr; if (D->doesThisDeclarationHaveABody() && FoundFunction->hasBody(Definition)) return Importer.MapImported(D, const_cast(Definition)); return nullptr; } void addDeclToContexts(Decl *FromD, Decl *ToD) { if (Importer.isMinimalImport()) { // In minimal import case the decl must be added even if it is not // contained in original context, for LLDB compatibility. // FIXME: Check if a better solution is possible. if (!FromD->getDescribedTemplate() && FromD->getFriendObjectKind() == Decl::FOK_None) ToD->getLexicalDeclContext()->addDeclInternal(ToD); return; } DeclContext *FromDC = FromD->getDeclContext(); DeclContext *FromLexicalDC = FromD->getLexicalDeclContext(); DeclContext *ToDC = ToD->getDeclContext(); DeclContext *ToLexicalDC = ToD->getLexicalDeclContext(); bool Visible = false; if (FromDC->containsDeclAndLoad(FromD)) { ToDC->addDeclInternal(ToD); Visible = true; } if (ToDC != ToLexicalDC && FromLexicalDC->containsDeclAndLoad(FromD)) { ToLexicalDC->addDeclInternal(ToD); Visible = true; } // If the Decl was added to any context, it was made already visible. // Otherwise it is still possible that it should be visible. if (!Visible) { if (auto *FromNamed = dyn_cast(FromD)) { auto *ToNamed = cast(ToD); DeclContextLookupResult FromLookup = FromDC->lookup(FromNamed->getDeclName()); if (llvm::is_contained(FromLookup, FromNamed)) ToDC->makeDeclVisibleInContext(ToNamed); } } } void updateLookupTableForTemplateParameters(TemplateParameterList &Params, DeclContext *OldDC) { ASTImporterLookupTable *LT = Importer.SharedState->getLookupTable(); if (!LT) return; for (NamedDecl *TP : Params) LT->update(TP, OldDC); } void updateLookupTableForTemplateParameters(TemplateParameterList &Params) { updateLookupTableForTemplateParameters( Params, Importer.getToContext().getTranslationUnitDecl()); } public: explicit ASTNodeImporter(ASTImporter &Importer) : Importer(Importer) {} using TypeVisitor::Visit; using DeclVisitor::Visit; using StmtVisitor::Visit; // Importing types ExpectedType VisitType(const Type *T); #define TYPE(Class, Base) \ ExpectedType Visit##Class##Type(const Class##Type *T); #include "clang/AST/TypeNodes.inc" // Importing declarations Error ImportDeclParts(NamedDecl *D, DeclarationName &Name, NamedDecl *&ToD, SourceLocation &Loc); Error ImportDeclParts( NamedDecl *D, DeclContext *&DC, DeclContext *&LexicalDC, DeclarationName &Name, NamedDecl *&ToD, SourceLocation &Loc); Error ImportDefinitionIfNeeded(Decl *FromD, Decl *ToD = nullptr); Error ImportDeclarationNameLoc( const DeclarationNameInfo &From, DeclarationNameInfo &To); Error ImportDeclContext(DeclContext *FromDC, bool ForceImport = false); Error ImportDeclContext( Decl *From, DeclContext *&ToDC, DeclContext *&ToLexicalDC); Error ImportImplicitMethods(const CXXRecordDecl *From, CXXRecordDecl *To); Error ImportFieldDeclDefinition(const FieldDecl *From, const FieldDecl *To); Expected ImportCastPath(CastExpr *E); Expected ImportAPValue(const APValue &FromValue); using Designator = DesignatedInitExpr::Designator; /// What we should import from the definition. enum ImportDefinitionKind { /// Import the default subset of the definition, which might be /// nothing (if minimal import is set) or might be everything (if minimal /// import is not set). IDK_Default, /// Import everything. IDK_Everything, /// Import only the bare bones needed to establish a valid /// DeclContext. IDK_Basic }; bool shouldForceImportDeclContext(ImportDefinitionKind IDK) { return IDK == IDK_Everything || (IDK == IDK_Default && !Importer.isMinimalImport()); } Error ImportInitializer(VarDecl *From, VarDecl *To); Error ImportDefinition( RecordDecl *From, RecordDecl *To, ImportDefinitionKind Kind = IDK_Default); Error ImportDefinition( EnumDecl *From, EnumDecl *To, ImportDefinitionKind Kind = IDK_Default); Error ImportDefinition( ObjCInterfaceDecl *From, ObjCInterfaceDecl *To, ImportDefinitionKind Kind = IDK_Default); Error ImportDefinition( ObjCProtocolDecl *From, ObjCProtocolDecl *To, ImportDefinitionKind Kind = IDK_Default); Error ImportTemplateArguments(ArrayRef FromArgs, 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); template Error ImportTemplateParameterLists(const DeclTy *FromD, DeclTy *ToD); Error ImportTemplateInformation(FunctionDecl *FromFD, FunctionDecl *ToFD); Error ImportFunctionDeclBody(FunctionDecl *FromFD, FunctionDecl *ToFD); Error ImportDefaultArgOfParmVarDecl(const ParmVarDecl *FromParam, ParmVarDecl *ToParam); Expected ImportInheritedConstructor(const InheritedConstructor &From); template bool hasSameVisibilityContextAndLinkage(T *Found, T *From); bool IsStructuralMatch(Decl *From, Decl *To, bool Complain = true, bool IgnoreTemplateParmDepth = false); ExpectedDecl VisitDecl(Decl *D); ExpectedDecl VisitImportDecl(ImportDecl *D); ExpectedDecl VisitEmptyDecl(EmptyDecl *D); ExpectedDecl VisitAccessSpecDecl(AccessSpecDecl *D); ExpectedDecl VisitStaticAssertDecl(StaticAssertDecl *D); ExpectedDecl VisitTranslationUnitDecl(TranslationUnitDecl *D); ExpectedDecl VisitBindingDecl(BindingDecl *D); ExpectedDecl VisitNamespaceDecl(NamespaceDecl *D); ExpectedDecl VisitNamespaceAliasDecl(NamespaceAliasDecl *D); ExpectedDecl VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias); ExpectedDecl VisitTypedefDecl(TypedefDecl *D); ExpectedDecl VisitTypeAliasDecl(TypeAliasDecl *D); ExpectedDecl VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D); ExpectedDecl VisitLabelDecl(LabelDecl *D); ExpectedDecl VisitEnumDecl(EnumDecl *D); ExpectedDecl VisitRecordDecl(RecordDecl *D); ExpectedDecl VisitEnumConstantDecl(EnumConstantDecl *D); ExpectedDecl VisitFunctionDecl(FunctionDecl *D); ExpectedDecl VisitCXXMethodDecl(CXXMethodDecl *D); ExpectedDecl VisitCXXConstructorDecl(CXXConstructorDecl *D); ExpectedDecl VisitCXXDestructorDecl(CXXDestructorDecl *D); ExpectedDecl VisitCXXConversionDecl(CXXConversionDecl *D); ExpectedDecl VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D); ExpectedDecl VisitFieldDecl(FieldDecl *D); ExpectedDecl VisitIndirectFieldDecl(IndirectFieldDecl *D); ExpectedDecl VisitFriendDecl(FriendDecl *D); ExpectedDecl VisitObjCIvarDecl(ObjCIvarDecl *D); ExpectedDecl VisitVarDecl(VarDecl *D); ExpectedDecl VisitImplicitParamDecl(ImplicitParamDecl *D); ExpectedDecl VisitParmVarDecl(ParmVarDecl *D); ExpectedDecl VisitObjCMethodDecl(ObjCMethodDecl *D); ExpectedDecl VisitObjCTypeParamDecl(ObjCTypeParamDecl *D); ExpectedDecl VisitObjCCategoryDecl(ObjCCategoryDecl *D); ExpectedDecl VisitObjCProtocolDecl(ObjCProtocolDecl *D); ExpectedDecl VisitLinkageSpecDecl(LinkageSpecDecl *D); ExpectedDecl VisitUsingDecl(UsingDecl *D); ExpectedDecl VisitUsingShadowDecl(UsingShadowDecl *D); ExpectedDecl VisitUsingDirectiveDecl(UsingDirectiveDecl *D); ExpectedDecl VisitUsingPackDecl(UsingPackDecl *D); ExpectedDecl ImportUsingShadowDecls(BaseUsingDecl *D, BaseUsingDecl *ToSI); ExpectedDecl VisitUsingEnumDecl(UsingEnumDecl *D); ExpectedDecl VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D); ExpectedDecl VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D); ExpectedDecl VisitBuiltinTemplateDecl(BuiltinTemplateDecl *D); ExpectedDecl VisitLifetimeExtendedTemporaryDecl(LifetimeExtendedTemporaryDecl *D); Expected 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 VisitSourceLocExpr(SourceLocExpr *E); ExpectedStmt VisitVAArgExpr(VAArgExpr *E); ExpectedStmt VisitChooseExpr(ChooseExpr *E); ExpectedStmt VisitConvertVectorExpr(ConvertVectorExpr *E); ExpectedStmt VisitShuffleVectorExpr(ShuffleVectorExpr *E); ExpectedStmt VisitGNUNullExpr(GNUNullExpr *E); ExpectedStmt VisitGenericSelectionExpr(GenericSelectionExpr *E); ExpectedStmt VisitPredefinedExpr(PredefinedExpr *E); ExpectedStmt VisitDeclRefExpr(DeclRefExpr *E); ExpectedStmt VisitImplicitValueInitExpr(ImplicitValueInitExpr *E); ExpectedStmt VisitDesignatedInitExpr(DesignatedInitExpr *E); ExpectedStmt VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E); ExpectedStmt VisitIntegerLiteral(IntegerLiteral *E); ExpectedStmt VisitFloatingLiteral(FloatingLiteral *E); ExpectedStmt VisitImaginaryLiteral(ImaginaryLiteral *E); ExpectedStmt VisitFixedPointLiteral(FixedPointLiteral *E); ExpectedStmt VisitCharacterLiteral(CharacterLiteral *E); ExpectedStmt VisitStringLiteral(StringLiteral *E); ExpectedStmt VisitCompoundLiteralExpr(CompoundLiteralExpr *E); ExpectedStmt VisitAtomicExpr(AtomicExpr *E); ExpectedStmt VisitAddrLabelExpr(AddrLabelExpr *E); ExpectedStmt VisitConstantExpr(ConstantExpr *E); ExpectedStmt VisitParenExpr(ParenExpr *E); ExpectedStmt VisitParenListExpr(ParenListExpr *E); ExpectedStmt VisitStmtExpr(StmtExpr *E); ExpectedStmt VisitUnaryOperator(UnaryOperator *E); ExpectedStmt VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E); ExpectedStmt VisitBinaryOperator(BinaryOperator *E); ExpectedStmt VisitConditionalOperator(ConditionalOperator *E); ExpectedStmt VisitBinaryConditionalOperator(BinaryConditionalOperator *E); ExpectedStmt VisitCXXRewrittenBinaryOperator(CXXRewrittenBinaryOperator *E); ExpectedStmt VisitOpaqueValueExpr(OpaqueValueExpr *E); ExpectedStmt VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E); ExpectedStmt VisitExpressionTraitExpr(ExpressionTraitExpr *E); ExpectedStmt VisitArraySubscriptExpr(ArraySubscriptExpr *E); ExpectedStmt VisitCompoundAssignOperator(CompoundAssignOperator *E); ExpectedStmt VisitImplicitCastExpr(ImplicitCastExpr *E); ExpectedStmt VisitExplicitCastExpr(ExplicitCastExpr *E); ExpectedStmt VisitOffsetOfExpr(OffsetOfExpr *OE); ExpectedStmt VisitCXXThrowExpr(CXXThrowExpr *E); ExpectedStmt VisitCXXNoexceptExpr(CXXNoexceptExpr *E); ExpectedStmt VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E); ExpectedStmt VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E); ExpectedStmt VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E); ExpectedStmt VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E); ExpectedStmt VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E); ExpectedStmt VisitPackExpansionExpr(PackExpansionExpr *E); ExpectedStmt VisitSizeOfPackExpr(SizeOfPackExpr *E); ExpectedStmt VisitCXXNewExpr(CXXNewExpr *E); ExpectedStmt VisitCXXDeleteExpr(CXXDeleteExpr *E); ExpectedStmt VisitCXXConstructExpr(CXXConstructExpr *E); ExpectedStmt VisitCXXMemberCallExpr(CXXMemberCallExpr *E); ExpectedStmt VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E); ExpectedStmt VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E); ExpectedStmt VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *E); ExpectedStmt VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E); ExpectedStmt VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E); ExpectedStmt VisitExprWithCleanups(ExprWithCleanups *E); ExpectedStmt VisitCXXThisExpr(CXXThisExpr *E); ExpectedStmt VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E); ExpectedStmt VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E); ExpectedStmt VisitMemberExpr(MemberExpr *E); ExpectedStmt VisitCallExpr(CallExpr *E); ExpectedStmt VisitLambdaExpr(LambdaExpr *LE); ExpectedStmt VisitInitListExpr(InitListExpr *E); ExpectedStmt VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *E); ExpectedStmt VisitCXXInheritedCtorInitExpr(CXXInheritedCtorInitExpr *E); ExpectedStmt VisitArrayInitLoopExpr(ArrayInitLoopExpr *E); ExpectedStmt VisitArrayInitIndexExpr(ArrayInitIndexExpr *E); ExpectedStmt VisitCXXDefaultInitExpr(CXXDefaultInitExpr *E); ExpectedStmt VisitCXXNamedCastExpr(CXXNamedCastExpr *E); ExpectedStmt VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *E); ExpectedStmt VisitTypeTraitExpr(TypeTraitExpr *E); ExpectedStmt VisitCXXTypeidExpr(CXXTypeidExpr *E); ExpectedStmt VisitCXXFoldExpr(CXXFoldExpr *E); // Helper for chaining together multiple imports. If an error is detected, // subsequent imports will return default constructed nodes, so that failure // can be detected with a single conditional branch after a sequence of // imports. template T importChecked(Error &Err, const T &From) { // Don't attempt to import nodes if we hit an error earlier. if (Err) return T{}; Expected MaybeVal = import(From); if (!MaybeVal) { Err = MaybeVal.takeError(); return T{}; } return *MaybeVal; } template Error ImportArrayChecked(IIter Ibegin, IIter Iend, OIter Obegin) { using ItemT = std::remove_reference_t; 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); // Returns true if the given function has a placeholder return type and // that type is declared inside the body of the function. // E.g. auto f() { struct X{}; return X(); } bool hasReturnTypeDeclaredInside(FunctionDecl *D); }; template 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. if (Error Err = ImportTemplateArguments(FTSInfo->TemplateArguments->asArray(), 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, /*isNullPtr*/ false, From.getIsDefaulted()); } case TemplateArgument::Integral: { ExpectedType ToTypeOrErr = import(From.getIntegralType()); if (!ToTypeOrErr) return ToTypeOrErr.takeError(); return TemplateArgument(From, *ToTypeOrErr); } case TemplateArgument::Declaration: { Expected ToOrErr = import(From.getAsDecl()); if (!ToOrErr) return ToOrErr.takeError(); ExpectedType ToTypeOrErr = import(From.getParamTypeForDecl()); if (!ToTypeOrErr) return ToTypeOrErr.takeError(); return TemplateArgument(dyn_cast((*ToOrErr)->getCanonicalDecl()), *ToTypeOrErr, From.getIsDefaulted()); } case TemplateArgument::NullPtr: { ExpectedType ToTypeOrErr = import(From.getNullPtrType()); if (!ToTypeOrErr) return ToTypeOrErr.takeError(); return TemplateArgument(*ToTypeOrErr, /*isNullPtr*/ true, From.getIsDefaulted()); } case TemplateArgument::StructuralValue: { ExpectedType ToTypeOrErr = import(From.getStructuralValueType()); if (!ToTypeOrErr) return ToTypeOrErr.takeError(); Expected ToValueOrErr = import(From.getAsStructuralValue()); if (!ToValueOrErr) return ToValueOrErr.takeError(); return TemplateArgument(Importer.getToContext(), *ToTypeOrErr, *ToValueOrErr); } case TemplateArgument::Template: { Expected ToTemplateOrErr = import(From.getAsTemplate()); if (!ToTemplateOrErr) return ToTemplateOrErr.takeError(); return TemplateArgument(*ToTemplateOrErr, From.getIsDefaulted()); } case TemplateArgument::TemplateExpansion: { Expected ToTemplateOrErr = import(From.getAsTemplateOrTemplatePattern()); if (!ToTemplateOrErr) return ToTemplateOrErr.takeError(); return TemplateArgument(*ToTemplateOrErr, From.getNumTemplateExpansions(), From.getIsDefaulted()); } case TemplateArgument::Expression: if (ExpectedExpr ToExpr = import(From.getAsExpr())) return TemplateArgument(*ToExpr, From.getIsDefaulted()); else return ToExpr.takeError(); case TemplateArgument::Pack: { SmallVector ToPack; ToPack.reserve(From.pack_size()); if (Error Err = ImportTemplateArguments(From.pack_elements(), ToPack)) return std::move(Err); return TemplateArgument( llvm::ArrayRef(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( Importer.getToContext(), *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 DesignatedInitExpr::Designator::CreateFieldDesignator( ToFieldName, *ToDotLocOrErr, *ToFieldLocOrErr); } ExpectedSLoc ToLBracketLocOrErr = import(D.getLBracketLoc()); if (!ToLBracketLocOrErr) return ToLBracketLocOrErr.takeError(); ExpectedSLoc ToRBracketLocOrErr = import(D.getRBracketLoc()); if (!ToRBracketLocOrErr) return ToRBracketLocOrErr.takeError(); if (D.isArrayDesignator()) return Designator::CreateArrayDesignator(D.getArrayIndex(), *ToLBracketLocOrErr, *ToRBracketLocOrErr); ExpectedSLoc ToEllipsisLocOrErr = import(D.getEllipsisLoc()); if (!ToEllipsisLocOrErr) return ToEllipsisLocOrErr.takeError(); assert(D.isArrayRangeDesignator()); return Designator::CreateArrayRangeDesignator( D.getArrayIndex(), *ToLBracketLocOrErr, *ToEllipsisLocOrErr, *ToRBracketLocOrErr); } template <> Expected ASTNodeImporter::import(ConceptReference *From) { Error Err = Error::success(); auto ToNNS = importChecked(Err, From->getNestedNameSpecifierLoc()); auto ToTemplateKWLoc = importChecked(Err, From->getTemplateKWLoc()); auto ToConceptNameLoc = importChecked(Err, From->getConceptNameInfo().getLoc()); auto ToConceptName = importChecked(Err, From->getConceptNameInfo().getName()); auto ToFoundDecl = importChecked(Err, From->getFoundDecl()); auto ToNamedConcept = importChecked(Err, From->getNamedConcept()); if (Err) return std::move(Err); TemplateArgumentListInfo ToTAInfo; const auto *ASTTemplateArgs = From->getTemplateArgsAsWritten(); if (ASTTemplateArgs) if (Error Err = ImportTemplateArgumentListInfo(*ASTTemplateArgs, ToTAInfo)) return std::move(Err); auto *ConceptRef = ConceptReference::Create( Importer.getToContext(), ToNNS, ToTemplateKWLoc, DeclarationNameInfo(ToConceptName, ToConceptNameLoc), ToFoundDecl, ToNamedConcept, ASTTemplateArgs ? ASTTemplateArgumentListInfo::Create( Importer.getToContext(), ToTAInfo) : nullptr); return ConceptRef; } template <> Expected ASTNodeImporter::import(const LambdaCapture &From) { ValueDecl *Var = nullptr; if (From.capturesVariable()) { if (auto VarOrErr = import(From.getCapturedVar())) Var = *VarOrErr; else return VarOrErr.takeError(); } auto LocationOrErr = import(From.getLocation()); if (!LocationOrErr) return LocationOrErr.takeError(); SourceLocation EllipsisLoc; if (From.isPackExpansion()) if (Error Err = importInto(EllipsisLoc, From.getEllipsisLoc())) return std::move(Err); return LambdaCapture( *LocationOrErr, From.isImplicit(), From.getCaptureKind(), Var, EllipsisLoc); } template bool ASTNodeImporter::hasSameVisibilityContextAndLinkage(T *Found, T *From) { if (Found->getLinkageInternal() != From->getLinkageInternal()) return false; if (From->hasExternalFormalLinkage()) return Found->hasExternalFormalLinkage(); if (Importer.GetFromTU(Found) != From->getTranslationUnitDecl()) return false; if (From->isInAnonymousNamespace()) return Found->isInAnonymousNamespace(); else return !Found->isInAnonymousNamespace() && !Found->hasExternalFormalLinkage(); } template <> bool ASTNodeImporter::hasSameVisibilityContextAndLinkage(TypedefNameDecl *Found, TypedefNameDecl *From) { if (Found->getLinkageInternal() != From->getLinkageInternal()) return false; if (From->isInAnonymousNamespace() && Found->isInAnonymousNamespace()) return Importer.GetFromTU(Found) == From->getTranslationUnitDecl(); return From->isInAnonymousNamespace() == Found->isInAnonymousNamespace(); } } // namespace clang //---------------------------------------------------------------------------- // Import Types //---------------------------------------------------------------------------- using namespace clang; ExpectedType ASTNodeImporter::VisitType(const Type *T) { Importer.FromDiag(SourceLocation(), diag::err_unsupported_ast_node) << T->getTypeClassName(); return make_error(ASTImportError::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 PPC_VECTOR_TYPE(Name, Id, Size) \ case BuiltinType::Id: \ return Importer.getToContext().Id##Ty; #include "clang/Basic/PPCTypes.def" #define RVV_TYPE(Name, Id, SingletonId) \ case BuiltinType::Id: \ return Importer.getToContext().SingletonId; #include "clang/Basic/RISCVVTypes.def" #define WASM_TYPE(Name, Id, SingletonId) \ case BuiltinType::Id: \ return Importer.getToContext().SingletonId; #include "clang/Basic/WebAssemblyReferenceTypes.def" #define AMDGPU_TYPE(Name, Id, SingletonId) \ case BuiltinType::Id: \ return Importer.getToContext().SingletonId; #include "clang/Basic/AMDGPUTypes.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(); ExpectedTypePtr ClassTypeOrErr = import(T->getClass()); if (!ClassTypeOrErr) return ClassTypeOrErr.takeError(); return Importer.getToContext().getMemberPointerType(*ToPointeeTypeOrErr, *ClassTypeOrErr); } ExpectedType ASTNodeImporter::VisitConstantArrayType(const ConstantArrayType *T) { Error Err = Error::success(); auto ToElementType = importChecked(Err, T->getElementType()); auto ToSizeExpr = importChecked(Err, T->getSizeExpr()); if (Err) return std::move(Err); return Importer.getToContext().getConstantArrayType( ToElementType, T->getSize(), ToSizeExpr, T->getSizeModifier(), T->getIndexTypeCVRQualifiers()); } ExpectedType ASTNodeImporter::VisitArrayParameterType(const ArrayParameterType *T) { ExpectedType ToArrayTypeOrErr = VisitConstantArrayType(T); if (!ToArrayTypeOrErr) return ToArrayTypeOrErr.takeError(); return Importer.getToContext().getArrayParameterType(*ToArrayTypeOrErr); } ExpectedType ASTNodeImporter::VisitIncompleteArrayType(const IncompleteArrayType *T) { ExpectedType ToElementTypeOrErr = import(T->getElementType()); if (!ToElementTypeOrErr) return ToElementTypeOrErr.takeError(); return Importer.getToContext().getIncompleteArrayType(*ToElementTypeOrErr, T->getSizeModifier(), T->getIndexTypeCVRQualifiers()); } ExpectedType ASTNodeImporter::VisitVariableArrayType(const VariableArrayType *T) { Error Err = Error::success(); QualType ToElementType = importChecked(Err, T->getElementType()); Expr *ToSizeExpr = importChecked(Err, T->getSizeExpr()); SourceRange ToBracketsRange = importChecked(Err, T->getBracketsRange()); if (Err) return std::move(Err); return Importer.getToContext().getVariableArrayType( ToElementType, ToSizeExpr, T->getSizeModifier(), T->getIndexTypeCVRQualifiers(), ToBracketsRange); } ExpectedType ASTNodeImporter::VisitDependentSizedArrayType( const DependentSizedArrayType *T) { Error Err = Error::success(); QualType ToElementType = importChecked(Err, T->getElementType()); Expr *ToSizeExpr = importChecked(Err, T->getSizeExpr()); SourceRange ToBracketsRange = importChecked(Err, T->getBracketsRange()); if (Err) return std::move(Err); // SizeExpr may be null if size is not specified directly. // For example, 'int a[]'. return Importer.getToContext().getDependentSizedArrayType( ToElementType, ToSizeExpr, T->getSizeModifier(), T->getIndexTypeCVRQualifiers(), ToBracketsRange); } ExpectedType ASTNodeImporter::VisitDependentSizedExtVectorType( const DependentSizedExtVectorType *T) { Error Err = Error::success(); QualType ToElementType = importChecked(Err, T->getElementType()); Expr *ToSizeExpr = importChecked(Err, T->getSizeExpr()); SourceLocation ToAttrLoc = importChecked(Err, T->getAttributeLoc()); if (Err) return std::move(Err); return Importer.getToContext().getDependentSizedExtVectorType( ToElementType, ToSizeExpr, ToAttrLoc); } ExpectedType ASTNodeImporter::VisitVectorType(const VectorType *T) { ExpectedType ToElementTypeOrErr = import(T->getElementType()); if (!ToElementTypeOrErr) return ToElementTypeOrErr.takeError(); return Importer.getToContext().getVectorType(*ToElementTypeOrErr, T->getNumElements(), T->getVectorKind()); } ExpectedType ASTNodeImporter::VisitExtVectorType(const ExtVectorType *T) { ExpectedType ToElementTypeOrErr = import(T->getElementType()); if (!ToElementTypeOrErr) return ToElementTypeOrErr.takeError(); return Importer.getToContext().getExtVectorType(*ToElementTypeOrErr, T->getNumElements()); } ExpectedType ASTNodeImporter::VisitFunctionNoProtoType(const FunctionNoProtoType *T) { // FIXME: What happens if we're importing a function without a prototype // into C++? Should we make it variadic? ExpectedType ToReturnTypeOrErr = import(T->getReturnType()); if (!ToReturnTypeOrErr) return ToReturnTypeOrErr.takeError(); return Importer.getToContext().getFunctionNoProtoType(*ToReturnTypeOrErr, T->getExtInfo()); } ExpectedType ASTNodeImporter::VisitFunctionProtoType(const FunctionProtoType *T) { ExpectedType ToReturnTypeOrErr = import(T->getReturnType()); if (!ToReturnTypeOrErr) return ToReturnTypeOrErr.takeError(); // Import argument types SmallVector 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(); Error Err = Error::success(); FunctionProtoType::ExtProtoInfo ToEPI; ToEPI.ExtInfo = FromEPI.ExtInfo; ToEPI.Variadic = FromEPI.Variadic; ToEPI.HasTrailingReturn = FromEPI.HasTrailingReturn; ToEPI.TypeQuals = FromEPI.TypeQuals; ToEPI.RefQualifier = FromEPI.RefQualifier; ToEPI.ExceptionSpec.Type = FromEPI.ExceptionSpec.Type; ToEPI.ExceptionSpec.NoexceptExpr = importChecked(Err, FromEPI.ExceptionSpec.NoexceptExpr); ToEPI.ExceptionSpec.SourceDecl = importChecked(Err, FromEPI.ExceptionSpec.SourceDecl); ToEPI.ExceptionSpec.SourceTemplate = importChecked(Err, FromEPI.ExceptionSpec.SourceTemplate); ToEPI.ExceptionSpec.Exceptions = ExceptionTypes; if (Err) return std::move(Err); return Importer.getToContext().getFunctionType( *ToReturnTypeOrErr, ArgTypes, ToEPI); } ExpectedType ASTNodeImporter::VisitUnresolvedUsingType( const UnresolvedUsingType *T) { Error Err = Error::success(); auto ToD = importChecked(Err, T->getDecl()); auto ToPrevD = importChecked(Err, T->getDecl()->getPreviousDecl()); if (Err) return std::move(Err); return Importer.getToContext().getTypeDeclType( ToD, cast_or_null(ToPrevD)); } ExpectedType ASTNodeImporter::VisitParenType(const ParenType *T) { ExpectedType ToInnerTypeOrErr = import(T->getInnerType()); if (!ToInnerTypeOrErr) return ToInnerTypeOrErr.takeError(); return Importer.getToContext().getParenType(*ToInnerTypeOrErr); } ExpectedType ASTNodeImporter::VisitPackIndexingType(clang::PackIndexingType const *T) { ExpectedType Pattern = import(T->getPattern()); if (!Pattern) return Pattern.takeError(); ExpectedExpr Index = import(T->getIndexExpr()); if (!Index) return Index.takeError(); return Importer.getToContext().getPackIndexingType(*Pattern, *Index); } ExpectedType ASTNodeImporter::VisitTypedefType(const TypedefType *T) { Expected ToDeclOrErr = import(T->getDecl()); if (!ToDeclOrErr) return ToDeclOrErr.takeError(); TypedefNameDecl *ToDecl = *ToDeclOrErr; if (ToDecl->getTypeForDecl()) return QualType(ToDecl->getTypeForDecl(), 0); ExpectedType ToUnderlyingTypeOrErr = import(T->desugar()); if (!ToUnderlyingTypeOrErr) return ToUnderlyingTypeOrErr.takeError(); return Importer.getToContext().getTypedefType(ToDecl, *ToUnderlyingTypeOrErr); } ExpectedType ASTNodeImporter::VisitTypeOfExprType(const TypeOfExprType *T) { ExpectedExpr ToExprOrErr = import(T->getUnderlyingExpr()); if (!ToExprOrErr) return ToExprOrErr.takeError(); return Importer.getToContext().getTypeOfExprType(*ToExprOrErr, T->getKind()); } ExpectedType ASTNodeImporter::VisitTypeOfType(const TypeOfType *T) { ExpectedType ToUnderlyingTypeOrErr = import(T->getUnmodifiedType()); if (!ToUnderlyingTypeOrErr) return ToUnderlyingTypeOrErr.takeError(); return Importer.getToContext().getTypeOfType(*ToUnderlyingTypeOrErr, T->getKind()); } ExpectedType ASTNodeImporter::VisitUsingType(const UsingType *T) { Expected FoundOrErr = import(T->getFoundDecl()); if (!FoundOrErr) return FoundOrErr.takeError(); Expected UnderlyingOrErr = import(T->getUnderlyingType()); if (!UnderlyingOrErr) return UnderlyingOrErr.takeError(); return Importer.getToContext().getUsingType(*FoundOrErr, *UnderlyingOrErr); } ExpectedType ASTNodeImporter::VisitDecltypeType(const DecltypeType *T) { // FIXME: Make sure that the "to" context supports C++0x! ExpectedExpr ToExprOrErr = import(T->getUnderlyingExpr()); if (!ToExprOrErr) return ToExprOrErr.takeError(); ExpectedType ToUnderlyingTypeOrErr = import(T->getUnderlyingType()); if (!ToUnderlyingTypeOrErr) return ToUnderlyingTypeOrErr.takeError(); return Importer.getToContext().getDecltypeType( *ToExprOrErr, *ToUnderlyingTypeOrErr); } ExpectedType ASTNodeImporter::VisitUnaryTransformType(const UnaryTransformType *T) { ExpectedType ToBaseTypeOrErr = import(T->getBaseType()); if (!ToBaseTypeOrErr) return ToBaseTypeOrErr.takeError(); ExpectedType ToUnderlyingTypeOrErr = import(T->getUnderlyingType()); if (!ToUnderlyingTypeOrErr) return ToUnderlyingTypeOrErr.takeError(); return Importer.getToContext().getUnaryTransformType( *ToBaseTypeOrErr, *ToUnderlyingTypeOrErr, T->getUTTKind()); } ExpectedType ASTNodeImporter::VisitAutoType(const AutoType *T) { // FIXME: Make sure that the "to" context supports C++11! ExpectedType ToDeducedTypeOrErr = import(T->getDeducedType()); if (!ToDeducedTypeOrErr) return ToDeducedTypeOrErr.takeError(); ExpectedDecl ToTypeConstraintConcept = import(T->getTypeConstraintConcept()); if (!ToTypeConstraintConcept) return ToTypeConstraintConcept.takeError(); SmallVector ToTemplateArgs; if (Error Err = ImportTemplateArguments(T->getTypeConstraintArguments(), ToTemplateArgs)) return std::move(Err); return Importer.getToContext().getAutoType( *ToDeducedTypeOrErr, T->getKeyword(), /*IsDependent*/false, /*IsPack=*/false, cast_or_null(*ToTypeConstraintConcept), ToTemplateArgs); } ExpectedType ASTNodeImporter::VisitDeducedTemplateSpecializationType( const DeducedTemplateSpecializationType *T) { // FIXME: Make sure that the "to" context supports C++17! Expected ToTemplateNameOrErr = import(T->getTemplateName()); if (!ToTemplateNameOrErr) return ToTemplateNameOrErr.takeError(); ExpectedType ToDeducedTypeOrErr = import(T->getDeducedType()); if (!ToDeducedTypeOrErr) return ToDeducedTypeOrErr.takeError(); return Importer.getToContext().getDeducedTemplateSpecializationType( *ToTemplateNameOrErr, *ToDeducedTypeOrErr, T->isDependentType()); } ExpectedType ASTNodeImporter::VisitInjectedClassNameType( const InjectedClassNameType *T) { Expected ToDeclOrErr = import(T->getDecl()); if (!ToDeclOrErr) return ToDeclOrErr.takeError(); // The InjectedClassNameType is created in VisitRecordDecl when the // T->getDecl() is imported. Here we can return the existing type. const Type *Ty = (*ToDeclOrErr)->getTypeForDecl(); assert(isa_and_nonnull(Ty)); return QualType(Ty, 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::VisitCountAttributedType(const CountAttributedType *T) { ExpectedType ToWrappedTypeOrErr = import(T->desugar()); if (!ToWrappedTypeOrErr) return ToWrappedTypeOrErr.takeError(); Error Err = Error::success(); Expr *CountExpr = importChecked(Err, T->getCountExpr()); SmallVector CoupledDecls; for (const TypeCoupledDeclRefInfo &TI : T->dependent_decls()) { Expected ToDeclOrErr = import(TI.getDecl()); if (!ToDeclOrErr) return ToDeclOrErr.takeError(); CoupledDecls.emplace_back(*ToDeclOrErr, TI.isDeref()); } return Importer.getToContext().getCountAttributedType( *ToWrappedTypeOrErr, CountExpr, T->isCountInBytes(), T->isOrNull(), ArrayRef(CoupledDecls.data(), CoupledDecls.size())); } 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) { Expected ReplacedOrErr = import(T->getAssociatedDecl()); if (!ReplacedOrErr) return ReplacedOrErr.takeError(); ExpectedType ToReplacementTypeOrErr = import(T->getReplacementType()); if (!ToReplacementTypeOrErr) return ToReplacementTypeOrErr.takeError(); return Importer.getToContext().getSubstTemplateTypeParmType( *ToReplacementTypeOrErr, *ReplacedOrErr, T->getIndex(), T->getPackIndex()); } ExpectedType ASTNodeImporter::VisitSubstTemplateTypeParmPackType( const SubstTemplateTypeParmPackType *T) { Expected ReplacedOrErr = import(T->getAssociatedDecl()); if (!ReplacedOrErr) return ReplacedOrErr.takeError(); Expected ToArgumentPack = import(T->getArgumentPack()); if (!ToArgumentPack) return ToArgumentPack.takeError(); return Importer.getToContext().getSubstTemplateTypeParmPackType( *ReplacedOrErr, T->getIndex(), T->getFinal(), *ToArgumentPack); } ExpectedType ASTNodeImporter::VisitTemplateSpecializationType( const TemplateSpecializationType *T) { auto ToTemplateOrErr = import(T->getTemplateName()); if (!ToTemplateOrErr) return ToTemplateOrErr.takeError(); SmallVector ToTemplateArgs; if (Error Err = ImportTemplateArguments(T->template_arguments(), ToTemplateArgs)) return std::move(Err); QualType ToCanonType; if (!T->isCanonicalUnqualified()) { 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(), /*ExpactPack=*/false); } 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->template_arguments().size()); if (Error Err = ImportTemplateArguments(T->template_arguments(), 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); } ExpectedType ASTNodeImporter::VisitMacroQualifiedType(const MacroQualifiedType *T) { ExpectedType ToUnderlyingTypeOrErr = import(T->getUnderlyingType()); if (!ToUnderlyingTypeOrErr) return ToUnderlyingTypeOrErr.takeError(); IdentifierInfo *ToIdentifier = Importer.Import(T->getMacroIdentifier()); return Importer.getToContext().getMacroQualifiedType(*ToUnderlyingTypeOrErr, ToIdentifier); } ExpectedType clang::ASTNodeImporter::VisitAdjustedType(const AdjustedType *T) { Error Err = Error::success(); QualType ToOriginalType = importChecked(Err, T->getOriginalType()); QualType ToAdjustedType = importChecked(Err, T->getAdjustedType()); if (Err) return std::move(Err); return Importer.getToContext().getAdjustedType(ToOriginalType, ToAdjustedType); } ExpectedType clang::ASTNodeImporter::VisitBitIntType(const BitIntType *T) { return Importer.getToContext().getBitIntType(T->isUnsigned(), T->getNumBits()); } ExpectedType clang::ASTNodeImporter::VisitBTFTagAttributedType( const clang::BTFTagAttributedType *T) { Error Err = Error::success(); const BTFTypeTagAttr *ToBTFAttr = importChecked(Err, T->getAttr()); QualType ToWrappedType = importChecked(Err, T->getWrappedType()); if (Err) return std::move(Err); return Importer.getToContext().getBTFTagAttributedType(ToBTFAttr, ToWrappedType); } ExpectedType clang::ASTNodeImporter::VisitConstantMatrixType( const clang::ConstantMatrixType *T) { ExpectedType ToElementTypeOrErr = import(T->getElementType()); if (!ToElementTypeOrErr) return ToElementTypeOrErr.takeError(); return Importer.getToContext().getConstantMatrixType( *ToElementTypeOrErr, T->getNumRows(), T->getNumColumns()); } ExpectedType clang::ASTNodeImporter::VisitDependentAddressSpaceType( const clang::DependentAddressSpaceType *T) { Error Err = Error::success(); QualType ToPointeeType = importChecked(Err, T->getPointeeType()); Expr *ToAddrSpaceExpr = importChecked(Err, T->getAddrSpaceExpr()); SourceLocation ToAttrLoc = importChecked(Err, T->getAttributeLoc()); if (Err) return std::move(Err); return Importer.getToContext().getDependentAddressSpaceType( ToPointeeType, ToAddrSpaceExpr, ToAttrLoc); } ExpectedType clang::ASTNodeImporter::VisitDependentBitIntType( const clang::DependentBitIntType *T) { ExpectedExpr ToNumBitsExprOrErr = import(T->getNumBitsExpr()); if (!ToNumBitsExprOrErr) return ToNumBitsExprOrErr.takeError(); return Importer.getToContext().getDependentBitIntType(T->isUnsigned(), *ToNumBitsExprOrErr); } ExpectedType clang::ASTNodeImporter::VisitDependentSizedMatrixType( const clang::DependentSizedMatrixType *T) { Error Err = Error::success(); QualType ToElementType = importChecked(Err, T->getElementType()); Expr *ToRowExpr = importChecked(Err, T->getRowExpr()); Expr *ToColumnExpr = importChecked(Err, T->getColumnExpr()); SourceLocation ToAttrLoc = importChecked(Err, T->getAttributeLoc()); if (Err) return std::move(Err); return Importer.getToContext().getDependentSizedMatrixType( ToElementType, ToRowExpr, ToColumnExpr, ToAttrLoc); } ExpectedType clang::ASTNodeImporter::VisitDependentVectorType( const clang::DependentVectorType *T) { Error Err = Error::success(); QualType ToElementType = importChecked(Err, T->getElementType()); Expr *ToSizeExpr = importChecked(Err, T->getSizeExpr()); SourceLocation ToAttrLoc = importChecked(Err, T->getAttributeLoc()); if (Err) return std::move(Err); return Importer.getToContext().getDependentVectorType( ToElementType, ToSizeExpr, ToAttrLoc, T->getVectorKind()); } ExpectedType clang::ASTNodeImporter::VisitObjCTypeParamType( const clang::ObjCTypeParamType *T) { Expected ToDeclOrErr = import(T->getDecl()); if (!ToDeclOrErr) return ToDeclOrErr.takeError(); SmallVector ToProtocols; for (ObjCProtocolDecl *FromProtocol : T->getProtocols()) { Expected ToProtocolOrErr = import(FromProtocol); if (!ToProtocolOrErr) return ToProtocolOrErr.takeError(); ToProtocols.push_back(*ToProtocolOrErr); } return Importer.getToContext().getObjCTypeParamType(*ToDeclOrErr, ToProtocols); } ExpectedType clang::ASTNodeImporter::VisitPipeType(const clang::PipeType *T) { ExpectedType ToElementTypeOrErr = import(T->getElementType()); if (!ToElementTypeOrErr) return ToElementTypeOrErr.takeError(); ASTContext &ToCtx = Importer.getToContext(); if (T->isReadOnly()) return ToCtx.getReadPipeType(*ToElementTypeOrErr); else return ToCtx.getWritePipeType(*ToElementTypeOrErr); } //---------------------------------------------------------------------------- // Import Declarations //---------------------------------------------------------------------------- Error ASTNodeImporter::ImportDeclParts( NamedDecl *D, DeclContext *&DC, DeclContext *&LexicalDC, DeclarationName &Name, NamedDecl *&ToD, SourceLocation &Loc) { // Check if RecordDecl is in FunctionDecl parameters to avoid infinite loop. // example: int struct_in_proto(struct data_t{int a;int b;} *d); // FIXME: We could support these constructs by importing a different type of // this parameter and by importing the original type of the parameter only // after the FunctionDecl is created. See // VisitFunctionDecl::UsedDifferentProtoType. DeclContext *OrigDC = D->getDeclContext(); FunctionDecl *FunDecl; if (isa(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(ASTImportError::UnsupportedConstruct); } } } // Import the context of this declaration. if (Error Err = ImportDeclContext(D, DC, LexicalDC)) return Err; // Import the name of this declaration. if (Error Err = importInto(Name, D->getDeclName())) return Err; // Import the location of this declaration. if (Error Err = importInto(Loc, D->getLocation())) return Err; ToD = cast_or_null(Importer.GetAlreadyImportedOrNull(D)); if (ToD) if (Error Err = ASTNodeImporter(*this).ImportDefinitionIfNeeded(D, ToD)) return Err; return Error::success(); } Error ASTNodeImporter::ImportDeclParts(NamedDecl *D, DeclarationName &Name, NamedDecl *&ToD, SourceLocation &Loc) { // Import the name of this declaration. if (Error Err = importInto(Name, D->getDeclName())) return Err; // Import the location of this declaration. if (Error Err = importInto(Loc, D->getLocation())) return Err; ToD = cast_or_null(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. ChildErrorHandlingStrategy HandleChildErrors(FromDC); auto MightNeedReordering = [](const Decl *D) { return isa(D) || isa(D) || isa(D); }; // Import everything that might need reordering first. Error ChildErrors = Error::success(); for (auto *From : FromDC->decls()) { if (!MightNeedReordering(From)) continue; ExpectedDecl ImportedOrErr = import(From); // If we are in the process of ImportDefinition(...) for a RecordDecl we // want to make sure that we are also completing each FieldDecl. There // are currently cases where this does not happen and this is correctness // fix since operations such as code generation will expect this to be so. if (!ImportedOrErr) { HandleChildErrors.handleChildImportResult(ChildErrors, ImportedOrErr.takeError()); continue; } FieldDecl *FieldFrom = dyn_cast_or_null(From); Decl *ImportedDecl = *ImportedOrErr; FieldDecl *FieldTo = dyn_cast_or_null(ImportedDecl); if (FieldFrom && FieldTo) { Error Err = ImportFieldDeclDefinition(FieldFrom, FieldTo); HandleChildErrors.handleChildImportResult(ChildErrors, std::move(Err)); } } // We reorder declarations in RecordDecls because they may have another order // in the "to" context than they have in the "from" context. This may happen // e.g when we import a class like this: // struct declToImport { // int a = c + b; // int b = 1; // int c = 2; // }; // During the import of `a` we import first the dependencies in sequence, // thus the order would be `c`, `b`, `a`. We will get the normal order by // first removing the already imported members and then adding them in the // order as they appear in the "from" context. // // Keeping field order is vital because it determines structure layout. // // Here and below, we cannot call field_begin() method and its callers on // ToDC if it has an external storage. Calling field_begin() will // automatically load all the fields by calling // LoadFieldsFromExternalStorage(). LoadFieldsFromExternalStorage() would // call ASTImporter::Import(). This is because the ExternalASTSource // interface in LLDB is implemented by the means of the ASTImporter. However, // calling an import at this point would result in an uncontrolled import, we // must avoid that. auto ToDCOrErr = Importer.ImportContext(FromDC); if (!ToDCOrErr) { consumeError(std::move(ChildErrors)); return ToDCOrErr.takeError(); } if (const auto *FromRD = dyn_cast(FromDC)) { DeclContext *ToDC = *ToDCOrErr; // Remove all declarations, which may be in wrong order in the // lexical DeclContext and then add them in the proper order. for (auto *D : FromRD->decls()) { if (!MightNeedReordering(D)) continue; assert(D && "DC contains a null decl"); if (Decl *ToD = Importer.GetAlreadyImportedOrNull(D)) { // Remove only the decls which we successfully imported. assert(ToDC == ToD->getLexicalDeclContext() && ToDC->containsDecl(ToD)); // Remove the decl from its wrong place in the linked list. ToDC->removeDecl(ToD); // Add the decl to the end of the linked list. // This time it will be at the proper place because the enclosing for // loop iterates in the original (good) order of the decls. ToDC->addDeclInternal(ToD); } } } // Import everything else. for (auto *From : FromDC->decls()) { if (MightNeedReordering(From)) continue; ExpectedDecl ImportedOrErr = import(From); if (!ImportedOrErr) HandleChildErrors.handleChildImportResult(ChildErrors, ImportedOrErr.takeError()); } return ChildErrors; } Error ASTNodeImporter::ImportFieldDeclDefinition(const FieldDecl *From, const FieldDecl *To) { RecordDecl *FromRecordDecl = nullptr; RecordDecl *ToRecordDecl = nullptr; // If we have a field that is an ArrayType we need to check if the array // element is a RecordDecl and if so we need to import the definition. QualType FromType = From->getType(); QualType ToType = To->getType(); if (FromType->isArrayType()) { // getBaseElementTypeUnsafe(...) handles multi-dimensonal arrays for us. FromRecordDecl = FromType->getBaseElementTypeUnsafe()->getAsRecordDecl(); ToRecordDecl = ToType->getBaseElementTypeUnsafe()->getAsRecordDecl(); } if (!FromRecordDecl || !ToRecordDecl) { const RecordType *RecordFrom = FromType->getAs(); const RecordType *RecordTo = ToType->getAs(); if (RecordFrom && RecordTo) { FromRecordDecl = RecordFrom->getDecl(); ToRecordDecl = RecordTo->getDecl(); } } if (FromRecordDecl && ToRecordDecl) { if (FromRecordDecl->isCompleteDefinition() && !ToRecordDecl->isCompleteDefinition()) return ImportDefinition(FromRecordDecl, ToRecordDecl); } return Error::success(); } Error ASTNodeImporter::ImportDeclContext( Decl *FromD, DeclContext *&ToDC, DeclContext *&ToLexicalDC) { auto ToDCOrErr = Importer.ImportContext(FromD->getDeclContext()); if (!ToDCOrErr) return ToDCOrErr.takeError(); ToDC = *ToDCOrErr; if (FromD->getDeclContext() != FromD->getLexicalDeclContext()) { auto ToLexicalDCOrErr = Importer.ImportContext( FromD->getLexicalDeclContext()); if (!ToLexicalDCOrErr) return ToLexicalDCOrErr.takeError(); ToLexicalDC = *ToLexicalDCOrErr; } else ToLexicalDC = ToDC; return Error::success(); } Error ASTNodeImporter::ImportImplicitMethods( const CXXRecordDecl *From, CXXRecordDecl *To) { assert(From->isCompleteDefinition() && To->getDefinition() == To && "Import implicit methods to or from non-definition"); for (CXXMethodDecl *FromM : From->methods()) if (FromM->isImplicit()) { Expected 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))) { if (To->isLambda()) { auto *FromCXXRD = cast(From); SmallVector ToCaptures; ToCaptures.reserve(FromCXXRD->capture_size()); for (const auto &FromCapture : FromCXXRD->captures()) { if (auto ToCaptureOrErr = import(FromCapture)) ToCaptures.push_back(*ToCaptureOrErr); else return ToCaptureOrErr.takeError(); } cast(To)->setCaptures(Importer.getToContext(), ToCaptures); } Error Result = ImportDeclContext(From, /*ForceImport=*/true); // Finish the definition of the lambda, set isBeingDefined to false. if (To->isLambda()) DefinitionCompleter(); return Result; } return Error::success(); } To->startDefinition(); // Set the definition to complete even if it is really not complete during // import. Some AST constructs (expressions) require the record layout // to be calculated (see 'clang::computeDependence') at the time they are // constructed. Import of such AST node is possible during import of the // same record, there is no way to have a completely defined record (all // fields imported) at that time without multiple AST import passes. if (!Importer.isMinimalImport()) To->setCompleteDefinition(true); // Complete the definition even if error is returned. // The RecordDecl may be already part of the AST so it is better to // have it in complete state even if something is wrong with it. auto DefinitionCompleterScopeExit = llvm::make_scope_exit(DefinitionCompleter); if (Error Err = setTypedefNameForAnonDecl(From, To, Importer)) return Err; // Add base classes. auto *ToCXX = dyn_cast(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(); #define FIELD(Name, Width, Merge) \ ToData.Name = FromData.Name; #include "clang/AST/CXXRecordDeclDefinitionBits.def" // Copy over the data stored in RecordDeclBits ToCXX->setArgPassingRestrictions(FromCXX->getArgPassingRestrictions()); SmallVector Bases; for (const auto &Base1 : FromCXX->bases()) { ExpectedType TyOrErr = import(Base1.getType()); if (!TyOrErr) return TyOrErr.takeError(); SourceLocation EllipsisLoc; if (Base1.isPackExpansion()) { if (ExpectedSLoc LocOrErr = import(Base1.getEllipsisLoc())) EllipsisLoc = *LocOrErr; else return LocOrErr.takeError(); } // Ensure that we have a definition for the base. if (Error Err = ImportDefinitionIfNeeded(Base1.getType()->getAsCXXRecordDecl())) return Err; auto RangeOrErr = import(Base1.getSourceRange()); if (!RangeOrErr) return RangeOrErr.takeError(); auto TSIOrErr = import(Base1.getTypeSourceInfo()); if (!TSIOrErr) return TSIOrErr.takeError(); Bases.push_back( new (Importer.getToContext()) CXXBaseSpecifier( *RangeOrErr, Base1.isVirtual(), Base1.isBaseOfClass(), Base1.getAccessSpecifierAsWritten(), *TSIOrErr, EllipsisLoc)); } if (!Bases.empty()) ToCXX->setBases(Bases.data(), Bases.size()); } if (shouldForceImportDeclContext(Kind)) { if (Error Err = ImportDeclContext(From, /*ForceImport=*/true)) return Err; } return Error::success(); } Error ASTNodeImporter::ImportInitializer(VarDecl *From, VarDecl *To) { if (To->getAnyInitializer()) return Error::success(); Expr *FromInit = From->getInit(); if (!FromInit) return Error::success(); ExpectedExpr ToInitOrErr = import(FromInit); if (!ToInitOrErr) return ToInitOrErr.takeError(); To->setInit(*ToInitOrErr); if (EvaluatedStmt *FromEval = From->getEvaluatedStmt()) { EvaluatedStmt *ToEval = To->ensureEvaluatedStmt(); ToEval->HasConstantInitialization = FromEval->HasConstantInitialization; ToEval->HasConstantDestruction = FromEval->HasConstantDestruction; // FIXME: Also import the initializer value. } // FIXME: Other bits to merge? return Error::success(); } Error ASTNodeImporter::ImportDefinition( EnumDecl *From, EnumDecl *To, ImportDefinitionKind Kind) { if (To->getDefinition() || To->isBeingDefined()) { if (Kind == IDK_Everything) return ImportDeclContext(From, /*ForceImport=*/true); return Error::success(); } To->startDefinition(); if (Error Err = setTypedefNameForAnonDecl(From, To, Importer)) return Err; ExpectedType ToTypeOrErr = import(Importer.getFromContext().getTypeDeclType(From)); if (!ToTypeOrErr) return ToTypeOrErr.takeError(); ExpectedType ToPromotionTypeOrErr = import(From->getPromotionType()); if (!ToPromotionTypeOrErr) return ToPromotionTypeOrErr.takeError(); if (shouldForceImportDeclContext(Kind)) if (Error Err = ImportDeclContext(From, /*ForceImport=*/true)) return Err; // FIXME: we might need to merge the number of positive or negative bits // if the enumerator lists don't match. To->completeDefinition(*ToTypeOrErr, *ToPromotionTypeOrErr, From->getNumPositiveBits(), From->getNumNegativeBits()); return Error::success(); } Error ASTNodeImporter::ImportTemplateArguments( ArrayRef FromArgs, SmallVectorImpl &ToArgs) { for (const auto &Arg : FromArgs) { if (auto ToOrErr = import(Arg)) ToArgs.push_back(*ToOrErr); else return ToOrErr.takeError(); } return Error::success(); } // FIXME: Do not forget to remove this and use only 'import'. Expected 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, bool IgnoreTemplateParmDepth) { // Eliminate a potential failure point where we attempt to re-import // something we're trying to import while completing ToRecord. Decl *ToOrigin = Importer.GetOriginalDecl(To); if (ToOrigin) { To = ToOrigin; } StructuralEquivalenceContext Ctx( Importer.getFromContext(), Importer.getToContext(), Importer.getNonEquivalentDecls(), getStructuralEquivalenceKind(Importer), /*StrictTypeSpelling=*/false, Complain, /*ErrorOnTagTypeMismatch=*/false, IgnoreTemplateParmDepth); return Ctx.IsEquivalent(From, To); } ExpectedDecl ASTNodeImporter::VisitDecl(Decl *D) { Importer.FromDiag(D->getLocation(), diag::err_unsupported_ast_node) << D->getDeclKindName(); return make_error(ASTImportError::UnsupportedConstruct); } ExpectedDecl ASTNodeImporter::VisitImportDecl(ImportDecl *D) { Importer.FromDiag(D->getLocation(), diag::err_unsupported_ast_node) << D->getDeclKindName(); return make_error(ASTImportError::UnsupportedConstruct); } ExpectedDecl ASTNodeImporter::VisitEmptyDecl(EmptyDecl *D) { // Import the context of this declaration. DeclContext *DC, *LexicalDC; if (Error Err = ImportDeclContext(D, DC, LexicalDC)) return std::move(Err); // Import the location of this declaration. ExpectedSLoc LocOrErr = import(D->getLocation()); if (!LocOrErr) return LocOrErr.takeError(); EmptyDecl *ToD; if (GetImportedOrCreateDecl(ToD, D, Importer.getToContext(), DC, *LocOrErr)) return ToD; ToD->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToD); return ToD; } ExpectedDecl ASTNodeImporter::VisitTranslationUnitDecl(TranslationUnitDecl *D) { TranslationUnitDecl *ToD = Importer.getToContext().getTranslationUnitDecl(); Importer.MapImported(D, ToD); return ToD; } ExpectedDecl ASTNodeImporter::VisitBindingDecl(BindingDecl *D) { DeclContext *DC, *LexicalDC; DeclarationName Name; SourceLocation Loc; NamedDecl *ToND; if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToND, Loc)) return std::move(Err); if (ToND) return ToND; BindingDecl *ToD; if (GetImportedOrCreateDecl(ToD, D, Importer.getToContext(), DC, Loc, Name.getAsIdentifierInfo())) return ToD; Error Err = Error::success(); QualType ToType = importChecked(Err, D->getType()); Expr *ToBinding = importChecked(Err, D->getBinding()); ValueDecl *ToDecomposedDecl = importChecked(Err, D->getDecomposedDecl()); if (Err) return std::move(Err); ToD->setBinding(ToType, ToBinding); ToD->setDecomposedDecl(ToDecomposedDecl); addDeclToContexts(D, ToD); return ToD; } ExpectedDecl ASTNodeImporter::VisitAccessSpecDecl(AccessSpecDecl *D) { ExpectedSLoc LocOrErr = import(D->getLocation()); if (!LocOrErr) return LocOrErr.takeError(); auto ColonLocOrErr = import(D->getColonLoc()); if (!ColonLocOrErr) return ColonLocOrErr.takeError(); // Import the context of this declaration. auto DCOrErr = Importer.ImportContext(D->getDeclContext()); if (!DCOrErr) return DCOrErr.takeError(); DeclContext *DC = *DCOrErr; AccessSpecDecl *ToD; if (GetImportedOrCreateDecl(ToD, D, Importer.getToContext(), D->getAccess(), DC, *LocOrErr, *ColonLocOrErr)) return ToD; // Lexical DeclContext and Semantic DeclContext // is always the same for the accessSpec. ToD->setLexicalDeclContext(DC); DC->addDeclInternal(ToD); return ToD; } ExpectedDecl ASTNodeImporter::VisitStaticAssertDecl(StaticAssertDecl *D) { auto DCOrErr = Importer.ImportContext(D->getDeclContext()); if (!DCOrErr) return DCOrErr.takeError(); DeclContext *DC = *DCOrErr; DeclContext *LexicalDC = DC; Error Err = Error::success(); auto ToLocation = importChecked(Err, D->getLocation()); auto ToRParenLoc = importChecked(Err, D->getRParenLoc()); auto ToAssertExpr = importChecked(Err, D->getAssertExpr()); auto ToMessage = importChecked(Err, D->getMessage()); if (Err) return std::move(Err); StaticAssertDecl *ToD; if (GetImportedOrCreateDecl( ToD, D, Importer.getToContext(), DC, ToLocation, ToAssertExpr, ToMessage, ToRParenLoc, D->isFailed())) return ToD; ToD->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToD); return ToD; } ExpectedDecl ASTNodeImporter::VisitNamespaceDecl(NamespaceDecl *D) { // Import the major distinguishing characteristics of this namespace. DeclContext *DC, *LexicalDC; DeclarationName Name; SourceLocation Loc; NamedDecl *ToD; if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) return std::move(Err); if (ToD) return ToD; NamespaceDecl *MergeWithNamespace = nullptr; if (!Name) { // This is an anonymous namespace. Adopt an existing anonymous // namespace if we can. // 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(); ExpectedSLoc RBraceLocOrErr = import(D->getRBraceLoc()); if (!RBraceLocOrErr) return RBraceLocOrErr.takeError(); // Create the "to" namespace, if needed. NamespaceDecl *ToNamespace = MergeWithNamespace; if (!ToNamespace) { if (GetImportedOrCreateDecl(ToNamespace, D, Importer.getToContext(), DC, D->isInline(), *BeginLocOrErr, Loc, Name.getAsIdentifierInfo(), /*PrevDecl=*/nullptr, D->isNested())) return ToNamespace; ToNamespace->setRBraceLoc(*RBraceLocOrErr); ToNamespace->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToNamespace); // If this is an anonymous namespace, register it as the anonymous // namespace within its context. if (!Name) { if (auto *TU = dyn_cast(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. Error Err = Error::success(); auto ToNamespaceLoc = importChecked(Err, D->getNamespaceLoc()); auto ToAliasLoc = importChecked(Err, D->getAliasLoc()); auto ToQualifierLoc = importChecked(Err, D->getQualifierLoc()); auto ToTargetNameLoc = importChecked(Err, D->getTargetNameLoc()); auto ToNamespace = importChecked(Err, D->getNamespace()); if (Err) return std::move(Err); IdentifierInfo *ToIdentifier = Importer.Import(D->getIdentifier()); NamespaceAliasDecl *ToD; if (GetImportedOrCreateDecl( ToD, D, Importer.getToContext(), DC, ToNamespaceLoc, ToAliasLoc, ToIdentifier, ToQualifierLoc, ToTargetNameLoc, ToNamespace)) return ToD; ToD->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToD); return ToD; } ExpectedDecl ASTNodeImporter::VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias) { // Import the major distinguishing characteristics of this typedef. DeclarationName Name; SourceLocation Loc; NamedDecl *ToD; // Do not import the DeclContext, we will import it once the TypedefNameDecl // is created. if (Error Err = ImportDeclParts(D, Name, ToD, Loc)) return std::move(Err); if (ToD) return ToD; DeclContext *DC = cast_or_null( Importer.GetAlreadyImportedOrNull(cast(D->getDeclContext()))); DeclContext *LexicalDC = cast_or_null(Importer.GetAlreadyImportedOrNull( cast(D->getLexicalDeclContext()))); // If this typedef is not in block scope, determine whether we've // seen a typedef with the same name (that we can merge with) or any // other entity by that name (which name lookup could conflict with). // Note: Repeated typedefs are not valid in C99: // 'typedef int T; typedef int T;' is invalid // We do not care about this now. if (DC && !DC->isFunctionOrMethod()) { SmallVector 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 (!hasSameVisibilityContextAndLinkage(FoundTypedef, D)) continue; QualType FromUT = D->getUnderlyingType(); QualType FoundUT = FoundTypedef->getUnderlyingType(); if (Importer.IsStructurallyEquivalent(FromUT, FoundUT)) { // If the underlying declarations are unnamed records these can be // imported as different types. We should create a distinct typedef // node in this case. // If we found an existing underlying type with a record in a // different context (than the imported), this is already reason for // having distinct typedef nodes for these. // Again this can create situation like // 'typedef int T; typedef int T;' but this is hard to avoid without // a rename strategy at import. if (!FromUT.isNull() && !FoundUT.isNull()) { RecordDecl *FromR = FromUT->getAsRecordDecl(); RecordDecl *FoundR = FoundUT->getAsRecordDecl(); if (FromR && FoundR && !hasSameVisibilityContextAndLinkage(FoundR, FromR)) continue; } // If the "From" context has a complete underlying type but we // already have a complete underlying type then return with that. if (!FromUT->isIncompleteType() && !FoundUT->isIncompleteType()) return Importer.MapImported(D, FoundTypedef); // FIXME Handle redecl chain. When you do that make consistent changes // in ASTImporterLookupTable too. } else { ConflictingDecls.push_back(FoundDecl); } } } if (!ConflictingDecls.empty()) { ExpectedName NameOrErr = Importer.HandleNameConflict( Name, DC, IDNS, ConflictingDecls.data(), ConflictingDecls.size()); if (NameOrErr) Name = NameOrErr.get(); else return NameOrErr.takeError(); } } Error Err = Error::success(); auto ToUnderlyingType = importChecked(Err, D->getUnderlyingType()); auto ToTypeSourceInfo = importChecked(Err, D->getTypeSourceInfo()); auto ToBeginLoc = importChecked(Err, D->getBeginLoc()); if (Err) return std::move(Err); // Create the new typedef node. // FIXME: ToUnderlyingType is not used. (void)ToUnderlyingType; TypedefNameDecl *ToTypedef; if (IsAlias) { if (GetImportedOrCreateDecl( 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; // Import the DeclContext and set it to the Typedef. if ((Err = ImportDeclContext(D, DC, LexicalDC))) return std::move(Err); ToTypedef->setDeclContext(DC); ToTypedef->setLexicalDeclContext(LexicalDC); // Add to the lookupTable because we could not do that in MapImported. Importer.AddToLookupTable(ToTypedef); ToTypedef->setAccess(D->getAccess()); // Templated declarations should not appear in DeclContext. TypeAliasDecl *FromAlias = IsAlias ? cast(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)) { if (IsStructuralMatch(D, FoundAlias)) return Importer.MapImported(D, FoundAlias); ConflictingDecls.push_back(FoundDecl); } } if (!ConflictingDecls.empty()) { ExpectedName NameOrErr = Importer.HandleNameConflict( Name, DC, IDNS, ConflictingDecls.data(), ConflictingDecls.size()); if (NameOrErr) Name = NameOrErr.get(); else return NameOrErr.takeError(); } } Error Err = Error::success(); auto ToTemplateParameters = importChecked(Err, D->getTemplateParameters()); auto ToTemplatedDecl = importChecked(Err, D->getTemplatedDecl()); if (Err) return std::move(Err); TypeAliasTemplateDecl *ToAlias; if (GetImportedOrCreateDecl(ToAlias, D, Importer.getToContext(), DC, Loc, Name, ToTemplateParameters, ToTemplatedDecl)) return ToAlias; ToTemplatedDecl->setDescribedAliasTemplate(ToAlias); ToAlias->setAccess(D->getAccess()); ToAlias->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToAlias); if (DC != Importer.getToContext().getTranslationUnitDecl()) updateLookupTableForTemplateParameters(*ToTemplateParameters); return ToAlias; } ExpectedDecl ASTNodeImporter::VisitLabelDecl(LabelDecl *D) { // Import the major distinguishing characteristics of this label. DeclContext *DC, *LexicalDC; DeclarationName Name; SourceLocation Loc; NamedDecl *ToD; if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) return std::move(Err); if (ToD) return ToD; assert(LexicalDC->isFunctionOrMethod()); LabelDecl *ToLabel; if (D->isGnuLocal()) { ExpectedSLoc BeginLocOrErr = import(D->getBeginLoc()); if (!BeginLocOrErr) return BeginLocOrErr.takeError(); if (GetImportedOrCreateDecl(ToLabel, D, Importer.getToContext(), DC, Loc, Name.getAsIdentifierInfo(), *BeginLocOrErr)) return ToLabel; } else { if (GetImportedOrCreateDecl(ToLabel, D, Importer.getToContext(), DC, Loc, Name.getAsIdentifierInfo())) return ToLabel; } Expected ToStmtOrErr = import(D->getStmt()); if (!ToStmtOrErr) return ToStmtOrErr.takeError(); ToLabel->setStmt(*ToStmtOrErr); ToLabel->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToLabel); return ToLabel; } ExpectedDecl ASTNodeImporter::VisitEnumDecl(EnumDecl *D) { // Import the major distinguishing characteristics of this enum. DeclContext *DC, *LexicalDC; DeclarationName Name; SourceLocation Loc; NamedDecl *ToD; if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) return std::move(Err); if (ToD) return ToD; // Figure out what enum name we're looking for. unsigned IDNS = Decl::IDNS_Tag; DeclarationName SearchName = Name; if (!SearchName && D->getTypedefNameForAnonDecl()) { if (Error Err = importInto( SearchName, D->getTypedefNameForAnonDecl()->getDeclName())) return std::move(Err); IDNS = Decl::IDNS_Ordinary; } else if (Importer.getToContext().getLangOpts().CPlusPlus) IDNS |= Decl::IDNS_Ordinary; // We may already have an enum of the same name; try to find and match it. EnumDecl *PrevDecl = nullptr; if (!DC->isFunctionOrMethod()) { SmallVector 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 (!hasSameVisibilityContextAndLinkage(FoundEnum, D)) continue; if (IsStructuralMatch(D, FoundEnum, !SearchName.isEmpty())) { EnumDecl *FoundDef = FoundEnum->getDefinition(); if (D->isThisDeclarationADefinition() && FoundDef) return Importer.MapImported(D, FoundDef); PrevDecl = FoundEnum->getMostRecentDecl(); break; } ConflictingDecls.push_back(FoundDecl); } } // In case of unnamed enums, we try to find an existing similar one, if none // was found, perform the import always. // Structural in-equivalence is not detected in this way here, but it may // be found when the parent decl is imported (if the enum is part of a // class). To make this totally exact a more difficult solution is needed. if (SearchName && !ConflictingDecls.empty()) { ExpectedName NameOrErr = Importer.HandleNameConflict( SearchName, DC, IDNS, ConflictingDecls.data(), ConflictingDecls.size()); if (NameOrErr) Name = NameOrErr.get(); else return NameOrErr.takeError(); } } Error Err = Error::success(); auto ToBeginLoc = importChecked(Err, D->getBeginLoc()); auto ToQualifierLoc = importChecked(Err, D->getQualifierLoc()); auto ToIntegerType = importChecked(Err, D->getIntegerType()); auto ToBraceRange = importChecked(Err, D->getBraceRange()); if (Err) return std::move(Err); // Create the enum declaration. EnumDecl *D2; if (GetImportedOrCreateDecl( D2, D, Importer.getToContext(), DC, ToBeginLoc, Loc, Name.getAsIdentifierInfo(), PrevDecl, D->isScoped(), D->isScopedUsingClassTag(), D->isFixed())) return D2; D2->setQualifierInfo(ToQualifierLoc); D2->setIntegerType(ToIntegerType); D2->setBraceRange(ToBraceRange); D2->setAccess(D->getAccess()); D2->setLexicalDeclContext(LexicalDC); addDeclToContexts(D, D2); if (MemberSpecializationInfo *MemberInfo = D->getMemberSpecializationInfo()) { TemplateSpecializationKind SK = MemberInfo->getTemplateSpecializationKind(); EnumDecl *FromInst = D->getInstantiatedFromMemberEnum(); if (Expected ToInstOrErr = import(FromInst)) D2->setInstantiationOfMemberEnum(*ToInstOrErr, SK); else return ToInstOrErr.takeError(); if (ExpectedSLoc POIOrErr = import(MemberInfo->getPointOfInstantiation())) D2->getMemberSpecializationInfo()->setPointOfInstantiation(*POIOrErr); else return POIOrErr.takeError(); } // Import the definition if (D->isCompleteDefinition()) if (Error Err = ImportDefinition(D, D2)) return std::move(Err); return D2; } ExpectedDecl ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { bool IsFriendTemplate = false; if (auto *DCXX = dyn_cast(D)) { IsFriendTemplate = DCXX->getDescribedClassTemplate() && DCXX->getDescribedClassTemplate()->getFriendObjectKind() != Decl::FOK_None; } // Import the major distinguishing characteristics of this record. DeclContext *DC = nullptr, *LexicalDC = nullptr; DeclarationName Name; SourceLocation Loc; NamedDecl *ToD = nullptr; if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) return std::move(Err); if (ToD) return ToD; // Figure out what structure name we're looking for. unsigned IDNS = Decl::IDNS_Tag; DeclarationName SearchName = Name; if (!SearchName && D->getTypedefNameForAnonDecl()) { if (Error Err = importInto( SearchName, D->getTypedefNameForAnonDecl()->getDeclName())) return std::move(Err); IDNS = Decl::IDNS_Ordinary; } else if (Importer.getToContext().getLangOpts().CPlusPlus) IDNS |= Decl::IDNS_Ordinary | Decl::IDNS_TagFriend; bool IsDependentContext = DC != LexicalDC ? LexicalDC->isDependentContext() : DC->isDependentContext(); bool DependentFriend = IsFriendTemplate && IsDependentContext; // We may already have a record of the same name; try to find and match it. RecordDecl *PrevDecl = nullptr; if (!DependentFriend && !DC->isFunctionOrMethod() && !D->isLambda()) { SmallVector 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 (!hasSameVisibilityContextAndLinkage(FoundRecord, D)) continue; if (IsStructuralMatch(D, FoundRecord)) { RecordDecl *FoundDef = FoundRecord->getDefinition(); if (D->isThisDeclarationADefinition() && FoundDef) { // FIXME: Structural equivalence check should check for same // user-defined methods. Importer.MapImported(D, FoundDef); if (const auto *DCXX = dyn_cast(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->getLambdaDependencyKind(), DCXX->isGenericLambda(), DCXX->getLambdaCaptureDefault())) return D2CXX; CXXRecordDecl::LambdaNumbering Numbering = DCXX->getLambdaNumbering(); ExpectedDecl CDeclOrErr = import(Numbering.ContextDecl); if (!CDeclOrErr) return CDeclOrErr.takeError(); Numbering.ContextDecl = *CDeclOrErr; D2CXX->setLambdaNumbering(Numbering); } else if (DCXX->isInjectedClassName()) { // We have to be careful to do a similar dance to the one in // Sema::ActOnStartCXXMemberDeclarations const bool DelayTypeCreation = true; if (GetImportedOrCreateDecl( D2CXX, D, Importer.getToContext(), D->getTagKind(), DC, *BeginLocOrErr, Loc, Name.getAsIdentifierInfo(), cast_or_null(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); addDeclToContexts(D, D2); if (ClassTemplateDecl *FromDescribed = DCXX->getDescribedClassTemplate()) { ClassTemplateDecl *ToDescribed; if (Error Err = importInto(ToDescribed, FromDescribed)) return std::move(Err); D2CXX->setDescribedClassTemplate(ToDescribed); if (!DCXX->isInjectedClassName() && !IsFriendTemplate) { // In a record describing a template the type should be an // InjectedClassNameType (see Sema::CheckClassTemplate). Update the // previously set type to the correct value here (ToDescribed is not // available at record create). CXXRecordDecl *Injected = nullptr; for (NamedDecl *Found : D2CXX->noload_lookup(Name)) { auto *Record = dyn_cast(Found); if (Record && Record->isInjectedClassName()) { Injected = Record; break; } } // Create an injected type for the whole redecl chain. // The chain may contain an already existing injected type at the start, // if yes this should be reused. We must ensure that only one type // object exists for the injected type (including the injected record // declaration), ASTContext does not check it. SmallVector Redecls = getCanonicalForwardRedeclChain(D2CXX); const Type *FrontTy = cast(Redecls.front())->getTypeForDecl(); QualType InjSpec; if (auto *InjTy = FrontTy->getAs()) InjSpec = InjTy->getInjectedSpecializationType(); else InjSpec = ToDescribed->getInjectedClassNameSpecialization(); for (auto *R : Redecls) { auto *RI = cast(R); if (R != Redecls.front() || !isa(RI->getTypeForDecl())) RI->setTypeForDecl(nullptr); // This function tries to get the injected type from getTypeForDecl, // then from the previous declaration if possible. If not, it creates // a new type. Importer.getToContext().getInjectedClassNameType(RI, InjSpec); } // Set the new type for the injected decl too. if (Injected) { Injected->setTypeForDecl(nullptr); // This function will copy the injected type from D2CXX into Injected. // The injected decl does not have a previous decl to copy from. Importer.getToContext().getTypeDeclType(Injected, D2CXX); } } } else if (MemberSpecializationInfo *MemberInfo = DCXX->getMemberSpecializationInfo()) { TemplateSpecializationKind SK = MemberInfo->getTemplateSpecializationKind(); CXXRecordDecl *FromInst = DCXX->getInstantiatedFromMemberClass(); if (Expected ToInstOrErr = import(FromInst)) D2CXX->setInstantiationOfMemberClass(*ToInstOrErr, SK); else return ToInstOrErr.takeError(); if (ExpectedSLoc POIOrErr = import(MemberInfo->getPointOfInstantiation())) D2CXX->getMemberSpecializationInfo()->setPointOfInstantiation( *POIOrErr); else return POIOrErr.takeError(); } } else { if (GetImportedOrCreateDecl(D2, D, Importer.getToContext(), D->getTagKind(), DC, *BeginLocOrErr, Loc, Name.getAsIdentifierInfo(), PrevDecl)) return D2; D2->setLexicalDeclContext(LexicalDC); addDeclToContexts(D, D2); } if (auto BraceRangeOrErr = import(D->getBraceRange())) D2->setBraceRange(*BraceRangeOrErr); else return BraceRangeOrErr.takeError(); if (auto QualifierLocOrErr = import(D->getQualifierLoc())) D2->setQualifierInfo(*QualifierLocOrErr); else return QualifierLocOrErr.takeError(); if (D->isAnonymousStructOrUnion()) D2->setAnonymousStructOrUnion(true); if (D->isCompleteDefinition()) if (Error Err = ImportDefinition(D, D2, IDK_Default)) return std::move(Err); return D2; } ExpectedDecl ASTNodeImporter::VisitEnumConstantDecl(EnumConstantDecl *D) { // Import the major distinguishing characteristics of this enumerator. DeclContext *DC, *LexicalDC; DeclarationName Name; SourceLocation Loc; NamedDecl *ToD; if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) return std::move(Err); if (ToD) return ToD; // Determine whether there are any other declarations with the same name and // in the same context. if (!LexicalDC->isFunctionOrMethod()) { SmallVector 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; } template Error ASTNodeImporter::ImportTemplateParameterLists(const DeclTy *FromD, DeclTy *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_DependentNonTemplate: if (Expected InstFDOrErr = import(FromFD->getInstantiatedFromDecl())) ToFD->setInstantiatedFromDecl(*InstFDOrErr); 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> Candidates; for (FunctionTemplateDecl *FTD : FromInfo->getCandidates()) { if (Expected ToFTDOrErr = import(FTD)) Candidates.addDecl(*ToFTDOrErr); else return ToFTDOrErr.takeError(); } // Import TemplateArgumentListInfo. TemplateArgumentListInfo ToTAInfo; const auto *FromTAArgsAsWritten = FromInfo->TemplateArgumentsAsWritten; if (FromTAArgsAsWritten) if (Error Err = ImportTemplateArgumentListInfo(*FromTAArgsAsWritten, ToTAInfo)) return Err; ToFD->setDependentTemplateSpecialization( Importer.getToContext(), Candidates, FromTAArgsAsWritten ? &ToTAInfo : nullptr); return Error::success(); } } llvm_unreachable("All cases should be covered!"); } Expected ASTNodeImporter::FindFunctionTemplateSpecialization(FunctionDecl *FromFD) { auto FunctionAndArgsOrErr = ImportFunctionTemplateWithTemplateArgsFromSpecialization(FromFD); if (!FunctionAndArgsOrErr) return FunctionAndArgsOrErr.takeError(); FunctionTemplateDecl *Template; TemplateArgsTy ToTemplArgs; std::tie(Template, ToTemplArgs) = *FunctionAndArgsOrErr; void *InsertPos = nullptr; auto *FoundSpec = Template->findSpecialization(ToTemplArgs, InsertPos); return FoundSpec; } Error ASTNodeImporter::ImportFunctionDeclBody(FunctionDecl *FromFD, FunctionDecl *ToFD) { if (Stmt *FromBody = FromFD->getBody()) { if (ExpectedStmt ToBodyOrErr = import(FromBody)) ToFD->setBody(*ToBodyOrErr); else return ToBodyOrErr.takeError(); } return Error::success(); } // Returns true if the given D has a DeclContext up to the TranslationUnitDecl // which is equal to the given DC, or D is equal to DC. static bool isAncestorDeclContextOf(const DeclContext *DC, const Decl *D) { const DeclContext *DCi = dyn_cast(D); if (!DCi) DCi = D->getDeclContext(); assert(DCi && "Declaration should have a context"); while (DCi != D->getTranslationUnitDecl()) { if (DCi == DC) return true; DCi = DCi->getParent(); } return false; } // Check if there is a declaration that has 'DC' as parent context and is // referenced from statement 'S' or one of its children. The search is done in // BFS order through children of 'S'. static bool isAncestorDeclContextOf(const DeclContext *DC, const Stmt *S) { SmallVector ToProcess; ToProcess.push_back(S); while (!ToProcess.empty()) { const Stmt *CurrentS = ToProcess.pop_back_val(); ToProcess.append(CurrentS->child_begin(), CurrentS->child_end()); if (const auto *DeclRef = dyn_cast(CurrentS)) { if (const Decl *D = DeclRef->getDecl()) if (isAncestorDeclContextOf(DC, D)) return true; } else if (const auto *E = dyn_cast_or_null(CurrentS)) { if (const Decl *D = E->getAssociatedDecl()) if (isAncestorDeclContextOf(DC, D)) return true; } } return false; } namespace { /// Check if a type has any reference to a declaration that is inside the body /// of a function. /// The \c CheckType(QualType) function should be used to determine /// this property. /// /// The type visitor visits one type object only (not recursive). /// To find all referenced declarations we must discover all type objects until /// the canonical type is reached (walk over typedef and similar objects). This /// is done by loop over all "sugar" type objects. For every such type we must /// check all declarations that are referenced from it. For this check the /// visitor is used. In the visit functions all referenced declarations except /// the one that follows in the sugar chain (if any) must be checked. For this /// check the same visitor is re-used (it has no state-dependent data). /// /// The visit functions have 3 possible return values: /// - True, found a declaration inside \c ParentDC. /// - False, found declarations only outside \c ParentDC and it is not possible /// to find more declarations (the "sugar" chain does not continue). /// - Empty optional value, found no declarations or only outside \c ParentDC, /// but it is possible to find more declarations in the type "sugar" chain. /// The loop over the "sugar" types can be implemented by using type visit /// functions only (call \c CheckType with the desugared type). With the current /// solution no visit function is needed if the type has only a desugared type /// as data. class IsTypeDeclaredInsideVisitor : public TypeVisitor> { public: IsTypeDeclaredInsideVisitor(const FunctionDecl *ParentDC) : ParentDC(ParentDC) {} bool CheckType(QualType T) { // Check the chain of "sugar" types. // The "sugar" types are typedef or similar types that have the same // canonical type. if (std::optional Res = Visit(T.getTypePtr())) return *Res; QualType DsT = T.getSingleStepDesugaredType(ParentDC->getParentASTContext()); while (DsT != T) { if (std::optional Res = Visit(DsT.getTypePtr())) return *Res; T = DsT; DsT = T.getSingleStepDesugaredType(ParentDC->getParentASTContext()); } return false; } std::optional VisitTagType(const TagType *T) { if (auto *Spec = dyn_cast(T->getDecl())) for (const auto &Arg : Spec->getTemplateArgs().asArray()) if (checkTemplateArgument(Arg)) return true; return isAncestorDeclContextOf(ParentDC, T->getDecl()); } std::optional VisitPointerType(const PointerType *T) { return CheckType(T->getPointeeType()); } std::optional VisitReferenceType(const ReferenceType *T) { return CheckType(T->getPointeeTypeAsWritten()); } std::optional VisitTypedefType(const TypedefType *T) { const TypedefNameDecl *TD = T->getDecl(); assert(TD); return isAncestorDeclContextOf(ParentDC, TD); } std::optional VisitUsingType(const UsingType *T) { if (T->getFoundDecl() && isAncestorDeclContextOf(ParentDC, T->getFoundDecl())) return true; return {}; } std::optional VisitTemplateSpecializationType(const TemplateSpecializationType *T) { for (const auto &Arg : T->template_arguments()) if (checkTemplateArgument(Arg)) return true; // This type is a "sugar" to a record type, it can have a desugared type. return {}; } std::optional VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T) { // The "associated declaration" can be the same as ParentDC. if (isAncestorDeclContextOf(ParentDC, T->getAssociatedDecl())) return true; return {}; } std::optional VisitConstantArrayType(const ConstantArrayType *T) { if (T->getSizeExpr() && isAncestorDeclContextOf(ParentDC, T->getSizeExpr())) return true; return CheckType(T->getElementType()); } std::optional VisitVariableArrayType(const VariableArrayType *T) { llvm_unreachable( "Variable array should not occur in deduced return type of a function"); } std::optional VisitIncompleteArrayType(const IncompleteArrayType *T) { llvm_unreachable("Incomplete array should not occur in deduced return type " "of a function"); } std::optional VisitDependentArrayType(const IncompleteArrayType *T) { llvm_unreachable("Dependent array should not occur in deduced return type " "of a function"); } private: const DeclContext *const ParentDC; bool checkTemplateArgument(const TemplateArgument &Arg) { switch (Arg.getKind()) { case TemplateArgument::Null: return false; case TemplateArgument::Integral: return CheckType(Arg.getIntegralType()); case TemplateArgument::Type: return CheckType(Arg.getAsType()); case TemplateArgument::Expression: return isAncestorDeclContextOf(ParentDC, Arg.getAsExpr()); case TemplateArgument::Declaration: // FIXME: The declaration in this case is not allowed to be in a function? return isAncestorDeclContextOf(ParentDC, Arg.getAsDecl()); case TemplateArgument::NullPtr: // FIXME: The type is not allowed to be in the function? return CheckType(Arg.getNullPtrType()); case TemplateArgument::StructuralValue: return CheckType(Arg.getStructuralValueType()); case TemplateArgument::Pack: for (const auto &PackArg : Arg.getPackAsArray()) if (checkTemplateArgument(PackArg)) return true; return false; case TemplateArgument::Template: // Templates can not be defined locally in functions. // A template passed as argument can be not in ParentDC. return false; case TemplateArgument::TemplateExpansion: // Templates can not be defined locally in functions. // A template passed as argument can be not in ParentDC. return false; } llvm_unreachable("Unknown TemplateArgument::ArgKind enum"); }; }; } // namespace /// This function checks if the given function has a return type that contains /// a reference (in any way) to a declaration inside the same function. bool ASTNodeImporter::hasReturnTypeDeclaredInside(FunctionDecl *D) { QualType FromTy = D->getType(); const auto *FromFPT = FromTy->getAs(); assert(FromFPT && "Must be called on FunctionProtoType"); auto IsCXX11LambdaWithouTrailingReturn = [&]() { if (Importer.FromContext.getLangOpts().CPlusPlus14) // C++14 or later return false; if (FromFPT->hasTrailingReturn()) return false; if (const auto *MD = dyn_cast(D)) return cast(MD->getDeclContext())->isLambda(); return false; }; QualType RetT = FromFPT->getReturnType(); if (isa(RetT.getTypePtr()) || IsCXX11LambdaWithouTrailingReturn()) { FunctionDecl *Def = D->getDefinition(); IsTypeDeclaredInsideVisitor Visitor(Def ? Def : D); return Visitor.CheckType(RetT); } return false; } ExplicitSpecifier ASTNodeImporter::importExplicitSpecifier(Error &Err, ExplicitSpecifier ESpec) { Expr *ExplicitExpr = ESpec.getExpr(); if (ExplicitExpr) ExplicitExpr = importChecked(Err, ESpec.getExpr()); return ExplicitSpecifier(ExplicitExpr, ESpec.getKind()); } ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { SmallVector 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 (!hasSameVisibilityContextAndLinkage(FoundFunction, D)) continue; if (IsStructuralMatch(D, FoundFunction)) { if (Decl *Def = FindAndMapDefinition(D, FoundFunction)) return Def; FoundByLookup = FoundFunction; break; } // FIXME: Check for overloading more carefully, e.g., by boosting // Sema::IsOverload out to the AST library. // Function overloading is okay in C++. if (Importer.getToContext().getLangOpts().CPlusPlus) continue; // Complain about inconsistent function types. Importer.ToDiag(Loc, diag::warn_odr_function_type_inconsistent) << Name << D->getType() << FoundFunction->getType(); Importer.ToDiag(FoundFunction->getLocation(), diag::note_odr_value_here) << FoundFunction->getType(); ConflictingDecls.push_back(FoundDecl); } } if (!ConflictingDecls.empty()) { ExpectedName NameOrErr = Importer.HandleNameConflict( Name, DC, IDNS, ConflictingDecls.data(), ConflictingDecls.size()); if (NameOrErr) Name = NameOrErr.get(); else return NameOrErr.takeError(); } } // We do not allow more than one in-class declaration of a function. This is // because AST clients like VTableBuilder asserts on this. VTableBuilder // assumes there is only one in-class declaration. Building a redecl // chain would result in more than one in-class declaration for // overrides (even if they are part of the same redecl chain inside the // derived class.) if (FoundByLookup) { if (isa(FoundByLookup)) { if (D->getLexicalDeclContext() == D->getDeclContext()) { if (!D->doesThisDeclarationHaveABody()) { if (FunctionTemplateDecl *DescribedD = D->getDescribedFunctionTemplate()) { // Handle a "templated" function together with its described // template. This avoids need for a similar check at import of the // described template. assert(FoundByLookup->getDescribedFunctionTemplate() && "Templated function mapped to non-templated?"); Importer.MapImported(DescribedD, FoundByLookup->getDescribedFunctionTemplate()); } return Importer.MapImported(D, FoundByLookup); } else { // Let's continue and build up the redecl chain in this case. // FIXME Merge the functions into one decl. } } } } DeclarationNameInfo NameInfo(Name, Loc); // Import additional name location/type info. if (Error Err = ImportDeclarationNameLoc(D->getNameInfo(), NameInfo)) return std::move(Err); QualType FromTy = D->getType(); TypeSourceInfo *FromTSI = D->getTypeSourceInfo(); // Set to true if we do not import the type of the function as is. There are // cases when the original type would result in an infinite recursion during // the import. To avoid an infinite recursion when importing, we create the // FunctionDecl with a simplified function type and update it only after the // relevant AST nodes are already imported. // The type is related to TypeSourceInfo (it references the type), so we must // do the same with TypeSourceInfo. bool UsedDifferentProtoType = false; if (const auto *FromFPT = FromTy->getAs()) { QualType FromReturnTy = FromFPT->getReturnType(); // Functions with auto return type may define a struct inside their body // and the return type could refer to that struct. // E.g.: auto foo() { struct X{}; return X(); } // To avoid an infinite recursion when importing, create the FunctionDecl // with a simplified return type. if (hasReturnTypeDeclaredInside(D)) { FromReturnTy = Importer.getFromContext().VoidTy; UsedDifferentProtoType = true; } FunctionProtoType::ExtProtoInfo FromEPI = FromFPT->getExtProtoInfo(); // FunctionProtoType::ExtProtoInfo's ExceptionSpecDecl can point to the // FunctionDecl that we are importing the FunctionProtoType for. // To avoid an infinite recursion when importing, create the FunctionDecl // with a simplified function type. if (FromEPI.ExceptionSpec.SourceDecl || FromEPI.ExceptionSpec.SourceTemplate || FromEPI.ExceptionSpec.NoexceptExpr) { FunctionProtoType::ExtProtoInfo DefaultEPI; FromEPI = DefaultEPI; UsedDifferentProtoType = true; } FromTy = Importer.getFromContext().getFunctionType( FromReturnTy, FromFPT->getParamTypes(), FromEPI); FromTSI = Importer.getFromContext().getTrivialTypeSourceInfo( FromTy, D->getBeginLoc()); } Error Err = Error::success(); auto T = importChecked(Err, FromTy); auto TInfo = importChecked(Err, FromTSI); auto ToInnerLocStart = importChecked(Err, D->getInnerLocStart()); auto ToEndLoc = importChecked(Err, D->getEndLoc()); auto ToDefaultLoc = importChecked(Err, D->getDefaultLoc()); auto ToQualifierLoc = importChecked(Err, D->getQualifierLoc()); auto TrailingRequiresClause = importChecked(Err, D->getTrailingRequiresClause()); if (Err) return std::move(Err); // 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)) { ExplicitSpecifier ESpec = importExplicitSpecifier(Err, FromConstructor->getExplicitSpecifier()); if (Err) return std::move(Err); auto ToInheritedConstructor = InheritedConstructor(); if (FromConstructor->isInheritingConstructor()) { Expected ImportedInheritedCtor = import(FromConstructor->getInheritedConstructor()); if (!ImportedInheritedCtor) return ImportedInheritedCtor.takeError(); ToInheritedConstructor = *ImportedInheritedCtor; } if (GetImportedOrCreateDecl( ToFunction, D, Importer.getToContext(), cast(DC), ToInnerLocStart, NameInfo, T, TInfo, ESpec, D->UsesFPIntrin(), D->isInlineSpecified(), D->isImplicit(), D->getConstexprKind(), ToInheritedConstructor, TrailingRequiresClause)) return ToFunction; } else if (CXXDestructorDecl *FromDtor = dyn_cast(D)) { Error Err = Error::success(); auto ToOperatorDelete = importChecked( Err, const_cast(FromDtor->getOperatorDelete())); auto ToThisArg = importChecked(Err, FromDtor->getOperatorDeleteThisArg()); if (Err) return std::move(Err); if (GetImportedOrCreateDecl( ToFunction, D, Importer.getToContext(), cast(DC), ToInnerLocStart, NameInfo, T, TInfo, D->UsesFPIntrin(), D->isInlineSpecified(), D->isImplicit(), D->getConstexprKind(), TrailingRequiresClause)) return ToFunction; CXXDestructorDecl *ToDtor = cast(ToFunction); ToDtor->setOperatorDelete(ToOperatorDelete, ToThisArg); } else if (CXXConversionDecl *FromConversion = dyn_cast(D)) { ExplicitSpecifier ESpec = importExplicitSpecifier(Err, FromConversion->getExplicitSpecifier()); if (Err) return std::move(Err); if (GetImportedOrCreateDecl( ToFunction, D, Importer.getToContext(), cast(DC), ToInnerLocStart, NameInfo, T, TInfo, D->UsesFPIntrin(), D->isInlineSpecified(), ESpec, D->getConstexprKind(), SourceLocation(), TrailingRequiresClause)) return ToFunction; } else if (auto *Method = dyn_cast(D)) { if (GetImportedOrCreateDecl( ToFunction, D, Importer.getToContext(), cast(DC), ToInnerLocStart, NameInfo, T, TInfo, Method->getStorageClass(), Method->UsesFPIntrin(), Method->isInlineSpecified(), D->getConstexprKind(), SourceLocation(), TrailingRequiresClause)) return ToFunction; } else if (auto *Guide = dyn_cast(D)) { ExplicitSpecifier ESpec = importExplicitSpecifier(Err, Guide->getExplicitSpecifier()); CXXConstructorDecl *Ctor = importChecked(Err, Guide->getCorrespondingConstructor()); if (Err) return std::move(Err); if (GetImportedOrCreateDecl( ToFunction, D, Importer.getToContext(), DC, ToInnerLocStart, ESpec, NameInfo, T, TInfo, ToEndLoc, Ctor)) return ToFunction; cast(ToFunction) ->setDeductionCandidateKind(Guide->getDeductionCandidateKind()); } else { if (GetImportedOrCreateDecl( ToFunction, D, Importer.getToContext(), DC, ToInnerLocStart, NameInfo, T, TInfo, D->getStorageClass(), D->UsesFPIntrin(), D->isInlineSpecified(), D->hasWrittenPrototype(), D->getConstexprKind(), TrailingRequiresClause)) return ToFunction; } // Connect the redecl chain. if (FoundByLookup) { auto *Recent = const_cast( FoundByLookup->getMostRecentDecl()); ToFunction->setPreviousDecl(Recent); // FIXME Probably we should merge exception specifications. E.g. In the // "To" context the existing function may have exception specification with // noexcept-unevaluated, while the newly imported function may have an // evaluated noexcept. A call to adjustExceptionSpec() on the imported // decl and its redeclarations may be required. } StringLiteral *Msg = D->getDeletedMessage(); if (Msg) { auto Imported = import(Msg); if (!Imported) return Imported.takeError(); Msg = *Imported; } ToFunction->setQualifierInfo(ToQualifierLoc); ToFunction->setAccess(D->getAccess()); ToFunction->setLexicalDeclContext(LexicalDC); ToFunction->setVirtualAsWritten(D->isVirtualAsWritten()); ToFunction->setTrivial(D->isTrivial()); ToFunction->setIsPureVirtual(D->isPureVirtual()); ToFunction->setDefaulted(D->isDefaulted()); ToFunction->setExplicitlyDefaulted(D->isExplicitlyDefaulted()); ToFunction->setDeletedAsWritten(D->isDeletedAsWritten()); ToFunction->setFriendConstraintRefersToEnclosingTemplate( D->FriendConstraintRefersToEnclosingTemplate()); ToFunction->setRangeEnd(ToEndLoc); ToFunction->setDefaultLoc(ToDefaultLoc); if (Msg) ToFunction->setDefaultedOrDeletedInfo( FunctionDecl::DefaultedOrDeletedFunctionInfo::Create( Importer.getToContext(), {}, Msg)); // Set the parameters. for (auto *Param : Parameters) { Param->setOwningFunction(ToFunction); ToFunction->addDeclInternal(Param); if (ASTImporterLookupTable *LT = Importer.SharedState->getLookupTable()) LT->update(Param, Importer.getToContext().getTranslationUnitDecl()); } ToFunction->setParams(Parameters); // We need to complete creation of FunctionProtoTypeLoc manually with setting // params it refers to. if (TInfo) { if (auto ProtoLoc = TInfo->getTypeLoc().IgnoreParens().getAs()) { for (unsigned I = 0, N = Parameters.size(); I != N; ++I) ProtoLoc.setParam(I, Parameters[I]); } } // Import the describing template function, if any. if (FromFT) { auto ToFTOrErr = import(FromFT); if (!ToFTOrErr) return ToFTOrErr.takeError(); } // Import Ctor initializers. if (auto *FromConstructor = dyn_cast(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 it is a template, import all related things. if (Error Err = ImportTemplateInformation(D, ToFunction)) return std::move(Err); if (auto *FromCXXMethod = dyn_cast(D)) if (Error Err = ImportOverriddenMethods(cast(ToFunction), FromCXXMethod)) return std::move(Err); if (D->doesThisDeclarationHaveABody()) { Error Err = ImportFunctionDeclBody(D, ToFunction); if (Err) return std::move(Err); } // Import and set the original type in case we used another type. if (UsedDifferentProtoType) { if (ExpectedType TyOrErr = import(D->getType())) ToFunction->setType(*TyOrErr); else return TyOrErr.takeError(); if (Expected TSIOrErr = import(D->getTypeSourceInfo())) ToFunction->setTypeSourceInfo(*TSIOrErr); else return TSIOrErr.takeError(); } // FIXME: Other bits to merge? addDeclToContexts(D, ToFunction); // Import the rest of the chain. I.e. import all subsequent declarations. for (++RedeclIt; RedeclIt != Redecls.end(); ++RedeclIt) { ExpectedDecl ToRedeclOrErr = import(*RedeclIt); if (!ToRedeclOrErr) return ToRedeclOrErr.takeError(); } return ToFunction; } ExpectedDecl ASTNodeImporter::VisitCXXMethodDecl(CXXMethodDecl *D) { return VisitFunctionDecl(D); } ExpectedDecl ASTNodeImporter::VisitCXXConstructorDecl(CXXConstructorDecl *D) { return VisitCXXMethodDecl(D); } ExpectedDecl ASTNodeImporter::VisitCXXDestructorDecl(CXXDestructorDecl *D) { return VisitCXXMethodDecl(D); } ExpectedDecl ASTNodeImporter::VisitCXXConversionDecl(CXXConversionDecl *D) { return VisitCXXMethodDecl(D); } ExpectedDecl ASTNodeImporter::VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D) { return VisitFunctionDecl(D); } ExpectedDecl ASTNodeImporter::VisitFieldDecl(FieldDecl *D) { // Import the major distinguishing characteristics of a variable. DeclContext *DC, *LexicalDC; DeclarationName Name; SourceLocation Loc; NamedDecl *ToD; if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) return std::move(Err); if (ToD) return ToD; // Determine whether we've already imported this field. auto FoundDecls = Importer.findDeclsInToCtx(DC, Name); for (auto *FoundDecl : FoundDecls) { if (FieldDecl *FoundField = dyn_cast(FoundDecl)) { // For anonymous fields, match up by index. if (!Name && ASTImporter::getFieldIndex(D) != ASTImporter::getFieldIndex(FoundField)) continue; if (Importer.IsStructurallyEquivalent(D->getType(), FoundField->getType())) { Importer.MapImported(D, FoundField); // In case of a FieldDecl of a ClassTemplateSpecializationDecl, the // initializer of a FieldDecl might not had been instantiated in the // "To" context. However, the "From" context might instantiated that, // thus we have to merge that. // Note: `hasInClassInitializer()` is not the same as non-null // `getInClassInitializer()` value. if (Expr *FromInitializer = D->getInClassInitializer()) { if (ExpectedExpr ToInitializerOrErr = import(FromInitializer)) { // Import of the FromInitializer may result in the setting of // InClassInitializer. If not, set it here. assert(FoundField->hasInClassInitializer() && "Field should have an in-class initializer if it has an " "expression for it."); if (!FoundField->getInClassInitializer()) FoundField->setInClassInitializer(*ToInitializerOrErr); } else { return ToInitializerOrErr.takeError(); } } return FoundField; } // FIXME: Why is this case not handled with calling HandleNameConflict? Importer.ToDiag(Loc, diag::warn_odr_field_type_inconsistent) << Name << D->getType() << FoundField->getType(); Importer.ToDiag(FoundField->getLocation(), diag::note_odr_value_here) << FoundField->getType(); return make_error(ASTImportError::NameConflict); } } Error Err = Error::success(); auto ToType = importChecked(Err, D->getType()); auto ToTInfo = importChecked(Err, D->getTypeSourceInfo()); auto ToBitWidth = importChecked(Err, D->getBitWidth()); auto ToInnerLocStart = importChecked(Err, D->getInnerLocStart()); if (Err) return std::move(Err); const Type *ToCapturedVLAType = nullptr; if (Error Err = Importer.importInto( ToCapturedVLAType, cast_or_null(D->getCapturedVLAType()))) return std::move(Err); FieldDecl *ToField; if (GetImportedOrCreateDecl(ToField, D, Importer.getToContext(), DC, ToInnerLocStart, Loc, Name.getAsIdentifierInfo(), ToType, ToTInfo, ToBitWidth, D->isMutable(), D->getInClassInitStyle())) return ToField; // We need [[no_unqiue_address]] attributes to be added to FieldDecl, before // we add fields in CXXRecordDecl::addedMember, otherwise record will be // marked as having non-zero size. Err = Importer.ImportAttrs(ToField, D); if (Err) return std::move(Err); ToField->setAccess(D->getAccess()); ToField->setLexicalDeclContext(LexicalDC); ToField->setImplicit(D->isImplicit()); if (ToCapturedVLAType) ToField->setCapturedVLAType(cast(ToCapturedVLAType)); LexicalDC->addDeclInternal(ToField); // Import initializer only after the field was created, it may have recursive // reference to the field. auto ToInitializer = importChecked(Err, D->getInClassInitializer()); if (Err) return std::move(Err); if (ToInitializer) { auto *AlreadyImported = ToField->getInClassInitializer(); if (AlreadyImported) assert(ToInitializer == AlreadyImported && "Duplicate import of in-class initializer."); else ToField->setInClassInitializer(ToInitializer); } return ToField; } ExpectedDecl ASTNodeImporter::VisitIndirectFieldDecl(IndirectFieldDecl *D) { // Import the major distinguishing characteristics of a variable. DeclContext *DC, *LexicalDC; DeclarationName Name; SourceLocation Loc; NamedDecl *ToD; if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) return std::move(Err); if (ToD) return ToD; // Determine whether we've already imported this field. auto FoundDecls = Importer.findDeclsInToCtx(DC, Name); for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { if (auto *FoundField = dyn_cast(FoundDecls[I])) { // For anonymous indirect fields, match up by index. if (!Name && ASTImporter::getFieldIndex(D) != ASTImporter::getFieldIndex(FoundField)) continue; if (Importer.IsStructurallyEquivalent(D->getType(), FoundField->getType(), !Name.isEmpty())) { Importer.MapImported(D, FoundField); return FoundField; } // If there are more anonymous fields to check, continue. if (!Name && I < N-1) continue; // FIXME: Why is this case not handled with calling HandleNameConflict? Importer.ToDiag(Loc, diag::warn_odr_field_type_inconsistent) << Name << D->getType() << FoundField->getType(); Importer.ToDiag(FoundField->getLocation(), diag::note_odr_value_here) << FoundField->getType(); return make_error(ASTImportError::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; } /// Used as return type of getFriendCountAndPosition. struct FriendCountAndPosition { /// Number of similar looking friends. unsigned int TotalCount; /// Index of the specific FriendDecl. unsigned int IndexOfDecl; }; static bool IsEquivalentFriend(ASTImporter &Importer, FriendDecl *FD1, FriendDecl *FD2) { if ((!FD1->getFriendType()) != (!FD2->getFriendType())) return false; if (const TypeSourceInfo *TSI = FD1->getFriendType()) return Importer.IsStructurallyEquivalent( TSI->getType(), FD2->getFriendType()->getType(), /*Complain=*/false); ASTImporter::NonEquivalentDeclSet NonEquivalentDecls; StructuralEquivalenceContext Ctx( FD1->getASTContext(), FD2->getASTContext(), NonEquivalentDecls, StructuralEquivalenceKind::Default, /* StrictTypeSpelling = */ false, /* Complain = */ false); return Ctx.IsEquivalent(FD1, FD2); } static FriendCountAndPosition getFriendCountAndPosition(ASTImporter &Importer, FriendDecl *FD) { unsigned int FriendCount = 0; std::optional FriendPosition; const auto *RD = cast(FD->getLexicalDeclContext()); for (FriendDecl *FoundFriend : RD->friends()) { if (FoundFriend == FD) { FriendPosition = FriendCount; ++FriendCount; } else if (IsEquivalentFriend(Importer, FD, FoundFriend)) { ++FriendCount; } } assert(FriendPosition && "Friend decl not found in own parent."); return {FriendCount, *FriendPosition}; } ExpectedDecl ASTNodeImporter::VisitFriendDecl(FriendDecl *D) { // Import the major distinguishing characteristics of a declaration. DeclContext *DC, *LexicalDC; if (Error Err = ImportDeclContext(D, DC, LexicalDC)) return std::move(Err); // Determine whether we've already imported this decl. // FriendDecl is not a NamedDecl so we cannot use lookup. // We try to maintain order and count of redundant friend declarations. const auto *RD = cast(DC); SmallVector ImportedEquivalentFriends; for (FriendDecl *ImportedFriend : RD->friends()) if (IsEquivalentFriend(Importer, D, ImportedFriend)) ImportedEquivalentFriends.push_back(ImportedFriend); FriendCountAndPosition CountAndPosition = getFriendCountAndPosition(Importer, D); assert(ImportedEquivalentFriends.size() <= CountAndPosition.TotalCount && "Class with non-matching friends is imported, ODR check wrong?"); if (ImportedEquivalentFriends.size() == CountAndPosition.TotalCount) return Importer.MapImported( D, ImportedEquivalentFriends[CountAndPosition.IndexOfDecl]); // Not found. Create it. // The declarations will be put into order later by ImportDeclContext. FriendDecl::FriendUnion ToFU; if (NamedDecl *FriendD = D->getFriendDecl()) { NamedDecl *ToFriendD; if (Error Err = importInto(ToFriendD, FriendD)) return std::move(Err); if (FriendD->getFriendObjectKind() != Decl::FOK_None && !(FriendD->isInIdentifierNamespace(Decl::IDNS_NonMemberOperator))) ToFriendD->setObjectOfFriendDecl(false); ToFU = ToFriendD; } else { // The friend is a type, not a decl. if (auto TSIOrErr = import(D->getFriendType())) ToFU = *TSIOrErr; else return TSIOrErr.takeError(); } SmallVector 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(ASTImportError::NameConflict); } } Error Err = Error::success(); auto ToType = importChecked(Err, D->getType()); auto ToTypeSourceInfo = importChecked(Err, D->getTypeSourceInfo()); auto ToBitWidth = importChecked(Err, D->getBitWidth()); auto ToInnerLocStart = importChecked(Err, D->getInnerLocStart()); if (Err) return std::move(Err); ObjCIvarDecl *ToIvar; if (GetImportedOrCreateDecl( ToIvar, D, Importer.getToContext(), cast(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 (!hasSameVisibilityContextAndLinkage(FoundVar, D)) continue; if (Importer.IsStructurallyEquivalent(D->getType(), FoundVar->getType())) { // The VarDecl in the "From" context has a definition, but in the // "To" context we already have a definition. VarDecl *FoundDef = FoundVar->getDefinition(); if (D->isThisDeclarationADefinition() && FoundDef) // FIXME Check for ODR error if the two definitions have // different initializers? return Importer.MapImported(D, FoundDef); // The VarDecl in the "From" context has an initializer, but in the // "To" context we already have an initializer. const VarDecl *FoundDInit = nullptr; if (D->getInit() && FoundVar->getAnyInitializer(FoundDInit)) // FIXME Diagnose ODR error if the two initializers are different? return Importer.MapImported(D, const_cast(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(); } } Error Err = Error::success(); auto ToType = importChecked(Err, D->getType()); auto ToTypeSourceInfo = importChecked(Err, D->getTypeSourceInfo()); auto ToInnerLocStart = importChecked(Err, D->getInnerLocStart()); auto ToQualifierLoc = importChecked(Err, D->getQualifierLoc()); if (Err) return std::move(Err); VarDecl *ToVar; if (auto *FromDecomp = dyn_cast(D)) { SmallVector Bindings(FromDecomp->bindings().size()); if (Error Err = ImportArrayChecked(FromDecomp->bindings(), Bindings.begin())) return std::move(Err); DecompositionDecl *ToDecomp; if (GetImportedOrCreateDecl( ToDecomp, FromDecomp, Importer.getToContext(), DC, ToInnerLocStart, Loc, ToType, ToTypeSourceInfo, D->getStorageClass(), Bindings)) return ToDecomp; ToVar = ToDecomp; } else { // Create the imported variable. if (GetImportedOrCreateDecl(ToVar, D, Importer.getToContext(), DC, ToInnerLocStart, Loc, Name.getAsIdentifierInfo(), ToType, ToTypeSourceInfo, D->getStorageClass())) return ToVar; } ToVar->setTSCSpec(D->getTSCSpec()); ToVar->setQualifierInfo(ToQualifierLoc); ToVar->setAccess(D->getAccess()); ToVar->setLexicalDeclContext(LexicalDC); if (D->isInlineSpecified()) ToVar->setInlineSpecified(); if (D->isInline()) ToVar->setImplicitlyInline(); if (FoundByLookup) { auto *Recent = const_cast(FoundByLookup->getMostRecentDecl()); ToVar->setPreviousDecl(Recent); } // Import the described template, if any. if (D->getDescribedVarTemplate()) { auto ToVTOrErr = import(D->getDescribedVarTemplate()); if (!ToVTOrErr) return ToVTOrErr.takeError(); } else if (MemberSpecializationInfo *MSI = D->getMemberSpecializationInfo()) { TemplateSpecializationKind SK = MSI->getTemplateSpecializationKind(); VarDecl *FromInst = D->getInstantiatedFromStaticDataMember(); if (Expected ToInstOrErr = import(FromInst)) ToVar->setInstantiationOfStaticDataMember(*ToInstOrErr, SK); else return ToInstOrErr.takeError(); if (ExpectedSLoc POIOrErr = import(MSI->getPointOfInstantiation())) ToVar->getMemberSpecializationInfo()->setPointOfInstantiation(*POIOrErr); else return POIOrErr.takeError(); } if (Error Err = ImportInitializer(D, ToVar)) return std::move(Err); if (D->isConstexpr()) ToVar->setConstexpr(true); addDeclToContexts(D, ToVar); // Import the rest of the chain. I.e. import all subsequent declarations. for (++RedeclIt; RedeclIt != Redecls.end(); ++RedeclIt) { ExpectedDecl RedeclOrErr = import(*RedeclIt); if (!RedeclOrErr) return RedeclOrErr.takeError(); } return ToVar; } ExpectedDecl ASTNodeImporter::VisitImplicitParamDecl(ImplicitParamDecl *D) { // Parameters are created in the translation unit's context, then moved // into the function declaration's context afterward. DeclContext *DC = Importer.getToContext().getTranslationUnitDecl(); Error Err = Error::success(); auto ToDeclName = importChecked(Err, D->getDeclName()); auto ToLocation = importChecked(Err, D->getLocation()); auto ToType = importChecked(Err, D->getType()); if (Err) return std::move(Err); // Create the imported parameter. ImplicitParamDecl *ToParm = nullptr; if (GetImportedOrCreateDecl(ToParm, D, Importer.getToContext(), DC, ToLocation, ToDeclName.getAsIdentifierInfo(), ToType, D->getParameterKind())) return ToParm; return ToParm; } Error ASTNodeImporter::ImportDefaultArgOfParmVarDecl( const ParmVarDecl *FromParam, ParmVarDecl *ToParam) { ToParam->setHasInheritedDefaultArg(FromParam->hasInheritedDefaultArg()); ToParam->setExplicitObjectParameterLoc( FromParam->getExplicitObjectParamThisLoc()); ToParam->setKNRPromoted(FromParam->isKNRPromoted()); if (FromParam->hasUninstantiatedDefaultArg()) { if (auto ToDefArgOrErr = import(FromParam->getUninstantiatedDefaultArg())) ToParam->setUninstantiatedDefaultArg(*ToDefArgOrErr); else return ToDefArgOrErr.takeError(); } else if (FromParam->hasUnparsedDefaultArg()) { ToParam->setUnparsedDefaultArg(); } else if (FromParam->hasDefaultArg()) { if (auto ToDefArgOrErr = import(FromParam->getDefaultArg())) ToParam->setDefaultArg(*ToDefArgOrErr); else return ToDefArgOrErr.takeError(); } return Error::success(); } Expected ASTNodeImporter::ImportInheritedConstructor(const InheritedConstructor &From) { Error Err = Error::success(); CXXConstructorDecl *ToBaseCtor = importChecked(Err, From.getConstructor()); ConstructorUsingShadowDecl *ToShadow = importChecked(Err, From.getShadowDecl()); if (Err) return std::move(Err); return InheritedConstructor(ToShadow, ToBaseCtor); } ExpectedDecl ASTNodeImporter::VisitParmVarDecl(ParmVarDecl *D) { // Parameters are created in the translation unit's context, then moved // into the function declaration's context afterward. DeclContext *DC = Importer.getToContext().getTranslationUnitDecl(); Error Err = Error::success(); auto ToDeclName = importChecked(Err, D->getDeclName()); auto ToLocation = importChecked(Err, D->getLocation()); auto ToInnerLocStart = importChecked(Err, D->getInnerLocStart()); auto ToType = importChecked(Err, D->getType()); auto ToTypeSourceInfo = importChecked(Err, D->getTypeSourceInfo()); if (Err) return std::move(Err); ParmVarDecl *ToParm; if (GetImportedOrCreateDecl(ToParm, D, Importer.getToContext(), DC, ToInnerLocStart, ToLocation, ToDeclName.getAsIdentifierInfo(), ToType, ToTypeSourceInfo, D->getStorageClass(), /*DefaultArg*/ nullptr)) return ToParm; // Set the default argument. It should be no problem if it was already done. // Do not import the default expression before GetImportedOrCreateDecl call // to avoid possible infinite import loop because circular dependency. if (Error Err = ImportDefaultArgOfParmVarDecl(D, ToParm)) return std::move(Err); if (D->isObjCMethodParameter()) { ToParm->setObjCMethodScopeInfo(D->getFunctionScopeIndex()); ToParm->setObjCDeclQualifier(D->getObjCDeclQualifier()); } else { ToParm->setScopeInfo(D->getFunctionScopeDepth(), D->getFunctionScopeIndex()); } return ToParm; } ExpectedDecl ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { // Import the major distinguishing characteristics of a method. DeclContext *DC, *LexicalDC; DeclarationName Name; SourceLocation Loc; NamedDecl *ToD; if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) return std::move(Err); if (ToD) return ToD; auto FoundDecls = Importer.findDeclsInToCtx(DC, Name); for (auto *FoundDecl : FoundDecls) { if (auto *FoundMethod = dyn_cast(FoundDecl)) { if (FoundMethod->isInstanceMethod() != D->isInstanceMethod()) continue; // Check return types. if (!Importer.IsStructurallyEquivalent(D->getReturnType(), FoundMethod->getReturnType())) { Importer.ToDiag(Loc, diag::warn_odr_objc_method_result_type_inconsistent) << D->isInstanceMethod() << Name << D->getReturnType() << FoundMethod->getReturnType(); Importer.ToDiag(FoundMethod->getLocation(), diag::note_odr_objc_method_here) << D->isInstanceMethod() << Name; return make_error(ASTImportError::NameConflict); } // Check the number of parameters. if (D->param_size() != FoundMethod->param_size()) { Importer.ToDiag(Loc, diag::warn_odr_objc_method_num_params_inconsistent) << D->isInstanceMethod() << Name << D->param_size() << FoundMethod->param_size(); Importer.ToDiag(FoundMethod->getLocation(), diag::note_odr_objc_method_here) << D->isInstanceMethod() << Name; return make_error(ASTImportError::NameConflict); } // Check parameter types. for (ObjCMethodDecl::param_iterator P = D->param_begin(), PEnd = D->param_end(), FoundP = FoundMethod->param_begin(); P != PEnd; ++P, ++FoundP) { if (!Importer.IsStructurallyEquivalent((*P)->getType(), (*FoundP)->getType())) { Importer.FromDiag((*P)->getLocation(), diag::warn_odr_objc_method_param_type_inconsistent) << D->isInstanceMethod() << Name << (*P)->getType() << (*FoundP)->getType(); Importer.ToDiag((*FoundP)->getLocation(), diag::note_odr_value_here) << (*FoundP)->getType(); return make_error(ASTImportError::NameConflict); } } // Check variadic/non-variadic. // Check the number of parameters. if (D->isVariadic() != FoundMethod->isVariadic()) { Importer.ToDiag(Loc, diag::warn_odr_objc_method_variadic_inconsistent) << D->isInstanceMethod() << Name; Importer.ToDiag(FoundMethod->getLocation(), diag::note_odr_objc_method_here) << D->isInstanceMethod() << Name; return make_error(ASTImportError::NameConflict); } // FIXME: Any other bits we need to merge? return Importer.MapImported(D, FoundMethod); } } Error Err = Error::success(); auto ToEndLoc = importChecked(Err, D->getEndLoc()); auto ToReturnType = importChecked(Err, D->getReturnType()); auto ToReturnTypeSourceInfo = importChecked(Err, D->getReturnTypeSourceInfo()); if (Err) return std::move(Err); ObjCMethodDecl *ToMethod; if (GetImportedOrCreateDecl( ToMethod, D, Importer.getToContext(), Loc, ToEndLoc, Name.getObjCSelector(), ToReturnType, ToReturnTypeSourceInfo, DC, D->isInstanceMethod(), D->isVariadic(), D->isPropertyAccessor(), D->isSynthesizedAccessorStub(), D->isImplicit(), D->isDefined(), D->getImplementationControl(), D->hasRelatedResultType())) return ToMethod; // FIXME: When we decide to merge method definitions, we'll need to // deal with implicit parameters. // Import the parameters SmallVector 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); // Implicit params are declared when Sema encounters the definition but this // never happens when the method is imported. Manually declare the implicit // params now that the MethodDecl knows its class interface. if (D->getSelfDecl()) ToMethod->createImplicitParams(Importer.getToContext(), ToMethod->getClassInterface()); return ToMethod; } ExpectedDecl ASTNodeImporter::VisitObjCTypeParamDecl(ObjCTypeParamDecl *D) { // Import the major distinguishing characteristics of a category. DeclContext *DC, *LexicalDC; DeclarationName Name; SourceLocation Loc; NamedDecl *ToD; if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) return std::move(Err); if (ToD) return ToD; Error Err = Error::success(); auto ToVarianceLoc = importChecked(Err, D->getVarianceLoc()); auto ToLocation = importChecked(Err, D->getLocation()); auto ToColonLoc = importChecked(Err, D->getColonLoc()); auto ToTypeSourceInfo = importChecked(Err, D->getTypeSourceInfo()); if (Err) return std::move(Err); ObjCTypeParamDecl *Result; if (GetImportedOrCreateDecl( Result, D, Importer.getToContext(), DC, D->getVariance(), ToVarianceLoc, D->getIndex(), ToLocation, Name.getAsIdentifierInfo(), ToColonLoc, ToTypeSourceInfo)) return Result; // Only import 'ObjCTypeParamType' after the decl is created. auto ToTypeForDecl = importChecked(Err, D->getTypeForDecl()); if (Err) return std::move(Err); Result->setTypeForDecl(ToTypeForDecl); Result->setLexicalDeclContext(LexicalDC); return Result; } ExpectedDecl ASTNodeImporter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) { // Import the major distinguishing characteristics of a category. DeclContext *DC, *LexicalDC; DeclarationName Name; SourceLocation Loc; NamedDecl *ToD; if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) return std::move(Err); if (ToD) return ToD; ObjCInterfaceDecl *ToInterface; if (Error Err = importInto(ToInterface, D->getClassInterface())) return std::move(Err); // Determine if we've already encountered this category. ObjCCategoryDecl *MergeWithCategory = ToInterface->FindCategoryDeclaration(Name.getAsIdentifierInfo()); ObjCCategoryDecl *ToCategory = MergeWithCategory; if (!ToCategory) { Error Err = Error::success(); auto ToAtStartLoc = importChecked(Err, D->getAtStartLoc()); auto ToCategoryNameLoc = importChecked(Err, D->getCategoryNameLoc()); auto ToIvarLBraceLoc = importChecked(Err, D->getIvarLBraceLoc()); auto ToIvarRBraceLoc = importChecked(Err, D->getIvarRBraceLoc()); if (Err) return std::move(Err); if (GetImportedOrCreateDecl(ToCategory, D, Importer.getToContext(), DC, ToAtStartLoc, Loc, ToCategoryNameLoc, Name.getAsIdentifierInfo(), ToInterface, /*TypeParamList=*/nullptr, ToIvarLBraceLoc, ToIvarRBraceLoc)) return ToCategory; ToCategory->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToCategory); // Import the type parameter list after MapImported, to avoid // loops when bringing in their DeclContext. if (auto PListOrErr = ImportObjCTypeParamList(D->getTypeParamList())) ToCategory->setTypeParamList(*PListOrErr); else return PListOrErr.takeError(); // Import protocols SmallVector 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::ImportUsingShadowDecls(BaseUsingDecl *D, BaseUsingDecl *ToSI) { for (UsingShadowDecl *FromShadow : D->shadows()) { if (Expected ToShadowOrErr = import(FromShadow)) ToSI->addShadowDecl(*ToShadowOrErr); else // FIXME: We return error here but the definition is already created // and available with lookups. How to fix this?.. return ToShadowOrErr.takeError(); } return ToSI; } ExpectedDecl ASTNodeImporter::VisitUsingDecl(UsingDecl *D) { DeclContext *DC, *LexicalDC; DeclarationName Name; SourceLocation Loc; NamedDecl *ToD = nullptr; if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) return std::move(Err); if (ToD) return ToD; Error Err = Error::success(); auto ToLoc = importChecked(Err, D->getNameInfo().getLoc()); auto ToUsingLoc = importChecked(Err, D->getUsingLoc()); auto ToQualifierLoc = importChecked(Err, D->getQualifierLoc()); if (Err) return std::move(Err); DeclarationNameInfo NameInfo(Name, ToLoc); if (Error Err = ImportDeclarationNameLoc(D->getNameInfo(), NameInfo)) return std::move(Err); UsingDecl *ToUsing; if (GetImportedOrCreateDecl(ToUsing, D, Importer.getToContext(), DC, ToUsingLoc, ToQualifierLoc, NameInfo, D->hasTypename())) return ToUsing; ToUsing->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToUsing); if (NamedDecl *FromPattern = Importer.getFromContext().getInstantiatedFromUsingDecl(D)) { if (Expected ToPatternOrErr = import(FromPattern)) Importer.getToContext().setInstantiatedFromUsingDecl( ToUsing, *ToPatternOrErr); else return ToPatternOrErr.takeError(); } return ImportUsingShadowDecls(D, ToUsing); } ExpectedDecl ASTNodeImporter::VisitUsingEnumDecl(UsingEnumDecl *D) { DeclContext *DC, *LexicalDC; DeclarationName Name; SourceLocation Loc; NamedDecl *ToD = nullptr; if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) return std::move(Err); if (ToD) return ToD; Error Err = Error::success(); auto ToUsingLoc = importChecked(Err, D->getUsingLoc()); auto ToEnumLoc = importChecked(Err, D->getEnumLoc()); auto ToNameLoc = importChecked(Err, D->getLocation()); auto *ToEnumType = importChecked(Err, D->getEnumType()); if (Err) return std::move(Err); UsingEnumDecl *ToUsingEnum; if (GetImportedOrCreateDecl(ToUsingEnum, D, Importer.getToContext(), DC, ToUsingLoc, ToEnumLoc, ToNameLoc, ToEnumType)) return ToUsingEnum; ToUsingEnum->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToUsingEnum); if (UsingEnumDecl *FromPattern = Importer.getFromContext().getInstantiatedFromUsingEnumDecl(D)) { if (Expected ToPatternOrErr = import(FromPattern)) Importer.getToContext().setInstantiatedFromUsingEnumDecl(ToUsingEnum, *ToPatternOrErr); else return ToPatternOrErr.takeError(); } return ImportUsingShadowDecls(D, ToUsingEnum); } ExpectedDecl ASTNodeImporter::VisitUsingShadowDecl(UsingShadowDecl *D) { DeclContext *DC, *LexicalDC; DeclarationName Name; SourceLocation Loc; NamedDecl *ToD = nullptr; if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) return std::move(Err); if (ToD) return ToD; Expected ToIntroducerOrErr = import(D->getIntroducer()); if (!ToIntroducerOrErr) return ToIntroducerOrErr.takeError(); Expected ToTargetOrErr = import(D->getTargetDecl()); if (!ToTargetOrErr) return ToTargetOrErr.takeError(); UsingShadowDecl *ToShadow; if (auto *FromConstructorUsingShadow = dyn_cast(D)) { Error Err = Error::success(); ConstructorUsingShadowDecl *Nominated = importChecked( Err, FromConstructorUsingShadow->getNominatedBaseClassShadowDecl()); if (Err) return std::move(Err); // The 'Target' parameter of ConstructorUsingShadowDecl constructor // is really the "NominatedBaseClassShadowDecl" value if it exists // (see code of ConstructorUsingShadowDecl::ConstructorUsingShadowDecl). // We should pass the NominatedBaseClassShadowDecl to it (if non-null) to // get the correct values. if (GetImportedOrCreateDecl( ToShadow, D, Importer.getToContext(), DC, Loc, cast(*ToIntroducerOrErr), Nominated ? Nominated : *ToTargetOrErr, FromConstructorUsingShadow->constructsVirtualBase())) return ToShadow; } else { if (GetImportedOrCreateDecl(ToShadow, D, Importer.getToContext(), DC, Loc, Name, *ToIntroducerOrErr, *ToTargetOrErr)) return ToShadow; } ToShadow->setLexicalDeclContext(LexicalDC); ToShadow->setAccess(D->getAccess()); if (UsingShadowDecl *FromPattern = Importer.getFromContext().getInstantiatedFromUsingShadowDecl(D)) { if (Expected ToPatternOrErr = import(FromPattern)) Importer.getToContext().setInstantiatedFromUsingShadowDecl( ToShadow, *ToPatternOrErr); else // FIXME: We return error here but the definition is already created // and available with lookups. How to fix this?.. return ToPatternOrErr.takeError(); } LexicalDC->addDeclInternal(ToShadow); return ToShadow; } ExpectedDecl ASTNodeImporter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) { DeclContext *DC, *LexicalDC; DeclarationName Name; SourceLocation Loc; NamedDecl *ToD = nullptr; if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) return std::move(Err); if (ToD) return ToD; auto ToComAncestorOrErr = Importer.ImportContext(D->getCommonAncestor()); if (!ToComAncestorOrErr) return ToComAncestorOrErr.takeError(); Error Err = Error::success(); auto ToNominatedNamespace = importChecked(Err, D->getNominatedNamespace()); auto ToUsingLoc = importChecked(Err, D->getUsingLoc()); auto ToNamespaceKeyLocation = importChecked(Err, D->getNamespaceKeyLocation()); auto ToQualifierLoc = importChecked(Err, D->getQualifierLoc()); auto ToIdentLocation = importChecked(Err, D->getIdentLocation()); if (Err) return std::move(Err); UsingDirectiveDecl *ToUsingDir; if (GetImportedOrCreateDecl(ToUsingDir, D, Importer.getToContext(), DC, ToUsingLoc, ToNamespaceKeyLocation, ToQualifierLoc, ToIdentLocation, ToNominatedNamespace, *ToComAncestorOrErr)) return ToUsingDir; ToUsingDir->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToUsingDir); return ToUsingDir; } ExpectedDecl ASTNodeImporter::VisitUsingPackDecl(UsingPackDecl *D) { DeclContext *DC, *LexicalDC; DeclarationName Name; SourceLocation Loc; NamedDecl *ToD = nullptr; if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) return std::move(Err); if (ToD) return ToD; auto ToInstantiatedFromUsingOrErr = Importer.Import(D->getInstantiatedFromUsingDecl()); if (!ToInstantiatedFromUsingOrErr) return ToInstantiatedFromUsingOrErr.takeError(); SmallVector Expansions(D->expansions().size()); if (Error Err = ImportArrayChecked(D->expansions(), Expansions.begin())) return std::move(Err); UsingPackDecl *ToUsingPack; if (GetImportedOrCreateDecl(ToUsingPack, D, Importer.getToContext(), DC, cast(*ToInstantiatedFromUsingOrErr), Expansions)) return ToUsingPack; addDeclToContexts(D, ToUsingPack); return ToUsingPack; } ExpectedDecl ASTNodeImporter::VisitUnresolvedUsingValueDecl( UnresolvedUsingValueDecl *D) { DeclContext *DC, *LexicalDC; DeclarationName Name; SourceLocation Loc; NamedDecl *ToD = nullptr; if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) return std::move(Err); if (ToD) return ToD; Error Err = Error::success(); auto ToLoc = importChecked(Err, D->getNameInfo().getLoc()); auto ToUsingLoc = importChecked(Err, D->getUsingLoc()); auto ToQualifierLoc = importChecked(Err, D->getQualifierLoc()); auto ToEllipsisLoc = importChecked(Err, D->getEllipsisLoc()); if (Err) return std::move(Err); DeclarationNameInfo NameInfo(Name, ToLoc); if (Error Err = ImportDeclarationNameLoc(D->getNameInfo(), NameInfo)) return std::move(Err); UnresolvedUsingValueDecl *ToUsingValue; if (GetImportedOrCreateDecl(ToUsingValue, D, Importer.getToContext(), DC, ToUsingLoc, ToQualifierLoc, NameInfo, ToEllipsisLoc)) return ToUsingValue; ToUsingValue->setAccess(D->getAccess()); ToUsingValue->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToUsingValue); return ToUsingValue; } ExpectedDecl ASTNodeImporter::VisitUnresolvedUsingTypenameDecl( UnresolvedUsingTypenameDecl *D) { DeclContext *DC, *LexicalDC; DeclarationName Name; SourceLocation Loc; NamedDecl *ToD = nullptr; if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) return std::move(Err); if (ToD) return ToD; Error Err = Error::success(); auto ToUsingLoc = importChecked(Err, D->getUsingLoc()); auto ToTypenameLoc = importChecked(Err, D->getTypenameLoc()); auto ToQualifierLoc = importChecked(Err, D->getQualifierLoc()); auto ToEllipsisLoc = importChecked(Err, D->getEllipsisLoc()); if (Err) return std::move(Err); UnresolvedUsingTypenameDecl *ToUsing; if (GetImportedOrCreateDecl(ToUsing, D, Importer.getToContext(), DC, ToUsingLoc, ToTypenameLoc, ToQualifierLoc, Loc, Name, ToEllipsisLoc)) return ToUsing; ToUsing->setAccess(D->getAccess()); ToUsing->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToUsing); return ToUsing; } ExpectedDecl ASTNodeImporter::VisitBuiltinTemplateDecl(BuiltinTemplateDecl *D) { Decl* ToD = nullptr; switch (D->getBuiltinTemplateKind()) { case BuiltinTemplateKind::BTK__make_integer_seq: ToD = Importer.getToContext().getMakeIntegerSeqDecl(); break; case BuiltinTemplateKind::BTK__type_pack_element: ToD = Importer.getToContext().getTypePackElementDecl(); break; } assert(ToD && "BuiltinTemplateDecl of unsupported kind!"); Importer.MapImported(D, ToD); return ToD; } Error ASTNodeImporter::ImportDefinition( ObjCInterfaceDecl *From, ObjCInterfaceDecl *To, ImportDefinitionKind Kind) { if (To->getDefinition()) { // Check consistency of superclass. ObjCInterfaceDecl *FromSuper = From->getSuperClass(); if (FromSuper) { if (auto FromSuperOrErr = import(FromSuper)) FromSuper = *FromSuperOrErr; else return FromSuperOrErr.takeError(); } ObjCInterfaceDecl *ToSuper = To->getSuperClass(); if ((bool)FromSuper != (bool)ToSuper || (FromSuper && !declaresSameEntity(FromSuper, ToSuper))) { Importer.ToDiag(To->getLocation(), diag::warn_odr_objc_superclass_inconsistent) << To->getDeclName(); if (ToSuper) Importer.ToDiag(To->getSuperClassLoc(), diag::note_odr_objc_superclass) << To->getSuperClass()->getDeclName(); else Importer.ToDiag(To->getLocation(), diag::note_odr_objc_missing_superclass); if (From->getSuperClass()) Importer.FromDiag(From->getSuperClassLoc(), diag::note_odr_objc_superclass) << From->getSuperClass()->getDeclName(); else Importer.FromDiag(From->getLocation(), diag::note_odr_objc_missing_superclass); } if (shouldForceImportDeclContext(Kind)) if (Error Err = ImportDeclContext(From)) return Err; return Error::success(); } // Start the definition. To->startDefinition(); // If this class has a superclass, import it. if (From->getSuperClass()) { if (auto SuperTInfoOrErr = import(From->getSuperClassTInfo())) To->setSuperClass(*SuperTInfoOrErr); else return SuperTInfoOrErr.takeError(); } // Import protocols SmallVector 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(); } // 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); Error Err = Error::success(); auto ToLocation = importChecked(Err, D->getLocation()); auto ToAtStartLoc = importChecked(Err, D->getAtStartLoc()); auto ToCategoryNameLoc = importChecked(Err, D->getCategoryNameLoc()); if (Err) return std::move(Err); if (GetImportedOrCreateDecl( ToImpl, D, Importer.getToContext(), DC, Importer.Import(D->getIdentifier()), Category->getClassInterface(), ToLocation, ToAtStartLoc, ToCategoryNameLoc)) return ToImpl; ToImpl->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToImpl); Category->setImplementation(ToImpl); } Importer.MapImported(D, ToImpl); if (Error Err = ImportDeclContext(D)) return std::move(Err); return ToImpl; } ExpectedDecl ASTNodeImporter::VisitObjCImplementationDecl(ObjCImplementationDecl *D) { // Find the corresponding interface. ObjCInterfaceDecl *Iface; if (Error Err = importInto(Iface, D->getClassInterface())) return std::move(Err); // Import the superclass, if any. ObjCInterfaceDecl *Super; if (Error Err = importInto(Super, D->getSuperClass())) return std::move(Err); ObjCImplementationDecl *Impl = Iface->getImplementation(); if (!Impl) { // We haven't imported an implementation yet. Create a new @implementation // now. DeclContext *DC, *LexicalDC; if (Error Err = ImportDeclContext(D, DC, LexicalDC)) return std::move(Err); Error Err = Error::success(); auto ToLocation = importChecked(Err, D->getLocation()); auto ToAtStartLoc = importChecked(Err, D->getAtStartLoc()); auto ToSuperClassLoc = importChecked(Err, D->getSuperClassLoc()); auto ToIvarLBraceLoc = importChecked(Err, D->getIvarLBraceLoc()); auto ToIvarRBraceLoc = importChecked(Err, D->getIvarRBraceLoc()); if (Err) return std::move(Err); if (GetImportedOrCreateDecl(Impl, D, Importer.getToContext(), DC, Iface, Super, ToLocation, ToAtStartLoc, ToSuperClassLoc, ToIvarLBraceLoc, ToIvarRBraceLoc)) return Impl; Impl->setLexicalDeclContext(LexicalDC); // Associate the implementation with the class it implements. Iface->setImplementation(Impl); Importer.MapImported(D, Iface->getImplementation()); } else { Importer.MapImported(D, Iface->getImplementation()); // Verify that the existing @implementation has the same superclass. if ((Super && !Impl->getSuperClass()) || (!Super && Impl->getSuperClass()) || (Super && Impl->getSuperClass() && !declaresSameEntity(Super->getCanonicalDecl(), Impl->getSuperClass()))) { Importer.ToDiag(Impl->getLocation(), diag::warn_odr_objc_superclass_inconsistent) << Iface->getDeclName(); // FIXME: It would be nice to have the location of the superclass // below. if (Impl->getSuperClass()) Importer.ToDiag(Impl->getLocation(), diag::note_odr_objc_superclass) << Impl->getSuperClass()->getDeclName(); else Importer.ToDiag(Impl->getLocation(), diag::note_odr_objc_missing_superclass); if (D->getSuperClass()) Importer.FromDiag(D->getLocation(), diag::note_odr_objc_superclass) << D->getSuperClass()->getDeclName(); else Importer.FromDiag(D->getLocation(), diag::note_odr_objc_missing_superclass); return make_error(ASTImportError::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)) { // Instance and class properties can share the same name but are different // declarations. if (FoundProp->isInstanceProperty() != D->isInstanceProperty()) continue; // Check property types. if (!Importer.IsStructurallyEquivalent(D->getType(), FoundProp->getType())) { Importer.ToDiag(Loc, diag::warn_odr_objc_property_type_inconsistent) << Name << D->getType() << FoundProp->getType(); Importer.ToDiag(FoundProp->getLocation(), diag::note_odr_value_here) << FoundProp->getType(); return make_error(ASTImportError::NameConflict); } // FIXME: Check property attributes, getters, setters, etc.? // Consider these properties to be equivalent. Importer.MapImported(D, FoundProp); return FoundProp; } } Error Err = Error::success(); auto ToType = importChecked(Err, D->getType()); auto ToTypeSourceInfo = importChecked(Err, D->getTypeSourceInfo()); auto ToAtLoc = importChecked(Err, D->getAtLoc()); auto ToLParenLoc = importChecked(Err, D->getLParenLoc()); if (Err) return std::move(Err); // Create the new property. ObjCPropertyDecl *ToProperty; if (GetImportedOrCreateDecl( ToProperty, D, Importer.getToContext(), DC, Loc, Name.getAsIdentifierInfo(), ToAtLoc, ToLParenLoc, ToType, ToTypeSourceInfo, D->getPropertyImplementation())) return ToProperty; auto ToGetterName = importChecked(Err, D->getGetterName()); auto ToSetterName = importChecked(Err, D->getSetterName()); auto ToGetterNameLoc = importChecked(Err, D->getGetterNameLoc()); auto ToSetterNameLoc = importChecked(Err, D->getSetterNameLoc()); auto ToGetterMethodDecl = importChecked(Err, D->getGetterMethodDecl()); auto ToSetterMethodDecl = importChecked(Err, D->getSetterMethodDecl()); auto ToPropertyIvarDecl = importChecked(Err, D->getPropertyIvarDecl()); if (Err) return std::move(Err); ToProperty->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToProperty); ToProperty->setPropertyAttributes(D->getPropertyAttributes()); ToProperty->setPropertyAttributesAsWritten( D->getPropertyAttributesAsWritten()); ToProperty->setGetterName(ToGetterName, ToGetterNameLoc); ToProperty->setSetterName(ToSetterName, ToSetterNameLoc); ToProperty->setGetterMethodDecl(ToGetterMethodDecl); ToProperty->setSetterMethodDecl(ToSetterMethodDecl); ToProperty->setPropertyIvarDecl(ToPropertyIvarDecl); return ToProperty; } ExpectedDecl ASTNodeImporter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) { ObjCPropertyDecl *Property; if (Error Err = importInto(Property, D->getPropertyDecl())) return std::move(Err); DeclContext *DC, *LexicalDC; if (Error Err = ImportDeclContext(D, DC, LexicalDC)) return std::move(Err); auto *InImpl = cast(LexicalDC); // Import the ivar (for an @synthesize). ObjCIvarDecl *Ivar = nullptr; if (Error Err = importInto(Ivar, D->getPropertyIvarDecl())) return std::move(Err); ObjCPropertyImplDecl *ToImpl = InImpl->FindPropertyImplDecl(Property->getIdentifier(), Property->getQueryKind()); if (!ToImpl) { Error Err = Error::success(); auto ToBeginLoc = importChecked(Err, D->getBeginLoc()); auto ToLocation = importChecked(Err, D->getLocation()); auto ToPropertyIvarDeclLoc = importChecked(Err, D->getPropertyIvarDeclLoc()); if (Err) return std::move(Err); if (GetImportedOrCreateDecl(ToImpl, D, Importer.getToContext(), DC, ToBeginLoc, ToLocation, Property, D->getPropertyImplementation(), Ivar, ToPropertyIvarDeclLoc)) return ToImpl; ToImpl->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToImpl); } else { // Check that we have the same kind of property implementation (@synthesize // vs. @dynamic). if (D->getPropertyImplementation() != ToImpl->getPropertyImplementation()) { Importer.ToDiag(ToImpl->getLocation(), diag::warn_odr_objc_property_impl_kind_inconsistent) << Property->getDeclName() << (ToImpl->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic); Importer.FromDiag(D->getLocation(), diag::note_odr_objc_property_impl_kind) << D->getPropertyDecl()->getDeclName() << (D->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic); return make_error(ASTImportError::NameConflict); } // For @synthesize, check that we have the same if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize && Ivar != ToImpl->getPropertyIvarDecl()) { Importer.ToDiag(ToImpl->getPropertyIvarDeclLoc(), diag::warn_odr_objc_synthesize_ivar_inconsistent) << Property->getDeclName() << ToImpl->getPropertyIvarDecl()->getDeclName() << Ivar->getDeclName(); Importer.FromDiag(D->getPropertyIvarDeclLoc(), diag::note_odr_objc_synthesize_ivar_here) << D->getPropertyIvarDecl()->getDeclName(); return make_error(ASTImportError::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. ExpectedSLoc BeginLocOrErr = import(D->getBeginLoc()); if (!BeginLocOrErr) return BeginLocOrErr.takeError(); ExpectedSLoc LocationOrErr = import(D->getLocation()); if (!LocationOrErr) return LocationOrErr.takeError(); TemplateTypeParmDecl *ToD = nullptr; if (GetImportedOrCreateDecl( ToD, D, Importer.getToContext(), Importer.getToContext().getTranslationUnitDecl(), *BeginLocOrErr, *LocationOrErr, D->getDepth(), D->getIndex(), Importer.Import(D->getIdentifier()), D->wasDeclaredWithTypename(), D->isParameterPack(), D->hasTypeConstraint())) return ToD; // Import the type-constraint if (const TypeConstraint *TC = D->getTypeConstraint()) { Error Err = Error::success(); auto ToConceptRef = importChecked(Err, TC->getConceptReference()); auto ToIDC = importChecked(Err, TC->getImmediatelyDeclaredConstraint()); if (Err) return std::move(Err); ToD->setTypeConstraint(ToConceptRef, ToIDC); } if (D->hasDefaultArgument()) { Expected ToDefaultArgOrErr = import(D->getDefaultArgument()); if (!ToDefaultArgOrErr) return ToDefaultArgOrErr.takeError(); ToD->setDefaultArgument(ToD->getASTContext(), *ToDefaultArgOrErr); } return ToD; } ExpectedDecl ASTNodeImporter::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) { Error Err = Error::success(); auto ToDeclName = importChecked(Err, D->getDeclName()); auto ToLocation = importChecked(Err, D->getLocation()); auto ToType = importChecked(Err, D->getType()); auto ToTypeSourceInfo = importChecked(Err, D->getTypeSourceInfo()); auto ToInnerLocStart = importChecked(Err, D->getInnerLocStart()); if (Err) return std::move(Err); NonTypeTemplateParmDecl *ToD = nullptr; if (GetImportedOrCreateDecl(ToD, D, Importer.getToContext(), Importer.getToContext().getTranslationUnitDecl(), ToInnerLocStart, ToLocation, D->getDepth(), D->getPosition(), ToDeclName.getAsIdentifierInfo(), ToType, D->isParameterPack(), ToTypeSourceInfo)) return ToD; if (D->hasDefaultArgument()) { Expected ToDefaultArgOrErr = import(D->getDefaultArgument()); if (!ToDefaultArgOrErr) return ToDefaultArgOrErr.takeError(); ToD->setDefaultArgument(Importer.getToContext(), *ToDefaultArgOrErr); } 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(); TemplateTemplateParmDecl *ToD = nullptr; if (GetImportedOrCreateDecl( ToD, D, Importer.getToContext(), Importer.getToContext().getTranslationUnitDecl(), *LocationOrErr, D->getDepth(), D->getPosition(), D->isParameterPack(), (*NameOrErr).getAsIdentifierInfo(), D->wasDeclaredWithTypename(), *TemplateParamsOrErr)) return ToD; if (D->hasDefaultArgument()) { Expected ToDefaultArgOrErr = import(D->getDefaultArgument()); if (!ToDefaultArgOrErr) return ToDefaultArgOrErr.takeError(); ToD->setDefaultArgument(Importer.getToContext(), *ToDefaultArgOrErr); } 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) { // Import the major distinguishing characteristics of this class template. DeclContext *DC, *LexicalDC; DeclarationName Name; SourceLocation Loc; NamedDecl *ToD; if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) return std::move(Err); if (ToD) return ToD; // Should check if a declaration is friend in a dependent context. // Such templates are not linked together in a declaration chain. // The ASTImporter strategy is to map existing forward declarations to // imported ones only if strictly necessary, otherwise import these as new // forward declarations. In case of the "dependent friend" declarations, new // declarations are created, but not linked in a declaration chain. auto IsDependentFriend = [](ClassTemplateDecl *TD) { return TD->getFriendObjectKind() != Decl::FOK_None && TD->getLexicalDeclContext()->isDependentContext(); }; bool DependentFriend = IsDependentFriend(D); ClassTemplateDecl *FoundByLookup = nullptr; // We may already have a template of the same name; try to find and match it. if (!DC->isFunctionOrMethod()) { SmallVector 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 (!hasSameVisibilityContextAndLinkage(FoundTemplate, D)) continue; // FIXME: sufficient conditon for 'IgnoreTemplateParmDepth'? bool IgnoreTemplateParmDepth = (FoundTemplate->getFriendObjectKind() != Decl::FOK_None) != (D->getFriendObjectKind() != Decl::FOK_None); if (IsStructuralMatch(D, FoundTemplate, /*Complain=*/true, IgnoreTemplateParmDepth)) { if (DependentFriend || IsDependentFriend(FoundTemplate)) continue; ClassTemplateDecl *TemplateWithDef = getTemplateDefinition(FoundTemplate); if (D->isThisDeclarationADefinition() && TemplateWithDef) return Importer.MapImported(D, TemplateWithDef); if (!FoundByLookup) FoundByLookup = FoundTemplate; // Search in all matches because there may be multiple decl chains, // see ASTTests test ImportExistingFriendClassTemplateDef. continue; } ConflictingDecls.push_back(FoundDecl); } } if (!ConflictingDecls.empty()) { ExpectedName NameOrErr = Importer.HandleNameConflict( Name, DC, Decl::IDNS_Ordinary, ConflictingDecls.data(), ConflictingDecls.size()); if (NameOrErr) Name = NameOrErr.get(); else return NameOrErr.takeError(); } } CXXRecordDecl *FromTemplated = D->getTemplatedDecl(); auto TemplateParamsOrErr = import(D->getTemplateParameters()); if (!TemplateParamsOrErr) return TemplateParamsOrErr.takeError(); // Create the declaration that is being templated. CXXRecordDecl *ToTemplated; if (Error Err = importInto(ToTemplated, FromTemplated)) return std::move(Err); // Create the class template declaration itself. ClassTemplateDecl *D2; if (GetImportedOrCreateDecl(D2, D, Importer.getToContext(), DC, Loc, Name, *TemplateParamsOrErr, ToTemplated)) return D2; ToTemplated->setDescribedClassTemplate(D2); D2->setAccess(D->getAccess()); D2->setLexicalDeclContext(LexicalDC); addDeclToContexts(D, D2); updateLookupTableForTemplateParameters(**TemplateParamsOrErr); if (FoundByLookup) { auto *Recent = const_cast(FoundByLookup->getMostRecentDecl()); // It is possible that during the import of the class template definition // we start the import of a fwd friend decl of the very same class template // and we add the fwd friend decl to the lookup table. But the ToTemplated // had been created earlier and by that time the lookup could not find // anything existing, so it has no previous decl. Later, (still during the // import of the fwd friend decl) we start to import the definition again // and this time the lookup finds the previous fwd friend class template. // In this case we must set up the previous decl for the templated decl. if (!ToTemplated->getPreviousDecl()) { assert(FoundByLookup->getTemplatedDecl() && "Found decl must have its templated decl set"); CXXRecordDecl *PrevTemplated = FoundByLookup->getTemplatedDecl()->getMostRecentDecl(); if (ToTemplated != PrevTemplated) ToTemplated->setPreviousDecl(PrevTemplated); } D2->setPreviousDecl(Recent); } return D2; } ExpectedDecl ASTNodeImporter::VisitClassTemplateSpecializationDecl( ClassTemplateSpecializationDecl *D) { ClassTemplateDecl *ClassTemplate; if (Error Err = importInto(ClassTemplate, D->getSpecializedTemplate())) return std::move(Err); // Import the context of this declaration. DeclContext *DC, *LexicalDC; if (Error Err = ImportDeclContext(D, DC, LexicalDC)) return std::move(Err); // Import template arguments. SmallVector TemplateArgs; if (Error Err = ImportTemplateArguments(D->getTemplateArgs().asArray(), TemplateArgs)) return std::move(Err); // Try to find an existing specialization with these template arguments and // template parameter list. void *InsertPos = nullptr; ClassTemplateSpecializationDecl *PrevDecl = nullptr; ClassTemplatePartialSpecializationDecl *PartialSpec = dyn_cast(D); // Import template parameters. TemplateParameterList *ToTPList = nullptr; if (PartialSpec) { auto ToTPListOrErr = import(PartialSpec->getTemplateParameters()); if (!ToTPListOrErr) return ToTPListOrErr.takeError(); ToTPList = *ToTPListOrErr; PrevDecl = ClassTemplate->findPartialSpecialization(TemplateArgs, *ToTPListOrErr, InsertPos); } else PrevDecl = ClassTemplate->findSpecialization(TemplateArgs, InsertPos); if (PrevDecl) { if (IsStructuralMatch(D, PrevDecl)) { CXXRecordDecl *PrevDefinition = PrevDecl->getDefinition(); if (D->isThisDeclarationADefinition() && PrevDefinition) { Importer.MapImported(D, PrevDefinition); // Import those default field initializers which have been // instantiated in the "From" context, but not in the "To" context. for (auto *FromField : D->fields()) { auto ToOrErr = import(FromField); if (!ToOrErr) return ToOrErr.takeError(); } // Import those methods which have been instantiated in the // "From" context, but not in the "To" context. for (CXXMethodDecl *FromM : D->methods()) { auto ToOrErr = import(FromM); if (!ToOrErr) return ToOrErr.takeError(); } // TODO Import instantiated default arguments. // TODO Import instantiated exception specifications. // // Generally, ASTCommon.h/DeclUpdateKind enum gives a very good hint // what else could be fused during an AST merge. return PrevDefinition; } } else { // ODR violation. // FIXME HandleNameConflict return make_error(ASTImportError::NameConflict); } } // Import the location of this declaration. ExpectedSLoc BeginLocOrErr = import(D->getBeginLoc()); if (!BeginLocOrErr) return BeginLocOrErr.takeError(); ExpectedSLoc IdLocOrErr = import(D->getLocation()); if (!IdLocOrErr) return IdLocOrErr.takeError(); // Import TemplateArgumentListInfo. TemplateArgumentListInfo ToTAInfo; if (const auto *ASTTemplateArgs = D->getTemplateArgsAsWritten()) { if (Error Err = ImportTemplateArgumentListInfo(*ASTTemplateArgs, ToTAInfo)) return std::move(Err); } // Create the specialization. ClassTemplateSpecializationDecl *D2 = nullptr; if (PartialSpec) { QualType CanonInjType; if (Error Err = importInto( CanonInjType, PartialSpec->getInjectedSpecializationType())) return std::move(Err); CanonInjType = CanonInjType.getCanonicalType(); if (GetImportedOrCreateDecl( D2, D, Importer.getToContext(), D->getTagKind(), DC, *BeginLocOrErr, *IdLocOrErr, ToTPList, ClassTemplate, llvm::ArrayRef(TemplateArgs.data(), TemplateArgs.size()), CanonInjType, cast_or_null(PrevDecl))) return D2; // Update InsertPos, because preceding import calls may have invalidated // it by adding new specializations. auto *PartSpec2 = cast(D2); if (!ClassTemplate->findPartialSpecialization(TemplateArgs, ToTPList, InsertPos)) // Add this partial specialization to the class template. ClassTemplate->AddPartialSpecialization(PartSpec2, InsertPos); if (Expected ToInstOrErr = import(PartialSpec->getInstantiatedFromMember())) PartSpec2->setInstantiatedFromMember(*ToInstOrErr); else return ToInstOrErr.takeError(); updateLookupTableForTemplateParameters(*ToTPList); } else { // Not a partial specialization. if (GetImportedOrCreateDecl( D2, D, Importer.getToContext(), D->getTagKind(), DC, *BeginLocOrErr, *IdLocOrErr, ClassTemplate, TemplateArgs, PrevDecl)) return D2; // Update InsertPos, because preceding import calls may have invalidated // it by adding new specializations. if (!ClassTemplate->findSpecialization(TemplateArgs, InsertPos)) // Add this specialization to the class template. ClassTemplate->AddSpecialization(D2, InsertPos); } D2->setSpecializationKind(D->getSpecializationKind()); // Set the context of this specialization/instantiation. D2->setLexicalDeclContext(LexicalDC); // Add to the DC only if it was an explicit specialization/instantiation. if (D2->isExplicitInstantiationOrSpecialization()) { LexicalDC->addDeclInternal(D2); } if (auto BraceRangeOrErr = import(D->getBraceRange())) D2->setBraceRange(*BraceRangeOrErr); else return BraceRangeOrErr.takeError(); if (Error Err = ImportTemplateParameterLists(D, D2)) return std::move(Err); // Import the qualifier, if any. if (auto LocOrErr = import(D->getQualifierLoc())) D2->setQualifierInfo(*LocOrErr); else return LocOrErr.takeError(); if (D->getTemplateArgsAsWritten()) D2->setTemplateArgsAsWritten(ToTAInfo); if (auto LocOrErr = import(D->getTemplateKeywordLoc())) D2->setTemplateKeywordLoc(*LocOrErr); else return LocOrErr.takeError(); if (auto LocOrErr = import(D->getExternKeywordLoc())) D2->setExternKeywordLoc(*LocOrErr); else return LocOrErr.takeError(); if (D->getPointOfInstantiation().isValid()) { if (auto POIOrErr = import(D->getPointOfInstantiation())) D2->setPointOfInstantiation(*POIOrErr); else return POIOrErr.takeError(); } D2->setTemplateSpecializationKind(D->getTemplateSpecializationKind()); if (auto P = D->getInstantiatedFrom()) { if (auto *CTD = P.dyn_cast()) { if (auto CTDorErr = import(CTD)) D2->setInstantiationOf(*CTDorErr); } else { auto *CTPSD = cast(P); auto CTPSDOrErr = import(CTPSD); if (!CTPSDOrErr) return CTPSDOrErr.takeError(); const TemplateArgumentList &DArgs = D->getTemplateInstantiationArgs(); SmallVector D2ArgsVec(DArgs.size()); for (unsigned I = 0; I < DArgs.size(); ++I) { const TemplateArgument &DArg = DArgs[I]; if (auto ArgOrErr = import(DArg)) D2ArgsVec[I] = *ArgOrErr; else return ArgOrErr.takeError(); } D2->setInstantiationOf( *CTPSDOrErr, TemplateArgumentList::CreateCopy(Importer.getToContext(), D2ArgsVec)); } } if (D->isCompleteDefinition()) if (Error Err = ImportDefinition(D, D2)) return std::move(Err); return D2; } ExpectedDecl ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) { // Import the major distinguishing characteristics of this variable template. DeclContext *DC, *LexicalDC; DeclarationName Name; SourceLocation Loc; NamedDecl *ToD; if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) return std::move(Err); if (ToD) return ToD; // We may already have a template of the same name; try to find and match it. assert(!DC->isFunctionOrMethod() && "Variable templates cannot be declared at function scope"); SmallVector ConflictingDecls; auto FoundDecls = Importer.findDeclsInToCtx(DC, Name); VarTemplateDecl *FoundByLookup = nullptr; for (auto *FoundDecl : FoundDecls) { if (!FoundDecl->isInIdentifierNamespace(Decl::IDNS_Ordinary)) continue; if (VarTemplateDecl *FoundTemplate = dyn_cast(FoundDecl)) { // Use the templated decl, some linkage flags are set only there. if (!hasSameVisibilityContextAndLinkage(FoundTemplate->getTemplatedDecl(), D->getTemplatedDecl())) continue; if (IsStructuralMatch(D, FoundTemplate)) { // FIXME Check for ODR error if the two definitions have // different initializers? VarTemplateDecl *FoundDef = getTemplateDefinition(FoundTemplate); if (D->getDeclContext()->isRecord()) { assert(FoundTemplate->getDeclContext()->isRecord() && "Member variable template imported as non-member, " "inconsistent imported AST?"); if (FoundDef) return Importer.MapImported(D, FoundDef); if (!D->isThisDeclarationADefinition()) return Importer.MapImported(D, FoundTemplate); } else { if (FoundDef && D->isThisDeclarationADefinition()) return Importer.MapImported(D, FoundDef); } FoundByLookup = FoundTemplate; break; } ConflictingDecls.push_back(FoundDecl); } } if (!ConflictingDecls.empty()) { ExpectedName NameOrErr = Importer.HandleNameConflict( Name, DC, Decl::IDNS_Ordinary, ConflictingDecls.data(), ConflictingDecls.size()); if (NameOrErr) Name = NameOrErr.get(); else return NameOrErr.takeError(); } VarDecl *DTemplated = D->getTemplatedDecl(); // Import the type. // FIXME: Value not used? ExpectedType TypeOrErr = import(DTemplated->getType()); if (!TypeOrErr) return TypeOrErr.takeError(); // Create the declaration that is being templated. VarDecl *ToTemplated; if (Error Err = importInto(ToTemplated, DTemplated)) return std::move(Err); // Create the variable template declaration itself. auto TemplateParamsOrErr = import(D->getTemplateParameters()); if (!TemplateParamsOrErr) return TemplateParamsOrErr.takeError(); VarTemplateDecl *ToVarTD; if (GetImportedOrCreateDecl(ToVarTD, D, Importer.getToContext(), DC, Loc, Name, *TemplateParamsOrErr, ToTemplated)) return ToVarTD; ToTemplated->setDescribedVarTemplate(ToVarTD); ToVarTD->setAccess(D->getAccess()); ToVarTD->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToVarTD); if (DC != Importer.getToContext().getTranslationUnitDecl()) updateLookupTableForTemplateParameters(**TemplateParamsOrErr); if (FoundByLookup) { auto *Recent = const_cast(FoundByLookup->getMostRecentDecl()); if (!ToTemplated->getPreviousDecl()) { auto *PrevTemplated = FoundByLookup->getTemplatedDecl()->getMostRecentDecl(); if (ToTemplated != PrevTemplated) ToTemplated->setPreviousDecl(PrevTemplated); } ToVarTD->setPreviousDecl(Recent); } return ToVarTD; } ExpectedDecl ASTNodeImporter::VisitVarTemplateSpecializationDecl( VarTemplateSpecializationDecl *D) { // A VarTemplateSpecializationDecl inherits from VarDecl, the import is done // in an analog way (but specialized for this case). SmallVector Redecls = getCanonicalForwardRedeclChain(D); auto RedeclIt = Redecls.begin(); // Import the first part of the decl chain. I.e. import all previous // declarations starting from the canonical decl. for (; RedeclIt != Redecls.end() && *RedeclIt != D; ++RedeclIt) { ExpectedDecl RedeclOrErr = import(*RedeclIt); if (!RedeclOrErr) return RedeclOrErr.takeError(); } assert(*RedeclIt == D); VarTemplateDecl *VarTemplate = nullptr; if (Error Err = importInto(VarTemplate, D->getSpecializedTemplate())) return std::move(Err); // Import the context of this declaration. DeclContext *DC, *LexicalDC; if (Error Err = ImportDeclContext(D, DC, LexicalDC)) return std::move(Err); // Import the location of this declaration. ExpectedSLoc BeginLocOrErr = import(D->getBeginLoc()); if (!BeginLocOrErr) return BeginLocOrErr.takeError(); auto IdLocOrErr = import(D->getLocation()); if (!IdLocOrErr) return IdLocOrErr.takeError(); // Import template arguments. SmallVector TemplateArgs; if (Error Err = ImportTemplateArguments(D->getTemplateArgs().asArray(), TemplateArgs)) return std::move(Err); // Try to find an existing specialization with these template arguments. void *InsertPos = nullptr; VarTemplateSpecializationDecl *FoundSpecialization = VarTemplate->findSpecialization(TemplateArgs, InsertPos); if (FoundSpecialization) { if (IsStructuralMatch(D, FoundSpecialization)) { VarDecl *FoundDef = FoundSpecialization->getDefinition(); if (D->getDeclContext()->isRecord()) { // In a record, it is allowed only to have one optional declaration and // one definition of the (static or constexpr) variable template. assert( FoundSpecialization->getDeclContext()->isRecord() && "Member variable template specialization imported as non-member, " "inconsistent imported AST?"); if (FoundDef) return Importer.MapImported(D, FoundDef); if (!D->isThisDeclarationADefinition()) return Importer.MapImported(D, FoundSpecialization); } else { // If definition is imported and there is already one, map to it. // Otherwise create a new variable and link it to the existing. if (FoundDef && D->isThisDeclarationADefinition()) return Importer.MapImported(D, FoundDef); } } else { return make_error(ASTImportError::NameConflict); } } VarTemplateSpecializationDecl *D2 = nullptr; TemplateArgumentListInfo ToTAInfo; if (const auto *Args = D->getTemplateArgsAsWritten()) { if (Error Err = ImportTemplateArgumentListInfo(*Args, ToTAInfo)) return std::move(Err); } using PartVarSpecDecl = VarTemplatePartialSpecializationDecl; // Create a new specialization. if (auto *FromPartial = dyn_cast(D)) { auto ToTPListOrErr = import(FromPartial->getTemplateParameters()); if (!ToTPListOrErr) return ToTPListOrErr.takeError(); PartVarSpecDecl *ToPartial; if (GetImportedOrCreateDecl(ToPartial, D, Importer.getToContext(), DC, *BeginLocOrErr, *IdLocOrErr, *ToTPListOrErr, VarTemplate, QualType(), nullptr, D->getStorageClass(), TemplateArgs)) return ToPartial; if (Expected ToInstOrErr = import(FromPartial->getInstantiatedFromMember())) ToPartial->setInstantiatedFromMember(*ToInstOrErr); else return ToInstOrErr.takeError(); if (FromPartial->isMemberSpecialization()) ToPartial->setMemberSpecialization(); D2 = ToPartial; // FIXME: Use this update if VarTemplatePartialSpecializationDecl is fixed // to adopt template parameters. // updateLookupTableForTemplateParameters(**ToTPListOrErr); } else { // Full specialization if (GetImportedOrCreateDecl(D2, D, Importer.getToContext(), DC, *BeginLocOrErr, *IdLocOrErr, VarTemplate, QualType(), nullptr, D->getStorageClass(), TemplateArgs)) return D2; } // Update InsertPos, because preceding import calls may have invalidated // it by adding new specializations. if (!VarTemplate->findSpecialization(TemplateArgs, InsertPos)) VarTemplate->AddSpecialization(D2, InsertPos); QualType T; if (Error Err = importInto(T, D->getType())) return std::move(Err); D2->setType(T); auto TInfoOrErr = import(D->getTypeSourceInfo()); if (!TInfoOrErr) return TInfoOrErr.takeError(); D2->setTypeSourceInfo(*TInfoOrErr); if (D->getPointOfInstantiation().isValid()) { if (ExpectedSLoc POIOrErr = import(D->getPointOfInstantiation())) D2->setPointOfInstantiation(*POIOrErr); else return POIOrErr.takeError(); } D2->setSpecializationKind(D->getSpecializationKind()); if (D->getTemplateArgsAsWritten()) D2->setTemplateArgsAsWritten(ToTAInfo); if (auto LocOrErr = import(D->getQualifierLoc())) D2->setQualifierInfo(*LocOrErr); else return LocOrErr.takeError(); if (D->isConstexpr()) D2->setConstexpr(true); D2->setAccess(D->getAccess()); if (Error Err = ImportInitializer(D, D2)) return std::move(Err); if (FoundSpecialization) D2->setPreviousDecl(FoundSpecialization->getMostRecentDecl()); addDeclToContexts(D, D2); // Import the rest of the chain. I.e. import all subsequent declarations. for (++RedeclIt; RedeclIt != Redecls.end(); ++RedeclIt) { ExpectedDecl RedeclOrErr = import(*RedeclIt); if (!RedeclOrErr) return RedeclOrErr.takeError(); } return D2; } ExpectedDecl ASTNodeImporter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { DeclContext *DC, *LexicalDC; DeclarationName Name; SourceLocation Loc; NamedDecl *ToD; if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) return std::move(Err); if (ToD) return ToD; const FunctionTemplateDecl *FoundByLookup = nullptr; // Try to find a function in our own ("to") context with the same name, same // type, and in the same context as the function we're importing. // FIXME Split this into a separate function. if (!LexicalDC->isFunctionOrMethod()) { unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_OrdinaryFriend; auto FoundDecls = Importer.findDeclsInToCtx(DC, Name); for (auto *FoundDecl : FoundDecls) { if (!FoundDecl->isInIdentifierNamespace(IDNS)) continue; if (auto *FoundTemplate = dyn_cast(FoundDecl)) { if (!hasSameVisibilityContextAndLinkage(FoundTemplate, D)) continue; if (IsStructuralMatch(D, FoundTemplate)) { FunctionTemplateDecl *TemplateWithDef = getTemplateDefinition(FoundTemplate); if (D->isThisDeclarationADefinition() && TemplateWithDef) return Importer.MapImported(D, TemplateWithDef); FoundByLookup = FoundTemplate; break; // TODO: handle conflicting names } } } } auto ParamsOrErr = import(D->getTemplateParameters()); if (!ParamsOrErr) return ParamsOrErr.takeError(); TemplateParameterList *Params = *ParamsOrErr; FunctionDecl *TemplatedFD; if (Error Err = importInto(TemplatedFD, D->getTemplatedDecl())) return std::move(Err); // At creation of the template the template parameters are "adopted" // (DeclContext is changed). After this possible change the lookup table // must be updated. // At deduction guides the DeclContext of the template parameters may be // different from what we would expect, it may be the class template, or a // probably different CXXDeductionGuideDecl. This may come from the fact that // the template parameter objects may be shared between deduction guides or // the class template, and at creation of multiple FunctionTemplateDecl // objects (for deduction guides) the same parameters are re-used. The // "adoption" happens multiple times with different parent, even recursively // for TemplateTemplateParmDecl. The same happens at import when the // FunctionTemplateDecl objects are created, but in different order. // In this way the DeclContext of these template parameters is not necessarily // the same as in the "from" context. SmallVector OldParamDC; OldParamDC.reserve(Params->size()); llvm::transform(*Params, std::back_inserter(OldParamDC), [](NamedDecl *ND) { return ND->getDeclContext(); }); FunctionTemplateDecl *ToFunc; if (GetImportedOrCreateDecl(ToFunc, D, Importer.getToContext(), DC, Loc, Name, Params, TemplatedFD)) return ToFunc; TemplatedFD->setDescribedFunctionTemplate(ToFunc); ToFunc->setAccess(D->getAccess()); ToFunc->setLexicalDeclContext(LexicalDC); addDeclToContexts(D, ToFunc); ASTImporterLookupTable *LT = Importer.SharedState->getLookupTable(); if (LT && !OldParamDC.empty()) { for (unsigned int I = 0; I < OldParamDC.size(); ++I) LT->updateForced(Params->getParam(I), OldParamDC[I]); } if (FoundByLookup) { auto *Recent = const_cast(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(ASTImportError::UnsupportedConstruct); } ExpectedStmt ASTNodeImporter::VisitGCCAsmStmt(GCCAsmStmt *S) { if (Importer.returnWithErrorInTest()) return make_error(ASTImportError::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) { Error Err = Error::success(); auto ToDG = importChecked(Err, S->getDeclGroup()); auto ToBeginLoc = importChecked(Err, S->getBeginLoc()); auto ToEndLoc = importChecked(Err, S->getEndLoc()); if (Err) return std::move(Err); return new (Importer.getToContext()) DeclStmt(ToDG, ToBeginLoc, ToEndLoc); } ExpectedStmt ASTNodeImporter::VisitNullStmt(NullStmt *S) { ExpectedSLoc ToSemiLocOrErr = import(S->getSemiLoc()); if (!ToSemiLocOrErr) return ToSemiLocOrErr.takeError(); return new (Importer.getToContext()) NullStmt( *ToSemiLocOrErr, S->hasLeadingEmptyMacro()); } ExpectedStmt ASTNodeImporter::VisitCompoundStmt(CompoundStmt *S) { SmallVector ToStmts(S->size()); if (Error Err = ImportContainerChecked(S->body(), ToStmts)) return std::move(Err); ExpectedSLoc ToLBracLocOrErr = import(S->getLBracLoc()); if (!ToLBracLocOrErr) return ToLBracLocOrErr.takeError(); ExpectedSLoc ToRBracLocOrErr = import(S->getRBracLoc()); if (!ToRBracLocOrErr) return ToRBracLocOrErr.takeError(); FPOptionsOverride FPO = S->hasStoredFPFeatures() ? S->getStoredFPFeatures() : FPOptionsOverride(); return CompoundStmt::Create(Importer.getToContext(), ToStmts, FPO, *ToLBracLocOrErr, *ToRBracLocOrErr); } ExpectedStmt ASTNodeImporter::VisitCaseStmt(CaseStmt *S) { Error Err = Error::success(); auto ToLHS = importChecked(Err, S->getLHS()); auto ToRHS = importChecked(Err, S->getRHS()); auto ToSubStmt = importChecked(Err, S->getSubStmt()); auto ToCaseLoc = importChecked(Err, S->getCaseLoc()); auto ToEllipsisLoc = importChecked(Err, S->getEllipsisLoc()); auto ToColonLoc = importChecked(Err, S->getColonLoc()); if (Err) return std::move(Err); auto *ToStmt = CaseStmt::Create(Importer.getToContext(), ToLHS, ToRHS, ToCaseLoc, ToEllipsisLoc, ToColonLoc); ToStmt->setSubStmt(ToSubStmt); return ToStmt; } ExpectedStmt ASTNodeImporter::VisitDefaultStmt(DefaultStmt *S) { Error Err = Error::success(); auto ToDefaultLoc = importChecked(Err, S->getDefaultLoc()); auto ToColonLoc = importChecked(Err, S->getColonLoc()); auto ToSubStmt = importChecked(Err, S->getSubStmt()); if (Err) return std::move(Err); return new (Importer.getToContext()) DefaultStmt( ToDefaultLoc, ToColonLoc, ToSubStmt); } ExpectedStmt ASTNodeImporter::VisitLabelStmt(LabelStmt *S) { Error Err = Error::success(); auto ToIdentLoc = importChecked(Err, S->getIdentLoc()); auto ToLabelDecl = importChecked(Err, S->getDecl()); auto ToSubStmt = importChecked(Err, S->getSubStmt()); if (Err) return std::move(Err); return new (Importer.getToContext()) LabelStmt( ToIdentLoc, ToLabelDecl, ToSubStmt); } ExpectedStmt ASTNodeImporter::VisitAttributedStmt(AttributedStmt *S) { ExpectedSLoc ToAttrLocOrErr = import(S->getAttrLoc()); if (!ToAttrLocOrErr) return ToAttrLocOrErr.takeError(); ArrayRef 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) { Error Err = Error::success(); auto ToIfLoc = importChecked(Err, S->getIfLoc()); auto ToInit = importChecked(Err, S->getInit()); auto ToConditionVariable = importChecked(Err, S->getConditionVariable()); auto ToCond = importChecked(Err, S->getCond()); auto ToLParenLoc = importChecked(Err, S->getLParenLoc()); auto ToRParenLoc = importChecked(Err, S->getRParenLoc()); auto ToThen = importChecked(Err, S->getThen()); auto ToElseLoc = importChecked(Err, S->getElseLoc()); auto ToElse = importChecked(Err, S->getElse()); if (Err) return std::move(Err); return IfStmt::Create(Importer.getToContext(), ToIfLoc, S->getStatementKind(), ToInit, ToConditionVariable, ToCond, ToLParenLoc, ToRParenLoc, ToThen, ToElseLoc, ToElse); } ExpectedStmt ASTNodeImporter::VisitSwitchStmt(SwitchStmt *S) { Error Err = Error::success(); auto ToInit = importChecked(Err, S->getInit()); auto ToConditionVariable = importChecked(Err, S->getConditionVariable()); auto ToCond = importChecked(Err, S->getCond()); auto ToLParenLoc = importChecked(Err, S->getLParenLoc()); auto ToRParenLoc = importChecked(Err, S->getRParenLoc()); auto ToBody = importChecked(Err, S->getBody()); auto ToSwitchLoc = importChecked(Err, S->getSwitchLoc()); if (Err) return std::move(Err); auto *ToStmt = SwitchStmt::Create(Importer.getToContext(), ToInit, ToConditionVariable, ToCond, ToLParenLoc, ToRParenLoc); ToStmt->setBody(ToBody); ToStmt->setSwitchLoc(ToSwitchLoc); // Now we have to re-chain the cases. SwitchCase *LastChainedSwitchCase = nullptr; for (SwitchCase *SC = S->getSwitchCaseList(); SC != nullptr; SC = SC->getNextSwitchCase()) { Expected ToSCOrErr = import(SC); if (!ToSCOrErr) return ToSCOrErr.takeError(); if (LastChainedSwitchCase) LastChainedSwitchCase->setNextSwitchCase(*ToSCOrErr); else ToStmt->setSwitchCaseList(*ToSCOrErr); LastChainedSwitchCase = *ToSCOrErr; } return ToStmt; } ExpectedStmt ASTNodeImporter::VisitWhileStmt(WhileStmt *S) { Error Err = Error::success(); auto ToConditionVariable = importChecked(Err, S->getConditionVariable()); auto ToCond = importChecked(Err, S->getCond()); auto ToBody = importChecked(Err, S->getBody()); auto ToWhileLoc = importChecked(Err, S->getWhileLoc()); auto ToLParenLoc = importChecked(Err, S->getLParenLoc()); auto ToRParenLoc = importChecked(Err, S->getRParenLoc()); if (Err) return std::move(Err); return WhileStmt::Create(Importer.getToContext(), ToConditionVariable, ToCond, ToBody, ToWhileLoc, ToLParenLoc, ToRParenLoc); } ExpectedStmt ASTNodeImporter::VisitDoStmt(DoStmt *S) { Error Err = Error::success(); auto ToBody = importChecked(Err, S->getBody()); auto ToCond = importChecked(Err, S->getCond()); auto ToDoLoc = importChecked(Err, S->getDoLoc()); auto ToWhileLoc = importChecked(Err, S->getWhileLoc()); auto ToRParenLoc = importChecked(Err, S->getRParenLoc()); if (Err) return std::move(Err); return new (Importer.getToContext()) DoStmt( ToBody, ToCond, ToDoLoc, ToWhileLoc, ToRParenLoc); } ExpectedStmt ASTNodeImporter::VisitForStmt(ForStmt *S) { Error Err = Error::success(); auto ToInit = importChecked(Err, S->getInit()); auto ToCond = importChecked(Err, S->getCond()); auto ToConditionVariable = importChecked(Err, S->getConditionVariable()); auto ToInc = importChecked(Err, S->getInc()); auto ToBody = importChecked(Err, S->getBody()); auto ToForLoc = importChecked(Err, S->getForLoc()); auto ToLParenLoc = importChecked(Err, S->getLParenLoc()); auto ToRParenLoc = importChecked(Err, S->getRParenLoc()); if (Err) return std::move(Err); return new (Importer.getToContext()) ForStmt( Importer.getToContext(), ToInit, ToCond, ToConditionVariable, ToInc, ToBody, ToForLoc, ToLParenLoc, ToRParenLoc); } ExpectedStmt ASTNodeImporter::VisitGotoStmt(GotoStmt *S) { Error Err = Error::success(); auto ToLabel = importChecked(Err, S->getLabel()); auto ToGotoLoc = importChecked(Err, S->getGotoLoc()); auto ToLabelLoc = importChecked(Err, S->getLabelLoc()); if (Err) return std::move(Err); return new (Importer.getToContext()) GotoStmt( ToLabel, ToGotoLoc, ToLabelLoc); } ExpectedStmt ASTNodeImporter::VisitIndirectGotoStmt(IndirectGotoStmt *S) { Error Err = Error::success(); auto ToGotoLoc = importChecked(Err, S->getGotoLoc()); auto ToStarLoc = importChecked(Err, S->getStarLoc()); auto ToTarget = importChecked(Err, S->getTarget()); if (Err) return std::move(Err); return new (Importer.getToContext()) IndirectGotoStmt( ToGotoLoc, ToStarLoc, ToTarget); } ExpectedStmt ASTNodeImporter::VisitContinueStmt(ContinueStmt *S) { ExpectedSLoc ToContinueLocOrErr = import(S->getContinueLoc()); if (!ToContinueLocOrErr) return ToContinueLocOrErr.takeError(); return new (Importer.getToContext()) ContinueStmt(*ToContinueLocOrErr); } ExpectedStmt ASTNodeImporter::VisitBreakStmt(BreakStmt *S) { auto ToBreakLocOrErr = import(S->getBreakLoc()); if (!ToBreakLocOrErr) return ToBreakLocOrErr.takeError(); return new (Importer.getToContext()) BreakStmt(*ToBreakLocOrErr); } ExpectedStmt ASTNodeImporter::VisitReturnStmt(ReturnStmt *S) { Error Err = Error::success(); auto ToReturnLoc = importChecked(Err, S->getReturnLoc()); auto ToRetValue = importChecked(Err, S->getRetValue()); auto ToNRVOCandidate = importChecked(Err, S->getNRVOCandidate()); if (Err) return std::move(Err); return ReturnStmt::Create(Importer.getToContext(), ToReturnLoc, ToRetValue, ToNRVOCandidate); } ExpectedStmt ASTNodeImporter::VisitCXXCatchStmt(CXXCatchStmt *S) { Error Err = Error::success(); auto ToCatchLoc = importChecked(Err, S->getCatchLoc()); auto ToExceptionDecl = importChecked(Err, S->getExceptionDecl()); auto ToHandlerBlock = importChecked(Err, S->getHandlerBlock()); if (Err) return std::move(Err); return new (Importer.getToContext()) CXXCatchStmt ( ToCatchLoc, ToExceptionDecl, ToHandlerBlock); } ExpectedStmt ASTNodeImporter::VisitCXXTryStmt(CXXTryStmt *S) { ExpectedSLoc ToTryLocOrErr = import(S->getTryLoc()); if (!ToTryLocOrErr) return ToTryLocOrErr.takeError(); ExpectedStmt ToTryBlockOrErr = import(S->getTryBlock()); if (!ToTryBlockOrErr) return ToTryBlockOrErr.takeError(); SmallVector ToHandlers(S->getNumHandlers()); for (unsigned HI = 0, HE = S->getNumHandlers(); HI != HE; ++HI) { CXXCatchStmt *FromHandler = S->getHandler(HI); if (auto ToHandlerOrErr = import(FromHandler)) ToHandlers[HI] = *ToHandlerOrErr; else return ToHandlerOrErr.takeError(); } return CXXTryStmt::Create(Importer.getToContext(), *ToTryLocOrErr, cast(*ToTryBlockOrErr), ToHandlers); } ExpectedStmt ASTNodeImporter::VisitCXXForRangeStmt(CXXForRangeStmt *S) { Error Err = Error::success(); auto ToInit = importChecked(Err, S->getInit()); auto ToRangeStmt = importChecked(Err, S->getRangeStmt()); auto ToBeginStmt = importChecked(Err, S->getBeginStmt()); auto ToEndStmt = importChecked(Err, S->getEndStmt()); auto ToCond = importChecked(Err, S->getCond()); auto ToInc = importChecked(Err, S->getInc()); auto ToLoopVarStmt = importChecked(Err, S->getLoopVarStmt()); auto ToBody = importChecked(Err, S->getBody()); auto ToForLoc = importChecked(Err, S->getForLoc()); auto ToCoawaitLoc = importChecked(Err, S->getCoawaitLoc()); auto ToColonLoc = importChecked(Err, S->getColonLoc()); auto ToRParenLoc = importChecked(Err, S->getRParenLoc()); if (Err) return std::move(Err); return new (Importer.getToContext()) CXXForRangeStmt( ToInit, ToRangeStmt, ToBeginStmt, ToEndStmt, ToCond, ToInc, ToLoopVarStmt, ToBody, ToForLoc, ToCoawaitLoc, ToColonLoc, ToRParenLoc); } ExpectedStmt ASTNodeImporter::VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) { Error Err = Error::success(); auto ToElement = importChecked(Err, S->getElement()); auto ToCollection = importChecked(Err, S->getCollection()); auto ToBody = importChecked(Err, S->getBody()); auto ToForLoc = importChecked(Err, S->getForLoc()); auto ToRParenLoc = importChecked(Err, S->getRParenLoc()); if (Err) return std::move(Err); return new (Importer.getToContext()) ObjCForCollectionStmt(ToElement, ToCollection, ToBody, ToForLoc, ToRParenLoc); } ExpectedStmt ASTNodeImporter::VisitObjCAtCatchStmt(ObjCAtCatchStmt *S) { Error Err = Error::success(); auto ToAtCatchLoc = importChecked(Err, S->getAtCatchLoc()); auto ToRParenLoc = importChecked(Err, S->getRParenLoc()); auto ToCatchParamDecl = importChecked(Err, S->getCatchParamDecl()); auto ToCatchBody = importChecked(Err, S->getCatchBody()); if (Err) return std::move(Err); return new (Importer.getToContext()) ObjCAtCatchStmt ( ToAtCatchLoc, ToRParenLoc, ToCatchParamDecl, ToCatchBody); } ExpectedStmt ASTNodeImporter::VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *S) { ExpectedSLoc ToAtFinallyLocOrErr = import(S->getAtFinallyLoc()); if (!ToAtFinallyLocOrErr) return ToAtFinallyLocOrErr.takeError(); ExpectedStmt ToAtFinallyStmtOrErr = import(S->getFinallyBody()); if (!ToAtFinallyStmtOrErr) return ToAtFinallyStmtOrErr.takeError(); return new (Importer.getToContext()) ObjCAtFinallyStmt(*ToAtFinallyLocOrErr, *ToAtFinallyStmtOrErr); } ExpectedStmt ASTNodeImporter::VisitObjCAtTryStmt(ObjCAtTryStmt *S) { Error Err = Error::success(); auto ToAtTryLoc = importChecked(Err, S->getAtTryLoc()); auto ToTryBody = importChecked(Err, S->getTryBody()); auto ToFinallyStmt = importChecked(Err, S->getFinallyStmt()); if (Err) return std::move(Err); SmallVector ToCatchStmts(S->getNumCatchStmts()); for (unsigned CI = 0, CE = S->getNumCatchStmts(); CI != CE; ++CI) { ObjCAtCatchStmt *FromCatchStmt = S->getCatchStmt(CI); if (ExpectedStmt ToCatchStmtOrErr = import(FromCatchStmt)) ToCatchStmts[CI] = *ToCatchStmtOrErr; else return ToCatchStmtOrErr.takeError(); } return ObjCAtTryStmt::Create(Importer.getToContext(), ToAtTryLoc, ToTryBody, ToCatchStmts.begin(), ToCatchStmts.size(), ToFinallyStmt); } ExpectedStmt ASTNodeImporter::VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S) { Error Err = Error::success(); auto ToAtSynchronizedLoc = importChecked(Err, S->getAtSynchronizedLoc()); auto ToSynchExpr = importChecked(Err, S->getSynchExpr()); auto ToSynchBody = importChecked(Err, S->getSynchBody()); if (Err) return std::move(Err); return new (Importer.getToContext()) ObjCAtSynchronizedStmt( ToAtSynchronizedLoc, ToSynchExpr, ToSynchBody); } ExpectedStmt ASTNodeImporter::VisitObjCAtThrowStmt(ObjCAtThrowStmt *S) { ExpectedSLoc ToThrowLocOrErr = import(S->getThrowLoc()); if (!ToThrowLocOrErr) return ToThrowLocOrErr.takeError(); ExpectedExpr ToThrowExprOrErr = import(S->getThrowExpr()); if (!ToThrowExprOrErr) return ToThrowExprOrErr.takeError(); return new (Importer.getToContext()) ObjCAtThrowStmt( *ToThrowLocOrErr, *ToThrowExprOrErr); } ExpectedStmt ASTNodeImporter::VisitObjCAutoreleasePoolStmt( ObjCAutoreleasePoolStmt *S) { ExpectedSLoc ToAtLocOrErr = import(S->getAtLoc()); if (!ToAtLocOrErr) return ToAtLocOrErr.takeError(); ExpectedStmt ToSubStmtOrErr = import(S->getSubStmt()); if (!ToSubStmtOrErr) return ToSubStmtOrErr.takeError(); return new (Importer.getToContext()) ObjCAutoreleasePoolStmt(*ToAtLocOrErr, *ToSubStmtOrErr); } //---------------------------------------------------------------------------- // Import Expressions //---------------------------------------------------------------------------- ExpectedStmt ASTNodeImporter::VisitExpr(Expr *E) { Importer.FromDiag(E->getBeginLoc(), diag::err_unsupported_ast_node) << E->getStmtClassName(); return make_error(ASTImportError::UnsupportedConstruct); } ExpectedStmt ASTNodeImporter::VisitSourceLocExpr(SourceLocExpr *E) { Error Err = Error::success(); auto ToType = importChecked(Err, E->getType()); auto BLoc = importChecked(Err, E->getBeginLoc()); auto RParenLoc = importChecked(Err, E->getEndLoc()); if (Err) return std::move(Err); auto ParentContextOrErr = Importer.ImportContext(E->getParentContext()); if (!ParentContextOrErr) return ParentContextOrErr.takeError(); return new (Importer.getToContext()) SourceLocExpr(Importer.getToContext(), E->getIdentKind(), ToType, BLoc, RParenLoc, *ParentContextOrErr); } ExpectedStmt ASTNodeImporter::VisitVAArgExpr(VAArgExpr *E) { Error Err = Error::success(); auto ToBuiltinLoc = importChecked(Err, E->getBuiltinLoc()); auto ToSubExpr = importChecked(Err, E->getSubExpr()); auto ToWrittenTypeInfo = importChecked(Err, E->getWrittenTypeInfo()); auto ToRParenLoc = importChecked(Err, E->getRParenLoc()); auto ToType = importChecked(Err, E->getType()); if (Err) return std::move(Err); return new (Importer.getToContext()) VAArgExpr( ToBuiltinLoc, ToSubExpr, ToWrittenTypeInfo, ToRParenLoc, ToType, E->isMicrosoftABI()); } ExpectedStmt ASTNodeImporter::VisitChooseExpr(ChooseExpr *E) { Error Err = Error::success(); auto ToCond = importChecked(Err, E->getCond()); auto ToLHS = importChecked(Err, E->getLHS()); auto ToRHS = importChecked(Err, E->getRHS()); auto ToBuiltinLoc = importChecked(Err, E->getBuiltinLoc()); auto ToRParenLoc = importChecked(Err, E->getRParenLoc()); auto ToType = importChecked(Err, E->getType()); if (Err) return std::move(Err); ExprValueKind VK = E->getValueKind(); ExprObjectKind OK = E->getObjectKind(); // The value of CondIsTrue only matters if the value is not // condition-dependent. bool CondIsTrue = !E->isConditionDependent() && E->isConditionTrue(); return new (Importer.getToContext()) ChooseExpr(ToBuiltinLoc, ToCond, ToLHS, ToRHS, ToType, VK, OK, ToRParenLoc, CondIsTrue); } ExpectedStmt ASTNodeImporter::VisitConvertVectorExpr(ConvertVectorExpr *E) { Error Err = Error::success(); auto *ToSrcExpr = importChecked(Err, E->getSrcExpr()); auto ToRParenLoc = importChecked(Err, E->getRParenLoc()); auto ToBuiltinLoc = importChecked(Err, E->getBuiltinLoc()); auto ToType = importChecked(Err, E->getType()); auto *ToTSI = importChecked(Err, E->getTypeSourceInfo()); if (Err) return std::move(Err); return new (Importer.getToContext()) ConvertVectorExpr(ToSrcExpr, ToTSI, ToType, E->getValueKind(), E->getObjectKind(), ToBuiltinLoc, ToRParenLoc); } ExpectedStmt ASTNodeImporter::VisitShuffleVectorExpr(ShuffleVectorExpr *E) { Error Err = Error::success(); auto ToRParenLoc = importChecked(Err, E->getRParenLoc()); auto ToBeginLoc = importChecked(Err, E->getBeginLoc()); auto ToType = importChecked(Err, E->getType()); const unsigned NumSubExprs = E->getNumSubExprs(); llvm::SmallVector ToSubExprs; llvm::ArrayRef FromSubExprs(E->getSubExprs(), NumSubExprs); ToSubExprs.resize(NumSubExprs); if ((Err = ImportContainerChecked(FromSubExprs, ToSubExprs))) return std::move(Err); return new (Importer.getToContext()) ShuffleVectorExpr( Importer.getToContext(), ToSubExprs, ToType, ToBeginLoc, ToRParenLoc); } ExpectedStmt ASTNodeImporter::VisitGNUNullExpr(GNUNullExpr *E) { ExpectedType TypeOrErr = import(E->getType()); if (!TypeOrErr) return TypeOrErr.takeError(); ExpectedSLoc BeginLocOrErr = import(E->getBeginLoc()); if (!BeginLocOrErr) return BeginLocOrErr.takeError(); return new (Importer.getToContext()) GNUNullExpr(*TypeOrErr, *BeginLocOrErr); } ExpectedStmt ASTNodeImporter::VisitGenericSelectionExpr(GenericSelectionExpr *E) { Error Err = Error::success(); auto ToGenericLoc = importChecked(Err, E->getGenericLoc()); Expr *ToControllingExpr = nullptr; TypeSourceInfo *ToControllingType = nullptr; if (E->isExprPredicate()) ToControllingExpr = importChecked(Err, E->getControllingExpr()); else ToControllingType = importChecked(Err, E->getControllingType()); assert((ToControllingExpr || ToControllingType) && "Either the controlling expr or type must be nonnull"); auto ToDefaultLoc = importChecked(Err, E->getDefaultLoc()); auto ToRParenLoc = importChecked(Err, E->getRParenLoc()); if (Err) return std::move(Err); ArrayRef FromAssocTypes(E->getAssocTypeSourceInfos()); SmallVector ToAssocTypes(FromAssocTypes.size()); if (Error Err = ImportContainerChecked(FromAssocTypes, ToAssocTypes)) return std::move(Err); ArrayRef FromAssocExprs(E->getAssocExprs()); SmallVector ToAssocExprs(FromAssocExprs.size()); if (Error Err = ImportContainerChecked(FromAssocExprs, ToAssocExprs)) return std::move(Err); const ASTContext &ToCtx = Importer.getToContext(); if (E->isResultDependent()) { if (ToControllingExpr) { return GenericSelectionExpr::Create( ToCtx, ToGenericLoc, ToControllingExpr, llvm::ArrayRef(ToAssocTypes), llvm::ArrayRef(ToAssocExprs), ToDefaultLoc, ToRParenLoc, E->containsUnexpandedParameterPack()); } return GenericSelectionExpr::Create( ToCtx, ToGenericLoc, ToControllingType, llvm::ArrayRef(ToAssocTypes), llvm::ArrayRef(ToAssocExprs), ToDefaultLoc, ToRParenLoc, E->containsUnexpandedParameterPack()); } if (ToControllingExpr) { return GenericSelectionExpr::Create( ToCtx, ToGenericLoc, ToControllingExpr, llvm::ArrayRef(ToAssocTypes), llvm::ArrayRef(ToAssocExprs), ToDefaultLoc, ToRParenLoc, E->containsUnexpandedParameterPack(), E->getResultIndex()); } return GenericSelectionExpr::Create( ToCtx, ToGenericLoc, ToControllingType, llvm::ArrayRef(ToAssocTypes), llvm::ArrayRef(ToAssocExprs), ToDefaultLoc, ToRParenLoc, E->containsUnexpandedParameterPack(), E->getResultIndex()); } ExpectedStmt ASTNodeImporter::VisitPredefinedExpr(PredefinedExpr *E) { Error Err = Error::success(); auto ToBeginLoc = importChecked(Err, E->getBeginLoc()); auto ToType = importChecked(Err, E->getType()); auto ToFunctionName = importChecked(Err, E->getFunctionName()); if (Err) return std::move(Err); return PredefinedExpr::Create(Importer.getToContext(), ToBeginLoc, ToType, E->getIdentKind(), E->isTransparent(), ToFunctionName); } ExpectedStmt ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) { Error Err = Error::success(); auto ToQualifierLoc = importChecked(Err, E->getQualifierLoc()); auto ToTemplateKeywordLoc = importChecked(Err, E->getTemplateKeywordLoc()); auto ToDecl = importChecked(Err, E->getDecl()); auto ToLocation = importChecked(Err, E->getLocation()); auto ToType = importChecked(Err, E->getType()); if (Err) return std::move(Err); NamedDecl *ToFoundD = nullptr; if (E->getDecl() != E->getFoundDecl()) { auto FoundDOrErr = import(E->getFoundDecl()); if (!FoundDOrErr) return FoundDOrErr.takeError(); ToFoundD = *FoundDOrErr; } TemplateArgumentListInfo ToTAInfo; TemplateArgumentListInfo *ToResInfo = nullptr; if (E->hasExplicitTemplateArgs()) { if (Error Err = ImportTemplateArgumentListInfo(E->getLAngleLoc(), E->getRAngleLoc(), E->template_arguments(), ToTAInfo)) return std::move(Err); ToResInfo = &ToTAInfo; } auto *ToE = DeclRefExpr::Create( Importer.getToContext(), ToQualifierLoc, ToTemplateKeywordLoc, ToDecl, E->refersToEnclosingVariableOrCapture(), ToLocation, ToType, E->getValueKind(), ToFoundD, ToResInfo, E->isNonOdrUse()); if (E->hadMultipleCandidates()) ToE->setHadMultipleCandidates(true); ToE->setIsImmediateEscalating(E->isImmediateEscalating()); return ToE; } ExpectedStmt ASTNodeImporter::VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) { ExpectedType TypeOrErr = import(E->getType()); if (!TypeOrErr) return TypeOrErr.takeError(); return new (Importer.getToContext()) ImplicitValueInitExpr(*TypeOrErr); } ExpectedStmt ASTNodeImporter::VisitDesignatedInitExpr(DesignatedInitExpr *E) { ExpectedExpr ToInitOrErr = import(E->getInit()); if (!ToInitOrErr) return ToInitOrErr.takeError(); ExpectedSLoc ToEqualOrColonLocOrErr = import(E->getEqualOrColonLoc()); if (!ToEqualOrColonLocOrErr) return ToEqualOrColonLocOrErr.takeError(); SmallVector 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::VisitFixedPointLiteral(FixedPointLiteral *E) { auto ToTypeOrErr = import(E->getType()); if (!ToTypeOrErr) return ToTypeOrErr.takeError(); ExpectedSLoc ToLocationOrErr = import(E->getLocation()); if (!ToLocationOrErr) return ToLocationOrErr.takeError(); return new (Importer.getToContext()) FixedPointLiteral( Importer.getToContext(), E->getValue(), *ToTypeOrErr, *ToLocationOrErr, Importer.getToContext().getFixedPointScale(*ToTypeOrErr)); } ExpectedStmt ASTNodeImporter::VisitCharacterLiteral(CharacterLiteral *E) { ExpectedType ToTypeOrErr = import(E->getType()); if (!ToTypeOrErr) return ToTypeOrErr.takeError(); ExpectedSLoc ToLocationOrErr = import(E->getLocation()); if (!ToLocationOrErr) return ToLocationOrErr.takeError(); return new (Importer.getToContext()) CharacterLiteral( E->getValue(), E->getKind(), *ToTypeOrErr, *ToLocationOrErr); } ExpectedStmt ASTNodeImporter::VisitStringLiteral(StringLiteral *E) { ExpectedType ToTypeOrErr = import(E->getType()); if (!ToTypeOrErr) return ToTypeOrErr.takeError(); SmallVector 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) { Error Err = Error::success(); auto ToLParenLoc = importChecked(Err, E->getLParenLoc()); auto ToTypeSourceInfo = importChecked(Err, E->getTypeSourceInfo()); auto ToType = importChecked(Err, E->getType()); auto ToInitializer = importChecked(Err, E->getInitializer()); if (Err) return std::move(Err); return new (Importer.getToContext()) CompoundLiteralExpr( ToLParenLoc, ToTypeSourceInfo, ToType, E->getValueKind(), ToInitializer, E->isFileScope()); } ExpectedStmt ASTNodeImporter::VisitAtomicExpr(AtomicExpr *E) { Error Err = Error::success(); auto ToBuiltinLoc = importChecked(Err, E->getBuiltinLoc()); auto ToType = importChecked(Err, E->getType()); auto ToRParenLoc = importChecked(Err, E->getRParenLoc()); if (Err) return std::move(Err); SmallVector ToExprs(E->getNumSubExprs()); if (Error Err = ImportArrayChecked( E->getSubExprs(), E->getSubExprs() + E->getNumSubExprs(), ToExprs.begin())) return std::move(Err); return new (Importer.getToContext()) AtomicExpr( ToBuiltinLoc, ToExprs, ToType, E->getOp(), ToRParenLoc); } ExpectedStmt ASTNodeImporter::VisitAddrLabelExpr(AddrLabelExpr *E) { Error Err = Error::success(); auto ToAmpAmpLoc = importChecked(Err, E->getAmpAmpLoc()); auto ToLabelLoc = importChecked(Err, E->getLabelLoc()); auto ToLabel = importChecked(Err, E->getLabel()); auto ToType = importChecked(Err, E->getType()); if (Err) return std::move(Err); return new (Importer.getToContext()) AddrLabelExpr( ToAmpAmpLoc, ToLabelLoc, ToLabel, ToType); } ExpectedStmt ASTNodeImporter::VisitConstantExpr(ConstantExpr *E) { Error Err = Error::success(); auto ToSubExpr = importChecked(Err, E->getSubExpr()); auto ToResult = importChecked(Err, E->getAPValueResult()); if (Err) return std::move(Err); return ConstantExpr::Create(Importer.getToContext(), ToSubExpr, ToResult); } ExpectedStmt ASTNodeImporter::VisitParenExpr(ParenExpr *E) { Error Err = Error::success(); auto ToLParen = importChecked(Err, E->getLParen()); auto ToRParen = importChecked(Err, E->getRParen()); auto ToSubExpr = importChecked(Err, E->getSubExpr()); if (Err) return std::move(Err); return new (Importer.getToContext()) ParenExpr(ToLParen, ToRParen, ToSubExpr); } ExpectedStmt ASTNodeImporter::VisitParenListExpr(ParenListExpr *E) { SmallVector ToExprs(E->getNumExprs()); if (Error Err = ImportContainerChecked(E->exprs(), ToExprs)) return std::move(Err); ExpectedSLoc ToLParenLocOrErr = import(E->getLParenLoc()); if (!ToLParenLocOrErr) return ToLParenLocOrErr.takeError(); ExpectedSLoc ToRParenLocOrErr = import(E->getRParenLoc()); if (!ToRParenLocOrErr) return ToRParenLocOrErr.takeError(); return ParenListExpr::Create(Importer.getToContext(), *ToLParenLocOrErr, ToExprs, *ToRParenLocOrErr); } ExpectedStmt ASTNodeImporter::VisitStmtExpr(StmtExpr *E) { Error Err = Error::success(); auto ToSubStmt = importChecked(Err, E->getSubStmt()); auto ToType = importChecked(Err, E->getType()); auto ToLParenLoc = importChecked(Err, E->getLParenLoc()); auto ToRParenLoc = importChecked(Err, E->getRParenLoc()); if (Err) return std::move(Err); return new (Importer.getToContext()) StmtExpr(ToSubStmt, ToType, ToLParenLoc, ToRParenLoc, E->getTemplateDepth()); } ExpectedStmt ASTNodeImporter::VisitUnaryOperator(UnaryOperator *E) { Error Err = Error::success(); auto ToSubExpr = importChecked(Err, E->getSubExpr()); auto ToType = importChecked(Err, E->getType()); auto ToOperatorLoc = importChecked(Err, E->getOperatorLoc()); if (Err) return std::move(Err); auto *UO = UnaryOperator::CreateEmpty(Importer.getToContext(), E->hasStoredFPFeatures()); UO->setType(ToType); UO->setSubExpr(ToSubExpr); UO->setOpcode(E->getOpcode()); UO->setOperatorLoc(ToOperatorLoc); UO->setCanOverflow(E->canOverflow()); if (E->hasStoredFPFeatures()) UO->setStoredFPFeatures(E->getStoredFPFeatures()); return UO; } ExpectedStmt ASTNodeImporter::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E) { Error Err = Error::success(); auto ToType = importChecked(Err, E->getType()); auto ToOperatorLoc = importChecked(Err, E->getOperatorLoc()); auto ToRParenLoc = importChecked(Err, E->getRParenLoc()); if (Err) return std::move(Err); if (E->isArgumentType()) { Expected ToArgumentTypeInfoOrErr = import(E->getArgumentTypeInfo()); if (!ToArgumentTypeInfoOrErr) return ToArgumentTypeInfoOrErr.takeError(); return new (Importer.getToContext()) UnaryExprOrTypeTraitExpr( E->getKind(), *ToArgumentTypeInfoOrErr, ToType, ToOperatorLoc, ToRParenLoc); } ExpectedExpr ToArgumentExprOrErr = import(E->getArgumentExpr()); if (!ToArgumentExprOrErr) return ToArgumentExprOrErr.takeError(); return new (Importer.getToContext()) UnaryExprOrTypeTraitExpr( E->getKind(), *ToArgumentExprOrErr, ToType, ToOperatorLoc, ToRParenLoc); } ExpectedStmt ASTNodeImporter::VisitBinaryOperator(BinaryOperator *E) { Error Err = Error::success(); auto ToLHS = importChecked(Err, E->getLHS()); auto ToRHS = importChecked(Err, E->getRHS()); auto ToType = importChecked(Err, E->getType()); auto ToOperatorLoc = importChecked(Err, E->getOperatorLoc()); if (Err) return std::move(Err); return BinaryOperator::Create( Importer.getToContext(), ToLHS, ToRHS, E->getOpcode(), ToType, E->getValueKind(), E->getObjectKind(), ToOperatorLoc, E->getFPFeatures()); } ExpectedStmt ASTNodeImporter::VisitConditionalOperator(ConditionalOperator *E) { Error Err = Error::success(); auto ToCond = importChecked(Err, E->getCond()); auto ToQuestionLoc = importChecked(Err, E->getQuestionLoc()); auto ToLHS = importChecked(Err, E->getLHS()); auto ToColonLoc = importChecked(Err, E->getColonLoc()); auto ToRHS = importChecked(Err, E->getRHS()); auto ToType = importChecked(Err, E->getType()); if (Err) return std::move(Err); return new (Importer.getToContext()) ConditionalOperator( ToCond, ToQuestionLoc, ToLHS, ToColonLoc, ToRHS, ToType, E->getValueKind(), E->getObjectKind()); } ExpectedStmt ASTNodeImporter::VisitBinaryConditionalOperator(BinaryConditionalOperator *E) { Error Err = Error::success(); auto ToCommon = importChecked(Err, E->getCommon()); auto ToOpaqueValue = importChecked(Err, E->getOpaqueValue()); auto ToCond = importChecked(Err, E->getCond()); auto ToTrueExpr = importChecked(Err, E->getTrueExpr()); auto ToFalseExpr = importChecked(Err, E->getFalseExpr()); auto ToQuestionLoc = importChecked(Err, E->getQuestionLoc()); auto ToColonLoc = importChecked(Err, E->getColonLoc()); auto ToType = importChecked(Err, E->getType()); if (Err) return std::move(Err); return new (Importer.getToContext()) BinaryConditionalOperator( ToCommon, ToOpaqueValue, ToCond, ToTrueExpr, ToFalseExpr, ToQuestionLoc, ToColonLoc, ToType, E->getValueKind(), E->getObjectKind()); } ExpectedStmt ASTNodeImporter::VisitCXXRewrittenBinaryOperator( CXXRewrittenBinaryOperator *E) { Error Err = Error::success(); auto ToSemanticForm = importChecked(Err, E->getSemanticForm()); if (Err) return std::move(Err); return new (Importer.getToContext()) CXXRewrittenBinaryOperator(ToSemanticForm, E->isReversed()); } ExpectedStmt ASTNodeImporter::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E) { Error Err = Error::success(); auto ToBeginLoc = importChecked(Err, E->getBeginLoc()); auto ToQueriedTypeSourceInfo = importChecked(Err, E->getQueriedTypeSourceInfo()); auto ToDimensionExpression = importChecked(Err, E->getDimensionExpression()); auto ToEndLoc = importChecked(Err, E->getEndLoc()); auto ToType = importChecked(Err, E->getType()); if (Err) return std::move(Err); return new (Importer.getToContext()) ArrayTypeTraitExpr( ToBeginLoc, E->getTrait(), ToQueriedTypeSourceInfo, E->getValue(), ToDimensionExpression, ToEndLoc, ToType); } ExpectedStmt ASTNodeImporter::VisitExpressionTraitExpr(ExpressionTraitExpr *E) { Error Err = Error::success(); auto ToBeginLoc = importChecked(Err, E->getBeginLoc()); auto ToQueriedExpression = importChecked(Err, E->getQueriedExpression()); auto ToEndLoc = importChecked(Err, E->getEndLoc()); auto ToType = importChecked(Err, E->getType()); if (Err) return std::move(Err); return new (Importer.getToContext()) ExpressionTraitExpr( ToBeginLoc, E->getTrait(), ToQueriedExpression, E->getValue(), ToEndLoc, ToType); } ExpectedStmt ASTNodeImporter::VisitOpaqueValueExpr(OpaqueValueExpr *E) { Error Err = Error::success(); auto ToLocation = importChecked(Err, E->getLocation()); auto ToType = importChecked(Err, E->getType()); auto ToSourceExpr = importChecked(Err, E->getSourceExpr()); if (Err) return std::move(Err); return new (Importer.getToContext()) OpaqueValueExpr( ToLocation, ToType, E->getValueKind(), E->getObjectKind(), ToSourceExpr); } ExpectedStmt ASTNodeImporter::VisitArraySubscriptExpr(ArraySubscriptExpr *E) { Error Err = Error::success(); auto ToLHS = importChecked(Err, E->getLHS()); auto ToRHS = importChecked(Err, E->getRHS()); auto ToType = importChecked(Err, E->getType()); auto ToRBracketLoc = importChecked(Err, E->getRBracketLoc()); if (Err) return std::move(Err); return new (Importer.getToContext()) ArraySubscriptExpr( ToLHS, ToRHS, ToType, E->getValueKind(), E->getObjectKind(), ToRBracketLoc); } ExpectedStmt ASTNodeImporter::VisitCompoundAssignOperator(CompoundAssignOperator *E) { Error Err = Error::success(); auto ToLHS = importChecked(Err, E->getLHS()); auto ToRHS = importChecked(Err, E->getRHS()); auto ToType = importChecked(Err, E->getType()); auto ToComputationLHSType = importChecked(Err, E->getComputationLHSType()); auto ToComputationResultType = importChecked(Err, E->getComputationResultType()); auto ToOperatorLoc = importChecked(Err, E->getOperatorLoc()); if (Err) return std::move(Err); return CompoundAssignOperator::Create( Importer.getToContext(), ToLHS, ToRHS, E->getOpcode(), ToType, E->getValueKind(), E->getObjectKind(), ToOperatorLoc, E->getFPFeatures(), ToComputationLHSType, ToComputationResultType); } Expected 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(), E->getFPFeatures()); } ExpectedStmt ASTNodeImporter::VisitExplicitCastExpr(ExplicitCastExpr *E) { Error Err = Error::success(); auto ToType = importChecked(Err, E->getType()); auto ToSubExpr = importChecked(Err, E->getSubExpr()); auto ToTypeInfoAsWritten = importChecked(Err, E->getTypeInfoAsWritten()); if (Err) return std::move(Err); Expected 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, CCE->getFPFeatures(), 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, FCE->getFPFeatures(), *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); } case Stmt::BuiltinBitCastExprClass: { auto *BBC = cast(E); ExpectedSLoc ToKWLocOrErr = import(BBC->getBeginLoc()); if (!ToKWLocOrErr) return ToKWLocOrErr.takeError(); ExpectedSLoc ToRParenLocOrErr = import(BBC->getEndLoc()); if (!ToRParenLocOrErr) return ToRParenLocOrErr.takeError(); return new (Importer.getToContext()) BuiltinBitCastExpr( ToType, E->getValueKind(), E->getCastKind(), ToSubExpr, ToTypeInfoAsWritten, *ToKWLocOrErr, *ToRParenLocOrErr); } default: llvm_unreachable("Cast expression of unsupported type!"); return make_error(ASTImportError::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) { Error Err = Error::success(); ToBeginLoc = importChecked(Err, FromNode.getBeginLoc()); ToEndLoc = importChecked(Err, FromNode.getEndLoc()); if (Err) return std::move(Err); } switch (FromNode.getKind()) { case OffsetOfNode::Array: ToNodes.push_back( OffsetOfNode(ToBeginLoc, FromNode.getArrayExprIndex(), ToEndLoc)); break; case OffsetOfNode::Base: { auto ToBSOrErr = import(FromNode.getBase()); if (!ToBSOrErr) return ToBSOrErr.takeError(); ToNodes.push_back(OffsetOfNode(*ToBSOrErr)); break; } case OffsetOfNode::Field: { auto ToFieldOrErr = import(FromNode.getField()); if (!ToFieldOrErr) return ToFieldOrErr.takeError(); ToNodes.push_back(OffsetOfNode(ToBeginLoc, *ToFieldOrErr, ToEndLoc)); break; } case OffsetOfNode::Identifier: { IdentifierInfo *ToII = Importer.Import(FromNode.getFieldName()); ToNodes.push_back(OffsetOfNode(ToBeginLoc, ToII, ToEndLoc)); break; } } } SmallVector ToExprs(E->getNumExpressions()); for (int I = 0, N = E->getNumExpressions(); I < N; ++I) { ExpectedExpr ToIndexExprOrErr = import(E->getIndexExpr(I)); if (!ToIndexExprOrErr) return ToIndexExprOrErr.takeError(); ToExprs[I] = *ToIndexExprOrErr; } Error Err = Error::success(); auto ToType = importChecked(Err, E->getType()); auto ToTypeSourceInfo = importChecked(Err, E->getTypeSourceInfo()); auto ToOperatorLoc = importChecked(Err, E->getOperatorLoc()); auto ToRParenLoc = importChecked(Err, E->getRParenLoc()); if (Err) return std::move(Err); return OffsetOfExpr::Create( Importer.getToContext(), ToType, ToOperatorLoc, ToTypeSourceInfo, ToNodes, ToExprs, ToRParenLoc); } ExpectedStmt ASTNodeImporter::VisitCXXNoexceptExpr(CXXNoexceptExpr *E) { Error Err = Error::success(); auto ToType = importChecked(Err, E->getType()); auto ToOperand = importChecked(Err, E->getOperand()); auto ToBeginLoc = importChecked(Err, E->getBeginLoc()); auto ToEndLoc = importChecked(Err, E->getEndLoc()); if (Err) return std::move(Err); CanThrowResult ToCanThrow; if (E->isValueDependent()) ToCanThrow = CT_Dependent; else ToCanThrow = E->getValue() ? CT_Can : CT_Cannot; return new (Importer.getToContext()) CXXNoexceptExpr( ToType, ToOperand, ToCanThrow, ToBeginLoc, ToEndLoc); } ExpectedStmt ASTNodeImporter::VisitCXXThrowExpr(CXXThrowExpr *E) { Error Err = Error::success(); auto ToSubExpr = importChecked(Err, E->getSubExpr()); auto ToType = importChecked(Err, E->getType()); auto ToThrowLoc = importChecked(Err, E->getThrowLoc()); if (Err) return std::move(Err); return new (Importer.getToContext()) CXXThrowExpr( ToSubExpr, ToType, ToThrowLoc, E->isThrownVariableInScope()); } ExpectedStmt ASTNodeImporter::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) { ExpectedSLoc ToUsedLocOrErr = import(E->getUsedLocation()); if (!ToUsedLocOrErr) return ToUsedLocOrErr.takeError(); auto ToParamOrErr = import(E->getParam()); if (!ToParamOrErr) return ToParamOrErr.takeError(); auto UsedContextOrErr = Importer.ImportContext(E->getUsedContext()); if (!UsedContextOrErr) return UsedContextOrErr.takeError(); // Import the default arg if it was not imported yet. // This is needed because it can happen that during the import of the // default expression (from VisitParmVarDecl) the same ParmVarDecl is // encountered here. The default argument for a ParmVarDecl is set in the // ParmVarDecl only after it is imported (set in VisitParmVarDecl if not here, // see VisitParmVarDecl). ParmVarDecl *ToParam = *ToParamOrErr; if (!ToParam->getDefaultArg()) { std::optional FromParam = Importer.getImportedFromDecl(ToParam); assert(FromParam && "ParmVarDecl was not imported?"); if (Error Err = ImportDefaultArgOfParmVarDecl(*FromParam, ToParam)) return std::move(Err); } Expr *RewrittenInit = nullptr; if (E->hasRewrittenInit()) { ExpectedExpr ExprOrErr = import(E->getRewrittenExpr()); if (!ExprOrErr) return ExprOrErr.takeError(); RewrittenInit = ExprOrErr.get(); } return CXXDefaultArgExpr::Create(Importer.getToContext(), *ToUsedLocOrErr, *ToParamOrErr, RewrittenInit, *UsedContextOrErr); } ExpectedStmt ASTNodeImporter::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) { Error Err = Error::success(); auto ToType = importChecked(Err, E->getType()); auto ToTypeSourceInfo = importChecked(Err, E->getTypeSourceInfo()); auto ToRParenLoc = importChecked(Err, E->getRParenLoc()); if (Err) return std::move(Err); return new (Importer.getToContext()) CXXScalarValueInitExpr( ToType, ToTypeSourceInfo, ToRParenLoc); } ExpectedStmt ASTNodeImporter::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) { ExpectedExpr ToSubExprOrErr = import(E->getSubExpr()); if (!ToSubExprOrErr) return ToSubExprOrErr.takeError(); auto ToDtorOrErr = import(E->getTemporary()->getDestructor()); if (!ToDtorOrErr) return ToDtorOrErr.takeError(); ASTContext &ToCtx = Importer.getToContext(); CXXTemporary *Temp = CXXTemporary::Create(ToCtx, *ToDtorOrErr); return CXXBindTemporaryExpr::Create(ToCtx, Temp, *ToSubExprOrErr); } ExpectedStmt ASTNodeImporter::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E) { Error Err = Error::success(); auto ToConstructor = importChecked(Err, E->getConstructor()); auto ToType = importChecked(Err, E->getType()); auto ToTypeSourceInfo = importChecked(Err, E->getTypeSourceInfo()); auto ToParenOrBraceRange = importChecked(Err, E->getParenOrBraceRange()); if (Err) return std::move(Err); SmallVector ToArgs(E->getNumArgs()); if (Error Err = ImportContainerChecked(E->arguments(), ToArgs)) return std::move(Err); return CXXTemporaryObjectExpr::Create( Importer.getToContext(), ToConstructor, ToType, ToTypeSourceInfo, ToArgs, ToParenOrBraceRange, E->hadMultipleCandidates(), E->isListInitialization(), E->isStdInitListInitialization(), E->requiresZeroInitialization()); } ExpectedDecl ASTNodeImporter::VisitLifetimeExtendedTemporaryDecl( LifetimeExtendedTemporaryDecl *D) { DeclContext *DC, *LexicalDC; if (Error Err = ImportDeclContext(D, DC, LexicalDC)) return std::move(Err); Error Err = Error::success(); auto Temporary = importChecked(Err, D->getTemporaryExpr()); auto ExtendingDecl = importChecked(Err, D->getExtendingDecl()); if (Err) return std::move(Err); // FIXME: Should ManglingNumber get numbers associated with 'to' context? LifetimeExtendedTemporaryDecl *To; if (GetImportedOrCreateDecl(To, D, Temporary, ExtendingDecl, D->getManglingNumber())) return To; To->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(To); return To; } ExpectedStmt ASTNodeImporter::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E) { Error Err = Error::success(); auto ToType = importChecked(Err, E->getType()); Expr *ToTemporaryExpr = importChecked( Err, E->getLifetimeExtendedTemporaryDecl() ? nullptr : E->getSubExpr()); auto ToMaterializedDecl = importChecked(Err, E->getLifetimeExtendedTemporaryDecl()); if (Err) return std::move(Err); if (!ToTemporaryExpr) ToTemporaryExpr = cast(ToMaterializedDecl->getTemporaryExpr()); auto *ToMTE = new (Importer.getToContext()) MaterializeTemporaryExpr( ToType, ToTemporaryExpr, E->isBoundToLvalueReference(), ToMaterializedDecl); return ToMTE; } ExpectedStmt ASTNodeImporter::VisitPackExpansionExpr(PackExpansionExpr *E) { Error Err = Error::success(); auto ToType = importChecked(Err, E->getType()); auto ToPattern = importChecked(Err, E->getPattern()); auto ToEllipsisLoc = importChecked(Err, E->getEllipsisLoc()); if (Err) return std::move(Err); return new (Importer.getToContext()) PackExpansionExpr( ToType, ToPattern, ToEllipsisLoc, E->getNumExpansions()); } ExpectedStmt ASTNodeImporter::VisitSizeOfPackExpr(SizeOfPackExpr *E) { Error Err = Error::success(); auto ToOperatorLoc = importChecked(Err, E->getOperatorLoc()); auto ToPack = importChecked(Err, E->getPack()); auto ToPackLoc = importChecked(Err, E->getPackLoc()); auto ToRParenLoc = importChecked(Err, E->getRParenLoc()); if (Err) return std::move(Err); std::optional Length; if (!E->isValueDependent()) Length = E->getPackLength(); SmallVector ToPartialArguments; if (E->isPartiallySubstituted()) { if (Error Err = ImportTemplateArguments(E->getPartialArguments(), ToPartialArguments)) return std::move(Err); } return SizeOfPackExpr::Create( Importer.getToContext(), ToOperatorLoc, ToPack, ToPackLoc, ToRParenLoc, Length, ToPartialArguments); } ExpectedStmt ASTNodeImporter::VisitCXXNewExpr(CXXNewExpr *E) { Error Err = Error::success(); auto ToOperatorNew = importChecked(Err, E->getOperatorNew()); auto ToOperatorDelete = importChecked(Err, E->getOperatorDelete()); auto ToTypeIdParens = importChecked(Err, E->getTypeIdParens()); auto ToArraySize = importChecked(Err, E->getArraySize()); auto ToInitializer = importChecked(Err, E->getInitializer()); auto ToType = importChecked(Err, E->getType()); auto ToAllocatedTypeSourceInfo = importChecked(Err, E->getAllocatedTypeSourceInfo()); auto ToSourceRange = importChecked(Err, E->getSourceRange()); auto ToDirectInitRange = importChecked(Err, E->getDirectInitRange()); if (Err) return std::move(Err); SmallVector 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) { Error Err = Error::success(); auto ToType = importChecked(Err, E->getType()); auto ToOperatorDelete = importChecked(Err, E->getOperatorDelete()); auto ToArgument = importChecked(Err, E->getArgument()); auto ToBeginLoc = importChecked(Err, E->getBeginLoc()); if (Err) return std::move(Err); return new (Importer.getToContext()) CXXDeleteExpr( ToType, E->isGlobalDelete(), E->isArrayForm(), E->isArrayFormAsWritten(), E->doesUsualArrayDeleteWantSize(), ToOperatorDelete, ToArgument, ToBeginLoc); } ExpectedStmt ASTNodeImporter::VisitCXXConstructExpr(CXXConstructExpr *E) { Error Err = Error::success(); auto ToType = importChecked(Err, E->getType()); auto ToLocation = importChecked(Err, E->getLocation()); auto ToConstructor = importChecked(Err, E->getConstructor()); auto ToParenOrBraceRange = importChecked(Err, E->getParenOrBraceRange()); if (Err) return std::move(Err); SmallVector ToArgs(E->getNumArgs()); if (Error Err = ImportContainerChecked(E->arguments(), ToArgs)) return std::move(Err); CXXConstructExpr *ToE = CXXConstructExpr::Create( Importer.getToContext(), ToType, ToLocation, ToConstructor, E->isElidable(), ToArgs, E->hadMultipleCandidates(), E->isListInitialization(), E->isStdInitListInitialization(), E->requiresZeroInitialization(), E->getConstructionKind(), ToParenOrBraceRange); ToE->setIsImmediateEscalating(E->isImmediateEscalating()); return ToE; } ExpectedStmt ASTNodeImporter::VisitExprWithCleanups(ExprWithCleanups *E) { ExpectedExpr ToSubExprOrErr = import(E->getSubExpr()); if (!ToSubExprOrErr) return ToSubExprOrErr.takeError(); SmallVector ToObjects(E->getNumObjects()); if (Error Err = ImportContainerChecked(E->getObjects(), ToObjects)) return std::move(Err); return ExprWithCleanups::Create( Importer.getToContext(), *ToSubExprOrErr, E->cleanupsHaveSideEffects(), ToObjects); } ExpectedStmt ASTNodeImporter::VisitCXXMemberCallExpr(CXXMemberCallExpr *E) { Error Err = Error::success(); auto ToCallee = importChecked(Err, E->getCallee()); auto ToType = importChecked(Err, E->getType()); auto ToRParenLoc = importChecked(Err, E->getRParenLoc()); if (Err) return std::move(Err); SmallVector ToArgs(E->getNumArgs()); if (Error Err = ImportContainerChecked(E->arguments(), ToArgs)) return std::move(Err); return CXXMemberCallExpr::Create(Importer.getToContext(), ToCallee, ToArgs, ToType, E->getValueKind(), ToRParenLoc, E->getFPFeatures()); } ExpectedStmt ASTNodeImporter::VisitCXXThisExpr(CXXThisExpr *E) { ExpectedType ToTypeOrErr = import(E->getType()); if (!ToTypeOrErr) return ToTypeOrErr.takeError(); ExpectedSLoc ToLocationOrErr = import(E->getLocation()); if (!ToLocationOrErr) return ToLocationOrErr.takeError(); return CXXThisExpr::Create(Importer.getToContext(), *ToLocationOrErr, *ToTypeOrErr, E->isImplicit()); } ExpectedStmt ASTNodeImporter::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) { ExpectedType ToTypeOrErr = import(E->getType()); if (!ToTypeOrErr) return ToTypeOrErr.takeError(); ExpectedSLoc ToLocationOrErr = import(E->getLocation()); if (!ToLocationOrErr) return ToLocationOrErr.takeError(); return CXXBoolLiteralExpr::Create(Importer.getToContext(), E->getValue(), *ToTypeOrErr, *ToLocationOrErr); } ExpectedStmt ASTNodeImporter::VisitMemberExpr(MemberExpr *E) { Error Err = Error::success(); auto ToBase = importChecked(Err, E->getBase()); auto ToOperatorLoc = importChecked(Err, E->getOperatorLoc()); auto ToQualifierLoc = importChecked(Err, E->getQualifierLoc()); auto ToTemplateKeywordLoc = importChecked(Err, E->getTemplateKeywordLoc()); auto ToMemberDecl = importChecked(Err, E->getMemberDecl()); auto ToType = importChecked(Err, E->getType()); auto ToDecl = importChecked(Err, E->getFoundDecl().getDecl()); auto ToName = importChecked(Err, E->getMemberNameInfo().getName()); auto ToLoc = importChecked(Err, E->getMemberNameInfo().getLoc()); if (Err) return std::move(Err); DeclAccessPair ToFoundDecl = DeclAccessPair::make(ToDecl, E->getFoundDecl().getAccess()); DeclarationNameInfo ToMemberNameInfo(ToName, ToLoc); TemplateArgumentListInfo ToTAInfo, *ResInfo = nullptr; if (E->hasExplicitTemplateArgs()) { if (Error Err = ImportTemplateArgumentListInfo(E->getLAngleLoc(), E->getRAngleLoc(), E->template_arguments(), ToTAInfo)) return std::move(Err); ResInfo = &ToTAInfo; } return MemberExpr::Create(Importer.getToContext(), ToBase, E->isArrow(), ToOperatorLoc, ToQualifierLoc, ToTemplateKeywordLoc, ToMemberDecl, ToFoundDecl, ToMemberNameInfo, ResInfo, ToType, E->getValueKind(), E->getObjectKind(), E->isNonOdrUse()); } ExpectedStmt ASTNodeImporter::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) { Error Err = Error::success(); auto ToBase = importChecked(Err, E->getBase()); auto ToOperatorLoc = importChecked(Err, E->getOperatorLoc()); auto ToQualifierLoc = importChecked(Err, E->getQualifierLoc()); auto ToScopeTypeInfo = importChecked(Err, E->getScopeTypeInfo()); auto ToColonColonLoc = importChecked(Err, E->getColonColonLoc()); auto ToTildeLoc = importChecked(Err, E->getTildeLoc()); if (Err) return std::move(Err); PseudoDestructorTypeStorage Storage; if (const IdentifierInfo *FromII = E->getDestroyedTypeIdentifier()) { const IdentifierInfo *ToII = Importer.Import(FromII); ExpectedSLoc ToDestroyedTypeLocOrErr = import(E->getDestroyedTypeLoc()); if (!ToDestroyedTypeLocOrErr) return ToDestroyedTypeLocOrErr.takeError(); Storage = PseudoDestructorTypeStorage(ToII, *ToDestroyedTypeLocOrErr); } else { if (auto ToTIOrErr = import(E->getDestroyedTypeInfo())) Storage = PseudoDestructorTypeStorage(*ToTIOrErr); else return ToTIOrErr.takeError(); } return new (Importer.getToContext()) CXXPseudoDestructorExpr( Importer.getToContext(), ToBase, E->isArrow(), ToOperatorLoc, ToQualifierLoc, ToScopeTypeInfo, ToColonColonLoc, ToTildeLoc, Storage); } ExpectedStmt ASTNodeImporter::VisitCXXDependentScopeMemberExpr( CXXDependentScopeMemberExpr *E) { Error Err = Error::success(); auto ToType = importChecked(Err, E->getType()); auto ToOperatorLoc = importChecked(Err, E->getOperatorLoc()); auto ToQualifierLoc = importChecked(Err, E->getQualifierLoc()); auto ToTemplateKeywordLoc = importChecked(Err, E->getTemplateKeywordLoc()); auto ToFirstQualifierFoundInScope = importChecked(Err, E->getFirstQualifierFoundInScope()); if (Err) return std::move(Err); Expr *ToBase = nullptr; if (!E->isImplicitAccess()) { if (ExpectedExpr ToBaseOrErr = import(E->getBase())) ToBase = *ToBaseOrErr; else return ToBaseOrErr.takeError(); } TemplateArgumentListInfo ToTAInfo, *ResInfo = nullptr; if (E->hasExplicitTemplateArgs()) { if (Error Err = ImportTemplateArgumentListInfo(E->getLAngleLoc(), E->getRAngleLoc(), E->template_arguments(), ToTAInfo)) return std::move(Err); ResInfo = &ToTAInfo; } auto ToMember = importChecked(Err, E->getMember()); auto ToMemberLoc = importChecked(Err, E->getMemberLoc()); if (Err) return std::move(Err); DeclarationNameInfo ToMemberNameInfo(ToMember, ToMemberLoc); // Import additional name location/type info. if (Error Err = ImportDeclarationNameLoc(E->getMemberNameInfo(), ToMemberNameInfo)) return std::move(Err); return CXXDependentScopeMemberExpr::Create( Importer.getToContext(), ToBase, ToType, E->isArrow(), ToOperatorLoc, ToQualifierLoc, ToTemplateKeywordLoc, ToFirstQualifierFoundInScope, ToMemberNameInfo, ResInfo); } ExpectedStmt ASTNodeImporter::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) { Error Err = Error::success(); auto ToQualifierLoc = importChecked(Err, E->getQualifierLoc()); auto ToTemplateKeywordLoc = importChecked(Err, E->getTemplateKeywordLoc()); auto ToDeclName = importChecked(Err, E->getDeclName()); auto ToNameLoc = importChecked(Err, E->getNameInfo().getLoc()); auto ToLAngleLoc = importChecked(Err, E->getLAngleLoc()); auto ToRAngleLoc = importChecked(Err, E->getRAngleLoc()); if (Err) return std::move(Err); DeclarationNameInfo ToNameInfo(ToDeclName, ToNameLoc); if (Error Err = ImportDeclarationNameLoc(E->getNameInfo(), ToNameInfo)) return std::move(Err); TemplateArgumentListInfo ToTAInfo(ToLAngleLoc, ToRAngleLoc); TemplateArgumentListInfo *ResInfo = nullptr; if (E->hasExplicitTemplateArgs()) { if (Error Err = ImportTemplateArgumentListInfo(E->template_arguments(), ToTAInfo)) return std::move(Err); ResInfo = &ToTAInfo; } return DependentScopeDeclRefExpr::Create( Importer.getToContext(), ToQualifierLoc, ToTemplateKeywordLoc, ToNameInfo, ResInfo); } ExpectedStmt ASTNodeImporter::VisitCXXUnresolvedConstructExpr( CXXUnresolvedConstructExpr *E) { Error Err = Error::success(); auto ToLParenLoc = importChecked(Err, E->getLParenLoc()); auto ToRParenLoc = importChecked(Err, E->getRParenLoc()); auto ToType = importChecked(Err, E->getType()); auto ToTypeSourceInfo = importChecked(Err, E->getTypeSourceInfo()); if (Err) return std::move(Err); SmallVector ToArgs(E->getNumArgs()); if (Error Err = ImportArrayChecked(E->arg_begin(), E->arg_end(), ToArgs.begin())) return std::move(Err); return CXXUnresolvedConstructExpr::Create( Importer.getToContext(), ToType, ToTypeSourceInfo, ToLParenLoc, llvm::ArrayRef(ToArgs), ToRParenLoc, E->isListInitialization()); } 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(); Error Err = Error::success(); auto ToName = importChecked(Err, E->getName()); auto ToNameLoc = importChecked(Err, E->getNameLoc()); if (Err) return std::move(Err); DeclarationNameInfo ToNameInfo(ToName, ToNameLoc); // Import additional name location/type info. if (Error Err = ImportDeclarationNameLoc(E->getNameInfo(), ToNameInfo)) return std::move(Err); UnresolvedSet<8> ToDecls; for (auto *D : E->decls()) if (auto ToDOrErr = import(D)) ToDecls.addDecl(cast(*ToDOrErr)); else return ToDOrErr.takeError(); if (E->hasExplicitTemplateArgs()) { TemplateArgumentListInfo ToTAInfo; if (Error Err = ImportTemplateArgumentListInfo( E->getLAngleLoc(), E->getRAngleLoc(), E->template_arguments(), ToTAInfo)) return std::move(Err); ExpectedSLoc ToTemplateKeywordLocOrErr = import(E->getTemplateKeywordLoc()); if (!ToTemplateKeywordLocOrErr) return ToTemplateKeywordLocOrErr.takeError(); const bool KnownDependent = (E->getDependence() & ExprDependence::TypeValue) == ExprDependence::TypeValue; return UnresolvedLookupExpr::Create( Importer.getToContext(), *ToNamingClassOrErr, *ToQualifierLocOrErr, *ToTemplateKeywordLocOrErr, ToNameInfo, E->requiresADL(), &ToTAInfo, ToDecls.begin(), ToDecls.end(), KnownDependent, /*KnownInstantiationDependent=*/E->isInstantiationDependent()); } return UnresolvedLookupExpr::Create( Importer.getToContext(), *ToNamingClassOrErr, *ToQualifierLocOrErr, ToNameInfo, E->requiresADL(), ToDecls.begin(), ToDecls.end(), /*KnownDependent=*/E->isTypeDependent(), /*KnownInstantiationDependent=*/E->isInstantiationDependent()); } ExpectedStmt ASTNodeImporter::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E) { Error Err = Error::success(); auto ToType = importChecked(Err, E->getType()); auto ToOperatorLoc = importChecked(Err, E->getOperatorLoc()); auto ToQualifierLoc = importChecked(Err, E->getQualifierLoc()); auto ToTemplateKeywordLoc = importChecked(Err, E->getTemplateKeywordLoc()); auto ToName = importChecked(Err, E->getName()); auto ToNameLoc = importChecked(Err, E->getNameLoc()); if (Err) return std::move(Err); DeclarationNameInfo ToNameInfo(ToName, ToNameLoc); // Import additional name location/type info. if (Error Err = ImportDeclarationNameLoc(E->getNameInfo(), ToNameInfo)) return std::move(Err); UnresolvedSet<8> ToDecls; for (Decl *D : E->decls()) if (auto ToDOrErr = import(D)) ToDecls.addDecl(cast(*ToDOrErr)); else return ToDOrErr.takeError(); TemplateArgumentListInfo ToTAInfo; TemplateArgumentListInfo *ResInfo = nullptr; if (E->hasExplicitTemplateArgs()) { TemplateArgumentListInfo FromTAInfo; E->copyTemplateArgumentsInto(FromTAInfo); if (Error Err = ImportTemplateArgumentListInfo(FromTAInfo, ToTAInfo)) return std::move(Err); ResInfo = &ToTAInfo; } Expr *ToBase = nullptr; if (!E->isImplicitAccess()) { if (ExpectedExpr ToBaseOrErr = import(E->getBase())) ToBase = *ToBaseOrErr; else return ToBaseOrErr.takeError(); } return UnresolvedMemberExpr::Create( Importer.getToContext(), E->hasUnresolvedUsing(), ToBase, ToType, E->isArrow(), ToOperatorLoc, ToQualifierLoc, ToTemplateKeywordLoc, ToNameInfo, ResInfo, ToDecls.begin(), ToDecls.end()); } ExpectedStmt ASTNodeImporter::VisitCallExpr(CallExpr *E) { Error Err = Error::success(); auto ToCallee = importChecked(Err, E->getCallee()); auto ToType = importChecked(Err, E->getType()); auto ToRParenLoc = importChecked(Err, E->getRParenLoc()); if (Err) return std::move(Err); unsigned NumArgs = E->getNumArgs(); llvm::SmallVector 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, E->getFPFeatures(), /*MinNumArgs=*/0, E->getADLCallKind()); } ExpectedStmt ASTNodeImporter::VisitLambdaExpr(LambdaExpr *E) { CXXRecordDecl *FromClass = E->getLambdaClass(); auto ToClassOrErr = import(FromClass); if (!ToClassOrErr) return ToClassOrErr.takeError(); CXXRecordDecl *ToClass = *ToClassOrErr; auto ToCallOpOrErr = import(E->getCallOperator()); if (!ToCallOpOrErr) return ToCallOpOrErr.takeError(); SmallVector ToCaptureInits(E->capture_size()); if (Error Err = ImportContainerChecked(E->capture_inits(), ToCaptureInits)) return std::move(Err); Error Err = Error::success(); auto ToIntroducerRange = importChecked(Err, E->getIntroducerRange()); auto ToCaptureDefaultLoc = importChecked(Err, E->getCaptureDefaultLoc()); auto ToEndLoc = importChecked(Err, E->getEndLoc()); if (Err) return std::move(Err); return LambdaExpr::Create(Importer.getToContext(), ToClass, ToIntroducerRange, E->getCaptureDefault(), ToCaptureDefaultLoc, E->hasExplicitParameters(), E->hasExplicitResultType(), ToCaptureInits, ToEndLoc, E->containsUnexpandedParameterPack()); } ExpectedStmt ASTNodeImporter::VisitInitListExpr(InitListExpr *E) { Error Err = Error::success(); auto ToLBraceLoc = importChecked(Err, E->getLBraceLoc()); auto ToRBraceLoc = importChecked(Err, E->getRBraceLoc()); auto ToType = importChecked(Err, E->getType()); if (Err) return std::move(Err); SmallVector ToExprs(E->getNumInits()); if (Error Err = ImportContainerChecked(E->inits(), ToExprs)) return std::move(Err); ASTContext &ToCtx = Importer.getToContext(); InitListExpr *To = new (ToCtx) InitListExpr( ToCtx, ToLBraceLoc, ToExprs, ToRBraceLoc); To->setType(ToType); if (E->hasArrayFiller()) { if (ExpectedExpr ToFillerOrErr = import(E->getArrayFiller())) To->setArrayFiller(*ToFillerOrErr); else return ToFillerOrErr.takeError(); } if (FieldDecl *FromFD = E->getInitializedFieldInUnion()) { if (auto ToFDOrErr = import(FromFD)) To->setInitializedFieldInUnion(*ToFDOrErr); else return ToFDOrErr.takeError(); } if (InitListExpr *SyntForm = E->getSyntacticForm()) { if (auto ToSyntFormOrErr = import(SyntForm)) To->setSyntacticForm(*ToSyntFormOrErr); else return ToSyntFormOrErr.takeError(); } // Copy InitListExprBitfields, which are not handled in the ctor of // InitListExpr. To->sawArrayRangeDesignator(E->hadArrayRangeDesignator()); return To; } ExpectedStmt ASTNodeImporter::VisitCXXStdInitializerListExpr( CXXStdInitializerListExpr *E) { ExpectedType ToTypeOrErr = import(E->getType()); if (!ToTypeOrErr) return ToTypeOrErr.takeError(); ExpectedExpr ToSubExprOrErr = import(E->getSubExpr()); if (!ToSubExprOrErr) return ToSubExprOrErr.takeError(); return new (Importer.getToContext()) CXXStdInitializerListExpr( *ToTypeOrErr, *ToSubExprOrErr); } ExpectedStmt ASTNodeImporter::VisitCXXInheritedCtorInitExpr( CXXInheritedCtorInitExpr *E) { Error Err = Error::success(); auto ToLocation = importChecked(Err, E->getLocation()); auto ToType = importChecked(Err, E->getType()); auto ToConstructor = importChecked(Err, E->getConstructor()); if (Err) return std::move(Err); return new (Importer.getToContext()) CXXInheritedCtorInitExpr( ToLocation, ToType, ToConstructor, E->constructsVBase(), E->inheritedFromVBase()); } ExpectedStmt ASTNodeImporter::VisitArrayInitLoopExpr(ArrayInitLoopExpr *E) { Error Err = Error::success(); auto ToType = importChecked(Err, E->getType()); auto ToCommonExpr = importChecked(Err, E->getCommonExpr()); auto ToSubExpr = importChecked(Err, E->getSubExpr()); if (Err) return std::move(Err); return new (Importer.getToContext()) ArrayInitLoopExpr( ToType, ToCommonExpr, ToSubExpr); } ExpectedStmt ASTNodeImporter::VisitArrayInitIndexExpr(ArrayInitIndexExpr *E) { ExpectedType ToTypeOrErr = import(E->getType()); if (!ToTypeOrErr) return ToTypeOrErr.takeError(); return new (Importer.getToContext()) ArrayInitIndexExpr(*ToTypeOrErr); } ExpectedStmt ASTNodeImporter::VisitCXXDefaultInitExpr(CXXDefaultInitExpr *E) { ExpectedSLoc ToBeginLocOrErr = import(E->getBeginLoc()); if (!ToBeginLocOrErr) return ToBeginLocOrErr.takeError(); auto ToFieldOrErr = import(E->getField()); if (!ToFieldOrErr) return ToFieldOrErr.takeError(); auto UsedContextOrErr = Importer.ImportContext(E->getUsedContext()); if (!UsedContextOrErr) return UsedContextOrErr.takeError(); FieldDecl *ToField = *ToFieldOrErr; assert(ToField->hasInClassInitializer() && "Field should have in-class initializer if there is a default init " "expression that uses it."); if (!ToField->getInClassInitializer()) { // The in-class initializer may be not yet set in "To" AST even if the // field is already there. This must be set here to make construction of // CXXDefaultInitExpr work. auto ToInClassInitializerOrErr = import(E->getField()->getInClassInitializer()); if (!ToInClassInitializerOrErr) return ToInClassInitializerOrErr.takeError(); ToField->setInClassInitializer(*ToInClassInitializerOrErr); } Expr *RewrittenInit = nullptr; if (E->hasRewrittenInit()) { ExpectedExpr ExprOrErr = import(E->getRewrittenExpr()); if (!ExprOrErr) return ExprOrErr.takeError(); RewrittenInit = ExprOrErr.get(); } return CXXDefaultInitExpr::Create(Importer.getToContext(), *ToBeginLocOrErr, ToField, *UsedContextOrErr, RewrittenInit); } ExpectedStmt ASTNodeImporter::VisitCXXNamedCastExpr(CXXNamedCastExpr *E) { Error Err = Error::success(); auto ToType = importChecked(Err, E->getType()); auto ToSubExpr = importChecked(Err, E->getSubExpr()); auto ToTypeInfoAsWritten = importChecked(Err, E->getTypeInfoAsWritten()); auto ToOperatorLoc = importChecked(Err, E->getOperatorLoc()); auto ToRParenLoc = importChecked(Err, E->getRParenLoc()); auto ToAngleBrackets = importChecked(Err, E->getAngleBrackets()); if (Err) return std::move(Err); ExprValueKind VK = E->getValueKind(); CastKind CK = E->getCastKind(); auto ToBasePathOrErr = ImportCastPath(E); if (!ToBasePathOrErr) return ToBasePathOrErr.takeError(); if (auto CCE = dyn_cast(E)) { return CXXStaticCastExpr::Create( Importer.getToContext(), ToType, VK, CK, ToSubExpr, &(*ToBasePathOrErr), ToTypeInfoAsWritten, CCE->getFPFeatures(), 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) { Error Err = Error::success(); auto ToType = importChecked(Err, E->getType()); auto ToExprLoc = importChecked(Err, E->getExprLoc()); auto ToAssociatedDecl = importChecked(Err, E->getAssociatedDecl()); auto ToReplacement = importChecked(Err, E->getReplacement()); if (Err) return std::move(Err); return new (Importer.getToContext()) SubstNonTypeTemplateParmExpr( ToType, E->getValueKind(), ToExprLoc, ToReplacement, ToAssociatedDecl, E->getIndex(), E->getPackIndex(), E->isReferenceParameter()); } ExpectedStmt ASTNodeImporter::VisitTypeTraitExpr(TypeTraitExpr *E) { Error Err = Error::success(); auto ToType = importChecked(Err, E->getType()); auto ToBeginLoc = importChecked(Err, E->getBeginLoc()); auto ToEndLoc = importChecked(Err, E->getEndLoc()); if (Err) return std::move(Err); SmallVector 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); } ExpectedStmt ASTNodeImporter::VisitCXXFoldExpr(CXXFoldExpr *E) { Error Err = Error::success(); QualType ToType = importChecked(Err, E->getType()); UnresolvedLookupExpr *ToCallee = importChecked(Err, E->getCallee()); SourceLocation ToLParenLoc = importChecked(Err, E->getLParenLoc()); Expr *ToLHS = importChecked(Err, E->getLHS()); SourceLocation ToEllipsisLoc = importChecked(Err, E->getEllipsisLoc()); Expr *ToRHS = importChecked(Err, E->getRHS()); SourceLocation ToRParenLoc = importChecked(Err, E->getRParenLoc()); if (Err) return std::move(Err); return new (Importer.getToContext()) CXXFoldExpr(ToType, ToCallee, ToLParenLoc, ToLHS, E->getOperator(), ToEllipsisLoc, ToRHS, ToRParenLoc, E->getNumExpansions()); } 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; std::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 std::nullopt; 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 std::nullopt; } ASTImporter::FoundDeclsTy ASTImporter::findDeclsInToCtx(DeclContext *DC, DeclarationName Name) { // We search in the redecl context because of transparent contexts. // E.g. a simple C language enum is a transparent context: // enum E { A, B }; // Now if we had a global variable in the TU // int A; // then the enum constant 'A' and the variable 'A' violates ODR. // We can diagnose this only if we search in the redecl context. DeclContext *ReDC = DC->getRedeclContext(); if (SharedState->getLookupTable()) { 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); } llvm::Expected ASTImporter::Import(ExprWithCleanups::CleanupObject From) { if (auto *CLE = From.dyn_cast()) { if (Expected R = Import(CLE)) return ExprWithCleanups::CleanupObject(cast(*R)); } // FIXME: Handle BlockDecl when we implement importing BlockExpr in // ASTNodeImporter. return make_error(ASTImportError::UnsupportedConstruct); } ExpectedTypePtr ASTImporter::Import(const Type *FromT) { if (!FromT) return FromT; // Check whether we've already imported this type. llvm::DenseMap::iterator Pos = ImportedTypes.find(FromT); if (Pos != ImportedTypes.end()) return Pos->second; // Import the type. ASTNodeImporter Importer(*this); ExpectedType ToTOrErr = Importer.Visit(FromT); if (!ToTOrErr) return ToTOrErr.takeError(); // Record the imported type. ImportedTypes[FromT] = ToTOrErr->getTypePtr(); return ToTOrErr->getTypePtr(); } Expected ASTImporter::Import(QualType FromT) { if (FromT.isNull()) return QualType{}; ExpectedTypePtr ToTyOrErr = Import(FromT.getTypePtr()); if (!ToTyOrErr) return ToTyOrErr.takeError(); return ToContext.getQualifiedType(*ToTyOrErr, FromT.getLocalQualifiers()); } Expected ASTImporter::Import(TypeSourceInfo *FromTSI) { if (!FromTSI) return FromTSI; // FIXME: For now we just create a "trivial" type source info based // on the type and a single location. Implement a real version of this. ExpectedType TOrErr = Import(FromTSI->getType()); if (!TOrErr) return TOrErr.takeError(); ExpectedSLoc BeginLocOrErr = Import(FromTSI->getTypeLoc().getBeginLoc()); if (!BeginLocOrErr) return BeginLocOrErr.takeError(); return ToContext.getTrivialTypeSourceInfo(*TOrErr, *BeginLocOrErr); } namespace { // To use this object, it should be created before the new attribute is created, // and destructed after it is created. The construction already performs the // import of the data. template struct AttrArgImporter { AttrArgImporter(const AttrArgImporter &) = delete; AttrArgImporter(AttrArgImporter &&) = default; AttrArgImporter &operator=(const AttrArgImporter &) = delete; AttrArgImporter &operator=(AttrArgImporter &&) = default; AttrArgImporter(ASTNodeImporter &I, Error &Err, const T &From) : To(I.importChecked(Err, From)) {} const T &value() { return To; } private: T To; }; // To use this object, it should be created before the new attribute is created, // and destructed after it is created. The construction already performs the // import of the data. The array data is accessible in a pointer form, this form // is used by the attribute classes. This object should be created once for the // array data to be imported (the array size is not imported, just copied). template struct AttrArgArrayImporter { AttrArgArrayImporter(const AttrArgArrayImporter &) = delete; AttrArgArrayImporter(AttrArgArrayImporter &&) = default; AttrArgArrayImporter &operator=(const AttrArgArrayImporter &) = delete; AttrArgArrayImporter &operator=(AttrArgArrayImporter &&) = default; AttrArgArrayImporter(ASTNodeImporter &I, Error &Err, const llvm::iterator_range &From, unsigned ArraySize) { if (Err) return; To.reserve(ArraySize); Err = I.ImportContainerChecked(From, To); } T *value() { return To.data(); } private: llvm::SmallVector To; }; class AttrImporter { Error Err{Error::success()}; Attr *ToAttr = nullptr; ASTImporter &Importer; ASTNodeImporter NImporter; public: AttrImporter(ASTImporter &I) : Importer(I), NImporter(I) {} // Useful for accessing the imported attribute. template T *castAttrAs() { return cast(ToAttr); } template const T *castAttrAs() const { return cast(ToAttr); } // Create an "importer" for an attribute parameter. // Result of the 'value()' of that object is to be passed to the function // 'importAttr', in the order that is expected by the attribute class. template AttrArgImporter importArg(const T &From) { return AttrArgImporter(NImporter, Err, From); } // Create an "importer" for an attribute parameter that has array type. // Result of the 'value()' of that object is to be passed to the function // 'importAttr', then the size of the array as next argument. template AttrArgArrayImporter importArrayArg(const llvm::iterator_range &From, unsigned ArraySize) { return AttrArgArrayImporter(NImporter, Err, From, ArraySize); } // Create an attribute object with the specified arguments. // The 'FromAttr' is the original (not imported) attribute, the 'ImportedArg' // should be values that are passed to the 'Create' function of the attribute. // (The 'Create' with 'ASTContext' first and 'AttributeCommonInfo' last is // used here.) As much data is copied or imported from the old attribute // as possible. The passed arguments should be already imported. // If an import error happens, the internal error is set to it, and any // further import attempt is ignored. template void importAttr(const T *FromAttr, Arg &&...ImportedArg) { static_assert(std::is_base_of::value, "T should be subclass of Attr."); assert(!ToAttr && "Use one AttrImporter to import one Attribute object."); const IdentifierInfo *ToAttrName = Importer.Import(FromAttr->getAttrName()); const IdentifierInfo *ToScopeName = Importer.Import(FromAttr->getScopeName()); SourceRange ToAttrRange = NImporter.importChecked(Err, FromAttr->getRange()); SourceLocation ToScopeLoc = NImporter.importChecked(Err, FromAttr->getScopeLoc()); if (Err) return; AttributeCommonInfo ToI(ToAttrName, ToScopeName, ToAttrRange, ToScopeLoc, FromAttr->getParsedKind(), FromAttr->getForm()); // The "SemanticSpelling" is not needed to be passed to the constructor. // That value is recalculated from the SpellingListIndex if needed. ToAttr = T::Create(Importer.getToContext(), std::forward(ImportedArg)..., ToI); ToAttr->setImplicit(FromAttr->isImplicit()); ToAttr->setPackExpansion(FromAttr->isPackExpansion()); if (auto *ToInheritableAttr = dyn_cast(ToAttr)) ToInheritableAttr->setInherited(FromAttr->isInherited()); } // Create a clone of the 'FromAttr' and import its source range only. // This causes objects with invalid references to be created if the 'FromAttr' // contains other data that should be imported. void cloneAttr(const Attr *FromAttr) { assert(!ToAttr && "Use one AttrImporter to import one Attribute object."); SourceRange ToRange = NImporter.importChecked(Err, FromAttr->getRange()); if (Err) return; ToAttr = FromAttr->clone(Importer.getToContext()); ToAttr->setRange(ToRange); ToAttr->setAttrName(Importer.Import(FromAttr->getAttrName())); } // Get the result of the previous import attempt (can be used only once). llvm::Expected getResult() && { if (Err) return std::move(Err); assert(ToAttr && "Attribute should be created."); return ToAttr; } }; } // namespace Expected ASTImporter::Import(const Attr *FromAttr) { AttrImporter AI(*this); // FIXME: Is there some kind of AttrVisitor to use here? switch (FromAttr->getKind()) { case attr::Aligned: { auto *From = cast(FromAttr); if (From->isAlignmentExpr()) AI.importAttr(From, true, AI.importArg(From->getAlignmentExpr()).value()); else AI.importAttr(From, false, AI.importArg(From->getAlignmentType()).value()); break; } case attr::AlignValue: { auto *From = cast(FromAttr); AI.importAttr(From, AI.importArg(From->getAlignment()).value()); break; } case attr::Format: { const auto *From = cast(FromAttr); AI.importAttr(From, Import(From->getType()), From->getFormatIdx(), From->getFirstArg()); break; } case attr::EnableIf: { const auto *From = cast(FromAttr); AI.importAttr(From, AI.importArg(From->getCond()).value(), From->getMessage()); break; } case attr::AssertCapability: { const auto *From = cast(FromAttr); AI.importAttr(From, AI.importArrayArg(From->args(), From->args_size()).value(), From->args_size()); break; } case attr::AcquireCapability: { const auto *From = cast(FromAttr); AI.importAttr(From, AI.importArrayArg(From->args(), From->args_size()).value(), From->args_size()); break; } case attr::TryAcquireCapability: { const auto *From = cast(FromAttr); AI.importAttr(From, AI.importArg(From->getSuccessValue()).value(), AI.importArrayArg(From->args(), From->args_size()).value(), From->args_size()); break; } case attr::ReleaseCapability: { const auto *From = cast(FromAttr); AI.importAttr(From, AI.importArrayArg(From->args(), From->args_size()).value(), From->args_size()); break; } case attr::RequiresCapability: { const auto *From = cast(FromAttr); AI.importAttr(From, AI.importArrayArg(From->args(), From->args_size()).value(), From->args_size()); break; } case attr::GuardedBy: { const auto *From = cast(FromAttr); AI.importAttr(From, AI.importArg(From->getArg()).value()); break; } case attr::PtGuardedBy: { const auto *From = cast(FromAttr); AI.importAttr(From, AI.importArg(From->getArg()).value()); break; } case attr::AcquiredAfter: { const auto *From = cast(FromAttr); AI.importAttr(From, AI.importArrayArg(From->args(), From->args_size()).value(), From->args_size()); break; } case attr::AcquiredBefore: { const auto *From = cast(FromAttr); AI.importAttr(From, AI.importArrayArg(From->args(), From->args_size()).value(), From->args_size()); break; } case attr::AssertExclusiveLock: { const auto *From = cast(FromAttr); AI.importAttr(From, AI.importArrayArg(From->args(), From->args_size()).value(), From->args_size()); break; } case attr::AssertSharedLock: { const auto *From = cast(FromAttr); AI.importAttr(From, AI.importArrayArg(From->args(), From->args_size()).value(), From->args_size()); break; } case attr::ExclusiveTrylockFunction: { const auto *From = cast(FromAttr); AI.importAttr(From, AI.importArg(From->getSuccessValue()).value(), AI.importArrayArg(From->args(), From->args_size()).value(), From->args_size()); break; } case attr::SharedTrylockFunction: { const auto *From = cast(FromAttr); AI.importAttr(From, AI.importArg(From->getSuccessValue()).value(), AI.importArrayArg(From->args(), From->args_size()).value(), From->args_size()); break; } case attr::LockReturned: { const auto *From = cast(FromAttr); AI.importAttr(From, AI.importArg(From->getArg()).value()); break; } case attr::LocksExcluded: { const auto *From = cast(FromAttr); AI.importAttr(From, AI.importArrayArg(From->args(), From->args_size()).value(), From->args_size()); break; } default: { // The default branch works for attributes that have no arguments to import. // FIXME: Handle every attribute type that has arguments of type to import // (most often Expr* or Decl* or type) in the switch above. AI.cloneAttr(FromAttr); break; } } return std::move(AI).getResult(); } Decl *ASTImporter::GetAlreadyImportedOrNull(const Decl *FromD) const { return ImportedDecls.lookup(FromD); } TranslationUnitDecl *ASTImporter::GetFromTU(Decl *ToD) { auto FromDPos = ImportedFromDecls.find(ToD); if (FromDPos == ImportedFromDecls.end()) return nullptr; return FromDPos->second->getTranslationUnitDecl(); } Error ASTImporter::ImportAttrs(Decl *ToD, Decl *FromD) { if (!FromD->hasAttrs() || ToD->hasAttrs()) return Error::success(); for (const Attr *FromAttr : FromD->getAttrs()) { auto ToAttrOrErr = Import(FromAttr); if (ToAttrOrErr) ToD->addAttr(*ToAttrOrErr); else return ToAttrOrErr.takeError(); } return Error::success(); } 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()) { // In the case of TypedefNameDecl we create the Decl first and only // then we import and set its DeclContext. So, the DC might not be set // when we reach here. if (ToD->getDeclContext()) SharedState->removeDeclFromLookup(ToD); ImportedFromDecls.erase(PosF); } // FIXME: AST may contain remaining references to the failed object. // However, the ImportDeclErrors in the shared state contains all the // failed objects together with their error. } // Error encountered for the first time. // After takeError the error is not usable any more in ToDOrErr. // Get a copy of the error object (any more simple solution for this?). ASTImportError ErrOut; handleAllErrors(ToDOrErr.takeError(), [&ErrOut](const ASTImportError &E) { ErrOut = E; }); setImportDeclError(FromD, ErrOut); // Set the error for the mapped to Decl, which is in the "to" context. if (Pos != ImportedDecls.end()) SharedState->setImportDeclError(Pos->second, ErrOut); // Set the error for all nodes which have been created before we // recognized the error. for (const auto &Path : SavedImportPaths[FromD]) { // The import path contains import-dependency nodes first. // Save the node that was imported as dependency of the current node. Decl *PrevFromDi = FromD; for (Decl *FromDi : Path) { // Begin and end of the path equals 'FromD', skip it. if (FromDi == FromD) continue; // We should not set import error on a node and all following nodes in // the path if child import errors are ignored. if (ChildErrorHandlingStrategy(FromDi).ignoreChildErrorOnParent( PrevFromDi)) break; PrevFromDi = FromDi; setImportDeclError(FromDi, ErrOut); //FIXME Should we remove these Decls from ImportedDecls? // Set the error for the mapped to Decl, which is in the "to" context. auto Ii = ImportedDecls.find(FromDi); if (Ii != ImportedDecls.end()) SharedState->setImportDeclError(Ii->second, ErrOut); // FIXME Should we remove these Decls from the LookupTable, // and from ImportedFromDecls? } } SavedImportPaths.erase(FromD); // Do not return ToDOrErr, error was taken out of it. return make_error(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?"); if (auto Error = ImportAttrs(ToD, FromD)) return std::move(Error); // Notify subclasses. Imported(FromD, ToD); updateFlags(FromD, ToD); SavedImportPaths.erase(FromD); return ToDOrErr; } llvm::Expected ASTImporter::Import(const InheritedConstructor &From) { return ASTNodeImporter(*this).ImportInheritedConstructor(From); } 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()) return ToDC; // If FromRecord is not defined we need to force it to be. // Simply calling CompleteDecl(...) for a RecordDecl will break some cases // it will start the definition but we never finish it. // If there are base classes they won't be imported and we will // be missing anything that we inherit from those bases. if (FromRecord->getASTContext().getExternalSource() && !FromRecord->isCompleteDefinition()) FromRecord->getASTContext().getExternalSource()->CompleteType(FromRecord); if (FromRecord->isCompleteDefinition()) if (Error Err = ASTNodeImporter(*this).ImportDefinition( FromRecord, ToRecord, ASTNodeImporter::IDK_Basic)) return std::move(Err); } else if (auto *ToEnum = dyn_cast(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->setDependence(FromE->getDependence()); } // 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 (ExpectedTypePtr TyOrErr = Import(FromNNS->getAsType())) { bool TSTemplate = FromNNS->getKind() == NestedNameSpecifier::TypeSpecWithTemplate; return NestedNameSpecifier::Create(ToContext, Prefix, TSTemplate, *TyOrErr); } 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); if (Kind == NestedNameSpecifier::TypeSpecWithTemplate) // ToLocalBeginLoc is here the location of the 'template' keyword. Builder.Extend(getToContext(), ToLocalBeginLoc, TSI->getTypeLoc(), ToLocalEndLoc); else // No location for 'template' keyword here. Builder.Extend(getToContext(), SourceLocation{}, 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)->getCanonicalDecl())); else return ToTemplateOrErr.takeError(); case TemplateName::OverloadedTemplate: { OverloadedTemplateStorage *FromStorage = From.getAsOverloadedTemplate(); UnresolvedSet<2> ToTemplates; for (auto *I : *FromStorage) { if (auto ToOrErr = Import(I)) ToTemplates.addDecl(cast(*ToOrErr)); else return ToOrErr.takeError(); } return ToContext.getOverloadedTemplateName(ToTemplates.begin(), ToTemplates.end()); } case TemplateName::AssumedTemplate: { AssumedTemplateStorage *FromStorage = From.getAsAssumedTemplateName(); auto DeclNameOrErr = Import(FromStorage->getDeclName()); if (!DeclNameOrErr) return DeclNameOrErr.takeError(); return ToContext.getAssumedTemplateName(*DeclNameOrErr); } case TemplateName::QualifiedTemplate: { QualifiedTemplateName *QTN = From.getAsQualifiedTemplateName(); auto QualifierOrErr = Import(QTN->getQualifier()); if (!QualifierOrErr) return QualifierOrErr.takeError(); auto TNOrErr = Import(QTN->getUnderlyingTemplate()); if (!TNOrErr) return TNOrErr.takeError(); return ToContext.getQualifiedTemplateName( *QualifierOrErr, QTN->hasTemplateKeyword(), *TNOrErr); } case TemplateName::DependentTemplate: { DependentTemplateName *DTN = From.getAsDependentTemplateName(); auto QualifierOrErr = Import(DTN->getQualifier()); if (!QualifierOrErr) return QualifierOrErr.takeError(); if (DTN->isIdentifier()) { return ToContext.getDependentTemplateName(*QualifierOrErr, Import(DTN->getIdentifier())); } return ToContext.getDependentTemplateName(*QualifierOrErr, DTN->getOperator()); } case TemplateName::SubstTemplateTemplateParm: { SubstTemplateTemplateParmStorage *Subst = From.getAsSubstTemplateTemplateParm(); auto ReplacementOrErr = Import(Subst->getReplacement()); if (!ReplacementOrErr) return ReplacementOrErr.takeError(); auto AssociatedDeclOrErr = Import(Subst->getAssociatedDecl()); if (!AssociatedDeclOrErr) return AssociatedDeclOrErr.takeError(); return ToContext.getSubstTemplateTemplateParm( *ReplacementOrErr, *AssociatedDeclOrErr, Subst->getIndex(), Subst->getPackIndex()); } case TemplateName::SubstTemplateTemplateParmPack: { SubstTemplateTemplateParmPackStorage *SubstPack = From.getAsSubstTemplateTemplateParmPack(); ASTNodeImporter Importer(*this); auto ArgPackOrErr = Importer.ImportTemplateArgument(SubstPack->getArgumentPack()); if (!ArgPackOrErr) return ArgPackOrErr.takeError(); auto AssociatedDeclOrErr = Import(SubstPack->getAssociatedDecl()); if (!AssociatedDeclOrErr) return AssociatedDeclOrErr.takeError(); return ToContext.getSubstTemplateTemplateParmPack( *ArgPackOrErr, *AssociatedDeclOrErr, SubstPack->getIndex(), SubstPack->getFinal()); } case TemplateName::UsingTemplate: { auto UsingOrError = Import(From.getAsUsingShadowDecl()); if (!UsingOrError) return UsingOrError.takeError(); return TemplateName(cast(*UsingOrError)); } } 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 ExLength = FromSM.getFileIDSize(FromID); SourceLocation MLoc; if (FromEx.isMacroArgExpansion()) { MLoc = ToSM.createMacroArgExpansionLoc(*ToSpLoc, *ToExLocS, ExLength); } else { if (ExpectedSLoc ToExLocE = Import(FromEx.getExpansionLocEnd())) MLoc = ToSM.createExpansionLoc(*ToSpLoc, *ToExLocS, *ToExLocE, ExLength, FromEx.isExpansionTokenRange()); else return ToExLocE.takeError(); } ToID = ToSM.getFileID(MLoc); } else { const SrcMgr::ContentCache *Cache = &FromSLoc.getFile().getContentCache(); if (!IsBuiltin && !Cache->BufferOverridden) { // Include location of this file. ExpectedSLoc ToIncludeLoc = Import(FromSLoc.getFile().getIncludeLoc()); if (!ToIncludeLoc) return ToIncludeLoc.takeError(); // Every FileID that is not the main FileID needs to have a valid include // location so that the include chain points to the main FileID. When // importing the main FileID (which has no include location), we need to // create a fake include location in the main file to keep this property // intact. SourceLocation ToIncludeLocOrFakeLoc = *ToIncludeLoc; if (FromID == FromSM.getMainFileID()) ToIncludeLocOrFakeLoc = ToSM.getLocForStartOfFile(ToSM.getMainFileID()); if (Cache->OrigEntry && Cache->OrigEntry->getDir()) { // FIXME: We probably want to use 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.getOptionalFileRef(Cache->OrigEntry->getName()); // FIXME: The filename may be a virtual name that does probably not // point to a valid file and we get no Entry here. In this case try with // the memory buffer below. if (Entry) ToID = ToSM.createFileID(*Entry, ToIncludeLocOrFakeLoc, FromSLoc.getFile().getFileCharacteristic()); } } if (ToID.isInvalid() || IsBuiltin) { // FIXME: We want to re-use the existing MemoryBuffer! std::optional FromBuf = Cache->getBufferOrNone(FromContext.getDiagnostics(), FromSM.getFileManager(), SourceLocation{}); if (!FromBuf) return llvm::make_error(ASTImportError::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; 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; } llvm::Expected ASTImporter::Import(const APValue &FromValue) { ASTNodeImporter Importer(*this); return Importer.ImportAPValue(FromValue); } Error ASTImporter::ImportDefinition(Decl *From) { ExpectedDecl ToOrErr = Import(From); if (!ToOrErr) return ToOrErr.takeError(); Decl *To = *ToOrErr; auto *FromDC = cast(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()); } llvm::Expected ASTNodeImporter::ImportAPValue(const APValue &FromValue) { APValue Result; llvm::Error Err = llvm::Error::success(); auto ImportLoop = [&](const APValue *From, APValue *To, unsigned Size) { for (unsigned Idx = 0; Idx < Size; Idx++) { APValue Tmp = importChecked(Err, From[Idx]); To[Idx] = Tmp; } }; switch (FromValue.getKind()) { case APValue::None: case APValue::Indeterminate: case APValue::Int: case APValue::Float: case APValue::FixedPoint: case APValue::ComplexInt: case APValue::ComplexFloat: Result = FromValue; break; case APValue::Vector: { Result.MakeVector(); MutableArrayRef Elts = Result.setVectorUninit(FromValue.getVectorLength()); ImportLoop(((const APValue::Vec *)(const char *)&FromValue.Data)->Elts, Elts.data(), FromValue.getVectorLength()); break; } case APValue::Array: Result.MakeArray(FromValue.getArrayInitializedElts(), FromValue.getArraySize()); ImportLoop(((const APValue::Arr *)(const char *)&FromValue.Data)->Elts, ((const APValue::Arr *)(const char *)&Result.Data)->Elts, FromValue.getArrayInitializedElts()); break; case APValue::Struct: Result.MakeStruct(FromValue.getStructNumBases(), FromValue.getStructNumFields()); ImportLoop( ((const APValue::StructData *)(const char *)&FromValue.Data)->Elts, ((const APValue::StructData *)(const char *)&Result.Data)->Elts, FromValue.getStructNumBases() + FromValue.getStructNumFields()); break; case APValue::Union: { Result.MakeUnion(); const Decl *ImpFDecl = importChecked(Err, FromValue.getUnionField()); APValue ImpValue = importChecked(Err, FromValue.getUnionValue()); if (Err) return std::move(Err); Result.setUnion(cast(ImpFDecl), ImpValue); break; } case APValue::AddrLabelDiff: { Result.MakeAddrLabelDiff(); const Expr *ImpLHS = importChecked(Err, FromValue.getAddrLabelDiffLHS()); const Expr *ImpRHS = importChecked(Err, FromValue.getAddrLabelDiffRHS()); if (Err) return std::move(Err); Result.setAddrLabelDiff(cast(ImpLHS), cast(ImpRHS)); break; } case APValue::MemberPointer: { const Decl *ImpMemPtrDecl = importChecked(Err, FromValue.getMemberPointerDecl()); if (Err) return std::move(Err); MutableArrayRef ToPath = Result.setMemberPointerUninit( cast(ImpMemPtrDecl), FromValue.isMemberPointerToDerivedMember(), FromValue.getMemberPointerPath().size()); llvm::ArrayRef FromPath = Result.getMemberPointerPath(); for (unsigned Idx = 0; Idx < FromValue.getMemberPointerPath().size(); Idx++) { const Decl *ImpDecl = importChecked(Err, FromPath[Idx]); if (Err) return std::move(Err); ToPath[Idx] = cast(ImpDecl->getCanonicalDecl()); } break; } case APValue::LValue: APValue::LValueBase Base; QualType FromElemTy; if (FromValue.getLValueBase()) { assert(!FromValue.getLValueBase().is() && "in C++20 dynamic allocation are transient so they shouldn't " "appear in the AST"); if (!FromValue.getLValueBase().is()) { if (const auto *E = FromValue.getLValueBase().dyn_cast()) { FromElemTy = E->getType(); const Expr *ImpExpr = importChecked(Err, E); if (Err) return std::move(Err); Base = APValue::LValueBase(ImpExpr, FromValue.getLValueBase().getCallIndex(), FromValue.getLValueBase().getVersion()); } else { FromElemTy = FromValue.getLValueBase().get()->getType(); const Decl *ImpDecl = importChecked( Err, FromValue.getLValueBase().get()); if (Err) return std::move(Err); Base = APValue::LValueBase(cast(ImpDecl), FromValue.getLValueBase().getCallIndex(), FromValue.getLValueBase().getVersion()); } } else { FromElemTy = FromValue.getLValueBase().getTypeInfoType(); const Type *ImpTypeInfo = importChecked( Err, FromValue.getLValueBase().get().getType()); QualType ImpType = importChecked(Err, FromValue.getLValueBase().getTypeInfoType()); if (Err) return std::move(Err); Base = APValue::LValueBase::getTypeInfo(TypeInfoLValue(ImpTypeInfo), ImpType); } } CharUnits Offset = FromValue.getLValueOffset(); unsigned PathLength = FromValue.getLValuePath().size(); Result.MakeLValue(); if (FromValue.hasLValuePath()) { MutableArrayRef ToPath = Result.setLValueUninit( Base, Offset, PathLength, FromValue.isLValueOnePastTheEnd(), FromValue.isNullPointer()); llvm::ArrayRef FromPath = FromValue.getLValuePath(); for (unsigned LoopIdx = 0; LoopIdx < PathLength; LoopIdx++) { if (FromElemTy->isRecordType()) { const Decl *FromDecl = FromPath[LoopIdx].getAsBaseOrMember().getPointer(); const Decl *ImpDecl = importChecked(Err, FromDecl); if (Err) return std::move(Err); if (auto *RD = dyn_cast(FromDecl)) FromElemTy = Importer.FromContext.getRecordType(RD); else FromElemTy = cast(FromDecl)->getType(); ToPath[LoopIdx] = APValue::LValuePathEntry(APValue::BaseOrMemberType( ImpDecl, FromPath[LoopIdx].getAsBaseOrMember().getInt())); } else { FromElemTy = Importer.FromContext.getAsArrayType(FromElemTy)->getElementType(); ToPath[LoopIdx] = APValue::LValuePathEntry::ArrayIndex( FromPath[LoopIdx].getAsArrayIndex()); } } } else Result.setLValue(Base, Offset, APValue::NoLValuePath{}, FromValue.isNullPointer()); } if (Err) return std::move(Err); return Result; } Expected ASTImporter::HandleNameConflict(DeclarationName Name, DeclContext *DC, unsigned IDNS, NamedDecl **Decls, unsigned NumDecls) { if (ODRHandling == ODRHandlingType::Conservative) // Report error at any name conflict. return make_error(ASTImportError::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; // In the case of TypedefNameDecl we create the Decl first and only then we // import and set its DeclContext. So, the DC is still not set when we reach // here from GetImportedOrCreateDecl. if (To->getDeclContext()) AddToLookupTable(To); return To; } std::optional ASTImporter::getImportDeclErrorIfAny(Decl *FromD) const { auto Pos = ImportDeclErrors.find(FromD); if (Pos != ImportDeclErrors.end()) return Pos->second; else return std::nullopt; } void ASTImporter::setImportDeclError(Decl *From, ASTImportError Error) { auto InsertRes = ImportDeclErrors.insert({From, Error}); (void)InsertRes; // Either we set the error for the first time, or we already had set one and // now we want to set the same error. assert(InsertRes.second || InsertRes.first->second.Error == Error.Error); } bool ASTImporter::IsStructurallyEquivalent(QualType From, QualType To, bool Complain) { llvm::DenseMap::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); }