| //===- ASTImporter.cpp - Importing ASTs from other Contexts ---------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file defines the ASTImporter class which imports AST nodes from one |
| // context into another context. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "clang/AST/ASTImporter.h" |
| #include "clang/AST/ASTImporterSharedState.h" |
| #include "clang/AST/ASTContext.h" |
| #include "clang/AST/ASTDiagnostic.h" |
| #include "clang/AST/ASTStructuralEquivalence.h" |
| #include "clang/AST/Attr.h" |
| #include "clang/AST/Decl.h" |
| #include "clang/AST/DeclAccessPair.h" |
| #include "clang/AST/DeclBase.h" |
| #include "clang/AST/DeclCXX.h" |
| #include "clang/AST/DeclFriend.h" |
| #include "clang/AST/DeclGroup.h" |
| #include "clang/AST/DeclObjC.h" |
| #include "clang/AST/DeclTemplate.h" |
| #include "clang/AST/DeclVisitor.h" |
| #include "clang/AST/DeclarationName.h" |
| #include "clang/AST/Expr.h" |
| #include "clang/AST/ExprCXX.h" |
| #include "clang/AST/ExprObjC.h" |
| #include "clang/AST/ExternalASTSource.h" |
| #include "clang/AST/LambdaCapture.h" |
| #include "clang/AST/NestedNameSpecifier.h" |
| #include "clang/AST/OperationKinds.h" |
| #include "clang/AST/Stmt.h" |
| #include "clang/AST/StmtCXX.h" |
| #include "clang/AST/StmtObjC.h" |
| #include "clang/AST/StmtVisitor.h" |
| #include "clang/AST/TemplateBase.h" |
| #include "clang/AST/TemplateName.h" |
| #include "clang/AST/Type.h" |
| #include "clang/AST/TypeLoc.h" |
| #include "clang/AST/TypeVisitor.h" |
| #include "clang/AST/UnresolvedSet.h" |
| #include "clang/Basic/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/None.h" |
| #include "llvm/ADT/Optional.h" |
| #include "llvm/ADT/ScopeExit.h" |
| #include "llvm/ADT/STLExtras.h" |
| #include "llvm/ADT/SmallVector.h" |
| #include "llvm/Support/Casting.h" |
| #include "llvm/Support/ErrorHandling.h" |
| #include "llvm/Support/MemoryBuffer.h" |
| #include <algorithm> |
| #include <cassert> |
| #include <cstddef> |
| #include <memory> |
| #include <type_traits> |
| #include <utility> |
| |
| namespace clang { |
| |
| using llvm::make_error; |
| using llvm::Error; |
| using llvm::Expected; |
| using ExpectedType = llvm::Expected<QualType>; |
| using ExpectedStmt = llvm::Expected<Stmt *>; |
| using ExpectedExpr = llvm::Expected<Expr *>; |
| using ExpectedDecl = llvm::Expected<Decl *>; |
| using ExpectedSLoc = llvm::Expected<SourceLocation>; |
| using ExpectedName = llvm::Expected<DeclarationName>; |
| |
| std::string ImportError::toString() const { |
| // FIXME: Improve error texts. |
| switch (Error) { |
| case NameConflict: |
| return "NameConflict"; |
| case UnsupportedConstruct: |
| return "UnsupportedConstruct"; |
| case Unknown: |
| return "Unknown error"; |
| } |
| llvm_unreachable("Invalid error code."); |
| return "Invalid error code."; |
| } |
| |
| void ImportError::log(raw_ostream &OS) const { |
| OS << toString(); |
| } |
| |
| std::error_code ImportError::convertToErrorCode() const { |
| llvm_unreachable("Function not implemented."); |
| } |
| |
| char ImportError::ID; |
| |
| template <class T> |
| SmallVector<Decl *, 2> |
| getCanonicalForwardRedeclChain(Redeclarable<T>* D) { |
| SmallVector<Decl *, 2> Redecls; |
| for (auto *R : D->getFirstDecl()->redecls()) { |
| if (R != D->getFirstDecl()) |
| Redecls.push_back(R); |
| } |
| Redecls.push_back(D->getFirstDecl()); |
| std::reverse(Redecls.begin(), Redecls.end()); |
| return Redecls; |
| } |
| |
| SmallVector<Decl*, 2> getCanonicalForwardRedeclChain(Decl* D) { |
| if (auto *FD = dyn_cast<FunctionDecl>(D)) |
| return getCanonicalForwardRedeclChain<FunctionDecl>(FD); |
| if (auto *VD = dyn_cast<VarDecl>(D)) |
| return getCanonicalForwardRedeclChain<VarDecl>(VD); |
| if (auto *TD = dyn_cast<TagDecl>(D)) |
| return getCanonicalForwardRedeclChain<TagDecl>(TD); |
| llvm_unreachable("Bad declaration kind"); |
| } |
| |
| void updateFlags(const Decl *From, Decl *To) { |
| // Check if some flags or attrs are new in 'From' and copy into 'To'. |
| // FIXME: Other flags or attrs? |
| if (From->isUsed(false) && !To->isUsed(false)) |
| To->setIsUsed(); |
| } |
| |
| class ASTNodeImporter : public TypeVisitor<ASTNodeImporter, ExpectedType>, |
| public DeclVisitor<ASTNodeImporter, ExpectedDecl>, |
| public StmtVisitor<ASTNodeImporter, ExpectedStmt> { |
| ASTImporter &Importer; |
| |
| // Use this instead of Importer.importInto . |
| template <typename ImportT> |
| LLVM_NODISCARD Error importInto(ImportT &To, const ImportT &From) { |
| return Importer.importInto(To, From); |
| } |
| |
| // Use this to import pointers of specific type. |
| template <typename ImportT> |
| LLVM_NODISCARD Error importInto(ImportT *&To, ImportT *From) { |
| auto ToOrErr = Importer.Import(From); |
| if (ToOrErr) |
| To = cast_or_null<ImportT>(*ToOrErr); |
| return ToOrErr.takeError(); |
| } |
| |
| // Call the import function of ASTImporter for a baseclass of type `T` and |
| // cast the return value to `T`. |
| template <typename T> |
| Expected<T *> import(T *From) { |
| auto ToOrErr = Importer.Import(From); |
| if (!ToOrErr) |
| return ToOrErr.takeError(); |
| return cast_or_null<T>(*ToOrErr); |
| } |
| |
| template <typename T> |
| Expected<T *> import(const T *From) { |
| return import(const_cast<T *>(From)); |
| } |
| |
| // Call the import function of ASTImporter for type `T`. |
| template <typename T> |
| Expected<T> import(const T &From) { |
| return Importer.Import(From); |
| } |
| |
| // Import an Optional<T> by importing the contained T, if any. |
| template<typename T> |
| Expected<Optional<T>> import(Optional<T> From) { |
| if (!From) |
| return Optional<T>(); |
| return import(*From); |
| } |
| |
| // Helper for chaining together multiple imports. If an error is detected, |
| // subsequent imports will return default constructed nodes, so that failure |
| // can be detected with a single conditional branch after a sequence of |
| // imports. |
| template <typename T> T importChecked(Error &Err, const T &From) { |
| // Don't attempt to import nodes if we hit an error earlier. |
| if (Err) |
| return T{}; |
| Expected<T> MaybeVal = import(From); |
| if (!MaybeVal) { |
| Err = MaybeVal.takeError(); |
| return T{}; |
| } |
| return *MaybeVal; |
| } |
| |
| ExplicitSpecifier importExplicitSpecifier(Error &Err, |
| ExplicitSpecifier ESpec); |
| |
| // Wrapper for an overload set. |
| template <typename ToDeclT> struct CallOverloadedCreateFun { |
| template <typename... Args> decltype(auto) operator()(Args &&... args) { |
| return ToDeclT::Create(std::forward<Args>(args)...); |
| } |
| }; |
| |
| // Always use these functions to create a Decl during import. There are |
| // certain tasks which must be done after the Decl was created, e.g. we |
| // must immediately register that as an imported Decl. The parameter `ToD` |
| // will be set to the newly created Decl or if had been imported before |
| // then to the already imported Decl. Returns a bool value set to true if |
| // the `FromD` had been imported before. |
| template <typename ToDeclT, typename FromDeclT, typename... Args> |
| LLVM_NODISCARD bool GetImportedOrCreateDecl(ToDeclT *&ToD, FromDeclT *FromD, |
| Args &&... args) { |
| // There may be several overloads of ToDeclT::Create. We must make sure |
| // to call the one which would be chosen by the arguments, thus we use a |
| // wrapper for the overload set. |
| CallOverloadedCreateFun<ToDeclT> OC; |
| return GetImportedOrCreateSpecialDecl(ToD, OC, FromD, |
| std::forward<Args>(args)...); |
| } |
| // Use this overload if a special Type is needed to be created. E.g if we |
| // want to create a `TypeAliasDecl` and assign that to a `TypedefNameDecl` |
| // then: |
| // TypedefNameDecl *ToTypedef; |
| // GetImportedOrCreateDecl<TypeAliasDecl>(ToTypedef, FromD, ...); |
| template <typename NewDeclT, typename ToDeclT, typename FromDeclT, |
| typename... Args> |
| LLVM_NODISCARD bool GetImportedOrCreateDecl(ToDeclT *&ToD, FromDeclT *FromD, |
| Args &&... args) { |
| CallOverloadedCreateFun<NewDeclT> OC; |
| return GetImportedOrCreateSpecialDecl(ToD, OC, FromD, |
| std::forward<Args>(args)...); |
| } |
| // Use this version if a special create function must be |
| // used, e.g. CXXRecordDecl::CreateLambda . |
| template <typename ToDeclT, typename CreateFunT, typename FromDeclT, |
| typename... Args> |
| LLVM_NODISCARD bool |
| GetImportedOrCreateSpecialDecl(ToDeclT *&ToD, CreateFunT CreateFun, |
| FromDeclT *FromD, Args &&... args) { |
| if (Importer.getImportDeclErrorIfAny(FromD)) { |
| ToD = nullptr; |
| return true; // Already imported but with error. |
| } |
| ToD = cast_or_null<ToDeclT>(Importer.GetAlreadyImportedOrNull(FromD)); |
| if (ToD) |
| return true; // Already imported. |
| ToD = CreateFun(std::forward<Args>(args)...); |
| // Keep track of imported Decls. |
| Importer.RegisterImportedDecl(FromD, ToD); |
| InitializeImportedDecl(FromD, ToD); |
| return false; // A new Decl is created. |
| } |
| |
| void InitializeImportedDecl(Decl *FromD, Decl *ToD) { |
| ToD->IdentifierNamespace = FromD->IdentifierNamespace; |
| if (FromD->isUsed()) |
| ToD->setIsUsed(); |
| if (FromD->isImplicit()) |
| ToD->setImplicit(); |
| } |
| |
| // Check if we have found an existing definition. Returns with that |
| // definition if yes, otherwise returns null. |
| Decl *FindAndMapDefinition(FunctionDecl *D, FunctionDecl *FoundFunction) { |
| const FunctionDecl *Definition = nullptr; |
| if (D->doesThisDeclarationHaveABody() && |
| FoundFunction->hasBody(Definition)) |
| return Importer.MapImported(D, const_cast<FunctionDecl *>(Definition)); |
| return nullptr; |
| } |
| |
| void addDeclToContexts(Decl *FromD, Decl *ToD) { |
| if (Importer.isMinimalImport()) { |
| // In minimal import case the decl must be added even if it is not |
| // contained in original context, for LLDB compatibility. |
| // FIXME: Check if a better solution is possible. |
| if (!FromD->getDescribedTemplate() && |
| FromD->getFriendObjectKind() == Decl::FOK_None) |
| ToD->getLexicalDeclContext()->addDeclInternal(ToD); |
| return; |
| } |
| |
| DeclContext *FromDC = FromD->getDeclContext(); |
| DeclContext *FromLexicalDC = FromD->getLexicalDeclContext(); |
| DeclContext *ToDC = ToD->getDeclContext(); |
| DeclContext *ToLexicalDC = ToD->getLexicalDeclContext(); |
| |
| bool Visible = false; |
| if (FromDC->containsDeclAndLoad(FromD)) { |
| ToDC->addDeclInternal(ToD); |
| Visible = true; |
| } |
| if (ToDC != ToLexicalDC && FromLexicalDC->containsDeclAndLoad(FromD)) { |
| ToLexicalDC->addDeclInternal(ToD); |
| Visible = true; |
| } |
| |
| // If the Decl was added to any context, it was made already visible. |
| // Otherwise it is still possible that it should be visible. |
| if (!Visible) { |
| if (auto *FromNamed = dyn_cast<NamedDecl>(FromD)) { |
| auto *ToNamed = cast<NamedDecl>(ToD); |
| DeclContextLookupResult FromLookup = |
| FromDC->lookup(FromNamed->getDeclName()); |
| for (NamedDecl *ND : FromLookup) |
| if (ND == FromNamed) { |
| ToDC->makeDeclVisibleInContext(ToNamed); |
| break; |
| } |
| } |
| } |
| } |
| |
| public: |
| explicit ASTNodeImporter(ASTImporter &Importer) : Importer(Importer) {} |
| |
| using TypeVisitor<ASTNodeImporter, ExpectedType>::Visit; |
| using DeclVisitor<ASTNodeImporter, ExpectedDecl>::Visit; |
| using StmtVisitor<ASTNodeImporter, ExpectedStmt>::Visit; |
| |
| // Importing types |
| ExpectedType VisitType(const Type *T); |
| ExpectedType VisitAtomicType(const AtomicType *T); |
| ExpectedType VisitBuiltinType(const BuiltinType *T); |
| ExpectedType VisitDecayedType(const DecayedType *T); |
| ExpectedType VisitComplexType(const ComplexType *T); |
| ExpectedType VisitPointerType(const PointerType *T); |
| ExpectedType VisitBlockPointerType(const BlockPointerType *T); |
| ExpectedType VisitLValueReferenceType(const LValueReferenceType *T); |
| ExpectedType VisitRValueReferenceType(const RValueReferenceType *T); |
| ExpectedType VisitMemberPointerType(const MemberPointerType *T); |
| ExpectedType VisitConstantArrayType(const ConstantArrayType *T); |
| ExpectedType VisitIncompleteArrayType(const IncompleteArrayType *T); |
| ExpectedType VisitVariableArrayType(const VariableArrayType *T); |
| ExpectedType VisitDependentSizedArrayType(const DependentSizedArrayType *T); |
| // FIXME: DependentSizedExtVectorType |
| ExpectedType VisitVectorType(const VectorType *T); |
| ExpectedType VisitExtVectorType(const ExtVectorType *T); |
| ExpectedType VisitFunctionNoProtoType(const FunctionNoProtoType *T); |
| ExpectedType VisitFunctionProtoType(const FunctionProtoType *T); |
| ExpectedType VisitUnresolvedUsingType(const UnresolvedUsingType *T); |
| ExpectedType VisitParenType(const ParenType *T); |
| ExpectedType VisitTypedefType(const TypedefType *T); |
| ExpectedType VisitTypeOfExprType(const TypeOfExprType *T); |
| // FIXME: DependentTypeOfExprType |
| ExpectedType VisitTypeOfType(const TypeOfType *T); |
| ExpectedType VisitDecltypeType(const DecltypeType *T); |
| ExpectedType VisitUnaryTransformType(const UnaryTransformType *T); |
| ExpectedType VisitAutoType(const AutoType *T); |
| ExpectedType VisitInjectedClassNameType(const InjectedClassNameType *T); |
| // FIXME: DependentDecltypeType |
| ExpectedType VisitRecordType(const RecordType *T); |
| ExpectedType VisitEnumType(const EnumType *T); |
| ExpectedType VisitAttributedType(const AttributedType *T); |
| ExpectedType VisitTemplateTypeParmType(const TemplateTypeParmType *T); |
| ExpectedType VisitSubstTemplateTypeParmType( |
| const SubstTemplateTypeParmType *T); |
| ExpectedType VisitTemplateSpecializationType( |
| const TemplateSpecializationType *T); |
| ExpectedType VisitElaboratedType(const ElaboratedType *T); |
| ExpectedType VisitDependentNameType(const DependentNameType *T); |
| ExpectedType VisitPackExpansionType(const PackExpansionType *T); |
| ExpectedType VisitDependentTemplateSpecializationType( |
| const DependentTemplateSpecializationType *T); |
| ExpectedType VisitObjCInterfaceType(const ObjCInterfaceType *T); |
| ExpectedType VisitObjCObjectType(const ObjCObjectType *T); |
| ExpectedType VisitObjCObjectPointerType(const ObjCObjectPointerType *T); |
| |
| // Importing declarations |
| Error ImportDeclParts(NamedDecl *D, 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); |
| |
| Expected<CXXCastPath> ImportCastPath(CastExpr *E); |
| Expected<APValue> ImportAPValue(const APValue &FromValue); |
| |
| using Designator = DesignatedInitExpr::Designator; |
| |
| /// What we should import from the definition. |
| enum ImportDefinitionKind { |
| /// Import the default subset of the definition, which might be |
| /// nothing (if minimal import is set) or might be everything (if minimal |
| /// import is not set). |
| IDK_Default, |
| /// Import everything. |
| IDK_Everything, |
| /// Import only the bare bones needed to establish a valid |
| /// DeclContext. |
| IDK_Basic |
| }; |
| |
| bool shouldForceImportDeclContext(ImportDefinitionKind IDK) { |
| return IDK == IDK_Everything || |
| (IDK == IDK_Default && !Importer.isMinimalImport()); |
| } |
| |
| Error ImportInitializer(VarDecl *From, VarDecl *To); |
| Error ImportDefinition( |
| RecordDecl *From, RecordDecl *To, |
| ImportDefinitionKind Kind = IDK_Default); |
| Error ImportDefinition( |
| EnumDecl *From, EnumDecl *To, |
| ImportDefinitionKind Kind = IDK_Default); |
| Error ImportDefinition( |
| ObjCInterfaceDecl *From, ObjCInterfaceDecl *To, |
| ImportDefinitionKind Kind = IDK_Default); |
| Error ImportDefinition( |
| ObjCProtocolDecl *From, ObjCProtocolDecl *To, |
| ImportDefinitionKind Kind = IDK_Default); |
| Error ImportTemplateArguments( |
| const TemplateArgument *FromArgs, unsigned NumFromArgs, |
| SmallVectorImpl<TemplateArgument> &ToArgs); |
| Expected<TemplateArgument> |
| ImportTemplateArgument(const TemplateArgument &From); |
| |
| template <typename InContainerTy> |
| Error ImportTemplateArgumentListInfo( |
| const InContainerTy &Container, TemplateArgumentListInfo &ToTAInfo); |
| |
| template<typename InContainerTy> |
| Error ImportTemplateArgumentListInfo( |
| SourceLocation FromLAngleLoc, SourceLocation FromRAngleLoc, |
| const InContainerTy &Container, TemplateArgumentListInfo &Result); |
| |
| using TemplateArgsTy = SmallVector<TemplateArgument, 8>; |
| using FunctionTemplateAndArgsTy = |
| std::tuple<FunctionTemplateDecl *, TemplateArgsTy>; |
| Expected<FunctionTemplateAndArgsTy> |
| ImportFunctionTemplateWithTemplateArgsFromSpecialization( |
| FunctionDecl *FromFD); |
| Error ImportTemplateParameterLists(const DeclaratorDecl *FromD, |
| DeclaratorDecl *ToD); |
| |
| Error ImportTemplateInformation(FunctionDecl *FromFD, FunctionDecl *ToFD); |
| |
| Error ImportFunctionDeclBody(FunctionDecl *FromFD, FunctionDecl *ToFD); |
| |
| Error ImportDefaultArgOfParmVarDecl(const ParmVarDecl *FromParam, |
| ParmVarDecl *ToParam); |
| |
| template <typename T> |
| bool hasSameVisibilityContextAndLinkage(T *Found, T *From); |
| |
| bool IsStructuralMatch(Decl *From, Decl *To, bool Complain); |
| bool IsStructuralMatch(RecordDecl *FromRecord, RecordDecl *ToRecord, |
| bool Complain = true); |
| bool IsStructuralMatch(VarDecl *FromVar, VarDecl *ToVar, |
| bool Complain = true); |
| bool IsStructuralMatch(EnumDecl *FromEnum, EnumDecl *ToRecord); |
| bool IsStructuralMatch(EnumConstantDecl *FromEC, EnumConstantDecl *ToEC); |
| bool IsStructuralMatch(FunctionTemplateDecl *From, |
| FunctionTemplateDecl *To); |
| bool IsStructuralMatch(FunctionDecl *From, FunctionDecl *To); |
| bool IsStructuralMatch(ClassTemplateDecl *From, ClassTemplateDecl *To); |
| bool IsStructuralMatch(VarTemplateDecl *From, VarTemplateDecl *To); |
| ExpectedDecl VisitDecl(Decl *D); |
| ExpectedDecl VisitImportDecl(ImportDecl *D); |
| ExpectedDecl VisitEmptyDecl(EmptyDecl *D); |
| ExpectedDecl VisitAccessSpecDecl(AccessSpecDecl *D); |
| ExpectedDecl VisitStaticAssertDecl(StaticAssertDecl *D); |
| ExpectedDecl VisitTranslationUnitDecl(TranslationUnitDecl *D); |
| ExpectedDecl VisitNamespaceDecl(NamespaceDecl *D); |
| ExpectedDecl VisitNamespaceAliasDecl(NamespaceAliasDecl *D); |
| ExpectedDecl VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias); |
| ExpectedDecl VisitTypedefDecl(TypedefDecl *D); |
| ExpectedDecl VisitTypeAliasDecl(TypeAliasDecl *D); |
| ExpectedDecl VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D); |
| ExpectedDecl VisitLabelDecl(LabelDecl *D); |
| ExpectedDecl VisitEnumDecl(EnumDecl *D); |
| ExpectedDecl VisitRecordDecl(RecordDecl *D); |
| ExpectedDecl VisitEnumConstantDecl(EnumConstantDecl *D); |
| ExpectedDecl VisitFunctionDecl(FunctionDecl *D); |
| ExpectedDecl VisitCXXMethodDecl(CXXMethodDecl *D); |
| ExpectedDecl VisitCXXConstructorDecl(CXXConstructorDecl *D); |
| ExpectedDecl VisitCXXDestructorDecl(CXXDestructorDecl *D); |
| ExpectedDecl VisitCXXConversionDecl(CXXConversionDecl *D); |
| ExpectedDecl 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 VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D); |
| ExpectedDecl VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D); |
| ExpectedDecl VisitBuiltinTemplateDecl(BuiltinTemplateDecl *D); |
| ExpectedDecl |
| VisitLifetimeExtendedTemporaryDecl(LifetimeExtendedTemporaryDecl *D); |
| |
| Expected<ObjCTypeParamList *> |
| ImportObjCTypeParamList(ObjCTypeParamList *list); |
| |
| ExpectedDecl VisitObjCInterfaceDecl(ObjCInterfaceDecl *D); |
| ExpectedDecl VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D); |
| ExpectedDecl VisitObjCImplementationDecl(ObjCImplementationDecl *D); |
| ExpectedDecl VisitObjCPropertyDecl(ObjCPropertyDecl *D); |
| ExpectedDecl VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D); |
| ExpectedDecl VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D); |
| ExpectedDecl VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D); |
| ExpectedDecl VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D); |
| ExpectedDecl VisitClassTemplateDecl(ClassTemplateDecl *D); |
| ExpectedDecl VisitClassTemplateSpecializationDecl( |
| ClassTemplateSpecializationDecl *D); |
| ExpectedDecl VisitVarTemplateDecl(VarTemplateDecl *D); |
| ExpectedDecl VisitVarTemplateSpecializationDecl(VarTemplateSpecializationDecl *D); |
| ExpectedDecl VisitFunctionTemplateDecl(FunctionTemplateDecl *D); |
| |
| // Importing statements |
| ExpectedStmt VisitStmt(Stmt *S); |
| ExpectedStmt VisitGCCAsmStmt(GCCAsmStmt *S); |
| ExpectedStmt VisitDeclStmt(DeclStmt *S); |
| ExpectedStmt VisitNullStmt(NullStmt *S); |
| ExpectedStmt VisitCompoundStmt(CompoundStmt *S); |
| ExpectedStmt VisitCaseStmt(CaseStmt *S); |
| ExpectedStmt VisitDefaultStmt(DefaultStmt *S); |
| ExpectedStmt VisitLabelStmt(LabelStmt *S); |
| ExpectedStmt VisitAttributedStmt(AttributedStmt *S); |
| ExpectedStmt VisitIfStmt(IfStmt *S); |
| ExpectedStmt VisitSwitchStmt(SwitchStmt *S); |
| ExpectedStmt VisitWhileStmt(WhileStmt *S); |
| ExpectedStmt VisitDoStmt(DoStmt *S); |
| ExpectedStmt VisitForStmt(ForStmt *S); |
| ExpectedStmt VisitGotoStmt(GotoStmt *S); |
| ExpectedStmt VisitIndirectGotoStmt(IndirectGotoStmt *S); |
| ExpectedStmt VisitContinueStmt(ContinueStmt *S); |
| ExpectedStmt VisitBreakStmt(BreakStmt *S); |
| ExpectedStmt VisitReturnStmt(ReturnStmt *S); |
| // FIXME: MSAsmStmt |
| // FIXME: SEHExceptStmt |
| // FIXME: SEHFinallyStmt |
| // FIXME: SEHTryStmt |
| // FIXME: SEHLeaveStmt |
| // FIXME: CapturedStmt |
| ExpectedStmt VisitCXXCatchStmt(CXXCatchStmt *S); |
| ExpectedStmt VisitCXXTryStmt(CXXTryStmt *S); |
| ExpectedStmt VisitCXXForRangeStmt(CXXForRangeStmt *S); |
| // FIXME: MSDependentExistsStmt |
| ExpectedStmt VisitObjCForCollectionStmt(ObjCForCollectionStmt *S); |
| ExpectedStmt VisitObjCAtCatchStmt(ObjCAtCatchStmt *S); |
| ExpectedStmt VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *S); |
| ExpectedStmt VisitObjCAtTryStmt(ObjCAtTryStmt *S); |
| ExpectedStmt VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S); |
| ExpectedStmt VisitObjCAtThrowStmt(ObjCAtThrowStmt *S); |
| ExpectedStmt VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S); |
| |
| // Importing expressions |
| ExpectedStmt VisitExpr(Expr *E); |
| ExpectedStmt VisitVAArgExpr(VAArgExpr *E); |
| ExpectedStmt VisitChooseExpr(ChooseExpr *E); |
| ExpectedStmt VisitGNUNullExpr(GNUNullExpr *E); |
| ExpectedStmt 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 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); |
| |
| template<typename IIter, typename OIter> |
| Error ImportArrayChecked(IIter Ibegin, IIter Iend, OIter Obegin) { |
| using ItemT = std::remove_reference_t<decltype(*Obegin)>; |
| for (; Ibegin != Iend; ++Ibegin, ++Obegin) { |
| Expected<ItemT> ToOrErr = import(*Ibegin); |
| if (!ToOrErr) |
| return ToOrErr.takeError(); |
| *Obegin = *ToOrErr; |
| } |
| return Error::success(); |
| } |
| |
| // Import every item from a container structure into an output container. |
| // If error occurs, stops at first error and returns the error. |
| // The output container should have space for all needed elements (it is not |
| // expanded, new items are put into from the beginning). |
| template<typename InContainerTy, typename OutContainerTy> |
| Error ImportContainerChecked( |
| const InContainerTy &InContainer, OutContainerTy &OutContainer) { |
| return ImportArrayChecked( |
| InContainer.begin(), InContainer.end(), OutContainer.begin()); |
| } |
| |
| template<typename InContainerTy, typename OIter> |
| Error ImportArrayChecked(const InContainerTy &InContainer, OIter Obegin) { |
| return ImportArrayChecked(InContainer.begin(), InContainer.end(), Obegin); |
| } |
| |
| Error ImportOverriddenMethods(CXXMethodDecl *ToMethod, |
| CXXMethodDecl *FromMethod); |
| |
| Expected<FunctionDecl *> FindFunctionTemplateSpecialization( |
| FunctionDecl *FromFD); |
| |
| // Returns true if the given function has a placeholder return type and |
| // that type is declared inside the body of the function. |
| // E.g. auto f() { struct X{}; return X(); } |
| bool hasAutoReturnTypeDeclaredInside(FunctionDecl *D); |
| }; |
| |
| template <typename InContainerTy> |
| Error ASTNodeImporter::ImportTemplateArgumentListInfo( |
| SourceLocation FromLAngleLoc, SourceLocation FromRAngleLoc, |
| const InContainerTy &Container, TemplateArgumentListInfo &Result) { |
| auto ToLAngleLocOrErr = import(FromLAngleLoc); |
| if (!ToLAngleLocOrErr) |
| return ToLAngleLocOrErr.takeError(); |
| auto ToRAngleLocOrErr = import(FromRAngleLoc); |
| if (!ToRAngleLocOrErr) |
| return ToRAngleLocOrErr.takeError(); |
| |
| TemplateArgumentListInfo ToTAInfo(*ToLAngleLocOrErr, *ToRAngleLocOrErr); |
| if (auto Err = ImportTemplateArgumentListInfo(Container, ToTAInfo)) |
| return Err; |
| Result = ToTAInfo; |
| return Error::success(); |
| } |
| |
| template <> |
| Error ASTNodeImporter::ImportTemplateArgumentListInfo<TemplateArgumentListInfo>( |
| const TemplateArgumentListInfo &From, TemplateArgumentListInfo &Result) { |
| return ImportTemplateArgumentListInfo( |
| From.getLAngleLoc(), From.getRAngleLoc(), From.arguments(), Result); |
| } |
| |
| template <> |
| Error ASTNodeImporter::ImportTemplateArgumentListInfo< |
| ASTTemplateArgumentListInfo>( |
| const ASTTemplateArgumentListInfo &From, |
| TemplateArgumentListInfo &Result) { |
| return ImportTemplateArgumentListInfo( |
| From.LAngleLoc, From.RAngleLoc, From.arguments(), Result); |
| } |
| |
| Expected<ASTNodeImporter::FunctionTemplateAndArgsTy> |
| ASTNodeImporter::ImportFunctionTemplateWithTemplateArgsFromSpecialization( |
| FunctionDecl *FromFD) { |
| assert(FromFD->getTemplatedKind() == |
| FunctionDecl::TK_FunctionTemplateSpecialization); |
| |
| FunctionTemplateAndArgsTy Result; |
| |
| auto *FTSInfo = FromFD->getTemplateSpecializationInfo(); |
| if (Error Err = importInto(std::get<0>(Result), FTSInfo->getTemplate())) |
| return std::move(Err); |
| |
| // Import template arguments. |
| auto TemplArgs = FTSInfo->TemplateArguments->asArray(); |
| if (Error Err = ImportTemplateArguments(TemplArgs.data(), TemplArgs.size(), |
| std::get<1>(Result))) |
| return std::move(Err); |
| |
| return Result; |
| } |
| |
| template <> |
| Expected<TemplateParameterList *> |
| ASTNodeImporter::import(TemplateParameterList *From) { |
| SmallVector<NamedDecl *, 4> To(From->size()); |
| if (Error Err = ImportContainerChecked(*From, To)) |
| return std::move(Err); |
| |
| ExpectedExpr ToRequiresClause = import(From->getRequiresClause()); |
| if (!ToRequiresClause) |
| return ToRequiresClause.takeError(); |
| |
| auto ToTemplateLocOrErr = import(From->getTemplateLoc()); |
| if (!ToTemplateLocOrErr) |
| return ToTemplateLocOrErr.takeError(); |
| auto ToLAngleLocOrErr = import(From->getLAngleLoc()); |
| if (!ToLAngleLocOrErr) |
| return ToLAngleLocOrErr.takeError(); |
| auto ToRAngleLocOrErr = import(From->getRAngleLoc()); |
| if (!ToRAngleLocOrErr) |
| return ToRAngleLocOrErr.takeError(); |
| |
| return TemplateParameterList::Create( |
| Importer.getToContext(), |
| *ToTemplateLocOrErr, |
| *ToLAngleLocOrErr, |
| To, |
| *ToRAngleLocOrErr, |
| *ToRequiresClause); |
| } |
| |
| template <> |
| Expected<TemplateArgument> |
| ASTNodeImporter::import(const TemplateArgument &From) { |
| switch (From.getKind()) { |
| case TemplateArgument::Null: |
| return TemplateArgument(); |
| |
| case TemplateArgument::Type: { |
| ExpectedType ToTypeOrErr = import(From.getAsType()); |
| if (!ToTypeOrErr) |
| return ToTypeOrErr.takeError(); |
| return TemplateArgument(*ToTypeOrErr); |
| } |
| |
| case TemplateArgument::Integral: { |
| ExpectedType ToTypeOrErr = import(From.getIntegralType()); |
| if (!ToTypeOrErr) |
| return ToTypeOrErr.takeError(); |
| return TemplateArgument(From, *ToTypeOrErr); |
| } |
| |
| case TemplateArgument::Declaration: { |
| Expected<ValueDecl *> ToOrErr = import(From.getAsDecl()); |
| if (!ToOrErr) |
| return ToOrErr.takeError(); |
| ExpectedType ToTypeOrErr = import(From.getParamTypeForDecl()); |
| if (!ToTypeOrErr) |
| return ToTypeOrErr.takeError(); |
| return TemplateArgument(*ToOrErr, *ToTypeOrErr); |
| } |
| |
| case TemplateArgument::NullPtr: { |
| ExpectedType ToTypeOrErr = import(From.getNullPtrType()); |
| if (!ToTypeOrErr) |
| return ToTypeOrErr.takeError(); |
| return TemplateArgument(*ToTypeOrErr, /*isNullPtr*/true); |
| } |
| |
| case TemplateArgument::Template: { |
| Expected<TemplateName> ToTemplateOrErr = import(From.getAsTemplate()); |
| if (!ToTemplateOrErr) |
| return ToTemplateOrErr.takeError(); |
| |
| return TemplateArgument(*ToTemplateOrErr); |
| } |
| |
| case TemplateArgument::TemplateExpansion: { |
| Expected<TemplateName> ToTemplateOrErr = |
| import(From.getAsTemplateOrTemplatePattern()); |
| if (!ToTemplateOrErr) |
| return ToTemplateOrErr.takeError(); |
| |
| return TemplateArgument( |
| *ToTemplateOrErr, From.getNumTemplateExpansions()); |
| } |
| |
| case TemplateArgument::Expression: |
| if (ExpectedExpr ToExpr = import(From.getAsExpr())) |
| return TemplateArgument(*ToExpr); |
| else |
| return ToExpr.takeError(); |
| |
| case TemplateArgument::Pack: { |
| SmallVector<TemplateArgument, 2> ToPack; |
| ToPack.reserve(From.pack_size()); |
| if (Error Err = ImportTemplateArguments( |
| From.pack_begin(), From.pack_size(), ToPack)) |
| return std::move(Err); |
| |
| return TemplateArgument( |
| llvm::makeArrayRef(ToPack).copy(Importer.getToContext())); |
| } |
| } |
| |
| llvm_unreachable("Invalid template argument kind"); |
| } |
| |
| template <> |
| Expected<TemplateArgumentLoc> |
| ASTNodeImporter::import(const TemplateArgumentLoc &TALoc) { |
| Expected<TemplateArgument> ArgOrErr = import(TALoc.getArgument()); |
| if (!ArgOrErr) |
| return ArgOrErr.takeError(); |
| TemplateArgument Arg = *ArgOrErr; |
| |
| TemplateArgumentLocInfo FromInfo = TALoc.getLocInfo(); |
| |
| TemplateArgumentLocInfo ToInfo; |
| if (Arg.getKind() == TemplateArgument::Expression) { |
| ExpectedExpr E = import(FromInfo.getAsExpr()); |
| if (!E) |
| return E.takeError(); |
| ToInfo = TemplateArgumentLocInfo(*E); |
| } else if (Arg.getKind() == TemplateArgument::Type) { |
| if (auto TSIOrErr = import(FromInfo.getAsTypeSourceInfo())) |
| ToInfo = TemplateArgumentLocInfo(*TSIOrErr); |
| else |
| return TSIOrErr.takeError(); |
| } else { |
| auto ToTemplateQualifierLocOrErr = |
| import(FromInfo.getTemplateQualifierLoc()); |
| if (!ToTemplateQualifierLocOrErr) |
| return ToTemplateQualifierLocOrErr.takeError(); |
| auto ToTemplateNameLocOrErr = import(FromInfo.getTemplateNameLoc()); |
| if (!ToTemplateNameLocOrErr) |
| return ToTemplateNameLocOrErr.takeError(); |
| auto ToTemplateEllipsisLocOrErr = |
| import(FromInfo.getTemplateEllipsisLoc()); |
| if (!ToTemplateEllipsisLocOrErr) |
| return ToTemplateEllipsisLocOrErr.takeError(); |
| ToInfo = TemplateArgumentLocInfo( |
| Importer.getToContext(), *ToTemplateQualifierLocOrErr, |
| *ToTemplateNameLocOrErr, *ToTemplateEllipsisLocOrErr); |
| } |
| |
| return TemplateArgumentLoc(Arg, ToInfo); |
| } |
| |
| template <> |
| Expected<DeclGroupRef> ASTNodeImporter::import(const DeclGroupRef &DG) { |
| if (DG.isNull()) |
| return DeclGroupRef::Create(Importer.getToContext(), nullptr, 0); |
| size_t NumDecls = DG.end() - DG.begin(); |
| SmallVector<Decl *, 1> ToDecls; |
| ToDecls.reserve(NumDecls); |
| for (Decl *FromD : DG) { |
| if (auto ToDOrErr = import(FromD)) |
| ToDecls.push_back(*ToDOrErr); |
| else |
| return ToDOrErr.takeError(); |
| } |
| return DeclGroupRef::Create(Importer.getToContext(), |
| ToDecls.begin(), |
| NumDecls); |
| } |
| |
| template <> |
| Expected<ASTNodeImporter::Designator> |
| ASTNodeImporter::import(const Designator &D) { |
| if (D.isFieldDesignator()) { |
| IdentifierInfo *ToFieldName = Importer.Import(D.getFieldName()); |
| |
| ExpectedSLoc ToDotLocOrErr = import(D.getDotLoc()); |
| if (!ToDotLocOrErr) |
| return ToDotLocOrErr.takeError(); |
| |
| ExpectedSLoc ToFieldLocOrErr = import(D.getFieldLoc()); |
| if (!ToFieldLocOrErr) |
| return ToFieldLocOrErr.takeError(); |
| |
| return Designator(ToFieldName, *ToDotLocOrErr, *ToFieldLocOrErr); |
| } |
| |
| ExpectedSLoc ToLBracketLocOrErr = import(D.getLBracketLoc()); |
| if (!ToLBracketLocOrErr) |
| return ToLBracketLocOrErr.takeError(); |
| |
| ExpectedSLoc ToRBracketLocOrErr = import(D.getRBracketLoc()); |
| if (!ToRBracketLocOrErr) |
| return ToRBracketLocOrErr.takeError(); |
| |
| if (D.isArrayDesignator()) |
| return Designator(D.getFirstExprIndex(), |
| *ToLBracketLocOrErr, *ToRBracketLocOrErr); |
| |
| ExpectedSLoc ToEllipsisLocOrErr = import(D.getEllipsisLoc()); |
| if (!ToEllipsisLocOrErr) |
| return ToEllipsisLocOrErr.takeError(); |
| |
| assert(D.isArrayRangeDesignator()); |
| return Designator( |
| D.getFirstExprIndex(), *ToLBracketLocOrErr, *ToEllipsisLocOrErr, |
| *ToRBracketLocOrErr); |
| } |
| |
| template <> |
| Expected<LambdaCapture> ASTNodeImporter::import(const LambdaCapture &From) { |
| VarDecl *Var = nullptr; |
| if (From.capturesVariable()) { |
| if (auto VarOrErr = import(From.getCapturedVar())) |
| Var = *VarOrErr; |
| else |
| return VarOrErr.takeError(); |
| } |
| |
| auto LocationOrErr = import(From.getLocation()); |
| if (!LocationOrErr) |
| return LocationOrErr.takeError(); |
| |
| SourceLocation EllipsisLoc; |
| if (From.isPackExpansion()) |
| if (Error Err = importInto(EllipsisLoc, From.getEllipsisLoc())) |
| return std::move(Err); |
| |
| return LambdaCapture( |
| *LocationOrErr, From.isImplicit(), From.getCaptureKind(), Var, |
| EllipsisLoc); |
| } |
| |
| template <typename T> |
| bool ASTNodeImporter::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<ImportError>(ImportError::UnsupportedConstruct); |
| } |
| |
| ExpectedType ASTNodeImporter::VisitAtomicType(const AtomicType *T){ |
| ExpectedType UnderlyingTypeOrErr = import(T->getValueType()); |
| if (!UnderlyingTypeOrErr) |
| return UnderlyingTypeOrErr.takeError(); |
| |
| return Importer.getToContext().getAtomicType(*UnderlyingTypeOrErr); |
| } |
| |
| ExpectedType ASTNodeImporter::VisitBuiltinType(const BuiltinType *T) { |
| switch (T->getKind()) { |
| #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ |
| case BuiltinType::Id: \ |
| return Importer.getToContext().SingletonId; |
| #include "clang/Basic/OpenCLImageTypes.def" |
| #define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \ |
| case BuiltinType::Id: \ |
| return Importer.getToContext().Id##Ty; |
| #include "clang/Basic/OpenCLExtensionTypes.def" |
| #define SVE_TYPE(Name, Id, SingletonId) \ |
| case BuiltinType::Id: \ |
| return Importer.getToContext().SingletonId; |
| #include "clang/Basic/AArch64SVEACLETypes.def" |
| #define PPC_VECTOR_TYPE(Name, Id, Size) \ |
| case BuiltinType::Id: \ |
| return Importer.getToContext().Id##Ty; |
| #include "clang/Basic/PPCTypes.def" |
| #define SHARED_SINGLETON_TYPE(Expansion) |
| #define BUILTIN_TYPE(Id, SingletonId) \ |
| case BuiltinType::Id: return Importer.getToContext().SingletonId; |
| #include "clang/AST/BuiltinTypes.def" |
| |
| // FIXME: for Char16, Char32, and NullPtr, make sure that the "to" |
| // context supports C++. |
| |
| // FIXME: for ObjCId, ObjCClass, and ObjCSel, make sure that the "to" |
| // context supports ObjC. |
| |
| case BuiltinType::Char_U: |
| // The context we're importing from has an unsigned 'char'. If we're |
| // importing into a context with a signed 'char', translate to |
| // 'unsigned char' instead. |
| if (Importer.getToContext().getLangOpts().CharIsSigned) |
| return Importer.getToContext().UnsignedCharTy; |
| |
| return Importer.getToContext().CharTy; |
| |
| case BuiltinType::Char_S: |
| // The context we're importing from has an unsigned 'char'. If we're |
| // importing into a context with a signed 'char', translate to |
| // 'unsigned char' instead. |
| if (!Importer.getToContext().getLangOpts().CharIsSigned) |
| return Importer.getToContext().SignedCharTy; |
| |
| return Importer.getToContext().CharTy; |
| |
| case BuiltinType::WChar_S: |
| case BuiltinType::WChar_U: |
| // FIXME: If not in C++, shall we translate to the C equivalent of |
| // wchar_t? |
| return Importer.getToContext().WCharTy; |
| } |
| |
| llvm_unreachable("Invalid BuiltinType Kind!"); |
| } |
| |
| ExpectedType ASTNodeImporter::VisitDecayedType(const DecayedType *T) { |
| ExpectedType ToOriginalTypeOrErr = import(T->getOriginalType()); |
| if (!ToOriginalTypeOrErr) |
| return ToOriginalTypeOrErr.takeError(); |
| |
| return Importer.getToContext().getDecayedType(*ToOriginalTypeOrErr); |
| } |
| |
| ExpectedType ASTNodeImporter::VisitComplexType(const ComplexType *T) { |
| ExpectedType ToElementTypeOrErr = import(T->getElementType()); |
| if (!ToElementTypeOrErr) |
| return ToElementTypeOrErr.takeError(); |
| |
| return Importer.getToContext().getComplexType(*ToElementTypeOrErr); |
| } |
| |
| ExpectedType ASTNodeImporter::VisitPointerType(const PointerType *T) { |
| ExpectedType ToPointeeTypeOrErr = import(T->getPointeeType()); |
| if (!ToPointeeTypeOrErr) |
| return ToPointeeTypeOrErr.takeError(); |
| |
| return Importer.getToContext().getPointerType(*ToPointeeTypeOrErr); |
| } |
| |
| ExpectedType ASTNodeImporter::VisitBlockPointerType(const BlockPointerType *T) { |
| // FIXME: Check for blocks support in "to" context. |
| ExpectedType ToPointeeTypeOrErr = import(T->getPointeeType()); |
| if (!ToPointeeTypeOrErr) |
| return ToPointeeTypeOrErr.takeError(); |
| |
| return Importer.getToContext().getBlockPointerType(*ToPointeeTypeOrErr); |
| } |
| |
| ExpectedType |
| ASTNodeImporter::VisitLValueReferenceType(const LValueReferenceType *T) { |
| // FIXME: Check for C++ support in "to" context. |
| ExpectedType ToPointeeTypeOrErr = import(T->getPointeeTypeAsWritten()); |
| if (!ToPointeeTypeOrErr) |
| return ToPointeeTypeOrErr.takeError(); |
| |
| return Importer.getToContext().getLValueReferenceType(*ToPointeeTypeOrErr); |
| } |
| |
| ExpectedType |
| ASTNodeImporter::VisitRValueReferenceType(const RValueReferenceType *T) { |
| // FIXME: Check for C++0x support in "to" context. |
| ExpectedType ToPointeeTypeOrErr = import(T->getPointeeTypeAsWritten()); |
| if (!ToPointeeTypeOrErr) |
| return ToPointeeTypeOrErr.takeError(); |
| |
| return Importer.getToContext().getRValueReferenceType(*ToPointeeTypeOrErr); |
| } |
| |
| ExpectedType |
| ASTNodeImporter::VisitMemberPointerType(const MemberPointerType *T) { |
| // FIXME: Check for C++ support in "to" context. |
| ExpectedType ToPointeeTypeOrErr = import(T->getPointeeType()); |
| if (!ToPointeeTypeOrErr) |
| return ToPointeeTypeOrErr.takeError(); |
| |
| ExpectedType ClassTypeOrErr = import(QualType(T->getClass(), 0)); |
| if (!ClassTypeOrErr) |
| return ClassTypeOrErr.takeError(); |
| |
| return Importer.getToContext().getMemberPointerType( |
| *ToPointeeTypeOrErr, (*ClassTypeOrErr).getTypePtr()); |
| } |
| |
| ExpectedType |
| ASTNodeImporter::VisitConstantArrayType(const ConstantArrayType *T) { |
| 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::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::VisitVectorType(const VectorType *T) { |
| ExpectedType ToElementTypeOrErr = import(T->getElementType()); |
| if (!ToElementTypeOrErr) |
| return ToElementTypeOrErr.takeError(); |
| |
| return Importer.getToContext().getVectorType(*ToElementTypeOrErr, |
| T->getNumElements(), |
| T->getVectorKind()); |
| } |
| |
| ExpectedType ASTNodeImporter::VisitExtVectorType(const ExtVectorType *T) { |
| ExpectedType ToElementTypeOrErr = import(T->getElementType()); |
| if (!ToElementTypeOrErr) |
| return ToElementTypeOrErr.takeError(); |
| |
| return Importer.getToContext().getExtVectorType(*ToElementTypeOrErr, |
| T->getNumElements()); |
| } |
| |
| ExpectedType |
| ASTNodeImporter::VisitFunctionNoProtoType(const FunctionNoProtoType *T) { |
| // FIXME: What happens if we're importing a function without a prototype |
| // into C++? Should we make it variadic? |
| ExpectedType ToReturnTypeOrErr = import(T->getReturnType()); |
| if (!ToReturnTypeOrErr) |
| return ToReturnTypeOrErr.takeError(); |
| |
| return Importer.getToContext().getFunctionNoProtoType(*ToReturnTypeOrErr, |
| T->getExtInfo()); |
| } |
| |
| ExpectedType |
| ASTNodeImporter::VisitFunctionProtoType(const FunctionProtoType *T) { |
| ExpectedType ToReturnTypeOrErr = import(T->getReturnType()); |
| if (!ToReturnTypeOrErr) |
| return ToReturnTypeOrErr.takeError(); |
| |
| // Import argument types |
| SmallVector<QualType, 4> ArgTypes; |
| for (const auto &A : T->param_types()) { |
| ExpectedType TyOrErr = import(A); |
| if (!TyOrErr) |
| return TyOrErr.takeError(); |
| ArgTypes.push_back(*TyOrErr); |
| } |
| |
| // Import exception types |
| SmallVector<QualType, 4> ExceptionTypes; |
| for (const auto &E : T->exceptions()) { |
| ExpectedType TyOrErr = import(E); |
| if (!TyOrErr) |
| return TyOrErr.takeError(); |
| ExceptionTypes.push_back(*TyOrErr); |
| } |
| |
| FunctionProtoType::ExtProtoInfo FromEPI = T->getExtProtoInfo(); |
| Error Err = Error::success(); |
| FunctionProtoType::ExtProtoInfo ToEPI; |
| ToEPI.ExtInfo = FromEPI.ExtInfo; |
| ToEPI.Variadic = FromEPI.Variadic; |
| ToEPI.HasTrailingReturn = FromEPI.HasTrailingReturn; |
| ToEPI.TypeQuals = FromEPI.TypeQuals; |
| ToEPI.RefQualifier = FromEPI.RefQualifier; |
| ToEPI.ExceptionSpec.Type = FromEPI.ExceptionSpec.Type; |
| ToEPI.ExceptionSpec.NoexceptExpr = |
| importChecked(Err, FromEPI.ExceptionSpec.NoexceptExpr); |
| ToEPI.ExceptionSpec.SourceDecl = |
| importChecked(Err, FromEPI.ExceptionSpec.SourceDecl); |
| ToEPI.ExceptionSpec.SourceTemplate = |
| importChecked(Err, FromEPI.ExceptionSpec.SourceTemplate); |
| ToEPI.ExceptionSpec.Exceptions = ExceptionTypes; |
| |
| if (Err) |
| return std::move(Err); |
| |
| return Importer.getToContext().getFunctionType( |
| *ToReturnTypeOrErr, ArgTypes, ToEPI); |
| } |
| |
| ExpectedType ASTNodeImporter::VisitUnresolvedUsingType( |
| const UnresolvedUsingType *T) { |
| Error Err = Error::success(); |
| auto ToD = importChecked(Err, T->getDecl()); |
| auto ToPrevD = importChecked(Err, T->getDecl()->getPreviousDecl()); |
| if (Err) |
| return std::move(Err); |
| |
| return Importer.getToContext().getTypeDeclType( |
| ToD, cast_or_null<TypeDecl>(ToPrevD)); |
| } |
| |
| ExpectedType ASTNodeImporter::VisitParenType(const ParenType *T) { |
| ExpectedType ToInnerTypeOrErr = import(T->getInnerType()); |
| if (!ToInnerTypeOrErr) |
| return ToInnerTypeOrErr.takeError(); |
| |
| return Importer.getToContext().getParenType(*ToInnerTypeOrErr); |
| } |
| |
| ExpectedType ASTNodeImporter::VisitTypedefType(const TypedefType *T) { |
| Expected<TypedefNameDecl *> ToDeclOrErr = import(T->getDecl()); |
| if (!ToDeclOrErr) |
| return ToDeclOrErr.takeError(); |
| |
| return Importer.getToContext().getTypeDeclType(*ToDeclOrErr); |
| } |
| |
| ExpectedType ASTNodeImporter::VisitTypeOfExprType(const TypeOfExprType *T) { |
| ExpectedExpr ToExprOrErr = import(T->getUnderlyingExpr()); |
| if (!ToExprOrErr) |
| return ToExprOrErr.takeError(); |
| |
| return Importer.getToContext().getTypeOfExprType(*ToExprOrErr); |
| } |
| |
| ExpectedType ASTNodeImporter::VisitTypeOfType(const TypeOfType *T) { |
| ExpectedType ToUnderlyingTypeOrErr = import(T->getUnderlyingType()); |
| if (!ToUnderlyingTypeOrErr) |
| return ToUnderlyingTypeOrErr.takeError(); |
| |
| return Importer.getToContext().getTypeOfType(*ToUnderlyingTypeOrErr); |
| } |
| |
| ExpectedType ASTNodeImporter::VisitDecltypeType(const DecltypeType *T) { |
| // FIXME: Make sure that the "to" context supports C++0x! |
| ExpectedExpr ToExprOrErr = import(T->getUnderlyingExpr()); |
| if (!ToExprOrErr) |
| return ToExprOrErr.takeError(); |
| |
| ExpectedType ToUnderlyingTypeOrErr = import(T->getUnderlyingType()); |
| if (!ToUnderlyingTypeOrErr) |
| return ToUnderlyingTypeOrErr.takeError(); |
| |
| return Importer.getToContext().getDecltypeType( |
| *ToExprOrErr, *ToUnderlyingTypeOrErr); |
| } |
| |
| ExpectedType |
| ASTNodeImporter::VisitUnaryTransformType(const UnaryTransformType *T) { |
| ExpectedType ToBaseTypeOrErr = import(T->getBaseType()); |
| if (!ToBaseTypeOrErr) |
| return ToBaseTypeOrErr.takeError(); |
| |
| ExpectedType ToUnderlyingTypeOrErr = import(T->getUnderlyingType()); |
| if (!ToUnderlyingTypeOrErr) |
| return ToUnderlyingTypeOrErr.takeError(); |
| |
| return Importer.getToContext().getUnaryTransformType( |
| *ToBaseTypeOrErr, *ToUnderlyingTypeOrErr, T->getUTTKind()); |
| } |
| |
| ExpectedType ASTNodeImporter::VisitAutoType(const AutoType *T) { |
| // FIXME: Make sure that the "to" context supports C++11! |
| ExpectedType ToDeducedTypeOrErr = import(T->getDeducedType()); |
| if (!ToDeducedTypeOrErr) |
| return ToDeducedTypeOrErr.takeError(); |
| |
| ExpectedDecl ToTypeConstraintConcept = import(T->getTypeConstraintConcept()); |
| if (!ToTypeConstraintConcept) |
| return ToTypeConstraintConcept.takeError(); |
| |
| SmallVector<TemplateArgument, 2> ToTemplateArgs; |
| ArrayRef<TemplateArgument> FromTemplateArgs = T->getTypeConstraintArguments(); |
| if (Error Err = ImportTemplateArguments(FromTemplateArgs.data(), |
| FromTemplateArgs.size(), |
| ToTemplateArgs)) |
| return std::move(Err); |
| |
| return Importer.getToContext().getAutoType( |
| *ToDeducedTypeOrErr, T->getKeyword(), /*IsDependent*/false, |
| /*IsPack=*/false, cast_or_null<ConceptDecl>(*ToTypeConstraintConcept), |
| ToTemplateArgs); |
| } |
| |
| ExpectedType ASTNodeImporter::VisitInjectedClassNameType( |
| const InjectedClassNameType *T) { |
| Expected<CXXRecordDecl *> ToDeclOrErr = import(T->getDecl()); |
| if (!ToDeclOrErr) |
| return ToDeclOrErr.takeError(); |
| |
| ExpectedType ToInjTypeOrErr = import(T->getInjectedSpecializationType()); |
| if (!ToInjTypeOrErr) |
| return ToInjTypeOrErr.takeError(); |
| |
| // FIXME: ASTContext::getInjectedClassNameType is not suitable for AST reading |
| // See comments in InjectedClassNameType definition for details |
| // return Importer.getToContext().getInjectedClassNameType(D, InjType); |
| enum { |
| TypeAlignmentInBits = 4, |
| TypeAlignment = 1 << TypeAlignmentInBits |
| }; |
| |
| return QualType(new (Importer.getToContext(), TypeAlignment) |
| InjectedClassNameType(*ToDeclOrErr, *ToInjTypeOrErr), 0); |
| } |
| |
| ExpectedType ASTNodeImporter::VisitRecordType(const RecordType *T) { |
| Expected<RecordDecl *> ToDeclOrErr = import(T->getDecl()); |
| if (!ToDeclOrErr) |
| return ToDeclOrErr.takeError(); |
| |
| return Importer.getToContext().getTagDeclType(*ToDeclOrErr); |
| } |
| |
| ExpectedType ASTNodeImporter::VisitEnumType(const EnumType *T) { |
| Expected<EnumDecl *> ToDeclOrErr = import(T->getDecl()); |
| if (!ToDeclOrErr) |
| return ToDeclOrErr.takeError(); |
| |
| return Importer.getToContext().getTagDeclType(*ToDeclOrErr); |
| } |
| |
| ExpectedType ASTNodeImporter::VisitAttributedType(const AttributedType *T) { |
| ExpectedType ToModifiedTypeOrErr = import(T->getModifiedType()); |
| if (!ToModifiedTypeOrErr) |
| return ToModifiedTypeOrErr.takeError(); |
| ExpectedType ToEquivalentTypeOrErr = import(T->getEquivalentType()); |
| if (!ToEquivalentTypeOrErr) |
| return ToEquivalentTypeOrErr.takeError(); |
| |
| return Importer.getToContext().getAttributedType(T->getAttrKind(), |
| *ToModifiedTypeOrErr, *ToEquivalentTypeOrErr); |
| } |
| |
| ExpectedType ASTNodeImporter::VisitTemplateTypeParmType( |
| const TemplateTypeParmType *T) { |
| Expected<TemplateTypeParmDecl *> ToDeclOrErr = import(T->getDecl()); |
| if (!ToDeclOrErr) |
| return ToDeclOrErr.takeError(); |
| |
| return Importer.getToContext().getTemplateTypeParmType( |
| T->getDepth(), T->getIndex(), T->isParameterPack(), *ToDeclOrErr); |
| } |
| |
| ExpectedType ASTNodeImporter::VisitSubstTemplateTypeParmType( |
| const SubstTemplateTypeParmType *T) { |
| ExpectedType ReplacedOrErr = import(QualType(T->getReplacedParameter(), 0)); |
| if (!ReplacedOrErr) |
| return ReplacedOrErr.takeError(); |
| const TemplateTypeParmType *Replaced = |
| cast<TemplateTypeParmType>((*ReplacedOrErr).getTypePtr()); |
| |
| ExpectedType ToReplacementTypeOrErr = import(T->getReplacementType()); |
| if (!ToReplacementTypeOrErr) |
| return ToReplacementTypeOrErr.takeError(); |
| |
| return Importer.getToContext().getSubstTemplateTypeParmType( |
| Replaced, (*ToReplacementTypeOrErr).getCanonicalType()); |
| } |
| |
| ExpectedType ASTNodeImporter::VisitTemplateSpecializationType( |
| const TemplateSpecializationType *T) { |
| auto ToTemplateOrErr = import(T->getTemplateName()); |
| if (!ToTemplateOrErr) |
| return ToTemplateOrErr.takeError(); |
| |
| SmallVector<TemplateArgument, 2> ToTemplateArgs; |
| if (Error Err = ImportTemplateArguments( |
| T->getArgs(), T->getNumArgs(), ToTemplateArgs)) |
| return std::move(Err); |
| |
| QualType ToCanonType; |
| if (!QualType(T, 0).isCanonical()) { |
| QualType FromCanonType |
| = Importer.getFromContext().getCanonicalType(QualType(T, 0)); |
| if (ExpectedType TyOrErr = import(FromCanonType)) |
| ToCanonType = *TyOrErr; |
| else |
| return TyOrErr.takeError(); |
| } |
| return Importer.getToContext().getTemplateSpecializationType(*ToTemplateOrErr, |
| ToTemplateArgs, |
| ToCanonType); |
| } |
| |
| ExpectedType ASTNodeImporter::VisitElaboratedType(const ElaboratedType *T) { |
| // Note: the qualifier in an ElaboratedType is optional. |
| auto ToQualifierOrErr = import(T->getQualifier()); |
| if (!ToQualifierOrErr) |
| return ToQualifierOrErr.takeError(); |
| |
| ExpectedType ToNamedTypeOrErr = import(T->getNamedType()); |
| if (!ToNamedTypeOrErr) |
| return ToNamedTypeOrErr.takeError(); |
| |
| Expected<TagDecl *> ToOwnedTagDeclOrErr = import(T->getOwnedTagDecl()); |
| if (!ToOwnedTagDeclOrErr) |
| return ToOwnedTagDeclOrErr.takeError(); |
| |
| return Importer.getToContext().getElaboratedType(T->getKeyword(), |
| *ToQualifierOrErr, |
| *ToNamedTypeOrErr, |
| *ToOwnedTagDeclOrErr); |
| } |
| |
| ExpectedType |
| ASTNodeImporter::VisitPackExpansionType(const PackExpansionType *T) { |
| ExpectedType ToPatternOrErr = import(T->getPattern()); |
| if (!ToPatternOrErr) |
| return ToPatternOrErr.takeError(); |
| |
| return Importer.getToContext().getPackExpansionType(*ToPatternOrErr, |
| T->getNumExpansions(), |
| /*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<TemplateArgument, 2> ToPack; |
| ToPack.reserve(T->getNumArgs()); |
| if (Error Err = ImportTemplateArguments( |
| T->getArgs(), T->getNumArgs(), ToPack)) |
| return std::move(Err); |
| |
| return Importer.getToContext().getDependentTemplateSpecializationType( |
| T->getKeyword(), *ToQualifierOrErr, ToName, ToPack); |
| } |
| |
| ExpectedType |
| ASTNodeImporter::VisitDependentNameType(const DependentNameType *T) { |
| auto ToQualifierOrErr = import(T->getQualifier()); |
| if (!ToQualifierOrErr) |
| return ToQualifierOrErr.takeError(); |
| |
| IdentifierInfo *Name = Importer.Import(T->getIdentifier()); |
| |
| QualType Canon; |
| if (T != T->getCanonicalTypeInternal().getTypePtr()) { |
| if (ExpectedType TyOrErr = import(T->getCanonicalTypeInternal())) |
| Canon = (*TyOrErr).getCanonicalType(); |
| else |
| return TyOrErr.takeError(); |
| } |
| |
| return Importer.getToContext().getDependentNameType(T->getKeyword(), |
| *ToQualifierOrErr, |
| Name, Canon); |
| } |
| |
| ExpectedType |
| ASTNodeImporter::VisitObjCInterfaceType(const ObjCInterfaceType *T) { |
| Expected<ObjCInterfaceDecl *> ToDeclOrErr = import(T->getDecl()); |
| if (!ToDeclOrErr) |
| return ToDeclOrErr.takeError(); |
| |
| return Importer.getToContext().getObjCInterfaceType(*ToDeclOrErr); |
| } |
| |
| ExpectedType ASTNodeImporter::VisitObjCObjectType(const ObjCObjectType *T) { |
| ExpectedType ToBaseTypeOrErr = import(T->getBaseType()); |
| if (!ToBaseTypeOrErr) |
| return ToBaseTypeOrErr.takeError(); |
| |
| SmallVector<QualType, 4> TypeArgs; |
| for (auto TypeArg : T->getTypeArgsAsWritten()) { |
| if (ExpectedType TyOrErr = import(TypeArg)) |
| TypeArgs.push_back(*TyOrErr); |
| else |
| return TyOrErr.takeError(); |
| } |
| |
| SmallVector<ObjCProtocolDecl *, 4> Protocols; |
| for (auto *P : T->quals()) { |
| if (Expected<ObjCProtocolDecl *> ProtocolOrErr = import(P)) |
| Protocols.push_back(*ProtocolOrErr); |
| else |
| return ProtocolOrErr.takeError(); |
| |
| } |
| |
| return Importer.getToContext().getObjCObjectType(*ToBaseTypeOrErr, TypeArgs, |
| Protocols, |
| T->isKindOfTypeAsWritten()); |
| } |
| |
| ExpectedType |
| ASTNodeImporter::VisitObjCObjectPointerType(const ObjCObjectPointerType *T) { |
| ExpectedType ToPointeeTypeOrErr = import(T->getPointeeType()); |
| if (!ToPointeeTypeOrErr) |
| return ToPointeeTypeOrErr.takeError(); |
| |
| return Importer.getToContext().getObjCObjectPointerType(*ToPointeeTypeOrErr); |
| } |
| |
| //---------------------------------------------------------------------------- |
| // Import Declarations |
| //---------------------------------------------------------------------------- |
| Error ASTNodeImporter::ImportDeclParts( |
| NamedDecl *D, DeclContext *&DC, DeclContext *&LexicalDC, |
| DeclarationName &Name, NamedDecl *&ToD, SourceLocation &Loc) { |
| // Check if RecordDecl is in FunctionDecl parameters to avoid infinite loop. |
| // example: int struct_in_proto(struct data_t{int a;int b;} *d); |
| // FIXME: We could support these constructs by importing a different type of |
| // this parameter and by importing the original type of the parameter only |
| // after the FunctionDecl is created. See |
| // VisitFunctionDecl::UsedDifferentProtoType. |
| DeclContext *OrigDC = D->getDeclContext(); |
| FunctionDecl *FunDecl; |
| if (isa<RecordDecl>(D) && (FunDecl = dyn_cast<FunctionDecl>(OrigDC)) && |
| FunDecl->hasBody()) { |
| auto getLeafPointeeType = [](const Type *T) { |
| while (T->isPointerType() || T->isArrayType()) { |
| T = T->getPointeeOrArrayElementType(); |
| } |
| return T; |
| }; |
| for (const ParmVarDecl *P : FunDecl->parameters()) { |
| const Type *LeafT = |
| getLeafPointeeType(P->getType().getCanonicalType().getTypePtr()); |
| auto *RT = dyn_cast<RecordType>(LeafT); |
| if (RT && RT->getDecl() == D) { |
| Importer.FromDiag(D->getLocation(), diag::err_unsupported_ast_node) |
| << D->getDeclKindName(); |
| return make_error<ImportError>(ImportError::UnsupportedConstruct); |
| } |
| } |
| } |
| |
| // Import the context of this declaration. |
| if (Error Err = ImportDeclContext(D, DC, LexicalDC)) |
| return Err; |
| |
| // Import the name of this declaration. |
| if (Error Err = importInto(Name, D->getDeclName())) |
| return Err; |
| |
| // Import the location of this declaration. |
| if (Error Err = importInto(Loc, D->getLocation())) |
| return Err; |
| |
| ToD = cast_or_null<NamedDecl>(Importer.GetAlreadyImportedOrNull(D)); |
| if (ToD) |
| if (Error Err = ASTNodeImporter(*this).ImportDefinitionIfNeeded(D, ToD)) |
| return Err; |
| |
| return Error::success(); |
| } |
| |
| Error ASTNodeImporter::ImportDeclParts(NamedDecl *D, DeclarationName &Name, |
| NamedDecl *&ToD, SourceLocation &Loc) { |
| |
| // Import the name of this declaration. |
| if (Error Err = importInto(Name, D->getDeclName())) |
| return Err; |
| |
| // Import the location of this declaration. |
| if (Error Err = importInto(Loc, D->getLocation())) |
| return Err; |
| |
| ToD = cast_or_null<NamedDecl>(Importer.GetAlreadyImportedOrNull(D)); |
| if (ToD) |
| if (Error Err = ASTNodeImporter(*this).ImportDefinitionIfNeeded(D, ToD)) |
| return Err; |
| |
| return Error::success(); |
| } |
| |
| Error ASTNodeImporter::ImportDefinitionIfNeeded(Decl *FromD, Decl *ToD) { |
| if (!FromD) |
| return Error::success(); |
| |
| if (!ToD) |
| if (Error Err = importInto(ToD, FromD)) |
| return Err; |
| |
| if (RecordDecl *FromRecord = dyn_cast<RecordDecl>(FromD)) { |
| if (RecordDecl *ToRecord = cast<RecordDecl>(ToD)) { |
| if (FromRecord->getDefinition() && FromRecord->isCompleteDefinition() && |
| !ToRecord->getDefinition()) { |
| if (Error Err = ImportDefinition(FromRecord, ToRecord)) |
| return Err; |
| } |
| } |
| return Error::success(); |
| } |
| |
| if (EnumDecl *FromEnum = dyn_cast<EnumDecl>(FromD)) { |
| if (EnumDecl *ToEnum = cast<EnumDecl>(ToD)) { |
| if (FromEnum->getDefinition() && !ToEnum->getDefinition()) { |
| if (Error Err = ImportDefinition(FromEnum, ToEnum)) |
| return Err; |
| } |
| } |
| return Error::success(); |
| } |
| |
| return Error::success(); |
| } |
| |
| Error |
| ASTNodeImporter::ImportDeclarationNameLoc( |
| const DeclarationNameInfo &From, DeclarationNameInfo& To) { |
| // NOTE: To.Name and To.Loc are already imported. |
| // We only have to import To.LocInfo. |
| switch (To.getName().getNameKind()) { |
| case DeclarationName::Identifier: |
| case DeclarationName::ObjCZeroArgSelector: |
| case DeclarationName::ObjCOneArgSelector: |
| case DeclarationName::ObjCMultiArgSelector: |
| case DeclarationName::CXXUsingDirective: |
| case DeclarationName::CXXDeductionGuideName: |
| return Error::success(); |
| |
| case DeclarationName::CXXOperatorName: { |
| if (auto ToRangeOrErr = import(From.getCXXOperatorNameRange())) |
| To.setCXXOperatorNameRange(*ToRangeOrErr); |
| else |
| return ToRangeOrErr.takeError(); |
| return Error::success(); |
| } |
| case DeclarationName::CXXLiteralOperatorName: { |
| if (ExpectedSLoc LocOrErr = import(From.getCXXLiteralOperatorNameLoc())) |
| To.setCXXLiteralOperatorNameLoc(*LocOrErr); |
| else |
| return LocOrErr.takeError(); |
| return Error::success(); |
| } |
| case DeclarationName::CXXConstructorName: |
| case DeclarationName::CXXDestructorName: |
| case DeclarationName::CXXConversionFunctionName: { |
| if (auto ToTInfoOrErr = import(From.getNamedTypeInfo())) |
| To.setNamedTypeInfo(*ToTInfoOrErr); |
| else |
| return ToTInfoOrErr.takeError(); |
| return Error::success(); |
| } |
| } |
| llvm_unreachable("Unknown name kind."); |
| } |
| |
| Error |
| ASTNodeImporter::ImportDeclContext(DeclContext *FromDC, bool ForceImport) { |
| if (Importer.isMinimalImport() && !ForceImport) { |
| auto ToDCOrErr = Importer.ImportContext(FromDC); |
| return ToDCOrErr.takeError(); |
| } |
| |
| // We use strict error handling in case of records and enums, but not |
| // with e.g. namespaces. |
| // |
| // FIXME Clients of the ASTImporter should be able to choose an |
| // appropriate error handling strategy for their needs. For instance, |
| // they may not want to mark an entire namespace as erroneous merely |
| // because there is an ODR error with two typedefs. As another example, |
| // the client may allow EnumConstantDecls with same names but with |
| // different values in two distinct translation units. |
| bool AccumulateChildErrors = isa<TagDecl>(FromDC); |
| |
| Error ChildErrors = Error::success(); |
| for (auto *From : FromDC->decls()) { |
| 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) { |
| FieldDecl *FieldFrom = dyn_cast_or_null<FieldDecl>(From); |
| Decl *ImportedDecl = *ImportedOrErr; |
| FieldDecl *FieldTo = dyn_cast_or_null<FieldDecl>(ImportedDecl); |
| if (FieldFrom && FieldTo) { |
| 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 defintion. |
| if (FieldFrom->getType()->isArrayType()) { |
| // getBaseElementTypeUnsafe(...) handles multi-dimensonal arrays for us. |
| FromRecordDecl = FieldFrom->getType()->getBaseElementTypeUnsafe()->getAsRecordDecl(); |
| ToRecordDecl = FieldTo->getType()->getBaseElementTypeUnsafe()->getAsRecordDecl(); |
| } |
| |
| if (!FromRecordDecl || !ToRecordDecl) { |
| const RecordType *RecordFrom = |
| FieldFrom->getType()->getAs<RecordType>(); |
| const RecordType *RecordTo = FieldTo->getType()->getAs<RecordType>(); |
| |
| if (RecordFrom && RecordTo) { |
| FromRecordDecl = RecordFrom->getDecl(); |
| ToRecordDecl = RecordTo->getDecl(); |
| } |
| } |
| |
| if (FromRecordDecl && ToRecordDecl) { |
| if (FromRecordDecl->isCompleteDefinition() && |
| !ToRecordDecl->isCompleteDefinition()) { |
| Error Err = ImportDefinition(FromRecordDecl, ToRecordDecl); |
| |
| if (Err && AccumulateChildErrors) |
| ChildErrors = joinErrors(std::move(ChildErrors), std::move(Err)); |
| else |
| consumeError(std::move(Err)); |
| } |
| } |
| } |
| } else { |
| if (AccumulateChildErrors) |
| ChildErrors = |
| joinErrors(std::move(ChildErrors), ImportedOrErr.takeError()); |
| else |
| consumeError(ImportedOrErr.takeError()); |
| } |
| } |
| |
| // We reorder declarations in RecordDecls because they may have another order |
| // in the "to" context than they have in the "from" context. This may happen |
| // e.g when we import a class like this: |
| // struct declToImport { |
| // int a = c + b; |
| // int b = 1; |
| // int c = 2; |
| // }; |
| // During the import of `a` we import first the dependencies in sequence, |
| // thus the order would be `c`, `b`, `a`. We will get the normal order by |
| // first removing the already imported members and then adding them in the |
| // order as they apper in the "from" context. |
| // |
| // Keeping field order is vital because it determines structure layout. |
| // |
| // Here and below, we cannot call field_begin() method and its callers on |
| // ToDC if it has an external storage. Calling field_begin() will |
| // automatically load all the fields by calling |
| // LoadFieldsFromExternalStorage(). LoadFieldsFromExternalStorage() would |
| // call ASTImporter::Import(). This is because the ExternalASTSource |
| // interface in LLDB is implemented by the means of the ASTImporter. However, |
| // calling an import at this point would result in an uncontrolled import, we |
| // must avoid that. |
| const auto *FromRD = dyn_cast<RecordDecl>(FromDC); |
| if (!FromRD) |
| return ChildErrors; |
| |
| auto ToDCOrErr = Importer.ImportContext(FromDC); |
| if (!ToDCOrErr) { |
| consumeError(std::move(ChildErrors)); |
| return ToDCOrErr.takeError(); |
| } |
| |
| DeclContext *ToDC = *ToDCOrErr; |
| // Remove all declarations, which may be in wrong order in the |
| // lexical DeclContext and then add them in the proper order. |
| for (auto *D : FromRD->decls()) { |
| if (isa<FieldDecl>(D) || isa<IndirectFieldDecl>(D) || isa<FriendDecl>(D)) { |
| assert(D && "DC contains a null decl"); |
| Decl *ToD = Importer.GetAlreadyImportedOrNull(D); |
| // Remove only the decls which we successfully imported. |
| if (ToD) { |
| assert(ToDC == ToD->getLexicalDeclContext() && ToDC->containsDecl(ToD)); |
| // Remove the decl from its wrong place in the linked list. |
| ToDC->removeDecl(ToD); |
| // Add the decl to the end of the linked list. |
| // This time it will be at the proper place because the enclosing for |
| // loop iterates in the original (good) order of the decls. |
| ToDC->addDeclInternal(ToD); |
| } |
| } |
| } |
| |
| return ChildErrors; |
| } |
| |
| Error ASTNodeImporter::ImportDeclContext( |
| Decl *FromD, DeclContext *&ToDC, DeclContext *&ToLexicalDC) { |
| auto ToDCOrErr = Importer.ImportContext(FromD->getDeclContext()); |
| if (!ToDCOrErr) |
| return ToDCOrErr.takeError(); |
| ToDC = *ToDCOrErr; |
| |
| if (FromD->getDeclContext() != FromD->getLexicalDeclContext()) { |
| auto ToLexicalDCOrErr = Importer.ImportContext( |
| FromD->getLexicalDeclContext()); |
| if (!ToLexicalDCOrErr) |
| return ToLexicalDCOrErr.takeError(); |
| ToLexicalDC = *ToLexicalDCOrErr; |
| } else |
| ToLexicalDC = ToDC; |
| |
| return Error::success(); |
| } |
| |
| Error ASTNodeImporter::ImportImplicitMethods( |
| const CXXRecordDecl *From, CXXRecordDecl *To) { |
| assert(From->isCompleteDefinition() && To->getDefinition() == To && |
| "Import implicit methods to or from non-definition"); |
| |
| for (CXXMethodDecl *FromM : From->methods()) |
| if (FromM->isImplicit()) { |
| Expected<CXXMethodDecl *> ToMOrErr = import(FromM); |
| if (!ToMOrErr) |
| return ToMOrErr.takeError(); |
| } |
| |
| return Error::success(); |
| } |
| |
| static Error setTypedefNameForAnonDecl(TagDecl *From, TagDecl *To, |
| ASTImporter &Importer) { |
| if (TypedefNameDecl *FromTypedef = From->getTypedefNameForAnonDecl()) { |
| if (ExpectedDecl ToTypedefOrErr = Importer.Import(FromTypedef)) |
| To->setTypedefNameForAnonDecl(cast<TypedefNameDecl>(*ToTypedefOrErr)); |
| else |
| return ToTypedefOrErr.takeError(); |
| } |
| return Error::success(); |
| } |
| |
| Error ASTNodeImporter::ImportDefinition( |
| RecordDecl *From, RecordDecl *To, ImportDefinitionKind Kind) { |
| auto DefinitionCompleter = [To]() { |
| // There are cases in LLDB when we first import a class without its |
| // members. The class will have DefinitionData, but no members. Then, |
| // importDefinition is called from LLDB, which tries to get the members, so |
| // when we get here, the class already has the DefinitionData set, so we |
| // must unset the CompleteDefinition here to be able to complete again the |
| // definition. |
| To->setCompleteDefinition(false); |
| To->completeDefinition(); |
| }; |
| |
| if (To->getDefinition() || To->isBeingDefined()) { |
| if (Kind == IDK_Everything || |
| // In case of lambdas, the class already has a definition ptr set, but |
| // the contained decls are not imported yet. Also, isBeingDefined was |
| // set in CXXRecordDecl::CreateLambda. We must import the contained |
| // decls here and finish the definition. |
| (To->isLambda() && shouldForceImportDeclContext(Kind))) { |
| if (To->isLambda()) { |
| auto *FromCXXRD = cast<CXXRecordDecl>(From); |
| SmallVector<LambdaCapture, 8> ToCaptures; |
| ToCaptures.reserve(FromCXXRD->capture_size()); |
| for (const auto &FromCapture : FromCXXRD->captures()) { |
| if (auto ToCaptureOrErr = import(FromCapture)) |
| ToCaptures.push_back(*ToCaptureOrErr); |
| else |
| return ToCaptureOrErr.takeError(); |
| } |
| cast<CXXRecordDecl>(To)->setCaptures(Importer.getToContext(), |
| ToCaptures); |
| } |
| |
| Error Result = ImportDeclContext(From, /*ForceImport=*/true); |
| // Finish the definition of the lambda, set isBeingDefined to false. |
| if (To->isLambda()) |
| DefinitionCompleter(); |
| return Result; |
| } |
| |
| return Error::success(); |
| } |
| |
| To->startDefinition(); |
| // Complete the definition even if error is returned. |
| // The RecordDecl may be already part of the AST so it is better to |
| // have it in complete state even if something is wrong with it. |
| auto DefinitionCompleterScopeExit = |
| llvm::make_scope_exit(DefinitionCompleter); |
| |
| if (Error Err = setTypedefNameForAnonDecl(From, To, Importer)) |
| return Err; |
| |
| // Add base classes. |
| auto *ToCXX = dyn_cast<CXXRecordDecl>(To); |
| auto *FromCXX = dyn_cast<CXXRecordDecl>(From); |
| if (ToCXX && FromCXX && ToCXX->dataPtr() && FromCXX->dataPtr()) { |
| |
| struct CXXRecordDecl::DefinitionData &ToData = ToCXX->data(); |
| struct CXXRecordDecl::DefinitionData &FromData = FromCXX->data(); |
| |
| #define FIELD(Name, Width, Merge) \ |
| ToData.Name = FromData.Name; |
| #include "clang/AST/CXXRecordDeclDefinitionBits.def" |
| |
| // Copy over the data stored in RecordDeclBits |
| ToCXX->setArgPassingRestrictions(FromCXX->getArgPassingRestrictions()); |
| |
| SmallVector<CXXBaseSpecifier *, 4> Bases; |
| for (const auto &Base1 : FromCXX->bases()) { |
| ExpectedType TyOrErr = import(Base1.getType()); |
| if (!TyOrErr) |
| return TyOrErr.takeError(); |
| |
| SourceLocation EllipsisLoc; |
| if (Base1.isPackExpansion()) { |
| if (ExpectedSLoc LocOrErr = import(Base1.getEllipsisLoc())) |
| EllipsisLoc = *LocOrErr; |
| else |
| return LocOrErr.takeError(); |
| } |
| |
| // Ensure that we have a definition for the base. |
| if (Error Err = |
| ImportDefinitionIfNeeded(Base1.getType()->getAsCXXRecordDecl())) |
| return Err; |
| |
| auto RangeOrErr = import(Base1.getSourceRange()); |
| if (!RangeOrErr) |
| return RangeOrErr.takeError(); |
| |
| auto TSIOrErr = import(Base1.getTypeSourceInfo()); |
| if (!TSIOrErr) |
| return TSIOrErr.takeError(); |
| |
| Bases.push_back( |
| new (Importer.getToContext()) CXXBaseSpecifier( |
| *RangeOrErr, |
| Base1.isVirtual(), |
| Base1.isBaseOfClass(), |
| Base1.getAccessSpecifierAsWritten(), |
| *TSIOrErr, |
| EllipsisLoc)); |
| } |
| if (!Bases.empty()) |
| ToCXX->setBases(Bases.data(), Bases.size()); |
| } |
| |
| if (shouldForceImportDeclContext(Kind)) |
| if (Error Err = ImportDeclContext(From, /*ForceImport=*/true)) |
| return Err; |
| |
| return Error::success(); |
| } |
| |
| Error ASTNodeImporter::ImportInitializer(VarDecl *From, VarDecl *To) { |
| if (To->getAnyInitializer()) |
| return Error::success(); |
| |
| Expr *FromInit = From->getInit(); |
| if (!FromInit) |
| return Error::success(); |
| |
| ExpectedExpr ToInitOrErr = import(FromInit); |
| if (!ToInitOrErr) |
| return ToInitOrErr.takeError(); |
| |
| To->setInit(*ToInitOrErr); |
| if (EvaluatedStmt *FromEval = From->getEvaluatedStmt()) { |
| EvaluatedStmt *ToEval = To->ensureEvaluatedStmt(); |
| ToEval->HasConstantInitialization = FromEval->HasConstantInitialization; |
| ToEval->HasConstantDestruction = FromEval->HasConstantDestruction; |
| // FIXME: Also import the initializer value. |
| } |
| |
| // FIXME: Other bits to merge? |
| return Error::success(); |
| } |
| |
| Error ASTNodeImporter::ImportDefinition( |
| EnumDecl *From, EnumDecl *To, ImportDefinitionKind Kind) { |
| if (To->getDefinition() || To->isBeingDefined()) { |
| if (Kind == IDK_Everything) |
| return ImportDeclContext(From, /*ForceImport=*/true); |
| return Error::success(); |
| } |
| |
| To->startDefinition(); |
| |
| if (Error Err = setTypedefNameForAnonDecl(From, To, Importer)) |
| return Err; |
| |
| ExpectedType ToTypeOrErr = |
| import(Importer.getFromContext().getTypeDeclType(From)); |
| if (!ToTypeOrErr) |
| return ToTypeOrErr.takeError(); |
| |
| ExpectedType ToPromotionTypeOrErr = import(From->getPromotionType()); |
| if (!ToPromotionTypeOrErr) |
| return ToPromotionTypeOrErr.takeError(); |
| |
| if (shouldForceImportDeclContext(Kind)) |
| if (Error Err = ImportDeclContext(From, /*ForceImport=*/true)) |
| return Err; |
| |
| // FIXME: we might need to merge the number of positive or negative bits |
| // if the enumerator lists don't match. |
| To->completeDefinition(*ToTypeOrErr, *ToPromotionTypeOrErr, |
| From->getNumPositiveBits(), |
| From->getNumNegativeBits()); |
| return Error::success(); |
| } |
| |
| Error ASTNodeImporter::ImportTemplateArguments( |
| const TemplateArgument *FromArgs, unsigned NumFromArgs, |
| SmallVectorImpl<TemplateArgument> &ToArgs) { |
| for (unsigned I = 0; I != NumFromArgs; ++I) { |
| if (auto ToOrErr = import(FromArgs[I])) |
| ToArgs.push_back(*ToOrErr); |
| else |
| return ToOrErr.takeError(); |
| } |
| |
| return Error::success(); |
| } |
| |
| // FIXME: Do not forget to remove this and use only 'import'. |
| Expected<TemplateArgument> |
| ASTNodeImporter::ImportTemplateArgument(const TemplateArgument &From) { |
| return import(From); |
| } |
| |
| template <typename InContainerTy> |
| Error ASTNodeImporter::ImportTemplateArgumentListInfo( |
| const InContainerTy &Container, TemplateArgumentListInfo &ToTAInfo) { |
| for (const auto &FromLoc : Container) { |
| if (auto ToLocOrErr = import(FromLoc)) |
| ToTAInfo.addArgument(*ToLocOrErr); |
| else |
| return ToLocOrErr.takeError(); |
| } |
| return Error::success(); |
| } |
| |
| static StructuralEquivalenceKind |
| getStructuralEquivalenceKind(const ASTImporter &Importer) { |
| return Importer.isMinimalImport() ? StructuralEquivalenceKind::Minimal |
| : StructuralEquivalenceKind::Default; |
| } |
| |
| bool ASTNodeImporter::IsStructuralMatch(Decl *From, Decl *To, bool Complain) { |
| StructuralEquivalenceContext Ctx( |
| Importer.getFromContext(), Importer.getToContext(), |
| Importer.getNonEquivalentDecls(), getStructuralEquivalenceKind(Importer), |
| false, Complain); |
| return Ctx.IsEquivalent(From, To); |
| } |
| |
| bool ASTNodeImporter::IsStructuralMatch(RecordDecl *FromRecord, |
| RecordDecl *ToRecord, bool Complain) { |
| // Eliminate a potential failure point where we attempt to re-import |
| // something we're trying to import while completing ToRecord. |
| Decl *ToOrigin = Importer.GetOriginalDecl(ToRecord); |
| if (ToOrigin) { |
| auto *ToOriginRecord = dyn_cast<RecordDecl>(ToOrigin); |
| if (ToOriginRecord) |
| ToRecord = ToOriginRecord; |
| } |
| |
| StructuralEquivalenceContext Ctx(Importer.getFromContext(), |
| ToRecord->getASTContext(), |
| Importer.getNonEquivalentDecls(), |
| getStructuralEquivalenceKind(Importer), |
| false, Complain); |
| return Ctx.IsEquivalent(FromRecord, ToRecord); |
| } |
| |
| bool ASTNodeImporter::IsStructuralMatch(VarDecl *FromVar, VarDecl *ToVar, |
| bool Complain) { |
| StructuralEquivalenceContext Ctx( |
| Importer.getFromContext(), Importer.getToContext(), |
| Importer.getNonEquivalentDecls(), getStructuralEquivalenceKind(Importer), |
| false, Complain); |
| return Ctx.IsEquivalent(FromVar, ToVar); |
| } |
| |
| bool ASTNodeImporter::IsStructuralMatch(EnumDecl *FromEnum, EnumDecl *ToEnum) { |
| // Eliminate a potential failure point where we attempt to re-import |
| // something we're trying to import while completing ToEnum. |
| if (Decl *ToOrigin = Importer.GetOriginalDecl(ToEnum)) |
| if (auto *ToOriginEnum = dyn_cast<EnumDecl>(ToOrigin)) |
| ToEnum = ToOriginEnum; |
| |
| StructuralEquivalenceContext Ctx( |
| Importer.getFromContext(), Importer.getToContext(), |
| Importer.getNonEquivalentDecls(), getStructuralEquivalenceKind(Importer)); |
| return Ctx.IsEquivalent(FromEnum, ToEnum); |
| } |
| |
| bool ASTNodeImporter::IsStructuralMatch(FunctionTemplateDecl *From, |
| FunctionTemplateDecl *To) { |
| StructuralEquivalenceContext Ctx( |
| Importer.getFromContext(), Importer.getToContext(), |
| Importer.getNonEquivalentDecls(), getStructuralEquivalenceKind(Importer), |
| false, false); |
| return Ctx.IsEquivalent(From, To); |
| } |
| |
| bool ASTNodeImporter::IsStructuralMatch(FunctionDecl *From, FunctionDecl *To) { |
| StructuralEquivalenceContext Ctx( |
| Importer.getFromContext(), Importer.getToContext(), |
| Importer.getNonEquivalentDecls(), getStructuralEquivalenceKind(Importer), |
| false, false); |
| return Ctx.IsEquivalent(From, To); |
| } |
| |
| bool ASTNodeImporter::IsStructuralMatch(EnumConstantDecl *FromEC, |
| EnumConstantDecl *ToEC) { |
| const llvm::APSInt &FromVal = FromEC->getInitVal(); |
| const llvm::APSInt &ToVal = ToEC->getInitVal(); |
| |
| return FromVal.isSigned() == ToVal.isSigned() && |
| FromVal.getBitWidth() == ToVal.getBitWidth() && |
| FromVal == ToVal; |
| } |
| |
| bool ASTNodeImporter::IsStructuralMatch(ClassTemplateDecl *From, |
| ClassTemplateDecl *To) { |
| StructuralEquivalenceContext Ctx(Importer.getFromContext(), |
| Importer.getToContext(), |
| Importer.getNonEquivalentDecls(), |
| getStructuralEquivalenceKind(Importer)); |
| return Ctx.IsEquivalent(From, To); |
| } |
| |
| bool ASTNodeImporter::IsStructuralMatch(VarTemplateDecl *From, |
| VarTemplateDecl *To) { |
| StructuralEquivalenceContext Ctx(Importer.getFromContext(), |
| Importer.getToContext(), |
| Importer.getNonEquivalentDecls(), |
| getStructuralEquivalenceKind(Importer)); |
| return Ctx.IsEquivalent(From, To); |
| } |
| |
| ExpectedDecl ASTNodeImporter::VisitDecl(Decl *D) { |
| Importer.FromDiag(D->getLocation(), diag::err_unsupported_ast_node) |
| << D->getDeclKindName(); |
| return make_error<ImportError>(ImportError::UnsupportedConstruct); |
| } |
| |
| ExpectedDecl ASTNodeImporter::VisitImportDecl(ImportDecl *D) { |
| Importer.FromDiag(D->getLocation(), diag::err_unsupported_ast_node) |
| << D->getDeclKindName(); |
| return make_error<ImportError>(ImportError::UnsupportedConstruct); |
| } |
| |
| ExpectedDecl ASTNodeImporter::VisitEmptyDecl(EmptyDecl *D) { |
| // Import the context of this declaration. |
| DeclContext *DC, *LexicalDC; |
| if (Error Err = ImportDeclContext(D, DC, LexicalDC)) |
| return std::move(Err); |
| |
| // Import the location of this declaration. |
| ExpectedSLoc LocOrErr = import(D->getLocation()); |
| if (!LocOrErr) |
| return LocOrErr.takeError(); |
| |
| EmptyDecl *ToD; |
| if (GetImportedOrCreateDecl(ToD, D, Importer.getToContext(), DC, *LocOrErr)) |
| return ToD; |
| |
| ToD->setLexicalDeclContext(LexicalDC); |
| LexicalDC->addDeclInternal(ToD); |
| return ToD; |
| } |
| |
| ExpectedDecl ASTNodeImporter::VisitTranslationUnitDecl(TranslationUnitDecl *D) { |
| TranslationUnitDecl *ToD = |
| Importer.getToContext().getTranslationUnitDecl(); |
| |
| Importer.MapImported(D, ToD); |
| |
| return ToD; |
| } |
| |
| ExpectedDecl ASTNodeImporter::VisitAccessSpecDecl(AccessSpecDecl *D) { |
| ExpectedSLoc LocOrErr = import(D->getLocation()); |
| if (!LocOrErr) |
| return LocOrErr.takeError(); |
| auto ColonLocOrErr = import(D->getColonLoc()); |
| if (!ColonLocOrErr) |
| return ColonLocOrErr.takeError(); |
| |
| // Import the context of this declaration. |
| auto DCOrErr = Importer.ImportContext(D->getDeclContext()); |
| if (!DCOrErr) |
| return DCOrErr.takeError(); |
| DeclContext *DC = *DCOrErr; |
| |
| AccessSpecDecl *ToD; |
| if (GetImportedOrCreateDecl(ToD, D, Importer.getToContext(), D->getAccess(), |
| DC, *LocOrErr, *ColonLocOrErr)) |
| return ToD; |
| |
| // Lexical DeclContext and Semantic DeclContext |
| // is always the same for the accessSpec. |
| ToD->setLexicalDeclContext(DC); |
| DC->addDeclInternal(ToD); |
| |
| return ToD; |
| } |
| |
| ExpectedDecl ASTNodeImporter::VisitStaticAssertDecl(StaticAssertDecl *D) { |
| auto DCOrErr = Importer.ImportContext(D->getDeclContext()); |
| if (!DCOrErr) |
| return DCOrErr.takeError(); |
| DeclContext *DC = *DCOrErr; |
| DeclContext *LexicalDC = DC; |
| |
| 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<TranslationUnitDecl>(DC)) |
| MergeWithNamespace = TU->getAnonymousNamespace(); |
| else |
| MergeWithNamespace = cast<NamespaceDecl>(DC)->getAnonymousNamespace(); |
| } else { |
| SmallVector<NamedDecl *, 4> ConflictingDecls; |
| auto FoundDecls = Importer.findDeclsInToCtx(DC, Name); |
| for (auto *FoundDecl : FoundDecls) { |
| if (!FoundDecl->isInIdentifierNamespace(Decl::IDNS_Namespace)) |
| continue; |
| |
| if (auto *FoundNS = dyn_cast<NamespaceDecl>(FoundDecl)) { |
| MergeWithNamespace = FoundNS; |
| ConflictingDecls.clear(); |
| break; |
| } |
| |
| ConflictingDecls.push_back(FoundDecl); |
| } |
| |
| if (!ConflictingDecls.empty()) { |
| ExpectedName NameOrErr = Importer.HandleNameConflict( |
| Name, DC, Decl::IDNS_Namespace, ConflictingDecls.data(), |
| ConflictingDecls.size()); |
| if (NameOrErr) |
| Name = NameOrErr.get(); |
| else |
| return NameOrErr.takeError(); |
| } |
| } |
| |
| ExpectedSLoc BeginLocOrErr = import(D->getBeginLoc()); |
| if (!BeginLocOrErr) |
| return BeginLocOrErr.takeError(); |
| 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)) |
| return ToNamespace; |
| ToNamespace->setRBraceLoc(*RBraceLocOrErr); |
| ToNamespace->setLexicalDeclContext(LexicalDC); |
| LexicalDC->addDeclInternal(ToNamespace); |
| |
| // If this is an anonymous namespace, register it as the anonymous |
| // namespace within its context. |
| if (!Name) { |
| if (auto *TU = dyn_cast<TranslationUnitDecl>(DC)) |
| TU->setAnonymousNamespace(ToNamespace); |
| else |
| cast<NamespaceDecl>(DC)->setAnonymousNamespace(ToNamespace); |
| } |
| } |
| Importer.MapImported(D, ToNamespace); |
| |
| if (Error Err = ImportDeclContext(D)) |
| return std::move(Err); |
| |
| return ToNamespace; |
| } |
| |
| ExpectedDecl ASTNodeImporter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { |
| // Import the major distinguishing characteristics of this namespace. |
| DeclContext *DC, *LexicalDC; |
| DeclarationName Name; |
| SourceLocation Loc; |
| NamedDecl *LookupD; |
| if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, LookupD, Loc)) |
| return std::move(Err); |
| if (LookupD) |
| return LookupD; |
| |
| // NOTE: No conflict resolution is done for namespace aliases now. |
| |
| Error Err = Error::success(); |
| auto ToNamespaceLoc = importChecked(Err, D->getNamespaceLoc()); |
| auto ToAliasLoc = importChecked(Err, D->getAliasLoc()); |
| auto ToQualifierLoc = importChecked(Err, D->getQualifierLoc()); |
| auto ToTargetNameLoc = importChecked(Err, D->getTargetNameLoc()); |
| auto ToNamespace = importChecked(Err, D->getNamespace()); |
| if (Err) |
| return std::move(Err); |
| |
| IdentifierInfo *ToIdentifier = Importer.Import(D->getIdentifier()); |
| |
| NamespaceAliasDecl *ToD; |
| if (GetImportedOrCreateDecl( |
| ToD, D, Importer.getToContext(), DC, ToNamespaceLoc, ToAliasLoc, |
| ToIdentifier, ToQualifierLoc, ToTargetNameLoc, ToNamespace)) |
| return ToD; |
| |
| ToD->setLexicalDeclContext(LexicalDC); |
| LexicalDC->addDeclInternal(ToD); |
| |
| return ToD; |
| } |
| |
| ExpectedDecl |
| ASTNodeImporter::VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias) { |
| // Import the major distinguishing characteristics of this typedef. |
| DeclarationName Name; |
| SourceLocation Loc; |
| NamedDecl *ToD; |
| // Do not import the DeclContext, we will import it once the TypedefNameDecl |
| // is created. |
| if (Error Err = ImportDeclParts(D, Name, ToD, Loc)) |
| return std::move(Err); |
| if (ToD) |
| return ToD; |
| |
| DeclContext *DC = cast_or_null<DeclContext>( |
| Importer.GetAlreadyImportedOrNull(cast<Decl>(D->getDeclContext()))); |
| DeclContext *LexicalDC = |
| cast_or_null<DeclContext>(Importer.GetAlreadyImportedOrNull( |
| cast<Decl>(D->getLexicalDeclContext()))); |
| |
| // If this typedef is not in block scope, determine whether we've |
| // seen a typedef with the same name (that we can merge with) or any |
| // other entity by that name (which name lookup could conflict with). |
| // Note: Repeated typedefs are not valid in C99: |
| // 'typedef int T; typedef int T;' is invalid |
| // We do not care about this now. |
| if (DC && !DC->isFunctionOrMethod()) { |
| SmallVector<NamedDecl *, 4> ConflictingDecls; |
| unsigned IDNS = Decl::IDNS_Ordinary; |
| auto FoundDecls = Importer.findDeclsInToCtx(DC, Name); |
| for (auto *FoundDecl : FoundDecls) { |
| if (!FoundDecl->isInIdentifierNamespace(IDNS)) |
| continue; |
| if (auto *FoundTypedef = dyn_cast<TypedefNameDecl>(FoundDecl)) { |
| if (!hasSameVisibilityContextAndLinkage(FoundTypedef, D)) |
| continue; |
| |
| QualType FromUT = D->getUnderlyingType(); |
| QualType FoundUT = FoundTypedef->getUnderlyingType(); |
| if (Importer.IsStructurallyEquivalent(FromUT, FoundUT)) { |
| // If the "From" context has a complete underlying type but we |
| // already have a complete underlying type then return with that. |
| if (!FromUT->isIncompleteType() && !FoundUT->isIncompleteType()) |
| return Importer.MapImported(D, FoundTypedef); |
| // FIXME Handle redecl chain. When you do that make consistent changes |
| // in ASTImporterLookupTable too. |
| } else { |
| ConflictingDecls.push_back(FoundDecl); |
| } |
| } |
| } |
| |
| if (!ConflictingDecls.empty()) { |
| ExpectedName NameOrErr = Importer.HandleNameConflict( |
| Name, DC, IDNS, ConflictingDecls.data(), ConflictingDecls.size()); |
| if (NameOrErr) |
| Name = NameOrErr.get(); |
| else |
| return NameOrErr.takeError(); |
| } |
| } |
| |
| Error Err = Error::success(); |
| auto ToUnderlyingType = importChecked(Err, D->getUnderlyingType()); |
| auto ToTypeSourceInfo = importChecked(Err, D->getTypeSourceInfo()); |
| auto ToBeginLoc = importChecked(Err, D->getBeginLoc()); |
| if (Err) |
| return std::move(Err); |
| |
| // Create the new typedef node. |
| // FIXME: ToUnderlyingType is not used. |
| (void)ToUnderlyingType; |
| TypedefNameDecl *ToTypedef; |
| if (IsAlias) { |
| if (GetImportedOrCreateDecl<TypeAliasDecl>( |
| ToTypedef, D, Importer.getToContext(), DC, ToBeginLoc, Loc, |
| Name.getAsIdentifierInfo(), ToTypeSourceInfo)) |
| return ToTypedef; |
| } else if (GetImportedOrCreateDecl<TypedefDecl>( |
| ToTypedef, D, Importer.getToContext(), DC, ToBeginLoc, Loc, |
| Name.getAsIdentifierInfo(), ToTypeSourceInfo)) |
| return ToTypedef; |
| |
| // Import the DeclContext and set it to the Typedef. |
| if ((Err = ImportDeclContext(D, DC, LexicalDC))) |
| return std::move(Err); |
| ToTypedef->setDeclContext(DC); |
| ToTypedef->setLexicalDeclContext(LexicalDC); |
| // Add to the lookupTable because we could not do that in MapImported. |
| Importer.AddToLookupTable(ToTypedef); |
| |
| ToTypedef->setAccess(D->getAccess()); |
| |
| // Templated declarations should not appear in DeclContext. |
| TypeAliasDecl *FromAlias = IsAlias ? cast<TypeAliasDecl>(D) : nullptr; |
| if (!FromAlias || !FromAlias->getDescribedAliasTemplate()) |
| LexicalDC->addDeclInternal(ToTypedef); |
| |
| return ToTypedef; |
| } |
| |
| ExpectedDecl ASTNodeImporter::VisitTypedefDecl(TypedefDecl *D) { |
| return VisitTypedefNameDecl(D, /*IsAlias=*/false); |
| } |
| |
| ExpectedDecl ASTNodeImporter::VisitTypeAliasDecl(TypeAliasDecl *D) { |
| return VisitTypedefNameDecl(D, /*IsAlias=*/true); |
| } |
| |
| ExpectedDecl |
| ASTNodeImporter::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) { |
| // Import the major distinguishing characteristics of this typedef. |
| DeclContext *DC, *LexicalDC; |
| DeclarationName Name; |
| SourceLocation Loc; |
| NamedDecl *FoundD; |
| if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, FoundD, Loc)) |
| return std::move(Err); |
| if (FoundD) |
| return FoundD; |
| |
| // If this typedef is not in block scope, determine whether we've |
| // seen a typedef with the same name (that we can merge with) or any |
| // other entity by that name (which name lookup could conflict with). |
| if (!DC->isFunctionOrMethod()) { |
| SmallVector<NamedDecl *, 4> ConflictingDecls; |
| unsigned IDNS = Decl::IDNS_Ordinary; |
| auto FoundDecls = Importer.findDeclsInToCtx(DC, Name); |
| for (auto *FoundDecl : FoundDecls) { |
| if (!FoundDecl->isInIdentifierNamespace(IDNS)) |
| continue; |
| if (auto *FoundAlias = dyn_cast<TypeAliasTemplateDecl>(FoundDecl)) |
| 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); |
| return ToAlias; |
| } |
| |
| ExpectedDecl ASTNodeImporter::VisitLabelDecl(LabelDecl *D) { |
| // Import the major distinguishing characteristics of this label. |
| DeclContext *DC, *LexicalDC; |
| DeclarationName Name; |
| SourceLocation Loc; |
| NamedDecl *ToD; |
| if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) |
| return std::move(Err); |
| if (ToD) |
| return ToD; |
| |
| assert(LexicalDC->isFunctionOrMethod()); |
| |
| LabelDecl *ToLabel; |
| if (D->isGnuLocal()) { |
| ExpectedSLoc BeginLocOrErr = import(D->getBeginLoc()); |
| if (!BeginLocOrErr) |
| return BeginLocOrErr.takeError(); |
| if (GetImportedOrCreateDecl(ToLabel, D, Importer.getToContext(), DC, Loc, |
| Name.getAsIdentifierInfo(), *BeginLocOrErr)) |
| return ToLabel; |
| |
| } else { |
| if (GetImportedOrCreateDecl(ToLabel, D, Importer.getToContext(), DC, Loc, |
| Name.getAsIdentifierInfo())) |
| return ToLabel; |
| |
| } |
| |
| Expected<LabelStmt *> ToStmtOrErr = import(D->getStmt()); |
| if (!ToStmtOrErr) |
| return ToStmtOrErr.takeError(); |
| |
| ToLabel->setStmt(*ToStmtOrErr); |
| ToLabel->setLexicalDeclContext(LexicalDC); |
| LexicalDC->addDeclInternal(ToLabel); |
| return ToLabel; |
| } |
| |
| ExpectedDecl ASTNodeImporter::VisitEnumDecl(EnumDecl *D) { |
| // Import the major distinguishing characteristics of this enum. |
| DeclContext *DC, *LexicalDC; |
| DeclarationName Name; |
| SourceLocation Loc; |
| NamedDecl *ToD; |
| if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) |
| return std::move(Err); |
| if (ToD) |
| return ToD; |
| |
| // Figure out what enum name we're looking for. |
| unsigned IDNS = Decl::IDNS_Tag; |
| DeclarationName SearchName = Name; |
| if (!SearchName && D->getTypedefNameForAnonDecl()) { |
| if (Error Err = importInto( |
| SearchName, D->getTypedefNameForAnonDecl()->getDeclName())) |
| return std::move(Err); |
| IDNS = Decl::IDNS_Ordinary; |
| } else if (Importer.getToContext().getLangOpts().CPlusPlus) |
| IDNS |= Decl::IDNS_Ordinary; |
| |
| // We may already have an enum of the same name; try to find and match it. |
| EnumDecl *PrevDecl = nullptr; |
| if (!DC->isFunctionOrMethod() && SearchName) { |
| SmallVector<NamedDecl *, 4> ConflictingDecls; |
| auto FoundDecls = |
| Importer.findDeclsInToCtx(DC, SearchName); |
| for (auto *FoundDecl : FoundDecls) { |
| if (!FoundDecl->isInIdentifierNamespace(IDNS)) |
| continue; |
| |
| if (auto *Typedef = dyn_cast<TypedefNameDecl>(FoundDecl)) { |
| if (const auto *Tag = Typedef->getUnderlyingType()->getAs<TagType>()) |
| FoundDecl = Tag->getDecl(); |
| } |
| |
| if (auto *FoundEnum = dyn_cast<EnumDecl>(FoundDecl)) { |
| if (!hasSameVisibilityContextAndLinkage(FoundEnum, D)) |
| continue; |
| if (IsStructuralMatch(D, FoundEnum)) { |
| EnumDecl *FoundDef = FoundEnum->getDefinition(); |
| if (D->isThisDeclarationADefinition() && FoundDef) |
| return Importer.MapImported(D, FoundDef); |
| PrevDecl = FoundEnum->getMostRecentDecl(); |
| break; |
| } |
| ConflictingDecls.push_back(FoundDecl); |
| } |
| } |
| |
| if (!ConflictingDecls.empty()) { |
| ExpectedName NameOrErr = Importer.HandleNameConflict( |
| SearchName, DC, IDNS, ConflictingDecls.data(), |
| ConflictingDecls.size()); |
| if (NameOrErr) |
| Name = NameOrErr.get(); |
| else |
| return NameOrErr.takeError(); |
| } |
| } |
| |
| 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); |
| LexicalDC->addDeclInternal(D2); |
| |
| // Import the definition |
| if (D->isCompleteDefinition()) |
| if (Error Err = ImportDefinition(D, D2)) |
| return std::move(Err); |
| |
| return D2; |
| } |
| |
| ExpectedDecl ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { |
| bool IsFriendTemplate = false; |
| if (auto *DCXX = dyn_cast<CXXRecordDecl>(D)) { |
| IsFriendTemplate = |
| DCXX->getDescribedClassTemplate() && |
| DCXX->getDescribedClassTemplate()->getFriendObjectKind() != |
| Decl::FOK_None; |
| } |
| |
| // Import the major distinguishing characteristics of this record. |
| DeclContext *DC = nullptr, *LexicalDC = nullptr; |
| DeclarationName Name; |
| SourceLocation Loc; |
| NamedDecl *ToD = nullptr; |
| if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) |
| return std::move(Err); |
| if (ToD) |
| return ToD; |
| |
| // Figure out what structure name we're looking for. |
| unsigned IDNS = Decl::IDNS_Tag; |
| DeclarationName SearchName = Name; |
| if (!SearchName && D->getTypedefNameForAnonDecl()) { |
| if (Error Err = importInto( |
| SearchName, D->getTypedefNameForAnonDecl()->getDeclName())) |
| return std::move(Err); |
| IDNS = Decl::IDNS_Ordinary; |
| } else if (Importer.getToContext().getLangOpts().CPlusPlus) |
| IDNS |= Decl::IDNS_Ordinary | Decl::IDNS_TagFriend; |
| |
| // We may already have a record of the same name; try to find and match it. |
| RecordDecl *PrevDecl = nullptr; |
| if (!DC->isFunctionOrMethod() && !D->isLambda()) { |
| SmallVector<NamedDecl *, 4> ConflictingDecls; |
| auto FoundDecls = |
| Importer.findDeclsInToCtx(DC, SearchName); |
| if (!FoundDecls.empty()) { |
| // We're going to have to compare D against potentially conflicting Decls, |
| // so complete it. |
| if (D->hasExternalLexicalStorage() && !D->isCompleteDefinition()) |
| D->getASTContext().getExternalSource()->CompleteType(D); |
| } |
| |
| for (auto *FoundDecl : FoundDecls) { |
| if (!FoundDecl->isInIdentifierNamespace(IDNS)) |
| continue; |
| |
| Decl *Found = FoundDecl; |
| if (auto *Typedef = dyn_cast<TypedefNameDecl>(Found)) { |
| if (const auto *Tag = Typedef->getUnderlyingType()->getAs<TagType>()) |
| Found = Tag->getDecl(); |
| } |
| |
| if (auto *FoundRecord = dyn_cast<RecordDecl>(Found)) { |
| // Do not emit false positive diagnostic in case of unnamed |
| // struct/union and in case of anonymous structs. Would be false |
| // because there may be several anonymous/unnamed structs in a class. |
| // E.g. these are both valid: |
| // struct A { // unnamed structs |
| // struct { struct A *next; } entry0; |
| // struct { struct A *next; } entry1; |
| // }; |
| // struct X { struct { int a; }; struct { int b; }; }; // anon structs |
| if (!SearchName) |
| if (!IsStructuralMatch(D, FoundRecord, false)) |
| continue; |
| |
| if (!hasSameVisibilityContextAndLinkage(FoundRecord, D)) |
| continue; |
| |
| if (IsStructuralMatch(D, FoundRecord)) { |
| RecordDecl *FoundDef = FoundRecord->getDefinition(); |
| if (D->isThisDeclarationADefinition() && FoundDef) { |
| // FIXME: Structural equivalence check should check for same |
| // user-defined methods. |
| Importer.MapImported(D, FoundDef); |
| if (const auto *DCXX = dyn_cast<CXXRecordDecl>(D)) { |
| auto *FoundCXX = dyn_cast<CXXRecordDecl>(FoundDef); |
| assert(FoundCXX && "Record type mismatch"); |
| |
| if (!Importer.isMinimalImport()) |
| // FoundDef may not have every implicit method that D has |
| // because implicit methods are created only if they are used. |
| if (Error Err = ImportImplicitMethods(DCXX, FoundCXX)) |
| return std::move(Err); |
| } |
| } |
| PrevDecl = FoundRecord->getMostRecentDecl(); |
| break; |
| } |
| ConflictingDecls.push_back(FoundDecl); |
| } // kind is RecordDecl |
| } // for |
| |
| if (!ConflictingDecls.empty() && SearchName) { |
| ExpectedName NameOrErr = Importer.HandleNameConflict( |
| SearchName, DC, IDNS, ConflictingDecls.data(), |
| ConflictingDecls.size()); |
| if (NameOrErr) |
| Name = NameOrErr.get(); |
| else |
| return NameOrErr.takeError(); |
| } |
| } |
| |
| ExpectedSLoc BeginLocOrErr = import(D->getBeginLoc()); |
| if (!BeginLocOrErr) |
| return BeginLocOrErr.takeError(); |
| |
| // Create the record declaration. |
| RecordDecl *D2 = nullptr; |
| CXXRecordDecl *D2CXX = nullptr; |
| if (auto *DCXX = dyn_cast<CXXRecordDecl>(D)) { |
| if (DCXX->isLambda()) { |
| auto TInfoOrErr = import(DCXX->getLambdaTypeInfo()); |
| if (!TInfoOrErr) |
| return TInfoOrErr.takeError(); |
| if (GetImportedOrCreateSpecialDecl( |
| D2CXX, CXXRecordDecl::CreateLambda, D, Importer.getToContext(), |
| DC, *TInfoOrErr, Loc, DCXX->isDependentLambda(), |
| DCXX->isGenericLambda(), DCXX->getLambdaCaptureDefault())) |
| return D2CXX; |
| ExpectedDecl CDeclOrErr = import(DCXX->getLambdaContextDecl()); |
| if (!CDeclOrErr) |
| return CDeclOrErr.takeError(); |
| D2CXX->setLambdaMangling(DCXX->getLambdaManglingNumber(), *CDeclOrErr, |
| DCXX->hasKnownLambdaInternalLinkage()); |
| D2CXX->setDeviceLambdaManglingNumber( |
| DCXX->getDeviceLambdaManglingNumber()); |
| } else if (DCXX->isInjectedClassName()) { |
| // We have to be careful to do a similar dance to the one in |
| // Sema::ActOnStartCXXMemberDeclarations |
| const bool DelayTypeCreation = true; |
| if (GetImportedOrCreateDecl( |
| D2CXX, D, Importer.getToContext(), D->getTagKind(), DC, |
| *BeginLocOrErr, Loc, Name.getAsIdentifierInfo(), |
| cast_or_null<CXXRecordDecl>(PrevDecl), DelayTypeCreation)) |
| return D2CXX; |
| Importer.getToContext().getTypeDeclType( |
| D2CXX, dyn_cast<CXXRecordDecl>(DC)); |
| } else { |
| if (GetImportedOrCreateDecl(D2CXX, D, Importer.getToContext(), |
| D->getTagKind(), DC, *BeginLocOrErr, Loc, |
| Name.getAsIdentifierInfo(), |
| cast_or_null<CXXRecordDecl>(PrevDecl))) |
| return D2CXX; |
| } |
| |
| D2 = D2CXX; |
| D2->setAccess(D->getAccess()); |
| D2->setLexicalDeclContext(LexicalDC); |
| addDeclToContexts(D, D2); |
| |
| if (ClassTemplateDecl *FromDescribed = |
| DCXX->getDescribedClassTemplate()) { |
| ClassTemplateDecl *ToDescribed; |
| if (Error Err = importInto(ToDescribed, FromDescribed)) |
| return std::move(Err); |
| D2CXX->setDescribedClassTemplate(ToDescribed); |
| if (!DCXX->isInjectedClassName() && !IsFriendTemplate) { |
| // In a record describing a template the type should be an |
| // InjectedClassNameType (see Sema::CheckClassTemplate). Update the |
| // previously set type to the correct value here (ToDescribed is not |
| // available at record create). |
| // FIXME: The previous type is cleared but not removed from |
| // ASTContext's internal storage. |
| CXXRecordDecl *Injected = nullptr; |
| for (NamedDecl *Found : D2CXX->noload_lookup(Name)) { |
| auto *Record = dyn_cast<CXXRecordDecl>(Found); |
| if (Record && Record->isInjectedClassName()) { |
| Injected = Record; |
| break; |
| } |
| } |
| // Create an injected type for the whole redecl chain. |
| SmallVector<Decl *, 2> Redecls = |
| getCanonicalForwardRedeclChain(D2CXX); |
| for (auto *R : Redecls) { |
| auto *RI = cast<CXXRecordDecl>(R); |
| RI->setTypeForDecl(nullptr); |
| // Below we create a new injected type and assign that to the |
| // canonical decl, subsequent declarations in the chain will reuse |
| // that type. |
| Importer.getToContext().getInjectedClassNameType( |
| RI, ToDescribed->getInjectedClassNameSpecialization()); |
| } |
| // Set the new type for the previous injected decl too. |
| if (Injected) { |
| Injected->setTypeForDecl(nullptr); |
| Importer.getToContext().getTypeDeclType(Injected, D2CXX); |
| } |
| } |
| } else if (MemberSpecializationInfo *MemberInfo = |
| DCXX->getMemberSpecializationInfo()) { |
| TemplateSpecializationKind SK = |
| MemberInfo->getTemplateSpecializationKind(); |
| CXXRecordDecl *FromInst = DCXX->getInstantiatedFromMemberClass(); |
| |
| if (Expected<CXXRecordDecl *> ToInstOrErr = import(FromInst)) |
| D2CXX->setInstantiationOfMemberClass(*ToInstOrErr, SK); |
| else |
| return ToInstOrErr.takeError(); |
| |
| if (ExpectedSLoc POIOrErr = |
| import(MemberInfo->getPointOfInstantiation())) |
| D2CXX->getMemberSpecializationInfo()->setPointOfInstantiation( |
| *POIOrErr); |
| else |
| return POIOrErr.takeError(); |
| } |
| |
| } else { |
| if (GetImportedOrCreateDecl(D2, D, Importer.getToContext(), |
| D->getTagKind(), DC, *BeginLocOrErr, Loc, |
| Name.getAsIdentifierInfo(), PrevDecl)) |
| return D2; |
| D2->setLexicalDeclContext(LexicalDC); |
| addDeclToContexts(D, D2); |
| } |
| |
| if (auto BraceRangeOrErr = import(D->getBraceRange())) |
| D2->setBraceRange(*BraceRangeOrErr); |
| else |
| return BraceRangeOrErr.takeError(); |
| if (auto QualifierLocOrErr = import(D->getQualifierLoc())) |
| D2->setQualifierInfo(*QualifierLocOrErr); |
| else |
| return QualifierLocOrErr.takeError(); |
| |
| if (D->isAnonymousStructOrUnion()) |
| D2->setAnonymousStructOrUnion(true); |
| |
| if (D->isCompleteDefinition()) |
| if (Error Err = ImportDefinition(D, D2, IDK_Default)) |
| return std::move(Err); |
| |
| return D2; |
| } |
| |
| ExpectedDecl ASTNodeImporter::VisitEnumConstantDecl(EnumConstantDecl *D) { |
| // Import the major distinguishing characteristics of this enumerator. |
| DeclContext *DC, *LexicalDC; |
| DeclarationName Name; |
| SourceLocation Loc; |
| NamedDecl *ToD; |
| if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) |
| return std::move(Err); |
| if (ToD) |
| return ToD; |
| |
| // Determine whether there are any other declarations with the same name and |
| // in the same context. |
| if (!LexicalDC->isFunctionOrMethod()) { |
| SmallVector<NamedDecl *, 4> ConflictingDecls; |
| unsigned IDNS = Decl::IDNS_Ordinary; |
| auto FoundDecls = Importer.findDeclsInToCtx(DC, Name); |
| for (auto *FoundDecl : FoundDecls) { |
| if (!FoundDecl->isInIdentifierNamespace(IDNS)) |
| continue; |
| |
| if (auto *FoundEnumConstant = dyn_cast<EnumConstantDecl>(FoundDecl)) { |
| if (IsStructuralMatch(D, FoundEnumConstant)) |
| return Importer.MapImported(D, FoundEnumConstant); |
| ConflictingDecls.push_back(FoundDecl); |
| } |
| } |
| |
| if (!ConflictingDecls.empty()) { |
| ExpectedName NameOrErr = Importer.HandleNameConflict( |
| Name, DC, IDNS, ConflictingDecls.data(), ConflictingDecls.size()); |
| if (NameOrErr) |
| Name = NameOrErr.get(); |
| else |
| return NameOrErr.takeError(); |
| } |
| } |
| |
| ExpectedType TypeOrErr = import(D->getType()); |
| if (!TypeOrErr) |
| return TypeOrErr.takeError(); |
| |
| ExpectedExpr InitOrErr = import(D->getInitExpr()); |
| if (!InitOrErr) |
| return InitOrErr.takeError(); |
| |
| EnumConstantDecl *ToEnumerator; |
| if (GetImportedOrCreateDecl( |
| ToEnumerator, D, Importer.getToContext(), cast<EnumDecl>(DC), Loc, |
| Name.getAsIdentifierInfo(), *TypeOrErr, *InitOrErr, D->getInitVal())) |
| return ToEnumerator; |
| |
| ToEnumerator->setAccess(D->getAccess()); |
| ToEnumerator->setLexicalDeclContext(LexicalDC); |
| LexicalDC->addDeclInternal(ToEnumerator); |
| return ToEnumerator; |
| } |
| |
| Error ASTNodeImporter::ImportTemplateParameterLists(const DeclaratorDecl *FromD, |
| DeclaratorDecl *ToD) { |
| unsigned int Num = FromD->getNumTemplateParameterLists(); |
| if (Num == 0) |
| return Error::success(); |
| SmallVector<TemplateParameterList *, 2> ToTPLists(Num); |
| for (unsigned int I = 0; I < Num; ++I) |
| if (Expected<TemplateParameterList *> ToTPListOrErr = |
| import(FromD->getTemplateParameterList(I))) |
| ToTPLists[I] = *ToTPListOrErr; |
| else |
| return ToTPListOrErr.takeError(); |
| ToD->setTemplateParameterListsInfo(Importer.ToContext, ToTPLists); |
| return Error::success(); |
| } |
| |
| Error ASTNodeImporter::ImportTemplateInformation( |
| FunctionDecl *FromFD, FunctionDecl *ToFD) { |
| switch (FromFD->getTemplatedKind()) { |
| case FunctionDecl::TK_NonTemplate: |
| case FunctionDecl::TK_FunctionTemplate: |
| return Error::success(); |
| |
| case FunctionDecl::TK_MemberSpecialization: { |
| TemplateSpecializationKind TSK = FromFD->getTemplateSpecializationKind(); |
| |
| if (Expected<FunctionDecl *> InstFDOrErr = |
| import(FromFD->getInstantiatedFromMemberFunction())) |
| ToFD->setInstantiationOfMemberFunction(*InstFDOrErr, TSK); |
| else |
| return InstFDOrErr.takeError(); |
| |
| if (ExpectedSLoc POIOrErr = import( |
| FromFD->getMemberSpecializationInfo()->getPointOfInstantiation())) |
| ToFD->getMemberSpecializationInfo()->setPointOfInstantiation(*POIOrErr); |
| else |
| return POIOrErr.takeError(); |
| |
| return Error::success(); |
| } |
| |
| case FunctionDecl::TK_FunctionTemplateSpecialization: { |
| auto FunctionAndArgsOrErr = |
| ImportFunctionTemplateWithTemplateArgsFromSpecialization(FromFD); |
| if (!FunctionAndArgsOrErr) |
| return FunctionAndArgsOrErr.takeError(); |
| |
| TemplateArgumentList *ToTAList = TemplateArgumentList::CreateCopy( |
| Importer.getToContext(), std::get<1>(*FunctionAndArgsOrErr)); |
| |
| auto *FTSInfo = FromFD->getTemplateSpecializationInfo(); |
| TemplateArgumentListInfo ToTAInfo; |
| const auto *FromTAArgsAsWritten = FTSInfo->TemplateArgumentsAsWritten; |
| if (FromTAArgsAsWritten) |
| if (Error Err = ImportTemplateArgumentListInfo( |
| *FromTAArgsAsWritten, ToTAInfo)) |
| return Err; |
| |
| ExpectedSLoc POIOrErr = import(FTSInfo->getPointOfInstantiation()); |
| if (!POIOrErr) |
| return POIOrErr.takeError(); |
| |
| if (Error Err = ImportTemplateParameterLists(FromFD, ToFD)) |
| return Err; |
| |
| TemplateSpecializationKind TSK = FTSInfo->getTemplateSpecializationKind(); |
| ToFD->setFunctionTemplateSpecialization( |
| std::get<0>(*FunctionAndArgsOrErr), ToTAList, /* InsertPos= */ nullptr, |
| TSK, FromTAArgsAsWritten ? &ToTAInfo : nullptr, *POIOrErr); |
| return Error::success(); |
| } |
| |
| case FunctionDecl::TK_DependentFunctionTemplateSpecialization: { |
| auto *FromInfo = FromFD->getDependentSpecializationInfo(); |
| UnresolvedSet<8> TemplDecls; |
| unsigned NumTemplates = FromInfo->getNumTemplates(); |
| for (unsigned I = 0; I < NumTemplates; I++) { |
| if (Expected<FunctionTemplateDecl *> ToFTDOrErr = |
| import(FromInfo->getTemplate(I))) |
| TemplDecls.addDecl(*ToFTDOrErr); |
| else |
| return ToFTDOrErr.takeError(); |
| } |
| |
| // Import TemplateArgumentListInfo. |
| TemplateArgumentListInfo ToTAInfo; |
| if (Error Err = ImportTemplateArgumentListInfo( |
| FromInfo->getLAngleLoc(), FromInfo->getRAngleLoc(), |
| llvm::makeArrayRef( |
| FromInfo->getTemplateArgs(), FromInfo->getNumTemplateArgs()), |
| ToTAInfo)) |
| return Err; |
| |
| ToFD->setDependentTemplateSpecialization(Importer.getToContext(), |
| TemplDecls, ToTAInfo); |
| return Error::success(); |
| } |
| } |
| llvm_unreachable("All cases should be covered!"); |
| } |
| |
| Expected<FunctionDecl *> |
| ASTNodeImporter::FindFunctionTemplateSpecialization(FunctionDecl *FromFD) { |
| auto FunctionAndArgsOrErr = |
| ImportFunctionTemplateWithTemplateArgsFromSpecialization(FromFD); |
| if (!FunctionAndArgsOrErr) |
| return FunctionAndArgsOrErr.takeError(); |
| |
| FunctionTemplateDecl *Template; |
| TemplateArgsTy ToTemplArgs; |
| std::tie(Template, ToTemplArgs) = *FunctionAndArgsOrErr; |
| void *InsertPos = nullptr; |
| auto *FoundSpec = Template->findSpecialization(ToTemplArgs, InsertPos); |
| return FoundSpec; |
| } |
| |
| Error ASTNodeImporter::ImportFunctionDeclBody(FunctionDecl *FromFD, |
| FunctionDecl *ToFD) { |
| if (Stmt *FromBody = FromFD->getBody()) { |
| if (ExpectedStmt ToBodyOrErr = import(FromBody)) |
| ToFD->setBody(*ToBodyOrErr); |
| else |
| return ToBodyOrErr.takeError(); |
| } |
| return Error::success(); |
| } |
| |
| // Returns true if the given D has a DeclContext up to the TranslationUnitDecl |
| // which is equal to the given DC. |
| static bool isAncestorDeclContextOf(const DeclContext *DC, const Decl *D) { |
| const DeclContext *DCi = D->getDeclContext(); |
| while (DCi != D->getTranslationUnitDecl()) { |
| if (DCi == DC) |
| return true; |
| DCi = DCi->getParent(); |
| } |
| return false; |
| } |
| |
| bool ASTNodeImporter::hasAutoReturnTypeDeclaredInside(FunctionDecl *D) { |
| QualType FromTy = D->getType(); |
| const FunctionProtoType *FromFPT = FromTy->getAs<FunctionProtoType>(); |
| assert(FromFPT && "Must be called on FunctionProtoType"); |
| if (AutoType *AutoT = FromFPT->getReturnType()->getContainedAutoType()) { |
| QualType DeducedT = AutoT->getDeducedType(); |
| if (const RecordType *RecordT = |
| DeducedT.isNull() ? nullptr : dyn_cast<RecordType>(DeducedT)) { |
| RecordDecl *RD = RecordT->getDecl(); |
| assert(RD); |
| if (isAncestorDeclContextOf(D, RD)) { |
| assert(RD->getLexicalDeclContext() == RD->getDeclContext()); |
| return true; |
| } |
| } |
| } |
| if (const TypedefType *TypedefT = |
| dyn_cast<TypedefType>(FromFPT->getReturnType())) { |
| TypedefNameDecl *TD = TypedefT->getDecl(); |
| assert(TD); |
| if (isAncestorDeclContextOf(D, TD)) { |
| assert(TD->getLexicalDeclContext() == TD->getDeclContext()); |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| ExplicitSpecifier |
| ASTNodeImporter::importExplicitSpecifier(Error &Err, ExplicitSpecifier ESpec) { |
| Expr *ExplicitExpr = ESpec.getExpr(); |
| if (ExplicitExpr) |
| ExplicitExpr = importChecked(Err, ESpec.getExpr()); |
| return ExplicitSpecifier(ExplicitExpr, ESpec.getKind()); |
| } |
| |
| ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { |
| |
| SmallVector<Decl *, 2> Redecls = getCanonicalForwardRedeclChain(D); |
| auto RedeclIt = Redecls.begin(); |
| // Import the first part of the decl chain. I.e. import all previous |
| // declarations starting from the canonical decl. |
| for (; RedeclIt != Redecls.end() && *RedeclIt != D; ++RedeclIt) { |
| ExpectedDecl ToRedeclOrErr = import(*RedeclIt); |
| if (!ToRedeclOrErr) |
| return ToRedeclOrErr.takeError(); |
| } |
| assert(*RedeclIt == D); |
| |
| // Import the major distinguishing characteristics of this function. |
| DeclContext *DC, *LexicalDC; |
| DeclarationName Name; |
| SourceLocation Loc; |
| NamedDecl *ToD; |
| if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) |
| return std::move(Err); |
| if (ToD) |
| return ToD; |
| |
| FunctionDecl *FoundByLookup = nullptr; |
| FunctionTemplateDecl *FromFT = D->getDescribedFunctionTemplate(); |
| |
| // If this is a function template specialization, then try to find the same |
| // existing specialization in the "to" context. The lookup below will not |
| // find any specialization, but would find the primary template; thus, we |
| // have to skip normal lookup in case of specializations. |
| // FIXME handle member function templates (TK_MemberSpecialization) similarly? |
| if (D->getTemplatedKind() == |
| FunctionDecl::TK_FunctionTemplateSpecialization) { |
| auto FoundFunctionOrErr = FindFunctionTemplateSpecialization(D); |
| if (!FoundFunctionOrErr) |
| return FoundFunctionOrErr.takeError(); |
| if (FunctionDecl *FoundFunction = *FoundFunctionOrErr) { |
| if (Decl *Def = FindAndMapDefinition(D, FoundFunction)) |
| return Def; |
| FoundByLookup = FoundFunction; |
| } |
| } |
| // Try to find a function in our own ("to") context with the same name, same |
| // type, and in the same context as the function we're importing. |
| else if (!LexicalDC->isFunctionOrMethod()) { |
| SmallVector<NamedDecl *, 4> ConflictingDecls; |
| unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_OrdinaryFriend; |
| auto FoundDecls = Importer.findDeclsInToCtx(DC, Name); |
| for (auto *FoundDecl : FoundDecls) { |
| if (!FoundDecl->isInIdentifierNamespace(IDNS)) |
| continue; |
| |
| if (auto *FoundFunction = dyn_cast<FunctionDecl>(FoundDecl)) { |
| if (!hasSameVisibilityContextAndLinkage(FoundFunction, D)) |
| continue; |
| |
| if (IsStructuralMatch(D, FoundFunction)) { |
| if (Decl *Def = FindAndMapDefinition(D, FoundFunction)) |
| return Def; |
| FoundByLookup = FoundFunction; |
| break; |
| } |
| // FIXME: Check for overloading more carefully, e.g., by boosting |
| // Sema::IsOverload out to the AST library. |
| |
| // Function overloading is okay in C++. |
| if (Importer.getToContext().getLangOpts().CPlusPlus) |
| continue; |
| |
| // Complain about inconsistent function types. |
| Importer.ToDiag(Loc, diag::warn_odr_function_type_inconsistent) |
| << Name << D->getType() << FoundFunction->getType(); |
| Importer.ToDiag(FoundFunction->getLocation(), diag::note_odr_value_here) |
| << FoundFunction->getType(); |
| ConflictingDecls.push_back(FoundDecl); |
| } |
| } |
| |
| if (!ConflictingDecls.empty()) { |
| ExpectedName NameOrErr = Importer.HandleNameConflict( |
| Name, DC, IDNS, ConflictingDecls.data(), ConflictingDecls.size()); |
| if (NameOrErr) |
| Name = NameOrErr.get(); |
| else |
| return NameOrErr.takeError(); |
| } |
| } |
| |
| // We do not allow more than one in-class declaration of a function. This is |
| // because AST clients like VTableBuilder asserts on this. VTableBuilder |
| // assumes there is only one in-class declaration. Building a redecl |
| // chain would result in more than one in-class declaration for |
| // overrides (even if they are part of the same redecl chain inside the |
| // derived class.) |
| if (FoundByLookup) { |
| if (isa<CXXMethodDecl>(FoundByLookup)) { |
| if (D->getLexicalDeclContext() == D->getDeclContext()) { |
| if (!D->doesThisDeclarationHaveABody()) { |
| if (FunctionTemplateDecl *DescribedD = |
| D->getDescribedFunctionTemplate()) { |
| // Handle a "templated" function together with its described |
| // template. This avoids need for a similar check at import of the |
| // described template. |
| assert(FoundByLookup->getDescribedFunctionTemplate() && |
| "Templated function mapped to non-templated?"); |
| Importer.MapImported(DescribedD, |
| FoundByLookup->getDescribedFunctionTemplate()); |
| } |
| return Importer.MapImported(D, FoundByLookup); |
| } else { |
| // Let's continue and build up the redecl chain in this case. |
| // FIXME Merge the functions into one decl. |
| } |
| } |
| } |
| } |
| |
| DeclarationNameInfo NameInfo(Name, Loc); |
| // Import additional name location/type info. |
| if (Error Err = ImportDeclarationNameLoc(D->getNameInfo(), NameInfo)) |
| return std::move(Err); |
| |
| QualType FromTy = D->getType(); |
| // 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. |
| bool UsedDifferentProtoType = false; |
| if (const auto *FromFPT = FromTy->getAs<FunctionProtoType>()) { |
| QualType FromReturnTy = FromFPT->getReturnType(); |
| // Functions with auto return type may define a struct inside their body |
| // and the return type could refer to that struct. |
| // E.g.: auto foo() { struct X{}; return X(); } |
| // To avoid an infinite recursion when importing, create the FunctionDecl |
| // with a simplified return type. |
| if (hasAutoReturnTypeDeclaredInside(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); |
| } |
| |
| Error Err = Error::success(); |
| auto T = importChecked(Err, FromTy); |
| auto TInfo = importChecked(Err, D->getTypeSourceInfo()); |
| auto ToInnerLocStart = importChecked(Err, D->getInnerLocStart()); |
| auto ToEndLoc = importChecked(Err, D->getEndLoc()); |
| auto ToQualifierLoc = importChecked(Err, D->getQualifierLoc()); |
| auto TrailingRequiresClause = |
| importChecked(Err, D->getTrailingRequiresClause()); |
| if (Err) |
| return std::move(Err); |
| |
| // Import the function parameters. |
| SmallVector<ParmVarDecl *, 8> Parameters; |
| for (auto P : D->parameters()) { |
| if (Expected<ParmVarDecl *> ToPOrErr = import(P)) |
| Parameters.push_back(*ToPOrErr); |
| else |
| return ToPOrErr.takeError(); |
| } |
| |
| // Create the imported function. |
| FunctionDecl *ToFunction = nullptr; |
| if (auto *FromConstructor = dyn_cast<CXXConstructorDecl>(D)) { |
| ExplicitSpecifier ESpec = |
| importExplicitSpecifier(Err, FromConstructor->getExplicitSpecifier()); |
| if (Err) |
| return std::move(Err); |
| if (GetImportedOrCreateDecl<CXXConstructorDecl>( |
| ToFunction, D, Importer.getToContext(), cast<CXXRecordDecl>(DC), |
| ToInnerLocStart, NameInfo, T, TInfo, ESpec, D->isInlineSpecified(), |
| D->isImplicit(), D->getConstexprKind(), |
| InheritedConstructor(), // FIXME: Properly import inherited |
| // constructor info |
| TrailingRequiresClause)) |
| return ToFunction; |
| } else if (CXXDestructorDecl *FromDtor = dyn_cast<CXXDestructorDecl>(D)) { |
| |
| Error Err = Error::success(); |
| auto ToOperatorDelete = importChecked( |
| Err, const_cast<FunctionDecl *>(FromDtor->getOperatorDelete())); |
| auto ToThisArg = importChecked(Err, FromDtor->getOperatorDeleteThisArg()); |
| if (Err) |
| return std::move(Err); |
| |
| if (GetImportedOrCreateDecl<CXXDestructorDecl>( |
| ToFunction, D, Importer.getToContext(), cast<CXXRecordDecl>(DC), |
| ToInnerLocStart, NameInfo, T, TInfo, D->isInlineSpecified(), |
| D->isImplicit(), D->getConstexprKind(), TrailingRequiresClause)) |
| return ToFunction; |
| |
| CXXDestructorDecl *ToDtor = cast<CXXDestructorDecl>(ToFunction); |
| |
| ToDtor->setOperatorDelete(ToOperatorDelete, ToThisArg); |
| } else if (CXXConversionDecl *FromConversion = |
| dyn_cast<CXXConversionDecl>(D)) { |
| ExplicitSpecifier ESpec = |
| importExplicitSpecifier(Err, FromConversion->getExplicitSpecifier()); |
| if (Err) |
| return std::move(Err); |
| if (GetImportedOrCreateDecl<CXXConversionDecl>( |
| ToFunction, D, Importer.getToContext(), cast<CXXRecordDecl>(DC), |
| ToInnerLocStart, NameInfo, T, TInfo, D->isInlineSpecified(), ESpec, |
| D->getConstexprKind(), SourceLocation(), TrailingRequiresClause)) |
| return ToFunction; |
| } else if (auto *Method = dyn_cast<CXXMethodDecl>(D)) { |
| if (GetImportedOrCreateDecl<CXXMethodDecl>( |
| ToFunction, D, Importer.getToContext(), cast<CXXRecordDecl>(DC), |
| ToInnerLocStart, NameInfo, T, TInfo, Method->getStorageClass(), |
| Method->isInlineSpecified(), D->getConstexprKind(), |
| SourceLocation(), TrailingRequiresClause)) |
| return ToFunction; |
| } else if (auto *Guide = dyn_cast<CXXDeductionGuideDecl>(D)) { |
| ExplicitSpecifier ESpec = |
| importExplicitSpecifier(Err, Guide->getExplicitSpecifier()); |
| if (Err) |
| return std::move(Err); |
| if (GetImportedOrCreateDecl<CXXDeductionGuideDecl>( |
| ToFunction, D, Importer.getToContext(), DC, ToInnerLocStart, ESpec, |
| NameInfo, T, TInfo, ToEndLoc)) |
| return ToFunction; |
| cast<CXXDeductionGuideDecl>(ToFunction) |
| ->setIsCopyDeductionCandidate(Guide->isCopyDeductionCandidate()); |
| } else { |
| if (GetImportedOrCreateDecl( |
| ToFunction, D, Importer.getToContext(), DC, ToInnerLocStart, |
| NameInfo, T, TInfo, D->getStorageClass(), D->isInlineSpecified(), |
| D->hasWrittenPrototype(), D->getConstexprKind(), |
| TrailingRequiresClause)) |
| return ToFunction; |
| } |
| |
| // Connect the redecl chain. |
| if (FoundByLookup) { |
| auto *Recent = const_cast<FunctionDecl *>( |
| FoundByLookup->getMostRecentDecl()); |
| ToFunction->setPreviousDecl(Recent); |
| // FIXME Probably we should merge exception specifications. E.g. In the |
| // "To" context the existing function may have exception specification with |
| // noexcept-unevaluated, while the newly imported function may have an |
| // evaluated noexcept. A call to adjustExceptionSpec() on the imported |
| // decl and its redeclarations may be required. |
| } |
| |
| ToFunction->setQualifierInfo(ToQualifierLoc); |
| ToFunction->setAccess(D->getAccess()); |
| ToFunction->setLexicalDeclContext(LexicalDC); |
| ToFunction->setVirtualAsWritten(D->isVirtualAsWritten()); |
| ToFunction->setTrivial(D->isTrivial()); |
| ToFunction->setPure(D->isPure()); |
| ToFunction->setDefaulted(D->isDefaulted()); |
| ToFunction->setExplicitlyDefaulted(D->isExplicitlyDefaulted()); |
| ToFunction->setDeletedAsWritten(D->isDeletedAsWritten()); |
| ToFunction->setRangeEnd(ToEndLoc); |
| |
| // Set the parameters. |
| for (auto *Param : Parameters) { |
| Param->setOwningFunction(ToFunction); |
| ToFunction->addDeclInternal(Param); |
| } |
| ToFunction->setParams(Parameters); |
| |
| // We need to complete creation of FunctionProtoTypeLoc manually with setting |
| // params it refers to. |
| if (TInfo) { |
| if (auto ProtoLoc = |
| TInfo->getTypeLoc().IgnoreParens().getAs<FunctionProtoTypeLoc>()) { |
| for (unsigned I = 0, N = Parameters.size(); I != N; ++I) |
| ProtoLoc.setParam(I, Parameters[I]); |
| } |
| } |
| |
| // Import the describing template function, if any. |
| if (FromFT) { |
| auto ToFTOrErr = import(FromFT); |
| if (!ToFTOrErr) |
| return ToFTOrErr.takeError(); |
| } |
| |
| // Import Ctor initializers. |
| if (auto *FromConstructor = dyn_cast<CXXConstructorDecl>(D)) { |
| if (unsigned NumInitializers = FromConstructor->getNumCtorInitializers()) { |
| SmallVector<CXXCtorInitializer *, 4> CtorInitializers(NumInitializers); |
| // Import first, then allocate memory and copy if there was no error. |
| if (Error Err = ImportContainerChecked( |
| FromConstructor->inits(), CtorInitializers)) |
| return std::move(Err); |
| auto **Memory = |
| new (Importer.getToContext()) CXXCtorInitializer *[NumInitializers]; |
| std::copy(CtorInitializers.begin(), CtorInitializers.end(), Memory); |
| auto *ToCtor = cast<CXXConstructorDecl>(ToFunction); |
| ToCtor->setCtorInitializers(Memory); |
| ToCtor->setNumCtorInitializers(NumInitializers); |
| } |
| } |
| |
| if (D->doesThisDeclarationHaveABody()) { |
| Error Err = ImportFunctionDeclBody(D, ToFunction); |
| |
| if (Err) |
| return std::move(Err); |
| } |
| |
| // 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(); |
| } |
| |
| // FIXME: Other bits to merge? |
| |
| // If it is a template, import all related things. |
| if (Error Err = ImportTemplateInformation(D, ToFunction)) |
| return std::move(Err); |
| |
| addDeclToContexts(D, ToFunction); |
| |
| if (auto *FromCXXMethod = dyn_cast<CXXMethodDecl>(D)) |
| if (Error Err = ImportOverriddenMethods(cast<CXXMethodDecl>(ToFunction), |
| FromCXXMethod)) |
| return std::move(Err); |
| |
| // Import the rest of the chain. I.e. import all subsequent declarations. |
| for (++RedeclIt; RedeclIt != Redecls.end(); ++RedeclIt) { |
| ExpectedDecl ToRedeclOrErr = import(*RedeclIt); |
| if (!ToRedeclOrErr) |
| return ToRedeclOrErr.takeError(); |
| } |
| |
| return ToFunction; |
| } |
| |
| ExpectedDecl ASTNodeImporter::VisitCXXMethodDecl(CXXMethodDecl *D) { |
| return VisitFunctionDecl(D); |
| } |
| |
| ExpectedDecl ASTNodeImporter::VisitCXXConstructorDecl(CXXConstructorDecl *D) { |
| return VisitCXXMethodDecl(D); |
| } |
| |
| ExpectedDecl ASTNodeImporter::VisitCXXDestructorDecl(CXXDestructorDecl *D) { |
| return VisitCXXMethodDecl(D); |
| } |
| |
| ExpectedDecl ASTNodeImporter::VisitCXXConversionDecl(CXXConversionDecl *D) { |
| return VisitCXXMethodDecl(D); |
| } |
| |
| ExpectedDecl |
| ASTNodeImporter::VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D) { |
| return VisitFunctionDecl(D); |
| } |
| |
| ExpectedDecl ASTNodeImporter::VisitFieldDecl(FieldDecl *D) { |
| // Import the major distinguishing characteristics of a variable. |
| DeclContext *DC, *LexicalDC; |
| DeclarationName Name; |
| SourceLocation Loc; |
| NamedDecl *ToD; |
| if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) |
| return std::move(Err); |
| if (ToD) |
| return ToD; |
| |
| // Determine whether we've already imported this field. |
| auto FoundDecls = Importer.findDeclsInToCtx(DC, Name); |
| for (auto *FoundDecl : FoundDecls) { |
| if (FieldDecl *FoundField = dyn_cast<FieldDecl>(FoundDecl)) { |
| // For anonymous fields, match up by index. |
| if (!Name && |
| ASTImporter::getFieldIndex(D) != |
| ASTImporter::getFieldIndex(FoundField)) |
| continue; |
| |
| if (Importer.IsStructurallyEquivalent(D->getType(), |
| FoundField->getType())) { |
| Importer.MapImported(D, FoundField); |
| // In case of a FieldDecl of a ClassTemplateSpecializationDecl, the |
| // initializer of a FieldDecl might not had been instantiated in the |
| // "To" context. However, the "From" context might instantiated that, |
| // thus we have to merge that. |
| if (Expr *FromInitializer = D->getInClassInitializer()) { |
| // We don't have yet the initializer set. |
| if (FoundField->hasInClassInitializer() && |
| !FoundField->getInClassInitializer()) { |
| if (ExpectedExpr ToInitializerOrErr = import(FromInitializer)) |
| FoundField->setInClassInitializer(*ToInitializerOrErr); |
| else { |
| // We can't return error here, |
| // since we already mapped D as imported. |
| // FIXME: warning message? |
| consumeError(ToInitializerOrErr.takeError()); |
| return FoundField; |
| } |
| } |
| } |
| return FoundField; |
| } |
| |
| // FIXME: Why is this case not handled with calling HandleNameConflict? |
| Importer.ToDiag(Loc, diag::warn_odr_field_type_inconsistent) |
| << Name << D->getType() << FoundField->getType(); |
| Importer.ToDiag(FoundField->getLocation(), diag::note_odr_value_here) |
| << FoundField->getType(); |
| |
| return make_error<ImportError>(ImportError::NameConflict); |
| } |
| } |
| |
| 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()); |
| auto ToInitializer = importChecked(Err, D->getInClassInitializer()); |
| if (Err) |
| return std::move(Err); |
| |
| FieldDecl *ToField; |
| if (GetImportedOrCreateDecl(ToField, D, Importer.getToContext(), DC, |
| ToInnerLocStart, Loc, Name.getAsIdentifierInfo(), |
| ToType, ToTInfo, ToBitWidth, D->isMutable(), |
| D->getInClassInitStyle())) |
| return ToField; |
| |
| ToField->setAccess(D->getAccess()); |
| ToField->setLexicalDeclContext(LexicalDC); |
| if (ToInitializer) |
| ToField->setInClassInitializer(ToInitializer); |
| ToField->setImplicit(D->isImplicit()); |
| LexicalDC->addDeclInternal(ToField); |
| return ToField; |
| } |
| |
| ExpectedDecl ASTNodeImporter::VisitIndirectFieldDecl(IndirectFieldDecl *D) { |
| // Import the major distinguishing characteristics of a variable. |
| DeclContext *DC, *LexicalDC; |
| DeclarationName Name; |
| SourceLocation Loc; |
| NamedDecl *ToD; |
| if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) |
| return std::move(Err); |
| if (ToD) |
| return ToD; |
| |
| // Determine whether we've already imported this field. |
| auto FoundDecls = Importer.findDeclsInToCtx(DC, Name); |
| for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { |
| if (auto *FoundField = dyn_cast<IndirectFieldDecl>(FoundDecls[I])) { |
| // For anonymous indirect fields, match up by index. |
| if (!Name && |
| ASTImporter::getFieldIndex(D) != |
| ASTImporter::getFieldIndex(FoundField)) |
| continue; |
| |
| if (Importer.IsStructurallyEquivalent(D->getType(), |
| FoundField->getType(), |
| !Name.isEmpty())) { |
| Importer.MapImported(D, FoundField); |
| return FoundField; |
| } |
| |
| // If there are more anonymous fields to check, continue. |
| if (!Name && I < N-1) |
| continue; |
| |
| // FIXME: Why is this case not handled with calling HandleNameConflict? |
| Importer.ToDiag(Loc, diag::warn_odr_field_type_inconsistent) |
| << Name << D->getType() << FoundField->getType(); |
| Importer.ToDiag(FoundField->getLocation(), diag::note_odr_value_here) |
| << FoundField->getType(); |
| |
| return make_error<ImportError>(ImportError::NameConflict); |
| } |
| } |
| |
| // Import the type. |
| auto TypeOrErr = import(D->getType()); |
| if (!TypeOrErr) |
| return TypeOrErr.takeError(); |
| |
| auto **NamedChain = |
| new (Importer.getToContext()) NamedDecl*[D->getChainingSize()]; |
| |
| unsigned i = 0; |
| for (auto *PI : D->chain()) |
| if (Expected<NamedDecl *> ToD = import(PI)) |
| NamedChain[i++] = *ToD; |
| else |
| return ToD.takeError(); |
| |
| llvm::MutableArrayRef<NamedDecl *> CH = {NamedChain, D->getChainingSize()}; |
| IndirectFieldDecl *ToIndirectField; |
| if (GetImportedOrCreateDecl(ToIndirectField, D, Importer.getToContext(), DC, |
| Loc, Name.getAsIdentifierInfo(), *TypeOrErr, CH)) |
| // FIXME here we leak `NamedChain` which is allocated before |
| return ToIndirectField; |
| |
| ToIndirectField->setAccess(D->getAccess()); |
| ToIndirectField->setLexicalDeclContext(LexicalDC); |
| LexicalDC->addDeclInternal(ToIndirectField); |
| return ToIndirectField; |
| } |
| |
| /// Used as return type of getFriendCountAndPosition. |
| struct FriendCountAndPosition { |
| /// Number of similar looking friends. |
| unsigned int TotalCount; |
| /// Index of the specific FriendDecl. |
| unsigned int IndexOfDecl; |
| }; |
| |
| template <class T> |
| static FriendCountAndPosition getFriendCountAndPosition( |
| const FriendDecl *FD, |
| llvm::function_ref<T(const FriendDecl *)> GetCanTypeOrDecl) { |
| unsigned int FriendCount = 0; |
| llvm::Optional<unsigned int> FriendPosition; |
| const auto *RD = cast<CXXRecordDecl>(FD->getLexicalDeclContext()); |
| |
| T TypeOrDecl = GetCanTypeOrDecl(FD); |
| |
| for (const FriendDecl *FoundFriend : RD->friends()) { |
| if (FoundFriend == FD) { |
| FriendPosition = FriendCount; |
| ++FriendCount; |
| } else if (!FoundFriend->getFriendDecl() == !FD->getFriendDecl() && |
| GetCanTypeOrDecl(FoundFriend) == TypeOrDecl) { |
| ++FriendCount; |
| } |
| } |
| |
| assert(FriendPosition && "Friend decl not found in own parent."); |
| |
| return {FriendCount, *FriendPosition}; |
| } |
| |
| static FriendCountAndPosition getFriendCountAndPosition(const FriendDecl *FD) { |
| if (FD->getFriendType()) |
| return getFriendCountAndPosition<QualType>(FD, [](const FriendDecl *F) { |
| if (TypeSourceInfo *TSI = F->getFriendType()) |
| return TSI->getType().getCanonicalType(); |
| llvm_unreachable("Wrong friend object type."); |
| }); |
| else |
| return getFriendCountAndPosition<Decl *>(FD, [](const FriendDecl *F) { |
| if (Decl *D = F->getFriendDecl()) |
| return D->getCanonicalDecl(); |
| llvm_unreachable("Wrong friend object type."); |
| }); |
| } |
| |
| ExpectedDecl ASTNodeImporter::VisitFriendDecl(FriendDecl *D) { |
| // Import the major distinguishing characteristics of a declaration. |
| DeclContext *DC, *LexicalDC; |
| if (Error Err = ImportDeclContext(D, DC, LexicalDC)) |
| return std::move(Err); |
| |
| // Determine whether we've already imported this decl. |
| // FriendDecl is not a NamedDecl so we cannot use lookup. |
| // We try to maintain order and count of redundant friend declarations. |
| const auto *RD = cast<CXXRecordDecl>(DC); |
| FriendDecl *ImportedFriend = RD->getFirstFriend(); |
| SmallVector<FriendDecl *, 2> ImportedEquivalentFriends; |
| |
| while (ImportedFriend) { |
| bool Match = false; |
| if (D->getFriendDecl() && ImportedFriend->getFriendDecl()) { |
| Match = |
| IsStructuralMatch(D->getFriendDecl(), ImportedFriend->getFriendDecl(), |
| /*Complain=*/false); |
| } else if (D->getFriendType() && ImportedFriend->getFriendType()) { |
| Match = Importer.IsStructurallyEquivalent( |
| D->getFriendType()->getType(), |
| ImportedFriend->getFriendType()->getType(), /*Complain=*/false); |
| } |
| if (Match) |
| ImportedEquivalentFriends.push_back(ImportedFriend); |
| |
| ImportedFriend = ImportedFriend->getNextFriend(); |
| } |
| FriendCountAndPosition CountAndPosition = getFriendCountAndPosition(D); |
| |
| assert(ImportedEquivalentFriends.size() <= CountAndPosition.TotalCount && |
| "Class with non-matching friends is imported, ODR check wrong?"); |
| if (ImportedEquivalentFriends.size() == CountAndPosition.TotalCount) |
| return Importer.MapImported( |
| D, ImportedEquivalentFriends[CountAndPosition.IndexOfDecl]); |
| |
| // Not found. Create it. |
| // The declarations will be put into order later by ImportDeclContext. |
| FriendDecl::FriendUnion ToFU; |
| if (NamedDecl *FriendD = D->getFriendDecl()) { |
| NamedDecl *ToFriendD; |
| if (Error Err = importInto(ToFriendD, FriendD)) |
| return std::move(Err); |
| |
| if (FriendD->getFriendObjectKind() != Decl::FOK_None && |
| !(FriendD->isInIdentifierNamespace(Decl::IDNS_NonMemberOperator))) |
| ToFriendD->setObjectOfFriendDecl(false); |
| |
| ToFU = ToFriendD; |
| } else { // The friend is a type, not a decl. |
| if (auto TSIOrErr = import(D->getFriendType())) |
| ToFU = *TSIOrErr; |
| else |
| return TSIOrErr.takeError(); |
| } |
| |
| SmallVector<TemplateParameterList *, 1> ToTPLists(D->NumTPLists); |
| auto **FromTPLists = D->getTrailingObjects<TemplateParameterList *>(); |
| for (unsigned I = 0; I < D->NumTPLists; I++) { |
| if (auto ListOrErr = import(FromTPLists[I])) |
| ToTPLists[I] = *ListOrErr; |
| else |
| return ListOrErr.takeError(); |
| } |
| |
| auto LocationOrErr = import(D->getLocation()); |
| if (!LocationOrErr) |
| return LocationOrErr.takeError(); |
| auto FriendLocOrErr = import(D->getFriendLoc()); |
| if (!FriendLocOrErr) |
| return FriendLocOrErr.takeError(); |
| |
| FriendDecl *FrD; |
| if (GetImportedOrCreateDecl(FrD, D, Importer.getToContext(), DC, |
| *LocationOrErr, ToFU, |
| *FriendLocOrErr, ToTPLists)) |
| return FrD; |
| |
| FrD->setAccess(D->getAccess()); |
| FrD->setLexicalDeclContext(LexicalDC); |
| LexicalDC->addDeclInternal(FrD); |
| return FrD; |
| } |
| |
| ExpectedDecl ASTNodeImporter::VisitObjCIvarDecl(ObjCIvarDecl *D) { |
| // Import the major distinguishing characteristics of an ivar. |
| DeclContext *DC, *LexicalDC; |
| DeclarationName Name; |
| SourceLocation Loc; |
| NamedDecl *ToD; |
| if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) |
| return std::move(Err); |
| if (ToD) |
| return ToD; |
| |
| // Determine whether we've already imported this ivar |
| auto FoundDecls = Importer.findDeclsInToCtx(DC, Name); |
| for (auto *FoundDecl : FoundDecls) { |
| if (ObjCIvarDecl *FoundIvar = dyn_cast<ObjCIvarDecl>(FoundDecl)) { |
| if (Importer.IsStructurallyEquivalent(D->getType(), |
| FoundIvar->getType())) { |
| Importer.MapImported(D, FoundIvar); |
| return FoundIvar; |
| } |
| |
| Importer.ToDiag(Loc, diag::warn_odr_ivar_type_inconsistent) |
| << Name << D->getType() << FoundIvar->getType(); |
| Importer.ToDiag(FoundIvar->getLocation(), diag::note_odr_value_here) |
| << FoundIvar->getType(); |
| |
| return make_error<ImportError>(ImportError::NameConflict); |
| } |
| } |
| |
| Error Err = Error::success(); |
| auto ToType = importChecked(Err, D->getType()); |
| auto ToTypeSourceInfo = importChecked(Err, D->getTypeSourceInfo()); |
| auto ToBitWidth = importChecked(Err, D->getBitWidth()); |
| auto ToInnerLocStart = importChecked(Err, D->getInnerLocStart()); |
| if (Err) |
| return std::move(Err); |
| |
| ObjCIvarDecl *ToIvar; |
| if (GetImportedOrCreateDecl( |
| ToIvar, D, Importer.getToContext(), cast<ObjCContainerDecl>(DC), |
| ToInnerLocStart, Loc, Name.getAsIdentifierInfo(), |
| ToType, ToTypeSourceInfo, |
| D->getAccessControl(),ToBitWidth, D->getSynthesize())) |
| return ToIvar; |
| |
| ToIvar->setLexicalDeclContext(LexicalDC); |
| LexicalDC->addDeclInternal(ToIvar); |
| return ToIvar; |
| } |
| |
| ExpectedDecl ASTNodeImporter::VisitVarDecl(VarDecl *D) { |
| |
| SmallVector<Decl*, 2> Redecls = getCanonicalForwardRedeclChain(D); |
| auto RedeclIt = Redecls.begin(); |
| // Import the first part of the decl chain. I.e. import all previous |
| // declarations starting from the canonical decl. |
| for (; RedeclIt != Redecls.end() && *RedeclIt != D; ++RedeclIt) { |
| ExpectedDecl RedeclOrErr = import(*RedeclIt); |
| if (!RedeclOrErr) |
| return RedeclOrErr.takeError(); |
| } |
| assert(*RedeclIt == D); |
| |
| // Import the major distinguishing characteristics of a variable. |
| DeclContext *DC, *LexicalDC; |
| DeclarationName Name; |
| SourceLocation Loc; |
| NamedDecl *ToD; |
| if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) |
| return std::move(Err); |
| if (ToD) |
| return ToD; |
| |
| // Try to find a variable in our own ("to") context with the same name and |
| // in the same context as the variable we're importing. |
| VarDecl *FoundByLookup = nullptr; |
| if (D->isFileVarDecl()) { |
| SmallVector<NamedDecl *, 4> ConflictingDecls; |
| unsigned IDNS = Decl::IDNS_Ordinary; |
| auto FoundDecls = Importer.findDeclsInToCtx(DC, Name); |
| for (auto *FoundDecl : FoundDecls) { |
| if (!FoundDecl->isInIdentifierNamespace(IDNS)) |
| continue; |
| |
| if (auto *FoundVar = dyn_cast<VarDecl>(FoundDecl)) { |
| if (!hasSameVisibilityContextAndLinkage(FoundVar, D)) |
| continue; |
| if (Importer.IsStructurallyEquivalent(D->getType(), |
| FoundVar->getType())) { |
| |
| // The VarDecl in the "From" context has a definition, but in the |
| // "To" context we already have a definition. |
| VarDecl *FoundDef = FoundVar->getDefinition(); |
| if (D->isThisDeclarationADefinition() && FoundDef) |
| // FIXME Check for ODR error if the two definitions have |
| // different initializers? |
| return Importer.MapImported(D, FoundDef); |
| |
| // The VarDecl in the "From" context has an initializer, but in the |
| // "To" context we already have an initializer. |
| const VarDecl *FoundDInit = nullptr; |
| if (D->getInit() && FoundVar->getAnyInitializer(FoundDInit)) |
| // FIXME Diagnose ODR error if the two initializers are different? |
| return Importer.MapImported(D, const_cast<VarDecl*>(FoundDInit)); |
| |
| FoundByLookup = FoundVar; |
| break; |
| } |
| |
| const ArrayType *FoundArray |
| = Importer.getToContext().getAsArrayType(FoundVar->getType()); |
| const ArrayType *TArray |
| = Importer.getToContext().getAsArrayType(D->getType()); |
| if (FoundArray && TArray) { |
| if (isa<IncompleteArrayType>(FoundArray) && |
| isa<ConstantArrayType>(TArray)) { |
| // Import the type. |
| if (auto TyOrErr = import(D->getType())) |
| FoundVar->setType(*TyOrErr); |
| else |
| return TyOrErr.takeError(); |
| |
| FoundByLookup = FoundVar; |
| break; |
| } else if (isa<IncompleteArrayType>(TArray) && |
| isa<ConstantArrayType>(FoundArray)) { |
| FoundByLookup = FoundVar; |
| break; |
| } |
| } |
| |
| Importer.ToDiag(Loc, diag::warn_odr_variable_type_inconsistent) |
| << Name << D->getType() << FoundVar->getType(); |
| Importer.ToDiag(FoundVar->getLocation(), diag::note_odr_value_here) |
| << FoundVar->getType(); |
| ConflictingDecls.push_back(FoundDecl); |
| } |
| } |
| |
| if (!ConflictingDecls.empty()) { |
| ExpectedName NameOrErr = Importer.HandleNameConflict( |
| Name, DC, IDNS, ConflictingDecls.data(), ConflictingDecls.size()); |
| if (NameOrErr) |
| Name = NameOrErr.get(); |
| else |
| return NameOrErr.takeError(); |
| } |
| } |
| |
| Error Err = Error::success(); |
| auto ToType = importChecked(Err, D->getType()); |
| auto ToTypeSourceInfo = importChecked(Err, D->getTypeSourceInfo()); |
| auto ToInnerLocStart = importChecked(Err, D->getInnerLocStart()); |
| auto ToQualifierLoc = importChecked(Err, D->getQualifierLoc()); |
| if (Err) |
| return std::move(Err); |
| |
| // Create the imported variable. |
| VarDecl *ToVar; |
| if (GetImportedOrCreateDecl(ToVar, D, Importer.getToContext(), DC, |
| ToInnerLocStart, Loc, |
| Name.getAsIdentifierInfo(), |
| ToType, ToTypeSourceInfo, |
| D->getStorageClass())) |
| return ToVar; |
| |
| ToVar->setQualifierInfo(ToQualifierLoc); |
| ToVar->setAccess(D->getAccess()); |
| ToVar->setLexicalDeclContext(LexicalDC); |
| |
| if (FoundByLookup) { |
| auto *Recent = const_cast<VarDecl *>(FoundByLookup->getMostRecentDecl()); |
| ToVar->setPreviousDecl(Recent); |
| } |
| |
| // Import the described template, if any. |
| if (D->getDescribedVarTemplate()) { |
| auto ToVTOrErr = import(D->getDescribedVarTemplate()); |
| if (!ToVTOrErr) |
| return ToVTOrErr.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->setKNRPromoted(FromParam->isKNRPromoted()); |
| |
| if (FromParam->hasUninstantiatedDefaultArg()) { |
| if (auto ToDefArgOrErr = import(FromParam->getUninstantiatedDefaultArg())) |
| ToParam->setUninstantiatedDefaultArg(*ToDefArgOrErr); |
| else |
| return ToDefArgOrErr.takeError(); |
| } else if (FromParam->hasUnparsedDefaultArg()) { |
| ToParam->setUnparsedDefaultArg(); |
| } else if (FromParam->hasDefaultArg()) { |
| if (auto ToDefArgOrErr = import(FromParam->getDefaultArg())) |
| ToParam->setDefaultArg(*ToDefArgOrErr); |
| else |
| return ToDefArgOrErr.takeError(); |
| } |
| |
| return Error::success(); |
| } |
| |
| ExpectedDecl ASTNodeImporter::VisitParmVarDecl(ParmVarDecl *D) { |
| // Parameters are created in the translation unit's context, then moved |
| // into the function declaration's context afterward. |
| DeclContext *DC = Importer.getToContext().getTranslationUnitDecl(); |
| |
| Error Err = Error::success(); |
| auto ToDeclName = importChecked(Err, D->getDeclName()); |
| auto ToLocation = importChecked(Err, D->getLocation()); |
| auto ToInnerLocStart = importChecked(Err, D->getInnerLocStart()); |
| auto ToType = importChecked(Err, D->getType()); |
| auto ToTypeSourceInfo = importChecked(Err, D->getTypeSourceInfo()); |
| if (Err) |
| return std::move(Err); |
| |
| ParmVarDecl *ToParm; |
| if (GetImportedOrCreateDecl(ToParm, D, Importer.getToContext(), DC, |
| ToInnerLocStart, ToLocation, |
| ToDeclName.getAsIdentifierInfo(), ToType, |
| ToTypeSourceInfo, D->getStorageClass(), |
| /*DefaultArg*/ nullptr)) |
| return ToParm; |
| |
| // Set the default argument. It should be no problem if it was already done. |
| // Do not import the default expression before GetImportedOrCreateDecl call |
| // to avoid possible infinite import loop because circular dependency. |
| if (Error Err = ImportDefaultArgOfParmVarDecl(D, ToParm)) |
| return std::move(Err); |
| |
| if (D->isObjCMethodParameter()) { |
| ToParm->setObjCMethodScopeInfo(D->getFunctionScopeIndex()); |
| ToParm->setObjCDeclQualifier(D->getObjCDeclQualifier()); |
| } else { |
| ToParm->setScopeInfo(D->getFunctionScopeDepth(), |
| D->getFunctionScopeIndex()); |
| } |
| |
| return ToParm; |
| } |
| |
| ExpectedDecl ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { |
| // Import the major distinguishing characteristics of a method. |
| DeclContext *DC, *LexicalDC; |
| DeclarationName Name; |
| SourceLocation Loc; |
| NamedDecl *ToD; |
| if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) |
| return std::move(Err); |
| if (ToD) |
| return ToD; |
| |
| auto FoundDecls = Importer.findDeclsInToCtx(DC, Name); |
| for (auto *FoundDecl : FoundDecls) { |
| if (auto *FoundMethod = dyn_cast<ObjCMethodDecl>(FoundDecl)) { |
| if (FoundMethod->isInstanceMethod() != D->isInstanceMethod()) |
| continue; |
| |
| // Check return types. |
| if (!Importer.IsStructurallyEquivalent(D->getReturnType(), |
| FoundMethod->getReturnType())) { |
| Importer.ToDiag(Loc, diag::warn_odr_objc_method_result_type_inconsistent) |
| << D->isInstanceMethod() << Name << D->getReturnType() |
| << FoundMethod->getReturnType(); |
| Importer.ToDiag(FoundMethod->getLocation(), |
| diag::note_odr_objc_method_here) |
| << D->isInstanceMethod() << Name; |
| |
| return make_error<ImportError>(ImportError::NameConflict); |
| } |
| |
| // Check the number of parameters. |
| if (D->param_size() != FoundMethod->param_size()) { |
| Importer.ToDiag(Loc, diag::warn_odr_objc_method_num_params_inconsistent) |
| << D->isInstanceMethod() << Name |
| << D->param_size() << FoundMethod->param_size(); |
| Importer.ToDiag(FoundMethod->getLocation(), |
| diag::note_odr_objc_method_here) |
| << D->isInstanceMethod() << Name; |
| |
| return make_error<ImportError>(ImportError::NameConflict); |
| } |
| |
| // Check parameter types. |
| for (ObjCMethodDecl::param_iterator P = D->param_begin(), |
| PEnd = D->param_end(), FoundP = FoundMethod->param_begin(); |
| P != PEnd; ++P, ++FoundP) { |
| if (!Importer.IsStructurallyEquivalent((*P)->getType(), |
| (*FoundP)->getType())) { |
| Importer.FromDiag((*P)->getLocation(), |
| diag::warn_odr_objc_method_param_type_inconsistent) |
| << D->isInstanceMethod() << Name |
| << (*P)->getType() << (*FoundP)->getType(); |
| Importer.ToDiag((*FoundP)->getLocation(), diag::note_odr_value_here) |
| << (*FoundP)->getType(); |
| |
| return make_error<ImportError>(ImportError::NameConflict); |
| } |
| } |
| |
| // Check variadic/non-variadic. |
| // Check the number of parameters. |
| if (D->isVariadic() != FoundMethod->isVariadic()) { |
| Importer.ToDiag(Loc, diag::warn_odr_objc_method_variadic_inconsistent) |
| << D->isInstanceMethod() << Name; |
| Importer.ToDiag(FoundMethod->getLocation(), |
| diag::note_odr_objc_method_here) |
| << D->isInstanceMethod() << Name; |
| |
| return make_error<ImportError>(ImportError::NameConflict); |
| } |
| |
| // FIXME: Any other bits we need to merge? |
| return Importer.MapImported(D, FoundMethod); |
| } |
| } |
| |
| Error Err = Error::success(); |
| auto ToEndLoc = importChecked(Err, D->getEndLoc()); |
| auto ToReturnType = importChecked(Err, D->getReturnType()); |
| auto ToReturnTypeSourceInfo = |
| importChecked(Err, D->getReturnTypeSourceInfo()); |
| if (Err) |
| return std::move(Err); |
| |
| ObjCMethodDecl *ToMethod; |
| if (GetImportedOrCreateDecl( |
| ToMethod, D, Importer.getToContext(), Loc, ToEndLoc, |
| Name.getObjCSelector(), ToReturnType, ToReturnTypeSourceInfo, DC, |
| D->isInstanceMethod(), D->isVariadic(), D->isPropertyAccessor(), |
| D->isSynthesizedAccessorStub(), D->isImplicit(), D->isDefined(), |
| D->getImplementationControl(), D->hasRelatedResultType())) |
| return ToMethod; |
| |
| // FIXME: When we decide to merge method definitions, we'll need to |
| // deal with implicit parameters. |
| |
| // Import the parameters |
| SmallVector<ParmVarDecl *, 5> ToParams; |
| for (auto *FromP : D->parameters()) { |
| if (Expected<ParmVarDecl *> ToPOrErr = import(FromP)) |
| ToParams.push_back(*ToPOrErr); |
| else |
| return ToPOrErr.takeError(); |
| } |
| |
| // Set the parameters. |
| for (auto *ToParam : ToParams) { |
| ToParam->setOwningFunction(ToMethod); |
| ToMethod->addDeclInternal(ToParam); |
| } |
| |
| SmallVector<SourceLocation, 12> FromSelLocs; |
| D->getSelectorLocs(FromSelLocs); |
| SmallVector<SourceLocation, 12> ToSelLocs(FromSelLocs.size()); |
| if (Error Err = ImportContainerChecked(FromSelLocs, ToSelLocs)) |
| return std::move(Err); |
| |
| ToMethod->setMethodParams(Importer.getToContext(), ToParams, ToSelLocs); |
| |
| ToMethod->setLexicalDeclContext(LexicalDC); |
| LexicalDC->addDeclInternal(ToMethod); |
| |
| // Implicit params are declared when Sema encounters the definition but this |
| // never happens when the method is imported. Manually declare the implicit |
| // params now that the MethodDecl knows its class interface. |
| if (D->getSelfDecl()) |
| ToMethod->createImplicitParams(Importer.getToContext(), |
| ToMethod->getClassInterface()); |
| |
| return ToMethod; |
| } |
| |
| ExpectedDecl ASTNodeImporter::VisitObjCTypeParamDecl(ObjCTypeParamDecl *D) { |
| // Import the major distinguishing characteristics of a category. |
| DeclContext *DC, *LexicalDC; |
| DeclarationName Name; |
| SourceLocation Loc; |
| NamedDecl *ToD; |
| if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) |
| return std::move(Err); |
| if (ToD) |
| return ToD; |
| |
| Error Err = Error::success(); |
| auto ToVarianceLoc = importChecked(Err, D->getVarianceLoc()); |
| auto ToLocation = importChecked(Err, D->getLocation()); |
| auto ToColonLoc = importChecked(Err, D->getColonLoc()); |
| auto ToTypeSourceInfo = importChecked(Err, D->getTypeSourceInfo()); |
| if (Err) |
| return std::move(Err); |
| |
| ObjCTypeParamDecl *Result; |
| if (GetImportedOrCreateDecl( |
| Result, D, Importer.getToContext(), DC, D->getVariance(), |
| ToVarianceLoc, D->getIndex(), |
| ToLocation, Name.getAsIdentifierInfo(), |
| ToColonLoc, ToTypeSourceInfo)) |
| return Result; |
| |
| Result->setLexicalDeclContext(LexicalDC); |
| return Result; |
| } |
| |
| ExpectedDecl ASTNodeImporter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) { |
| // Import the major distinguishing characteristics of a category. |
| DeclContext *DC, *LexicalDC; |
| DeclarationName Name; |
| SourceLocation Loc; |
| NamedDecl *ToD; |
| if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) |
| return std::move(Err); |
| if (ToD) |
| return ToD; |
| |
| ObjCInterfaceDecl *ToInterface; |
| if (Error Err = importInto(ToInterface, D->getClassInterface())) |
| return std::move(Err); |
| |
| // Determine if we've already encountered this category. |
| ObjCCategoryDecl *MergeWithCategory |
| = ToInterface->FindCategoryDeclaration(Name.getAsIdentifierInfo()); |
| ObjCCategoryDecl *ToCategory = MergeWithCategory; |
| if (!ToCategory) { |
| |
| Error Err = Error::success(); |
| auto ToAtStartLoc = importChecked(Err, D->getAtStartLoc()); |
| auto ToCategoryNameLoc = importChecked(Err, D->getCategoryNameLoc()); |
| auto ToIvarLBraceLoc = importChecked(Err, D->getIvarLBraceLoc()); |
| auto ToIvarRBraceLoc = importChecked(Err, D->getIvarRBraceLoc()); |
| if (Err) |
| return std::move(Err); |
| |
| if (GetImportedOrCreateDecl(ToCategory, D, Importer.getToContext(), DC, |
| ToAtStartLoc, Loc, |
| ToCategoryNameLoc, |
| Name.getAsIdentifierInfo(), ToInterface, |
| /*TypeParamList=*/nullptr, |
| ToIvarLBraceLoc, |
| ToIvarRBraceLoc)) |
| return ToCategory; |
| |
| ToCategory->setLexicalDeclContext(LexicalDC); |
| LexicalDC->addDeclInternal(ToCategory); |
| // Import the type parameter list after MapImported, to avoid |
| // loops when bringing in their DeclContext. |
| if (auto PListOrErr = ImportObjCTypeParamList(D->getTypeParamList())) |
| ToCategory->setTypeParamList(*PListOrErr); |
| else |
| return PListOrErr.takeError(); |
| |
| // Import protocols |
| SmallVector<ObjCProtocolDecl *, 4> Protocols; |
| SmallVector<SourceLocation, 4> ProtocolLocs; |
| ObjCCategoryDecl::protocol_loc_iterator FromProtoLoc |
| = D->protocol_loc_begin(); |
| for (ObjCCategoryDecl::protocol_iterator FromProto = D->protocol_begin(), |
| FromProtoEnd = D->protocol_end(); |
| FromProto != FromProtoEnd; |
| ++FromProto, ++FromProtoLoc) { |
| if (Expected<ObjCProtocolDecl *> ToProtoOrErr = import(*FromProto)) |
| Protocols.push_back(*ToProtoOrErr); |
| else |
| return ToProtoOrErr.takeError(); |
| |
| if (ExpectedSLoc ToProtoLocOrErr = import(*FromProtoLoc)) |
| ProtocolLocs.push_back(*ToProtoLocOrErr); |
| else |
| return ToProtoLocOrErr.takeError(); |
| } |
| |
| // FIXME: If we're merging, make sure that the protocol list is the same. |
| ToCategory->setProtocolList(Protocols.data(), Protocols.size(), |
| ProtocolLocs.data(), Importer.getToContext()); |
| |
| } else { |
| Importer.MapImported(D, ToCategory); |
| } |
| |
| // Import all of the members of this category. |
| if (Error Err = ImportDeclContext(D)) |
| return std::move(Err); |
| |
| // If we have an implementation, import it as well. |
| if (D->getImplementation()) { |
| if (Expected<ObjCCategoryImplDecl *> ToImplOrErr = |
| import(D->getImplementation())) |
| ToCategory->setImplementation(*ToImplOrErr); |
| else |
| return ToImplOrErr.takeError(); |
| } |
| |
| return ToCategory; |
| } |
| |
| Error ASTNodeImporter::ImportDefinition( |
| ObjCProtocolDecl *From, ObjCProtocolDecl *To, ImportDefinitionKind Kind) { |
| if (To->getDefinition()) { |
| if (shouldForceImportDeclContext(Kind)) |
| if (Error Err = ImportDeclContext(From)) |
| return Err; |
| return Error::success(); |
| } |
| |
| // Start the protocol definition |
| To->startDefinition(); |
| |
| // Import protocols |
| SmallVector<ObjCProtocolDecl *, 4> Protocols; |
| SmallVector<SourceLocation, 4> ProtocolLocs; |
| ObjCProtocolDecl::protocol_loc_iterator FromProtoLoc = |
| From->protocol_loc_begin(); |
| for (ObjCProtocolDecl::protocol_iterator FromProto = From->protocol_begin(), |
| FromProtoEnd = From->protocol_end(); |
| FromProto != FromProtoEnd; |
| ++FromProto, ++FromProtoLoc) { |
| if (Expected<ObjCProtocolDecl *> ToProtoOrErr = import(*FromProto)) |
| Protocols.push_back(*ToProtoOrErr); |
| else |
| return ToProtoOrErr.takeError(); |
| |
| if (ExpectedSLoc ToProtoLocOrErr = import(*FromProtoLoc)) |
| ProtocolLocs.push_back(*ToProtoLocOrErr); |
| else |
| return ToProtoLocOrErr.takeError(); |
| |
| } |
| |
| // FIXME: If we're merging, make sure that the protocol list is the same. |
| To->setProtocolList(Protocols.data(), Protocols.size(), |
| ProtocolLocs.data(), Importer.getToContext()); |
| |
| if (shouldForceImportDeclContext(Kind)) { |
| // Import all of the members of this protocol. |
| if (Error Err = ImportDeclContext(From, /*ForceImport=*/true)) |
| return Err; |
| } |
| return Error::success(); |
| } |
| |
| ExpectedDecl ASTNodeImporter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) { |
| // If this protocol has a definition in the translation unit we're coming |
| // from, but this particular declaration is not that definition, import the |
| // definition and map to that. |
| ObjCProtocolDecl *Definition = D->getDefinition(); |
| if (Definition && Definition != D) { |
| if (ExpectedDecl ImportedDefOrErr = import(Definition)) |
| return Importer.MapImported(D, *ImportedDefOrErr); |
| else |
| return ImportedDefOrErr.takeError(); |
| } |
| |
| // Import the major distinguishing characteristics of a protocol. |
| DeclContext *DC, *LexicalDC; |
| DeclarationName Name; |
| SourceLocation Loc; |
| NamedDecl *ToD; |
| if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) |
| return std::move(Err); |
| if (ToD) |
| return ToD; |
| |
| ObjCProtocolDecl *MergeWithProtocol = nullptr; |
| auto FoundDecls = Importer.findDeclsInToCtx(DC, Name); |
| for (auto *FoundDecl : FoundDecls) { |
| if (!FoundDecl->isInIdentifierNamespace(Decl::IDNS_ObjCProtocol)) |
| continue; |
| |
| if ((MergeWithProtocol = dyn_cast<ObjCProtocolDecl>(FoundDecl))) |
| break; |
| } |
| |
| ObjCProtocolDecl *ToProto = MergeWithProtocol; |
| if (!ToProto) { |
| auto ToAtBeginLocOrErr = import(D->getAtStartLoc()); |
| if (!ToAtBeginLocOrErr) |
| return ToAtBeginLocOrErr.takeError(); |
| |
| if (GetImportedOrCreateDecl(ToProto, D, Importer.getToContext(), DC, |
| Name.getAsIdentifierInfo(), Loc, |
| *ToAtBeginLocOrErr, |
| /*PrevDecl=*/nullptr)) |
| return ToProto; |
| ToProto->setLexicalDeclContext(LexicalDC); |
| LexicalDC->addDeclInternal(ToProto); |
| } |
| |
| Importer.MapImported(D, ToProto); |
| |
| if (D->isThisDeclarationADefinition()) |
| if (Error Err = ImportDefinition(D, ToProto)) |
| return std::move(Err); |
| |
| return ToProto; |
| } |
| |
| ExpectedDecl ASTNodeImporter::VisitLinkageSpecDecl(LinkageSpecDecl *D) { |
| DeclContext *DC, *LexicalDC; |
| if (Error Err = ImportDeclContext(D, DC, LexicalDC)) |
| return std::move(Err); |
| |
| ExpectedSLoc ExternLocOrErr = import(D->getExternLoc()); |
| if (!ExternLocOrErr) |
| return ExternLocOrErr.takeError(); |
| |
| ExpectedSLoc LangLocOrErr = import(D->getLocation()); |
| if (!LangLocOrErr) |
| return LangLocOrErr.takeError(); |
| |
| bool HasBraces = D->hasBraces(); |
| |
| LinkageSpecDecl *ToLinkageSpec; |
| if (GetImportedOrCreateDecl(ToLinkageSpec, D, Importer.getToContext(), DC, |
| *ExternLocOrErr, *LangLocOrErr, |
| D->getLanguage(), HasBraces)) |
| return ToLinkageSpec; |
| |
| if (HasBraces) { |
| ExpectedSLoc RBraceLocOrErr = import(D->getRBraceLoc()); |
| if (!RBraceLocOrErr) |
| return RBraceLocOrErr.takeError(); |
| ToLinkageSpec->setRBraceLoc(*RBraceLocOrErr); |
| } |
| |
| ToLinkageSpec->setLexicalDeclContext(LexicalDC); |
| LexicalDC->addDeclInternal(ToLinkageSpec); |
| |
| return ToLinkageSpec; |
| } |
| |
| ExpectedDecl ASTNodeImporter::VisitUsingDecl(UsingDecl *D) { |
| DeclContext *DC, *LexicalDC; |
| DeclarationName Name; |
| SourceLocation Loc; |
| NamedDecl *ToD = nullptr; |
| if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) |
| return std::move(Err); |
| if (ToD) |
| return ToD; |
| |
| Error Err = Error::success(); |
| auto ToLoc = importChecked(Err, D->getNameInfo().getLoc()); |
| auto ToUsingLoc = importChecked(Err, D->getUsingLoc()); |
| auto ToQualifierLoc = importChecked(Err, D->getQualifierLoc()); |
| if (Err) |
| return std::move(Err); |
| |
| DeclarationNameInfo NameInfo(Name, ToLoc); |
| if (Error Err = ImportDeclarationNameLoc(D->getNameInfo(), NameInfo)) |
| return std::move(Err); |
| |
| UsingDecl *ToUsing; |
| if (GetImportedOrCreateDecl(ToUsing, D, Importer.getToContext(), DC, |
| ToUsingLoc, ToQualifierLoc, NameInfo, |
| D->hasTypename())) |
| return ToUsing; |
| |
| ToUsing->setLexicalDeclContext(LexicalDC); |
| LexicalDC->addDeclInternal(ToUsing); |
| |
| if (NamedDecl *FromPattern = |
| Importer.getFromContext().getInstantiatedFromUsingDecl(D)) { |
| if (Expected<NamedDecl *> ToPatternOrErr = import(FromPattern)) |
| Importer.getToContext().setInstantiatedFromUsingDecl( |
| ToUsing, *ToPatternOrErr); |
| else |
| return ToPatternOrErr.takeError(); |
| } |
| |
| for (UsingShadowDecl *FromShadow : D->shadows()) { |
| if (Expected<UsingShadowDecl *> ToShadowOrErr = import(FromShadow)) |
| ToUsing->addShadowDecl(*ToShadowOrErr); |
| else |
| // FIXME: We return error here but the definition is already created |
| // and available with lookups. How to fix this?.. |
| return ToShadowOrErr.takeError(); |
| } |
| return ToUsing; |
| } |
| |
| ExpectedDecl ASTNodeImporter::VisitUsingShadowDecl(UsingShadowDecl *D) { |
| DeclContext *DC, *LexicalDC; |
| DeclarationName Name; |
| SourceLocation Loc; |
| NamedDecl *ToD = nullptr; |
| if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) |
| return std::move(Err); |
| if (ToD) |
| return ToD; |
| |
| Expected<UsingDecl *> ToUsingOrErr = import(D->getUsingDecl()); |
| if (!ToUsingOrErr) |
| return ToUsingOrErr.takeError(); |
| |
| Expected<NamedDecl *> ToTargetOrErr = import(D->getTargetDecl()); |
| if (!ToTargetOrErr) |
| return ToTargetOrErr.takeError(); |
| |
| UsingShadowDecl *ToShadow; |
| if (GetImportedOrCreateDecl(ToShadow, D, Importer.getToContext(), DC, Loc, |
| *ToUsingOrErr, *ToTargetOrErr)) |
| return ToShadow; |
| |
| ToShadow->setLexicalDeclContext(LexicalDC); |
| ToShadow->setAccess(D->getAccess()); |
| |
| if (UsingShadowDecl *FromPattern = |
| Importer.getFromContext().getInstantiatedFromUsingShadowDecl(D)) { |
| if (Expected<UsingShadowDecl *> ToPatternOrErr = import(FromPattern)) |
| Importer.getToContext().setInstantiatedFromUsingShadowDecl( |
| ToShadow, *ToPatternOrErr); |
| else |
| // FIXME: We return error here but the definition is already created |
| // and available with lookups. How to fix this?.. |
| return ToPatternOrErr.takeError(); |
| } |
| |
| LexicalDC->addDeclInternal(ToShadow); |
| |
| return ToShadow; |
| } |
| |
| ExpectedDecl ASTNodeImporter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) { |
| DeclContext *DC, *LexicalDC; |
| DeclarationName Name; |
| SourceLocation Loc; |
| NamedDecl *ToD = nullptr; |
| if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) |
| return std::move(Err); |
| if (ToD) |
| return ToD; |
| |
| auto ToComAncestorOrErr = Importer.ImportContext(D->getCommonAncestor()); |
| if (!ToComAncestorOrErr) |
| return ToComAncestorOrErr.takeError(); |
| |
| 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::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<ObjCProtocolDecl *, 4> Protocols; |
| SmallVector<SourceLocation, 4> ProtocolLocs; |
| ObjCInterfaceDecl::protocol_loc_iterator FromProtoLoc = |
| From->protocol_loc_begin(); |
| |
| for (ObjCInterfaceDecl::protocol_iterator FromProto = From->protocol_begin(), |
| FromProtoEnd = From->protocol_end(); |
| FromProto != FromProtoEnd; |
| ++FromProto, ++FromProtoLoc) { |
| if (Expected<ObjCProtocolDecl *> ToProtoOrErr = import(*FromProto)) |
| Protocols.push_back(*ToProtoOrErr); |
| else |
| return ToProtoOrErr.takeError(); |
| |
| if (ExpectedSLoc ToProtoLocOrErr = import(*FromProtoLoc)) |
| ProtocolLocs.push_back(*ToProtoLocOrErr); |
| else |
| return ToProtoLocOrErr.takeError(); |
| |
| } |
| |
| // FIXME: If we're merging, make sure that the protocol list is the same. |
| To->setProtocolList(Protocols.data(), Protocols.size(), |
| ProtocolLocs.data(), Importer.getToContext()); |
| |
| // Import categories. When the categories themselves are imported, they'll |
| // hook themselves into this interface. |
| for (auto *Cat : From->known_categories()) { |
| auto ToCatOrErr = import(Cat); |
| if (!ToCatOrErr) |
| return ToCatOrErr.takeError(); |
| } |
| |
| // If we have an @implementation, import it as well. |
| if (From->getImplementation()) { |
| if (Expected<ObjCImplementationDecl *> ToImplOrErr = |
| import(From->getImplementation())) |
| To->setImplementation(*ToImplOrErr); |
| else |
| return ToImplOrErr.takeError(); |
| } |
| |
| // Import all of the members of this class. |
| if (Error Err = ImportDeclContext(From, /*ForceImport=*/true)) |
| return Err; |
| |
| return Error::success(); |
| } |
| |
| Expected<ObjCTypeParamList *> |
| ASTNodeImporter::ImportObjCTypeParamList(ObjCTypeParamList *list) { |
| if (!list) |
| return nullptr; |
| |
| SmallVector<ObjCTypeParamDecl *, 4> toTypeParams; |
| for (auto *fromTypeParam : *list) { |
| if (auto toTypeParamOrErr = import(fromTypeParam)) |
| toTypeParams.push_back(*toTypeParamOrErr); |
| else |
| return toTypeParamOrErr.takeError(); |
| } |
| |
| auto LAngleLocOrErr = import(list->getLAngleLoc()); |
| if (!LAngleLocOrErr) |
| return LAngleLocOrErr.takeError(); |
| |
| auto RAngleLocOrErr = import(list->getRAngleLoc()); |
| if (!RAngleLocOrErr) |
| return RAngleLocOrErr.takeError(); |
| |
| return ObjCTypeParamList::create(Importer.getToContext(), |
| *LAngleLocOrErr, |
| toTypeParams, |
| *RAngleLocOrErr); |
| } |
| |
| ExpectedDecl ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { |
| // If this class has a definition in the translation unit we're coming from, |
| // but this particular declaration is not that definition, import the |
| // definition and map to that. |
| ObjCInterfaceDecl *Definition = D->getDefinition(); |
| if (Definition && Definition != D) { |
| if (ExpectedDecl ImportedDefOrErr = import(Definition)) |
| return Importer.MapImported(D, *ImportedDefOrErr); |
| else |
| return ImportedDefOrErr.takeError(); |
| } |
| |
| // Import the major distinguishing characteristics of an @interface. |
| DeclContext *DC, *LexicalDC; |
| DeclarationName Name; |
| SourceLocation Loc; |
| NamedDecl *ToD; |
| if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) |
| return std::move(Err); |
| if (ToD) |
| return ToD; |
| |
| // Look for an existing interface with the same name. |
| ObjCInterfaceDecl *MergeWithIface = nullptr; |
| auto FoundDecls = Importer.findDeclsInToCtx(DC, Name); |
| for (auto *FoundDecl : FoundDecls) { |
| if (!FoundDecl->isInIdentifierNamespace(Decl::IDNS_Ordinary)) |
| continue; |
| |
| if ((MergeWithIface = dyn_cast<ObjCInterfaceDecl>(FoundDecl))) |
| break; |
| } |
| |
| // Create an interface declaration, if one does not already exist. |
| ObjCInterfaceDecl *ToIface = MergeWithIface; |
| if (!ToIface) { |
| ExpectedSLoc AtBeginLocOrErr = import(D->getAtStartLoc()); |
| if (!AtBeginLocOrErr) |
| return AtBeginLocOrErr.takeError(); |
| |
| if (GetImportedOrCreateDecl( |
| ToIface, D, Importer.getToContext(), DC, |
| *AtBeginLocOrErr, Name.getAsIdentifierInfo(), |
| /*TypeParamList=*/nullptr, |
| /*PrevDecl=*/nullptr, Loc, D->isImplicitInterfaceDecl())) |
| return ToIface; |
| ToIface->setLexicalDeclContext(LexicalDC); |
| LexicalDC->addDeclInternal(ToIface); |
| } |
| Importer.MapImported(D, ToIface); |
| // Import the type parameter list after MapImported, to avoid |
| // loops when bringing in their DeclContext. |
| if (auto ToPListOrErr = |
| ImportObjCTypeParamList(D->getTypeParamListAsWritten())) |
| ToIface->setTypeParamList(*ToPListOrErr); |
| else |
| return ToPListOrErr.takeError(); |
| |
| if (D->isThisDeclarationADefinition()) |
| if (Error Err = ImportDefinition(D, ToIface)) |
| return std::move(Err); |
| |
| return ToIface; |
| } |
| |
| ExpectedDecl |
| ASTNodeImporter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) { |
| ObjCCategoryDecl *Category; |
| if (Error Err = importInto(Category, D->getCategoryDecl())) |
| return std::move(Err); |
| |
| ObjCCategoryImplDecl *ToImpl = Category->getImplementation(); |
| if (!ToImpl) { |
| DeclContext *DC, *LexicalDC; |
| if (Error Err = ImportDeclContext(D, DC, LexicalDC)) |
| return std::move(Err); |
| |
| Error Err = Error::success(); |
| auto ToLocation = importChecked(Err, D->getLocation()); |
| auto ToAtStartLoc = importChecked(Err, D->getAtStartLoc()); |
| auto ToCategoryNameLoc = importChecked(Err, D->getCategoryNameLoc()); |
| if (Err) |
| return std::move(Err); |
| |
| if (GetImportedOrCreateDecl( |
| ToImpl, D, Importer.getToContext(), DC, |
| Importer.Import(D->getIdentifier()), Category->getClassInterface(), |
| ToLocation, ToAtStartLoc, ToCategoryNameLoc)) |
| return ToImpl; |
| |
| ToImpl->setLexicalDeclContext(LexicalDC); |
| LexicalDC->addDeclInternal(ToImpl); |
| Category->setImplementation(ToImpl); |
| } |
| |
| Importer.MapImported(D, ToImpl); |
| if (Error Err = ImportDeclContext(D)) |
| return std::move(Err); |
| |
| return ToImpl; |
| } |
| |
| ExpectedDecl |
| ASTNodeImporter::VisitObjCImplementationDecl(ObjCImplementationDecl *D) { |
| // Find the corresponding interface. |
| ObjCInterfaceDecl *Iface; |
| if (Error Err = importInto(Iface, D->getClassInterface())) |
| return std::move(Err); |
| |
| // Import the superclass, if any. |
| ObjCInterfaceDecl *Super; |
| if (Error Err = importInto(Super, D->getSuperClass())) |
| return std::move(Err); |
| |
| ObjCImplementationDecl *Impl = Iface->getImplementation(); |
| if (!Impl) { |
| // We haven't imported an implementation yet. Create a new @implementation |
| // now. |
| DeclContext *DC, *LexicalDC; |
| if (Error Err = ImportDeclContext(D, DC, LexicalDC)) |
| return std::move(Err); |
| |
| Error Err = Error::success(); |
| auto ToLocation = importChecked(Err, D->getLocation()); |
| auto ToAtStartLoc = importChecked(Err, D->getAtStartLoc()); |
| auto ToSuperClassLoc = importChecked(Err, D->getSuperClassLoc()); |
| auto ToIvarLBraceLoc = importChecked(Err, D->getIvarLBraceLoc()); |
| auto ToIvarRBraceLoc = importChecked(Err, D->getIvarRBraceLoc()); |
| if (Err) |
| return std::move(Err); |
| |
| if (GetImportedOrCreateDecl(Impl, D, Importer.getToContext(), |
| DC, Iface, Super, |
| ToLocation, |
| ToAtStartLoc, |
| ToSuperClassLoc, |
| ToIvarLBraceLoc, |
| ToIvarRBraceLoc)) |
| return Impl; |
| |
| Impl->setLexicalDeclContext(LexicalDC); |
| |
| // Associate the implementation with the class it implements. |
| Iface->setImplementation(Impl); |
| Importer.MapImported(D, Iface->getImplementation()); |
| } else { |
| Importer.MapImported(D, Iface->getImplementation()); |
| |
| // Verify that the existing @implementation has the same superclass. |
| if ((Super && !Impl->getSuperClass()) || |
| (!Super && Impl->getSuperClass()) || |
| (Super && Impl->getSuperClass() && |
| !declaresSameEntity(Super->getCanonicalDecl(), |
| Impl->getSuperClass()))) { |
| Importer.ToDiag(Impl->getLocation(), |
| diag::warn_odr_objc_superclass_inconsistent) |
| << Iface->getDeclName(); |
| // FIXME: It would be nice to have the location of the superclass |
| // below. |
| if (Impl->getSuperClass()) |
| Importer.ToDiag(Impl->getLocation(), |
| diag::note_odr_objc_superclass) |
| << Impl->getSuperClass()->getDeclName(); |
| else |
| Importer.ToDiag(Impl->getLocation(), |
| diag::note_odr_objc_missing_superclass); |
| if (D->getSuperClass()) |
| Importer.FromDiag(D->getLocation(), |
| diag::note_odr_objc_superclass) |
| << D->getSuperClass()->getDeclName(); |
| else |
| Importer.FromDiag(D->getLocation(), |
| diag::note_odr_objc_missing_superclass); |
| |
| return make_error<ImportError>(ImportError::NameConflict); |
| } |
| } |
| |
| // Import all of the members of this @implementation. |
| if (Error Err = ImportDeclContext(D)) |
| return std::move(Err); |
| |
| return Impl; |
| } |
| |
| ExpectedDecl ASTNodeImporter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) { |
| // Import the major distinguishing characteristics of an @property. |
| DeclContext *DC, *LexicalDC; |
| DeclarationName Name; |
| SourceLocation Loc; |
| NamedDecl *ToD; |
| if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) |
| return std::move(Err); |
| if (ToD) |
| return ToD; |
| |
| // Check whether we have already imported this property. |
| auto FoundDecls = Importer.findDeclsInToCtx(DC, Name); |
| for (auto *FoundDecl : FoundDecls) { |
| if (auto *FoundProp = dyn_cast<ObjCPropertyDecl>(FoundDecl)) { |
| // Check property types. |
| if (!Importer.IsStructurallyEquivalent(D->getType(), |
| FoundProp->getType())) { |
| Importer.ToDiag(Loc, diag::warn_odr_objc_property_type_inconsistent) |
| << Name << D->getType() << FoundProp->getType(); |
| Importer.ToDiag(FoundProp->getLocation(), diag::note_odr_value_here) |
| << FoundProp->getType(); |
| |
| return make_error<ImportError>(ImportError::NameConflict); |
| } |
| |
| // FIXME: Check property attributes, getters, setters, etc.? |
| |
| // Consider these properties to be equivalent. |
| Importer.MapImported(D, FoundProp); |
| return FoundProp; |
| } |
| } |
| |
| Error Err = Error::success(); |
| auto ToType = importChecked(Err, D->getType()); |
| auto ToTypeSourceInfo = importChecked(Err, D->getTypeSourceInfo()); |
| auto ToAtLoc = importChecked(Err, D->getAtLoc()); |
| auto ToLParenLoc = importChecked(Err, D->getLParenLoc()); |
| if (Err) |
| return std::move(Err); |
| |
| // Create the new property. |
| ObjCPropertyDecl *ToProperty; |
| if (GetImportedOrCreateDecl( |
| ToProperty, D, Importer.getToContext(), DC, Loc, |
| Name.getAsIdentifierInfo(), ToAtLoc, |
| ToLParenLoc, ToType, |
| ToTypeSourceInfo, D->getPropertyImplementation())) |
| return ToProperty; |
| |
| auto ToGetterName = importChecked(Err, D->getGetterName()); |
| auto ToSetterName = importChecked(Err, D->getSetterName()); |
| auto ToGetterNameLoc = importChecked(Err, D->getGetterNameLoc()); |
| auto ToSetterNameLoc = importChecked(Err, D->getSetterNameLoc()); |
| auto ToGetterMethodDecl = importChecked(Err, D->getGetterMethodDecl()); |
| auto ToSetterMethodDecl = importChecked(Err, D->getSetterMethodDecl()); |
| auto ToPropertyIvarDecl = importChecked(Err, D->getPropertyIvarDecl()); |
| if (Err) |
| return std::move(Err); |
| |
| ToProperty->setLexicalDeclContext(LexicalDC); |
| LexicalDC->addDeclInternal(ToProperty); |
| |
| ToProperty->setPropertyAttributes(D->getPropertyAttributes()); |
| ToProperty->setPropertyAttributesAsWritten( |
| D->getPropertyAttributesAsWritten()); |
| ToProperty->setGetterName(ToGetterName, ToGetterNameLoc); |
| ToProperty->setSetterName(ToSetterName, ToSetterNameLoc); |
| ToProperty->setGetterMethodDecl(ToGetterMethodDecl); |
| ToProperty->setSetterMethodDecl(ToSetterMethodDecl); |
| ToProperty->setPropertyIvarDecl(ToPropertyIvarDecl); |
| return ToProperty; |
| } |
| |
| ExpectedDecl |
| ASTNodeImporter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) { |
| ObjCPropertyDecl *Property; |
| if (Error Err = importInto(Property, D->getPropertyDecl())) |
| return std::move(Err); |
| |
| DeclContext *DC, *LexicalDC; |
| if (Error Err = ImportDeclContext(D, DC, LexicalDC)) |
| return std::move(Err); |
| |
| auto *InImpl = cast<ObjCImplDecl>(LexicalDC); |
| |
| // Import the ivar (for an @synthesize). |
| ObjCIvarDecl *Ivar = nullptr; |
| if (Error Err = importInto(Ivar, D->getPropertyIvarDecl())) |
| return std::move(Err); |
| |
| ObjCPropertyImplDecl *ToImpl |
| = InImpl->FindPropertyImplDecl(Property->getIdentifier(), |
| Property->getQueryKind()); |
| if (!ToImpl) { |
| |
| Error Err = Error::success(); |
| auto ToBeginLoc = importChecked(Err, D->getBeginLoc()); |
| auto ToLocation = importChecked(Err, D->getLocation()); |
| auto ToPropertyIvarDeclLoc = |
| importChecked(Err, D->getPropertyIvarDeclLoc()); |
| if (Err) |
| return std::move(Err); |
| |
| if (GetImportedOrCreateDecl(ToImpl, D, Importer.getToContext(), DC, |
| ToBeginLoc, |
| ToLocation, Property, |
| D->getPropertyImplementation(), Ivar, |
| ToPropertyIvarDeclLoc)) |
| return ToImpl; |
| |
| ToImpl->setLexicalDeclContext(LexicalDC); |
| LexicalDC->addDeclInternal(ToImpl); |
| } else { |
| // Check that we have the same kind of property implementation (@synthesize |
| // vs. @dynamic). |
| if (D->getPropertyImplementation() != ToImpl->getPropertyImplementation()) { |
| Importer.ToDiag(ToImpl->getLocation(), |
| diag::warn_odr_objc_property_impl_kind_inconsistent) |
| << Property->getDeclName() |
| << (ToImpl->getPropertyImplementation() |
| == ObjCPropertyImplDecl::Dynamic); |
| Importer.FromDiag(D->getLocation(), |
| diag::note_odr_objc_property_impl_kind) |
| << D->getPropertyDecl()->getDeclName() |
| << (D->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic); |
| |
| return make_error<ImportError>(ImportError::NameConflict); |
| } |
| |
| // For @synthesize, check that we have the same |
| if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize && |
| Ivar != ToImpl->getPropertyIvarDecl()) { |
| Importer.ToDiag(ToImpl->getPropertyIvarDeclLoc(), |
| diag::warn_odr_objc_synthesize_ivar_inconsistent) |
| << Property->getDeclName() |
| << ToImpl->getPropertyIvarDecl()->getDeclName() |
| << Ivar->getDeclName(); |
| Importer.FromDiag(D->getPropertyIvarDeclLoc(), |
| diag::note_odr_objc_synthesize_ivar_here) |
| << D->getPropertyIvarDecl()->getDeclName(); |
| |
| return make_error<ImportError>(ImportError::NameConflict); |
| } |
| |
| // Merge the existing implementation with the new implementation. |
| Importer.MapImported(D, ToImpl); |
| } |
| |
| return ToImpl; |
| } |
| |
| ExpectedDecl |
| ASTNodeImporter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) { |
| // For template arguments, we adopt the translation unit as our declaration |
| // context. This context will be fixed when the actual template declaration |
| // is created. |
| |
| 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 ToNNS = importChecked(Err, TC->getNestedNameSpecifierLoc()); |
| auto ToName = importChecked(Err, TC->getConceptNameInfo().getName()); |
| auto ToNameLoc = importChecked(Err, TC->getConceptNameInfo().getLoc()); |
| auto ToFoundDecl = importChecked(Err, TC->getFoundDecl()); |
| auto ToNamedConcept = importChecked(Err, TC->getNamedConcept()); |
| auto ToIDC = importChecked(Err, TC->getImmediatelyDeclaredConstraint()); |
| if (Err) |
| return std::move(Err); |
| |
| TemplateArgumentListInfo ToTAInfo; |
| const auto *ASTTemplateArgs = TC->getTemplateArgsAsWritten(); |
| if (ASTTemplateArgs) |
| if (Error Err = ImportTemplateArgumentListInfo(*ASTTemplateArgs, |
| ToTAInfo)) |
| return std::move(Err); |
| |
| ToD->setTypeConstraint(ToNNS, DeclarationNameInfo(ToName, ToNameLoc), |
| ToFoundDecl, ToNamedConcept, |
| ASTTemplateArgs ? |
| ASTTemplateArgumentListInfo::Create(Importer.getToContext(), |
| ToTAInfo) : nullptr, |
| ToIDC); |
| } |
| |
| if (D->hasDefaultArgument()) { |
| Expected<TypeSourceInfo *> ToDefaultArgOrErr = |
| import(D->getDefaultArgumentInfo()); |
| if (!ToDefaultArgOrErr) |
| return ToDefaultArgOrErr.takeError(); |
| ToD->setDefaultArgument(*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()) { |
| ExpectedExpr ToDefaultArgOrErr = import(D->getDefaultArgument()); |
| if (!ToDefaultArgOrErr) |
| return ToDefaultArgOrErr.takeError(); |
| ToD->setDefaultArgument(*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(), *TemplateParamsOrErr)) |
| return ToD; |
| |
| if (D->hasDefaultArgument()) { |
| Expected<TemplateArgumentLoc> 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 <typename T> static auto getTemplateDefinition(T *D) -> T * { |
| assert(D->getTemplatedDecl() && "Should be called on templates only"); |
| auto *ToTemplatedDef = D->getTemplatedDecl()->getDefinition(); |
| if (!ToTemplatedDef) |
| return nullptr; |
| auto *TemplateWithDef = ToTemplatedDef->getDescribedTemplate(); |
| return cast_or_null<T>(TemplateWithDef); |
| } |
| |
| ExpectedDecl ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) { |
| |
| // Import the major distinguishing characteristics of this class template. |
| DeclContext *DC, *LexicalDC; |
| DeclarationName Name; |
| SourceLocation Loc; |
| NamedDecl *ToD; |
| if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) |
| return std::move(Err); |
| if (ToD) |
| return ToD; |
| |
| ClassTemplateDecl *FoundByLookup = nullptr; |
| |
| // We may already have a template of the same name; try to find and match it. |
| if (!DC->isFunctionOrMethod()) { |
| SmallVector<NamedDecl *, 4> ConflictingDecls; |
| auto FoundDecls = Importer.findDeclsInToCtx(DC, Name); |
| for (auto *FoundDecl : FoundDecls) { |
| if (!FoundDecl->isInIdentifierNamespace(Decl::IDNS_Ordinary | |
| Decl::IDNS_TagFriend)) |
| continue; |
| |
| Decl *Found = FoundDecl; |
| auto *FoundTemplate = dyn_cast<ClassTemplateDecl>(Found); |
| if (FoundTemplate) { |
| if (!hasSameVisibilityContextAndLinkage(FoundTemplate, D)) |
| continue; |
| |
| if (IsStructuralMatch(D, FoundTemplate)) { |
| ClassTemplateDecl *TemplateWithDef = |
| getTemplateDefinition(FoundTemplate); |
| if (D->isThisDeclarationADefinition() && TemplateWithDef) |
| return Importer.MapImported(D, TemplateWithDef); |
| if (!FoundByLookup) |
| FoundByLookup = FoundTemplate; |
| // Search in all matches because there may be multiple decl chains, |
| // see ASTTests test ImportExistingFriendClassTemplateDef. |
| continue; |
| } |
| ConflictingDecls.push_back(FoundDecl); |
| } |
| } |
| |
| if (!ConflictingDecls.empty()) { |
| ExpectedName NameOrErr = Importer.HandleNameConflict( |
| Name, DC, Decl::IDNS_Ordinary, ConflictingDecls.data(), |
| ConflictingDecls.size()); |
| if (NameOrErr) |
| Name = NameOrErr.get(); |
| else |
| return NameOrErr.takeError(); |
| } |
| } |
| |
| CXXRecordDecl *FromTemplated = D->getTemplatedDecl(); |
| |
| 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); |
| |
| if (FoundByLookup) { |
| auto *Recent = |
| const_cast<ClassTemplateDecl *>(FoundByLookup->getMostRecentDecl()); |
| |
| // It is possible that during the import of the class template definition |
| // we start the import of a fwd friend decl of the very same class template |
| // and we add the fwd friend decl to the lookup table. But the ToTemplated |
| // had been created earlier and by that time the lookup could not find |
| // anything existing, so it has no previous decl. Later, (still during the |
| // import of the fwd friend decl) we start to import the definition again |
| // and this time the lookup finds the previous fwd friend class template. |
| // In this case we must set up the previous decl for the templated decl. |
| if (!ToTemplated->getPreviousDecl()) { |
| assert(FoundByLookup->getTemplatedDecl() && |
| "Found decl must have its templated decl set"); |
| CXXRecordDecl *PrevTemplated = |
| FoundByLookup->getTemplatedDecl()->getMostRecentDecl(); |
| if (ToTemplated != PrevTemplated) |
| ToTemplated->setPreviousDecl(PrevTemplated); |
| } |
| |
| D2->setPreviousDecl(Recent); |
| } |
| |
| if (FromTemplated->isCompleteDefinition() && |
| !ToTemplated->isCompleteDefinition()) { |
| // FIXME: Import definition! |
| } |
| |
| return D2; |
| } |
| |
| ExpectedDecl ASTNodeImporter::VisitClassTemplateSpecializationDecl( |
| ClassTemplateSpecializationDecl *D) { |
| ClassTemplateDecl *ClassTemplate; |
| if (Error Err = importInto(ClassTemplate, D->getSpecializedTemplate())) |
| return std::move(Err); |
| |
| // Import the context of this declaration. |
| DeclContext *DC, *LexicalDC; |
| if (Error Err = ImportDeclContext(D, DC, LexicalDC)) |
| return std::move(Err); |
| |
| // Import template arguments. |
| SmallVector<TemplateArgument, 2> TemplateArgs; |
| if (Error Err = ImportTemplateArguments( |
| D->getTemplateArgs().data(), D->getTemplateArgs().size(), TemplateArgs)) |
| return std::move(Err); |
| // Try to find an existing specialization with these template arguments and |
| // template parameter list. |
| void *InsertPos = nullptr; |
| ClassTemplateSpecializationDecl *PrevDecl = nullptr; |
| ClassTemplatePartialSpecializationDecl *PartialSpec = |
| dyn_cast<ClassTemplatePartialSpecializationDecl>(D); |
| |
| // Import template parameters. |
| TemplateParameterList *ToTPList = nullptr; |
| |
| if (PartialSpec) { |
| auto ToTPListOrErr = import(PartialSpec->getTemplateParameters()); |
| if (!ToTPListOrErr) |
| return ToTPListOrErr.takeError(); |
| ToTPList = *ToTPListOrErr; |
| PrevDecl = ClassTemplate->findPartialSpecialization(TemplateArgs, |
| *ToTPListOrErr, |
| InsertPos); |
| } else |
| PrevDecl = ClassTemplate->findSpecialization(TemplateArgs, InsertPos); |
| |
| if (PrevDecl) { |
| if (IsStructuralMatch(D, PrevDecl)) { |
| CXXRecordDecl *PrevDefinition = PrevDecl->getDefinition(); |
| if (D->isThisDeclarationADefinition() && PrevDefinition) { |
| Importer.MapImported(D, PrevDefinition); |
| // Import those default field initializers which have been |
| // instantiated in the "From" context, but not in the "To" context. |
| for (auto *FromField : D->fields()) { |
| auto ToOrErr = import(FromField); |
| if (!ToOrErr) |
| return ToOrErr.takeError(); |
| } |
| |
| // Import those methods which have been instantiated in the |
| // "From" context, but not in the "To" context. |
| for (CXXMethodDecl *FromM : D->methods()) { |
| auto ToOrErr = import(FromM); |
| if (!ToOrErr) |
| return ToOrErr.takeError(); |
| } |
| |
| // TODO Import instantiated default arguments. |
| // TODO Import instantiated exception specifications. |
| // |
| // Generally, ASTCommon.h/DeclUpdateKind enum gives a very good hint |
| // what else could be fused during an AST merge. |
| return PrevDefinition; |
| } |
| } else { // ODR violation. |
| // FIXME HandleNameConflict |
| return make_error<ImportError>(ImportError::NameConflict); |
| } |
| } |
| |
| // Import the location of this declaration. |
| ExpectedSLoc BeginLocOrErr = import(D->getBeginLoc()); |
| if (!BeginLocOrErr) |
| return BeginLocOrErr.takeError(); |
| ExpectedSLoc IdLocOrErr = import(D->getLocation()); |
| if (!IdLocOrErr) |
| return IdLocOrErr.takeError(); |
| |
| // Create the specialization. |
| ClassTemplateSpecializationDecl *D2 = nullptr; |
| if (PartialSpec) { |
| // Import TemplateArgumentListInfo. |
| TemplateArgumentListInfo ToTAInfo; |
| const auto &ASTTemplateArgs = *PartialSpec->getTemplateArgsAsWritten(); |
| if (Error Err = ImportTemplateArgumentListInfo(ASTTemplateArgs, ToTAInfo)) |
| return std::move(Err); |
| |
| QualType CanonInjType; |
| if (Error Err = importInto( |
| CanonInjType, PartialSpec->getInjectedSpecializationType())) |
| return std::move(Err); |
| CanonInjType = CanonInjType.getCanonicalType(); |
| |
| if (GetImportedOrCreateDecl<ClassTemplatePartialSpecializationDecl>( |
| D2, D, Importer.getToContext(), D->getTagKind(), DC, |
| *BeginLocOrErr, *IdLocOrErr, ToTPList, ClassTemplate, |
| llvm::makeArrayRef(TemplateArgs.data(), TemplateArgs.size()), |
| ToTAInfo, CanonInjType, |
| cast_or_null<ClassTemplatePartialSpecializationDecl>(PrevDecl))) |
| return D2; |
| |
| // Update InsertPos, because preceding import calls may have invalidated |
| // it by adding new specializations. |
| auto *PartSpec2 = cast<ClassTemplatePartialSpecializationDecl>(D2); |
| if (!ClassTemplate->findPartialSpecialization(TemplateArgs, ToTPList, |
| InsertPos)) |
| // Add this partial specialization to the class template. |
| ClassTemplate->AddPartialSpecialization(PartSpec2, InsertPos); |
| |
| } else { // Not a partial specialization. |
| if (GetImportedOrCreateDecl( |
| D2, D, Importer.getToContext(), D->getTagKind(), DC, |
| *BeginLocOrErr, *IdLocOrErr, ClassTemplate, TemplateArgs, |
| PrevDecl)) |
| return D2; |
| |
| // Update InsertPos, because preceding import calls may have invalidated |
| // it by adding new specializations. |
| if (!ClassTemplate->findSpecialization(TemplateArgs, InsertPos)) |
| // Add this specialization to the class template. |
| ClassTemplate->AddSpecialization(D2, InsertPos); |
| } |
| |
| D2->setSpecializationKind(D->getSpecializationKind()); |
| |
| // Set the context of this specialization/instantiation. |
| D2->setLexicalDeclContext(LexicalDC); |
| |
| // Add to the DC only if it was an explicit specialization/instantiation. |
| if (D2->isExplicitInstantiationOrSpecialization()) { |
| LexicalDC->addDeclInternal(D2); |
| } |
| |
| if (auto BraceRangeOrErr = import(D->getBraceRange())) |
| D2->setBraceRange(*BraceRangeOrErr); |
| else |
| return BraceRangeOrErr.takeError(); |
| |
| // Import the qualifier, if any. |
| if (auto LocOrErr = import(D->getQualifierLoc())) |
| D2->setQualifierInfo(*LocOrErr); |
| else |
| return LocOrErr.takeError(); |
| |
| if (auto *TSI = D->getTypeAsWritten()) { |
| if (auto TInfoOrErr = import(TSI)) |
| D2->setTypeAsWritten(*TInfoOrErr); |
| else |
| return TInfoOrErr.takeError(); |
| |
| if (auto LocOrErr = import(D->getTemplateKeywordLoc())) |
| D2->setTemplateKeywordLoc(*LocOrErr); |
| else |
| return LocOrErr.takeError(); |
| |
| if (auto LocOrErr = import(D->getExternLoc())) |
| D2->setExternLoc(*LocOrErr); |
| else |
| return LocOrErr.takeError(); |
| } |
| |
| if (D->getPointOfInstantiation().isValid()) { |
| if (auto POIOrErr = import(D->getPointOfInstantiation())) |
| D2->setPointOfInstantiation(*POIOrErr); |
| else |
| return POIOrErr.takeError(); |
| } |
| |
| D2->setTemplateSpecializationKind(D->getTemplateSpecializationKind()); |
| |
| if (D->isCompleteDefinition()) |
| if (Error Err = ImportDefinition(D, D2)) |
| return std::move(Err); |
| |
| return D2; |
| } |
| |
| ExpectedDecl ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) { |
| // Import the major distinguishing characteristics of this variable template. |
| DeclContext *DC, *LexicalDC; |
| DeclarationName Name; |
| SourceLocation Loc; |
| NamedDecl *ToD; |
| if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) |
| return std::move(Err); |
| if (ToD) |
| return ToD; |
| |
| // We may already have a template of the same name; try to find and match it. |
| assert(!DC->isFunctionOrMethod() && |
| "Variable templates cannot be declared at function scope"); |
| |
| SmallVector<NamedDecl *, 4> ConflictingDecls; |
| auto FoundDecls = Importer.findDeclsInToCtx(DC, Name); |
| VarTemplateDecl *FoundByLookup = nullptr; |
| for (auto *FoundDecl : FoundDecls) { |
| if (!FoundDecl->isInIdentifierNamespace(Decl::IDNS_Ordinary)) |
| continue; |
| |
| if (VarTemplateDecl *FoundTemplate = dyn_cast<VarTemplateDecl>(FoundDecl)) { |
| // Use the templated decl, some linkage flags are set only there. |
| if (!hasSameVisibilityContextAndLinkage(FoundTemplate->getTemplatedDecl(), |
| D->getTemplatedDecl())) |
| continue; |
| if (IsStructuralMatch(D, FoundTemplate)) { |
| // The Decl in the "From" context has a definition, but in the |
| // "To" context we already have a definition. |
| VarTemplateDecl *FoundDef = getTemplateDefinition(FoundTemplate); |
| if (D->isThisDeclarationADefinition() && FoundDef) |
| // FIXME Check for ODR error if the two definitions have |
| // different initializers? |
| 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 (FoundByLookup) { |
| auto *Recent = |
| const_cast<VarTemplateDecl *>(FoundByLookup->getMostRecentDecl()); |
| if (!ToTemplated->getPreviousDecl()) { |
| auto *PrevTemplated = |
| FoundByLookup->getTemplatedDecl()->getMostRecentDecl(); |
| if (ToTemplated != PrevTemplated) |
| ToTemplated->setPreviousDecl(PrevTemplated); |
| } |
| ToVarTD->setPreviousDecl(Recent); |
| } |
| |
| if (DTemplated->isThisDeclarationADefinition() && |
| !ToTemplated->isThisDeclarationADefinition()) { |
| // FIXME: Import definition! |
| } |
| |
| return ToVarTD; |
| } |
| |
| ExpectedDecl ASTNodeImporter::VisitVarTemplateSpecializationDecl( |
| VarTemplateSpecializationDecl *D) { |
| // If this record has a definition in the translation unit we're coming from, |
| // but this particular declaration is not that definition, import the |
| // definition and map to that. |
| VarDecl *Definition = D->getDefinition(); |
| if (Definition && Definition != D) { |
| if (ExpectedDecl ImportedDefOrErr = import(Definition)) |
| return Importer.MapImported(D, *ImportedDefOrErr); |
| else |
| return ImportedDefOrErr.takeError(); |
| } |
| |
| VarTemplateDecl *VarTemplate = nullptr; |
| if (Error Err = importInto(VarTemplate, D->getSpecializedTemplate())) |
| return std::move(Err); |
| |
| // Import the context of this declaration. |
| DeclContext *DC, *LexicalDC; |
| if (Error Err = ImportDeclContext(D, DC, LexicalDC)) |
| return std::move(Err); |
| |
| // Import the location of this declaration. |
| ExpectedSLoc BeginLocOrErr = import(D->getBeginLoc()); |
| if (!BeginLocOrErr) |
| return BeginLocOrErr.takeError(); |
| |
| auto IdLocOrErr = import(D->getLocation()); |
| if (!IdLocOrErr) |
| return IdLocOrErr.takeError(); |
| |
| // Import template arguments. |
| SmallVector<TemplateArgument, 2> TemplateArgs; |
| if (Error Err = ImportTemplateArguments( |
| D->getTemplateArgs().data(), D->getTemplateArgs().size(), TemplateArgs)) |
| return std::move(Err); |
| |
| // Try to find an existing specialization with these template arguments. |
| void *InsertPos = nullptr; |
| VarTemplateSpecializationDecl *D2 = VarTemplate->findSpecialization( |
| TemplateArgs, InsertPos); |
| if (D2) { |
| // We already have a variable template specialization with these template |
| // arguments. |
| |
| // FIXME: Check for specialization vs. instantiation errors. |
| |
| if (VarDecl *FoundDef = D2->getDefinition()) { |
| if (!D->isThisDeclarationADefinition() || |
| IsStructuralMatch(D, FoundDef)) { |
| // The record types structurally match, or the "from" translation |
| // unit only had a forward declaration anyway; call it the same |
| // variable. |
| return Importer.MapImported(D, FoundDef); |
| } |
| } |
| } else { |
| // Import the type. |
| QualType T; |
| if (Error Err = importInto(T, D->getType())) |
| return std::move(Err); |
| |
| auto TInfoOrErr = import(D->getTypeSourceInfo()); |
| if (!TInfoOrErr) |
| return TInfoOrErr.takeError(); |
| |
| TemplateArgumentListInfo ToTAInfo; |
| if (Error Err = ImportTemplateArgumentListInfo( |
| D->getTemplateArgsInfo(), ToTAInfo)) |
| return std::move(Err); |
| |
| using PartVarSpecDecl = VarTemplatePartialSpecializationDecl; |
| // Create a new specialization. |
| if (auto *FromPartial = dyn_cast<PartVarSpecDecl>(D)) { |
| // Import TemplateArgumentListInfo |
| TemplateArgumentListInfo ArgInfos; |
| const auto *FromTAArgsAsWritten = FromPartial->getTemplateArgsAsWritten(); |
| // NOTE: FromTAArgsAsWritten and template parameter list are non-null. |
| if (Error Err = ImportTemplateArgumentListInfo( |
| *FromTAArgsAsWritten, ArgInfos)) |
| return std::move(Err); |
| |
| auto ToTPListOrErr = import(FromPartial->getTemplateParameters()); |
| if (!ToTPListOrErr) |
| return ToTPListOrErr.takeError(); |
| |
| PartVarSpecDecl *ToPartial; |
| if (GetImportedOrCreateDecl(ToPartial, D, Importer.getToContext(), DC, |
| *BeginLocOrErr, *IdLocOrErr, *ToTPListOrErr, |
| VarTemplate, T, *TInfoOrErr, |
| D->getStorageClass(), TemplateArgs, ArgInfos)) |
| return ToPartial; |
| |
| if (Expected<PartVarSpecDecl *> ToInstOrErr = import( |
| FromPartial->getInstantiatedFromMember())) |
| ToPartial->setInstantiatedFromMember(*ToInstOrErr); |
| else |
| return ToInstOrErr.takeError(); |
| |
| if (FromPartial->isMemberSpecialization()) |
| ToPartial->setMemberSpecialization(); |
| |
| D2 = ToPartial; |
| |
| } else { // Full specialization |
| if (GetImportedOrCreateDecl(D2, D, Importer.getToContext(), DC, |
| *BeginLocOrErr, *IdLocOrErr, VarTemplate, |
| T, *TInfoOrErr, |
| D->getStorageClass(), TemplateArgs)) |
| return D2; |
| } |
| |
| if (D->getPointOfInstantiation().isValid()) { |
| if (ExpectedSLoc POIOrErr = import(D->getPointOfInstantiation())) |
| D2->setPointOfInstantiation(*POIOrErr); |
| else |
| return POIOrErr.takeError(); |
| } |
| |
| D2->setSpecializationKind(D->getSpecializationKind()); |
| D2->setTemplateArgsInfo(ToTAInfo); |
| |
| // Add this specialization to the class template. |
| VarTemplate->AddSpecialization(D2, InsertPos); |
| |
| // Import the qualifier, if any. |
| if (auto LocOrErr = import(D->getQualifierLoc())) |
| D2->setQualifierInfo(*LocOrErr); |
| else |
| return LocOrErr.takeError(); |
| |
| if (D->isConstexpr()) |
| D2->setConstexpr(true); |
| |
| // Add the specialization to this context. |
| D2->setLexicalDeclContext(LexicalDC); |
| LexicalDC->addDeclInternal(D2); |
| |
| D2->setAccess(D->getAccess()); |
| } |
| |
| if (Error Err = ImportInitializer(D, D2)) |
| return std::move(Err); |
| |
| return D2; |
| } |
| |
| ExpectedDecl |
| ASTNodeImporter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { |
| DeclContext *DC, *LexicalDC; |
| DeclarationName Name; |
| SourceLocation Loc; |
| NamedDecl *ToD; |
| |
| if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) |
| return std::move(Err); |
| |
| if (ToD) |
| return ToD; |
| |
| const FunctionTemplateDecl *FoundByLookup = nullptr; |
| |
| // Try to find a function in our own ("to") context with the same name, same |
| // type, and in the same context as the function we're importing. |
| // FIXME Split this into a separate function. |
| if (!LexicalDC->isFunctionOrMethod()) { |
| unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_OrdinaryFriend; |
| auto FoundDecls = Importer.findDeclsInToCtx(DC, Name); |
| for (auto *FoundDecl : FoundDecls) { |
| if (!FoundDecl->isInIdentifierNamespace(IDNS)) |
| continue; |
| |
| if (auto *FoundTemplate = dyn_cast<FunctionTemplateDecl>(FoundDecl)) { |
| if (!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(); |
| |
| FunctionDecl *TemplatedFD; |
| if (Error Err = importInto(TemplatedFD, D->getTemplatedDecl())) |
| return std::move(Err); |
| |
| FunctionTemplateDecl *ToFunc; |
| if (GetImportedOrCreateDecl(ToFunc, D, Importer.getToContext(), DC, Loc, Name, |
| *ParamsOrErr, TemplatedFD)) |
| return ToFunc; |
| |
| TemplatedFD->setDescribedFunctionTemplate(ToFunc); |
| |
| ToFunc->setAccess(D->getAccess()); |
| ToFunc->setLexicalDeclContext(LexicalDC); |
| LexicalDC->addDeclInternal(ToFunc); |
| |
| if (FoundByLookup) { |
| auto *Recent = |
| const_cast<FunctionTemplateDecl *>(FoundByLookup->getMostRecentDecl()); |
| if (!TemplatedFD->getPreviousDecl()) { |
| assert(FoundByLookup->getTemplatedDecl() && |
| "Found decl must have its templated decl set"); |
| auto *PrevTemplated = |
| FoundByLookup->getTemplatedDecl()->getMostRecentDecl(); |
| if (TemplatedFD != PrevTemplated) |
| TemplatedFD->setPreviousDecl(PrevTemplated); |
| } |
| ToFunc->setPreviousDecl(Recent); |
| } |
| |
| return ToFunc; |
| } |
| |
| //---------------------------------------------------------------------------- |
| // Import Statements |
| //---------------------------------------------------------------------------- |
| |
| ExpectedStmt ASTNodeImporter::VisitStmt(Stmt *S) { |
| Importer.FromDiag(S->getBeginLoc(), diag::err_unsupported_ast_node) |
| << S->getStmtClassName(); |
| return make_error<ImportError>(ImportError::UnsupportedConstruct); |
| } |
| |
| |
| ExpectedStmt ASTNodeImporter::VisitGCCAsmStmt(GCCAsmStmt *S) { |
| if (Importer.returnWithErrorInTest()) |
| return make_error<ImportError>(ImportError::UnsupportedConstruct); |
| SmallVector<IdentifierInfo *, 4> Names; |
| for (unsigned I = 0, E = S->getNumOutputs(); I != E; I++) { |
| IdentifierInfo *ToII = Importer.Import(S->getOutputIdentifier(I)); |
| // ToII is nullptr when no symbolic name is given for output operand |
| // see ParseStmtAsm::ParseAsmOperandsOpt |
| Names.push_back(ToII); |
| } |
| |
| for (unsigned I = 0, E = S->getNumInputs(); I != E; I++) { |
| IdentifierInfo *ToII = Importer.Import(S->getInputIdentifier(I)); |
| // ToII is nullptr when no symbolic name is given for input operand |
| // see ParseStmtAsm::ParseAsmOperandsOpt |
| Names.push_back(ToII); |
| } |
| |
| SmallVector<StringLiteral *, 4> Clobbers; |
| for (unsigned I = 0, E = S->getNumClobbers(); I != E; I++) { |
| if (auto ClobberOrErr = import(S->getClobberStringLiteral(I))) |
| Clobbers.push_back(*ClobberOrErr); |
| else |
| return ClobberOrErr.takeError(); |
| |
| } |
| |
| SmallVector<StringLiteral *, 4> Constraints; |
| for (unsigned I = 0, E = S->getNumOutputs(); I != E; I++) { |
| if (auto OutputOrErr = import(S->getOutputConstraintLiteral(I))) |
| Constraints.push_back(*OutputOrErr); |
| else |
| return OutputOrErr.takeError(); |
| } |
| |
| for (unsigned I = 0, E = S->getNumInputs(); I != E; I++) { |
| if (auto InputOrErr = import(S->getInputConstraintLiteral(I))) |
| Constraints.push_back(*InputOrErr); |
| else |
| return InputOrErr.takeError(); |
| } |
| |
| SmallVector<Expr *, 4> Exprs(S->getNumOutputs() + S->getNumInputs() + |
| S->getNumLabels()); |
| if (Error Err = ImportContainerChecked(S->outputs(), Exprs)) |
| return std::move(Err); |
| |
| if (Error Err = |
| ImportArrayChecked(S->inputs(), Exprs.begin() + S->getNumOutputs())) |
| return std::move(Err); |
| |
| if (Error Err = ImportArrayChecked( |
| S->labels(), Exprs.begin() + S->getNumOutputs() + S->getNumInputs())) |
| return std::move(Err); |
| |
| ExpectedSLoc AsmLocOrErr = import(S->getAsmLoc()); |
| if (!AsmLocOrErr) |
| return AsmLocOrErr.takeError(); |
| auto AsmStrOrErr = import(S->getAsmString()); |
| if (!AsmStrOrErr) |
| return AsmStrOrErr.takeError(); |
| ExpectedSLoc RParenLocOrErr = import(S->getRParenLoc()); |
| if (!RParenLocOrErr) |
| return RParenLocOrErr.takeError(); |
| |
| return new (Importer.getToContext()) GCCAsmStmt( |
| Importer.getToContext(), |
| *AsmLocOrErr, |
| S->isSimple(), |
| S->isVolatile(), |
| S->getNumOutputs(), |
| S->getNumInputs(), |
| Names.data(), |
| Constraints.data(), |
| Exprs.data(), |
| *AsmStrOrErr, |
| S->getNumClobbers(), |
| Clobbers.data(), |
| S->getNumLabels(), |
| *RParenLocOrErr); |
| } |
| |
| ExpectedStmt ASTNodeImporter::VisitDeclStmt(DeclStmt *S) { |
| |
| Error Err = Error::success(); |
| auto ToDG = importChecked(Err, S->getDeclGroup()); |
| auto ToBeginLoc = importChecked(Err, S->getBeginLoc()); |
| auto ToEndLoc = importChecked(Err, S->getEndLoc()); |
| if (Err) |
| return std::move(Err); |
| return new (Importer.getToContext()) DeclStmt(ToDG, ToBeginLoc, ToEndLoc); |
| } |
| |
| ExpectedStmt ASTNodeImporter::VisitNullStmt(NullStmt *S) { |
| ExpectedSLoc ToSemiLocOrErr = import(S->getSemiLoc()); |
| if (!ToSemiLocOrErr) |
| return ToSemiLocOrErr.takeError(); |
| return new (Importer.getToContext()) NullStmt( |
| *ToSemiLocOrErr, S->hasLeadingEmptyMacro()); |
| } |
| |
| ExpectedStmt ASTNodeImporter::VisitCompoundStmt(CompoundStmt *S) { |
| SmallVector<Stmt *, 8> ToStmts(S->size()); |
| |
| if (Error Err = ImportContainerChecked(S->body(), ToStmts)) |
| return std::move(Err); |
| |
| ExpectedSLoc ToLBracLocOrErr = import(S->getLBracLoc()); |
| if (!ToLBracLocOrErr) |
| return ToLBracLocOrErr.takeError(); |
| |
| ExpectedSLoc ToRBracLocOrErr = import(S->getRBracLoc()); |
| if (!ToRBracLocOrErr) |
| return ToRBracLocOrErr.takeError(); |
| |
| return CompoundStmt::Create( |
| Importer.getToContext(), ToStmts, |
| *ToLBracLocOrErr, *ToRBracLocOrErr); |
| } |
| |
| ExpectedStmt ASTNodeImporter::VisitCaseStmt(CaseStmt *S) { |
| |
| Error Err = Error::success(); |
| auto ToLHS = importChecked(Err, S->getLHS()); |
| auto ToRHS = importChecked(Err, S->getRHS()); |
| auto ToSubStmt = importChecked(Err, S->getSubStmt()); |
| auto ToCaseLoc = importChecked(Err, S->getCaseLoc()); |
| auto ToEllipsisLoc = importChecked(Err, S->getEllipsisLoc()); |
| auto ToColonLoc = importChecked(Err, S->getColonLoc()); |
| if (Err) |
| return std::move(Err); |
| |
| auto *ToStmt = CaseStmt::Create(Importer.getToContext(), ToLHS, ToRHS, |
| ToCaseLoc, ToEllipsisLoc, ToColonLoc); |
| ToStmt->setSubStmt(ToSubStmt); |
| |
| return ToStmt; |
| } |
| |
| ExpectedStmt ASTNodeImporter::VisitDefaultStmt(DefaultStmt *S) { |
| |
| Error Err = Error::success(); |
| auto ToDefaultLoc = importChecked(Err, S->getDefaultLoc()); |
| auto ToColonLoc = importChecked(Err, S->getColonLoc()); |
| auto ToSubStmt = importChecked(Err, S->getSubStmt()); |
| if (Err) |
| return std::move(Err); |
| |
| return new (Importer.getToContext()) DefaultStmt( |
| ToDefaultLoc, ToColonLoc, ToSubStmt); |
| } |
| |
| ExpectedStmt ASTNodeImporter::VisitLabelStmt(LabelStmt *S) { |
| |
| Error Err = Error::success(); |
| auto ToIdentLoc = importChecked(Err, S->getIdentLoc()); |
| auto ToLabelDecl = importChecked(Err, S->getDecl()); |
| auto ToSubStmt = importChecked(Err, S->getSubStmt()); |
| if (Err) |
| return std::move(Err); |
| |
| return new (Importer.getToContext()) LabelStmt( |
| ToIdentLoc, ToLabelDecl, ToSubStmt); |
| } |
| |
| ExpectedStmt ASTNodeImporter::VisitAttributedStmt(AttributedStmt *S) { |
| ExpectedSLoc ToAttrLocOrErr = import(S->getAttrLoc()); |
| if (!ToAttrLocOrErr) |
| return ToAttrLocOrErr.takeError(); |
| ArrayRef<const Attr*> FromAttrs(S->getAttrs()); |
| SmallVector<const Attr *, 1> ToAttrs(FromAttrs.size()); |
| if (Error Err = ImportContainerChecked(FromAttrs, ToAttrs)) |
| return std::move(Err); |
| ExpectedStmt ToSubStmtOrErr = import(S->getSubStmt()); |
| if (!ToSubStmtOrErr) |
| return ToSubStmtOrErr.takeError(); |
| |
| return AttributedStmt::Create( |
| Importer.getToContext(), *ToAttrLocOrErr, ToAttrs, *ToSubStmtOrErr); |
| } |
| |
| ExpectedStmt ASTNodeImporter::VisitIfStmt(IfStmt *S) { |
| |
| Error Err = Error::success(); |
| auto ToIfLoc = importChecked(Err, S->getIfLoc()); |
| auto ToInit = importChecked(Err, S->getInit()); |
| auto ToConditionVariable = importChecked(Err, S->getConditionVariable()); |
| auto ToCond = importChecked(Err, S->getCond()); |
| auto ToLParenLoc = importChecked(Err, S->getLParenLoc()); |
| auto ToRParenLoc = importChecked(Err, S->getRParenLoc()); |
| auto ToThen = importChecked(Err, S->getThen()); |
| auto ToElseLoc = importChecked(Err, S->getElseLoc()); |
| auto ToElse = importChecked(Err, S->getElse()); |
| if (Err) |
| return std::move(Err); |
| |
| return IfStmt::Create(Importer.getToContext(), ToIfLoc, S->isConstexpr(), |
| ToInit, ToConditionVariable, ToCond, ToLParenLoc, |
| ToRParenLoc, ToThen, ToElseLoc, ToElse); |
| } |
| |
| ExpectedStmt ASTNodeImporter::VisitSwitchStmt(SwitchStmt *S) { |
| |
| Error Err = Error::success(); |
| auto ToInit = importChecked(Err, S->getInit()); |
| auto ToConditionVariable = importChecked(Err, S->getConditionVariable()); |
| auto ToCond = importChecked(Err, S->getCond()); |
| auto ToLParenLoc = importChecked(Err, S->getLParenLoc()); |
| auto ToRParenLoc = importChecked(Err, S->getRParenLoc()); |
| auto ToBody = importChecked(Err, S->getBody()); |
| auto ToSwitchLoc = importChecked(Err, S->getSwitchLoc()); |
| if (Err) |
| return std::move(Err); |
| |
| auto *ToStmt = |
| SwitchStmt::Create(Importer.getToContext(), ToInit, ToConditionVariable, |
| ToCond, ToLParenLoc, ToRParenLoc); |
| ToStmt->setBody(ToBody); |
| ToStmt->setSwitchLoc(ToSwitchLoc); |
| |
| // Now we have to re-chain the cases. |
| SwitchCase *LastChainedSwitchCase = nullptr; |
| for (SwitchCase *SC = S->getSwitchCaseList(); SC != nullptr; |
| SC = SC->getNextSwitchCase()) { |
| Expected<SwitchCase *> ToSCOrErr = import(SC); |
| if (!ToSCOrErr) |
| return ToSCOrErr.takeError(); |
| if (LastChainedSwitchCase) |
| LastChainedSwitchCase->setNextSwitchCase(*ToSCOrErr); |
| else |
| ToStmt->setSwitchCaseList(*ToSCOrErr); |
| LastChainedSwitchCase = *ToSCOrErr; |
| } |
| |
| return ToStmt; |
| } |
| |
| ExpectedStmt ASTNodeImporter::VisitWhileStmt(WhileStmt *S) { |
| |
| Error Err = Error::success(); |
| auto ToConditionVariable = importChecked(Err, S->getConditionVariable()); |
| auto ToCond = importChecked(Err, S->getCond()); |
| auto ToBody = importChecked(Err, S->getBody()); |
| auto ToWhileLoc = importChecked(Err, S->getWhileLoc()); |
| auto ToLParenLoc = importChecked(Err, S->getLParenLoc()); |
| auto ToRParenLoc = importChecked(Err, S->getRParenLoc()); |
| if (Err) |
| return std::move(Err); |
| |
| return WhileStmt::Create(Importer.getToContext(), ToConditionVariable, ToCond, |
| ToBody, ToWhileLoc, ToLParenLoc, ToRParenLoc); |
| } |
| |
| ExpectedStmt ASTNodeImporter::VisitDoStmt(DoStmt *S) { |
| |
| Error Err = Error::success(); |
| auto ToBody = importChecked(Err, S->getBody()); |
| auto ToCond = importChecked(Err, S->getCond()); |
| auto ToDoLoc = importChecked(Err, S->getDoLoc()); |
| auto ToWhileLoc = importChecked(Err, S->getWhileLoc()); |
| auto ToRParenLoc = importChecked(Err, S->getRParenLoc()); |
| if (Err) |
| return std::move(Err); |
| |
| return new (Importer.getToContext()) DoStmt( |
| ToBody, ToCond, ToDoLoc, ToWhileLoc, ToRParenLoc); |
| } |
| |
| ExpectedStmt ASTNodeImporter::VisitForStmt(ForStmt *S) { |
| |
| Error Err = Error::success(); |
| auto ToInit = importChecked(Err, S->getInit()); |
| auto ToCond = importChecked(Err, S->getCond()); |
| auto ToConditionVariable = importChecked(Err, S->getConditionVariable()); |
| auto ToInc = importChecked(Err, S->getInc()); |
| auto ToBody = importChecked(Err, S->getBody()); |
| auto ToForLoc = importChecked(Err, S->getForLoc()); |
| auto ToLParenLoc = importChecked(Err, S->getLParenLoc()); |
| auto ToRParenLoc = importChecked(Err, S->getRParenLoc()); |
| if (Err) |
| return std::move(Err); |
| |
| return new (Importer.getToContext()) ForStmt( |
| Importer.getToContext(), |
| ToInit, ToCond, ToConditionVariable, ToInc, ToBody, ToForLoc, ToLParenLoc, |
| ToRParenLoc); |
| } |
| |
| ExpectedStmt ASTNodeImporter::VisitGotoStmt(GotoStmt *S) { |
| |
| Error Err = Error::success(); |
| auto ToLabel = importChecked(Err, S->getLabel()); |
| auto ToGotoLoc = importChecked(Err, S->getGotoLoc()); |
| auto ToLabelLoc = importChecked(Err, S->getLabelLoc()); |
| if (Err) |
| return std::move(Err); |
| |
| return new (Importer.getToContext()) GotoStmt( |
| ToLabel, ToGotoLoc, ToLabelLoc); |
| } |
| |
| ExpectedStmt ASTNodeImporter::VisitIndirectGotoStmt(IndirectGotoStmt *S) { |
| |
| Error Err = Error::success(); |
| auto ToGotoLoc = importChecked(Err, S->getGotoLoc()); |
| auto ToStarLoc = importChecked(Err, S->getStarLoc()); |
| auto ToTarget = importChecked(Err, S->getTarget()); |
| if (Err) |
| return std::move(Err); |
| |
| return new (Importer.getToContext()) IndirectGotoStmt( |
| ToGotoLoc, ToStarLoc, ToTarget); |
| } |
| |
| ExpectedStmt ASTNodeImporter::VisitContinueStmt(ContinueStmt *S) { |
| ExpectedSLoc ToContinueLocOrErr = import(S->getContinueLoc()); |
| if (!ToContinueLocOrErr) |
| return ToContinueLocOrErr.takeError(); |
| return new (Importer.getToContext()) ContinueStmt(*ToContinueLocOrErr); |
| } |
| |
| ExpectedStmt ASTNodeImporter::VisitBreakStmt(BreakStmt *S) { |
| auto ToBreakLocOrErr = import(S->getBreakLoc()); |
| if (!ToBreakLocOrErr) |
| return ToBreakLocOrErr.takeError(); |
| return new (Importer.getToContext()) BreakStmt(*ToBreakLocOrErr); |
| } |
| |
| ExpectedStmt ASTNodeImporter::VisitReturnStmt(ReturnStmt *S) { |
| |
| Error Err = Error::success(); |
| auto ToReturnLoc = importChecked(Err, S->getReturnLoc()); |
| auto ToRetValue = importChecked(Err, S->getRetValue()); |
| auto ToNRVOCandidate = importChecked(Err, S->getNRVOCandidate()); |
| if (Err) |
| return std::move(Err); |
| |
| return ReturnStmt::Create(Importer.getToContext(), ToReturnLoc, ToRetValue, |
| ToNRVOCandidate); |
| } |
| |
| ExpectedStmt ASTNodeImporter::VisitCXXCatchStmt(CXXCatchStmt *S) { |
| |
| Error Err = Error::success(); |
| auto ToCatchLoc = importChecked(Err, S->getCatchLoc()); |
| auto ToExceptionDecl = importChecked(Err, S->getExceptionDecl()); |
| auto ToHandlerBlock = importChecked(Err, S->getHandlerBlock()); |
| if (Err) |
| return std::move(Err); |
| |
| return new (Importer.getToContext()) CXXCatchStmt ( |
| ToCatchLoc, ToExceptionDecl, ToHandlerBlock); |
| } |
| |
| ExpectedStmt ASTNodeImporter::VisitCXXTryStmt(CXXTryStmt *S) { |
| ExpectedSLoc ToTryLocOrErr = import(S->getTryLoc()); |
| if (!ToTryLocOrErr) |
| return ToTryLocOrErr.takeError(); |
| |
| ExpectedStmt ToTryBlockOrErr = import(S->getTryBlock()); |
| if (!ToTryBlockOrErr) |
| return ToTryBlockOrErr.takeError(); |
| |
| SmallVector<Stmt *, 1> ToHandlers(S->getNumHandlers()); |
| for (unsigned HI = 0, HE = S->getNumHandlers(); HI != HE; ++HI) { |
| CXXCatchStmt *FromHandler = S->getHandler(HI); |
| if (auto ToHandlerOrErr = import(FromHandler)) |
| ToHandlers[HI] = *ToHandlerOrErr; |
| else |
| return ToHandlerOrErr.takeError(); |
| } |
| |
| return CXXTryStmt::Create( |
| Importer.getToContext(), *ToTryLocOrErr,*ToTryBlockOrErr, ToHandlers); |
| } |
| |
| ExpectedStmt ASTNodeImporter::VisitCXXForRangeStmt(CXXForRangeStmt *S) { |
| |
| Error Err = Error::success(); |
| auto ToInit = importChecked(Err, S->getInit()); |
| auto ToRangeStmt = importChecked(Err, S->getRangeStmt()); |
| auto ToBeginStmt = importChecked(Err, S->getBeginStmt()); |
| auto ToEndStmt = importChecked(Err, S->getEndStmt()); |
| auto ToCond = importChecked(Err, S->getCond()); |
| auto ToInc = importChecked(Err, S->getInc()); |
| auto ToLoopVarStmt = importChecked(Err, S->getLoopVarStmt()); |
| auto ToBody = importChecked(Err, S->getBody()); |
| auto ToForLoc = importChecked(Err, S->getForLoc()); |
| auto ToCoawaitLoc = importChecked(Err, S->getCoawaitLoc()); |
| auto ToColonLoc = importChecked(Err, S->getColonLoc()); |
| auto ToRParenLoc = importChecked(Err, S->getRParenLoc()); |
| if (Err) |
| return std::move(Err); |
| |
| return new (Importer.getToContext()) CXXForRangeStmt( |
| ToInit, ToRangeStmt, ToBeginStmt, ToEndStmt, ToCond, ToInc, ToLoopVarStmt, |
| ToBody, ToForLoc, ToCoawaitLoc, ToColonLoc, ToRParenLoc); |
| } |
| |
| ExpectedStmt |
| ASTNodeImporter::VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) { |
| Error Err = Error::success(); |
| auto ToElement = importChecked(Err, S->getElement()); |
| auto ToCollection = importChecked(Err, S->getCollection()); |
| auto ToBody = importChecked(Err, S->getBody()); |
| auto ToForLoc = importChecked(Err, S->getForLoc()); |
| auto ToRParenLoc = importChecked(Err, S->getRParenLoc()); |
| if (Err) |
| return std::move(Err); |
| |
| return new (Importer.getToContext()) ObjCForCollectionStmt(ToElement, |
| ToCollection, |
| ToBody, |
| ToForLoc, |
| ToRParenLoc); |
| } |
| |
| ExpectedStmt ASTNodeImporter::VisitObjCAtCatchStmt(ObjCAtCatchStmt *S) { |
| |
| Error Err = Error::success(); |
| auto ToAtCatchLoc = importChecked(Err, S->getAtCatchLoc()); |
| auto ToRParenLoc = importChecked(Err, S->getRParenLoc()); |
| auto ToCatchParamDecl = importChecked(Err, S->getCatchParamDecl()); |
| auto ToCatchBody = importChecked(Err, S->getCatchBody()); |
| if (Err) |
| return std::move(Err); |
| |
| return new (Importer.getToContext()) ObjCAtCatchStmt ( |
| ToAtCatchLoc, ToRParenLoc, ToCatchParamDecl, ToCatchBody); |
| } |
| |
| ExpectedStmt ASTNodeImporter::VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *S) { |
| ExpectedSLoc ToAtFinallyLocOrErr = import(S->getAtFinallyLoc()); |
| if (!ToAtFinallyLocOrErr) |
| return ToAtFinallyLocOrErr.takeError(); |
| ExpectedStmt ToAtFinallyStmtOrErr = import(S->getFinallyBody()); |
| if (!ToAtFinallyStmtOrErr) |
| return ToAtFinallyStmtOrErr.takeError(); |
| return new (Importer.getToContext()) ObjCAtFinallyStmt(*ToAtFinallyLocOrErr, |
| *ToAtFinallyStmtOrErr); |
| } |
| |
| ExpectedStmt ASTNodeImporter::VisitObjCAtTryStmt(ObjCAtTryStmt *S) { |
| |
| Error Err = Error::success(); |
| auto ToAtTryLoc = importChecked(Err, S->getAtTryLoc()); |
| auto ToTryBody = importChecked(Err, S->getTryBody()); |
| auto ToFinallyStmt = importChecked(Err, S->getFinallyStmt()); |
| if (Err) |
| return std::move(Err); |
| |
| SmallVector<Stmt *, 1> ToCatchStmts(S->getNumCatchStmts()); |
| for (unsigned CI = 0, CE = S->getNumCatchStmts(); CI != CE; ++CI) { |
| ObjCAtCatchStmt *FromCatchStmt = S->getCatchStmt(CI); |
| if (ExpectedStmt ToCatchStmtOrErr = import(FromCatchStmt)) |
| ToCatchStmts[CI] = *ToCatchStmtOrErr; |
| else |
| return ToCatchStmtOrErr.takeError(); |
| } |
| |
| return ObjCAtTryStmt::Create(Importer.getToContext(), |
| ToAtTryLoc, ToTryBody, |
| ToCatchStmts.begin(), ToCatchStmts.size(), |
| ToFinallyStmt); |
| } |
| |
| ExpectedStmt |
| ASTNodeImporter::VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S) { |
| |
| Error Err = Error::success(); |
| auto ToAtSynchronizedLoc = importChecked(Err, S->getAtSynchronizedLoc()); |
| auto ToSynchExpr = importChecked(Err, S->getSynchExpr()); |
| auto ToSynchBody = importChecked(Err, S->getSynchBody()); |
| if (Err) |
| return std::move(Err); |
| |
| return new (Importer.getToContext()) ObjCAtSynchronizedStmt( |
| ToAtSynchronizedLoc, ToSynchExpr, ToSynchBody); |
| } |
| |
| ExpectedStmt ASTNodeImporter::VisitObjCAtThrowStmt(ObjCAtThrowStmt *S) { |
| ExpectedSLoc ToThrowLocOrErr = import(S->getThrowLoc()); |
| if (!ToThrowLocOrErr) |
| return ToThrowLocOrErr.takeError(); |
| ExpectedExpr ToThrowExprOrErr = import(S->getThrowExpr()); |
| if (!ToThrowExprOrErr) |
| return ToThrowExprOrErr.takeError(); |
| return new (Importer.getToContext()) ObjCAtThrowStmt( |
| *ToThrowLocOrErr, *ToThrowExprOrErr); |
| } |
| |
| ExpectedStmt ASTNodeImporter::VisitObjCAutoreleasePoolStmt( |
| ObjCAutoreleasePoolStmt *S) { |
| ExpectedSLoc ToAtLocOrErr = import(S->getAtLoc()); |
| if (!ToAtLocOrErr) |
| return ToAtLocOrErr.takeError(); |
| ExpectedStmt ToSubStmtOrErr = import(S->getSubStmt()); |
| if (!ToSubStmtOrErr) |
| return ToSubStmtOrErr.takeError(); |
| return new (Importer.getToContext()) ObjCAutoreleasePoolStmt(*ToAtLocOrErr, |
| *ToSubStmtOrErr); |
| } |
| |
| //---------------------------------------------------------------------------- |
| // Import Expressions |
| //---------------------------------------------------------------------------- |
| ExpectedStmt ASTNodeImporter::VisitExpr(Expr *E) { |
| Importer.FromDiag(E->getBeginLoc(), diag::err_unsupported_ast_node) |
| << E->getStmtClassName(); |
| return make_error<ImportError>(ImportError::UnsupportedConstruct); |
| } |
| |
| 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::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()); |
| auto *ToControllingExpr = importChecked(Err, E->getControllingExpr()); |
| auto ToDefaultLoc = importChecked(Err, E->getDefaultLoc()); |
| auto ToRParenLoc = importChecked(Err, E->getRParenLoc()); |
| if (Err) |
| return std::move(Err); |
| |
| ArrayRef<const TypeSourceInfo *> FromAssocTypes(E->getAssocTypeSourceInfos()); |
| SmallVector<TypeSourceInfo *, 1> ToAssocTypes(FromAssocTypes.size()); |
| if (Error Err = ImportContainerChecked(FromAssocTypes, ToAssocTypes)) |
| return std::move(Err); |
| |
| ArrayRef<const Expr *> FromAssocExprs(E->getAssocExprs()); |
| SmallVector<Expr *, 1> ToAssocExprs(FromAssocExprs.size()); |
| if (Error Err = ImportContainerChecked(FromAssocExprs, ToAssocExprs)) |
| return std::move(Err); |
| |
| const ASTContext &ToCtx = Importer.getToContext(); |
| if (E->isResultDependent()) { |
| return GenericSelectionExpr::Create( |
| ToCtx, ToGenericLoc, ToControllingExpr, |
| llvm::makeArrayRef(ToAssocTypes), llvm::makeArrayRef(ToAssocExprs), |
| ToDefaultLoc, ToRParenLoc, E->containsUnexpandedParameterPack()); |
| } |
| |
| return GenericSelectionExpr::Create( |
| ToCtx, ToGenericLoc, ToControllingExpr, llvm::makeArrayRef(ToAssocTypes), |
| llvm::makeArrayRef(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(), 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); |
| return ToE; |
| } |
| |
| ExpectedStmt ASTNodeImporter::VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) { |
| ExpectedType TypeOrErr = import(E->getType()); |
| if (!TypeOrErr) |
| return TypeOrErr.takeError(); |
| |
| return new (Importer.getToContext()) ImplicitValueInitExpr(*TypeOrErr); |
| } |
| |
| ExpectedStmt ASTNodeImporter::VisitDesignatedInitExpr(DesignatedInitExpr *E) { |
| ExpectedExpr ToInitOrErr = import(E->getInit()); |
| if (!ToInitOrErr) |
| return ToInitOrErr.takeError(); |
| |
| ExpectedSLoc ToEqualOrColonLocOrErr = import(E->getEqualOrColonLoc()); |
| if (!ToEqualOrColonLocOrErr) |
| return ToEqualOrColonLocOrErr.takeError(); |
| |
| SmallVector<Expr *, 4> ToIndexExprs(E->getNumSubExprs() - 1); |
| // List elements from the second, the first is Init itself |
| for (unsigned I = 1, N = E->getNumSubExprs(); I < N; I++) { |
| if (ExpectedExpr ToArgOrErr = import(E->getSubExpr(I))) |
| ToIndexExprs[I - 1] = *ToArgOrErr; |
| else |
| return ToArgOrErr.takeError(); |
| } |
| |
| SmallVector<Designator, 4> ToDesignators(E->size()); |
| if (Error Err = ImportContainerChecked(E->designators(), ToDesignators)) |
| return std::move(Err); |
| |
| return DesignatedInitExpr::Create( |
| Importer.getToContext(), ToDesignators, |
| ToIndexExprs, *ToEqualOrColonLocOrErr, |
| E->usesGNUSyntax(), *ToInitOrErr); |
| } |
| |
| ExpectedStmt |
| ASTNodeImporter::VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E) { |
| ExpectedType ToTypeOrErr = import(E->getType()); |
| if (!ToTypeOrErr) |
| return ToTypeOrErr.takeError(); |
| |
| ExpectedSLoc ToLocationOrErr = import(E->getLocation()); |
| if (!ToLocationOrErr) |
| return ToLocationOrErr.takeError(); |
| |
| return new (Importer.getToContext()) CXXNullPtrLiteralExpr( |
| *ToTypeOrErr, *ToLocationOrErr); |
| } |
| |
| ExpectedStmt ASTNodeImporter::VisitIntegerLiteral(IntegerLiteral *E) { |
| ExpectedType ToTypeOrErr = import(E->getType()); |
| if (!ToTypeOrErr) |
| return ToTypeOrErr.takeError(); |
| |
| ExpectedSLoc ToLocationOrErr = import(E->getLocation()); |
| if (!ToLocationOrErr) |
| return ToLocationOrErr.takeError(); |
| |
| return IntegerLiteral::Create( |
| Importer.getToContext(), E->getValue(), *ToTypeOrErr, *ToLocationOrErr); |
| } |
| |
| |
| ExpectedStmt ASTNodeImporter::VisitFloatingLiteral(FloatingLiteral *E) { |
| ExpectedType ToTypeOrErr = import(E->getType()); |
| if (!ToTypeOrErr) |
| return ToTypeOrErr.takeError(); |
| |
| ExpectedSLoc ToLocationOrErr = import(E->getLocation()); |
| if (!ToLocationOrErr) |
| return ToLocationOrErr.takeError(); |
| |
| return FloatingLiteral::Create( |
| Importer.getToContext(), E->getValue(), E->isExact(), |
| *ToTypeOrErr, *ToLocationOrErr); |
| } |
| |
| ExpectedStmt ASTNodeImporter::VisitImaginaryLiteral(ImaginaryLiteral *E) { |
| auto ToTypeOrErr = import(E->getType()); |
| if (!ToTypeOrErr) |
| return ToTypeOrErr.takeError(); |
| |
| ExpectedExpr ToSubExprOrErr = import(E->getSubExpr()); |
| if (!ToSubExprOrErr) |
| return ToSubExprOrErr.takeError(); |
| |
| return new (Importer.getToContext()) ImaginaryLiteral( |
| *ToSubExprOrErr, *ToTypeOrErr); |
| } |
| |
| ExpectedStmt ASTNodeImporter::VisitFixedPointLiteral(FixedPointLiteral *E) { |
| auto ToTypeOrErr = import(E->getType()); |
| if (!ToTypeOrErr) |
| return ToTypeOrErr.takeError(); |
| |
| ExpectedSLoc ToLocationOrErr = import(E->getLocation()); |
| if (!ToLocationOrErr) |
| return ToLocationOrErr.takeError(); |
| |
| return new (Importer.getToContext()) FixedPointLiteral( |
| Importer.getToContext(), E->getValue(), *ToTypeOrErr, *ToLocationOrErr, |
| Importer.getToContext().getFixedPointScale(*ToTypeOrErr)); |
| } |
| |
| ExpectedStmt ASTNodeImporter::VisitCharacterLiteral(CharacterLiteral *E) { |
| ExpectedType ToTypeOrErr = import(E->getType()); |
| if (!ToTypeOrErr) |
| return ToTypeOrErr.takeError(); |
| |
| ExpectedSLoc ToLocationOrErr = import(E->getLocation()); |
| if (!ToLocationOrErr) |
| return ToLocationOrErr.takeError(); |
| |
| return new (Importer.getToContext()) CharacterLiteral( |
| E->getValue(), E->getKind(), *ToTypeOrErr, *ToLocationOrErr); |
| } |
| |
| ExpectedStmt ASTNodeImporter::VisitStringLiteral(StringLiteral *E) { |
| ExpectedType ToTypeOrErr = import(E->getType()); |
| if (!ToTypeOrErr) |
| return ToTypeOrErr.takeError(); |
| |
| SmallVector<SourceLocation, 4> ToLocations(E->getNumConcatenated()); |
| if (Error Err = ImportArrayChecked( |
| E->tokloc_begin(), E->tokloc_end(), ToLocations.begin())) |
| return std::move(Err); |
| |
| return StringLiteral::Create( |
| Importer.getToContext(), E->getBytes(), E->getKind(), E->isPascal(), |
| *ToTypeOrErr, ToLocations.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<Expr *, 6> ToExprs(E->getNumSubExprs()); |
| if (Error Err = ImportArrayChecked( |
| E->getSubExprs(), E->getSubExprs() + E->getNumSubExprs(), |
| ToExprs.begin())) |
| return std::move(Err); |
| |
| return new (Importer.getToContext()) AtomicExpr( |
| |
| ToBuiltinLoc, ToExprs, ToType, E->getOp(), ToRParenLoc); |
| } |
| |
| ExpectedStmt ASTNodeImporter::VisitAddrLabelExpr(AddrLabelExpr *E) { |
| Error Err = Error::success(); |
| auto ToAmpAmpLoc = importChecked(Err, E->getAmpAmpLoc()); |
| auto ToLabelLoc = importChecked(Err, E->getLabelLoc()); |
| auto ToLabel = importChecked(Err, E->getLabel()); |
| auto ToType = importChecked(Err, E->getType()); |
| if (Err) |
| return std::move(Err); |
| |
| return new (Importer.getToContext()) AddrLabelExpr( |
| ToAmpAmpLoc, ToLabelLoc, ToLabel, ToType); |
| } |
| ExpectedStmt ASTNodeImporter::VisitConstantExpr(ConstantExpr *E) { |
| Error Err = Error::success(); |
| auto ToSubExpr = importChecked(Err, E->getSubExpr()); |
| auto ToResult = importChecked(Err, E->getAPValueResult()); |
| if (Err) |
| return std::move(Err); |
| |
| return ConstantExpr::Create(Importer.getToContext(), ToSubExpr, ToResult); |
| } |
| ExpectedStmt ASTNodeImporter::VisitParenExpr(ParenExpr *E) { |
| Error Err = Error::success(); |
| auto ToLParen = importChecked(Err, E->getLParen()); |
| auto ToRParen = importChecked(Err, E->getRParen()); |
| auto ToSubExpr = importChecked(Err, E->getSubExpr()); |
| if (Err) |
| return std::move(Err); |
| |
| return new (Importer.getToContext()) |
| ParenExpr(ToLParen, ToRParen, ToSubExpr); |
| } |
| |
| ExpectedStmt ASTNodeImporter::VisitParenListExpr(ParenListExpr *E) { |
| SmallVector<Expr *, 4> ToExprs(E->getNumExprs()); |
| if (Error Err = ImportContainerChecked(E->exprs(), ToExprs)) |
| return std::move(Err); |
| |
| ExpectedSLoc ToLParenLocOrErr = import(E->getLParenLoc()); |
| if (!ToLParenLocOrErr) |
| return ToLParenLocOrErr.takeError(); |
| |
| ExpectedSLoc ToRParenLocOrErr = import(E->getRParenLoc()); |
| if (!ToRParenLocOrErr) |
| return ToRParenLocOrErr.takeError(); |
| |
| return ParenListExpr::Create(Importer.getToContext(), *ToLParenLocOrErr, |
| ToExprs, *ToRParenLocOrErr); |
| } |
| |
| ExpectedStmt ASTNodeImporter::VisitStmtExpr(StmtExpr *E) { |
| Error Err = Error::success(); |
| auto ToSubStmt = importChecked(Err, E->getSubStmt()); |
| auto ToType = importChecked(Err, E->getType()); |
| auto ToLParenLoc = importChecked(Err, E->getLParenLoc()); |
| auto ToRParenLoc = importChecked(Err, E->getRParenLoc()); |
| if (Err) |
| return std::move(Err); |
| |
| return new (Importer.getToContext()) |
| StmtExpr(ToSubStmt, ToType, ToLParenLoc, ToRParenLoc, |
| E->getTemplateDepth()); |
| } |
| |
| ExpectedStmt ASTNodeImporter::VisitUnaryOperator(UnaryOperator *E) { |
| Error Err = Error::success(); |
| auto ToSubExpr = importChecked(Err, E->getSubExpr()); |
| auto ToType = importChecked(Err, E->getType()); |
| auto ToOperatorLoc = importChecked(Err, E->getOperatorLoc()); |
| if (Err) |
| return std::move(Err); |
| |
| return UnaryOperator::Create( |
| Importer.getToContext(), ToSubExpr, E->getOpcode(), ToType, |
| E->getValueKind(), E->getObjectKind(), ToOperatorLoc, E->canOverflow(), |
| E->getFPOptionsOverride()); |
| } |
| |
| ExpectedStmt |
| |
| ASTNodeImporter::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E) { |
| Error Err = Error::success(); |
| auto ToType = importChecked(Err, E->getType()); |
| auto ToOperatorLoc = importChecked(Err, E->getOperatorLoc()); |
| auto ToRParenLoc = importChecked(Err, E->getRParenLoc()); |
| if (Err) |
| return std::move(Err); |
| |
| if (E->isArgumentType()) { |
| Expected<TypeSourceInfo *> ToArgumentTypeInfoOrErr = |
| import(E->getArgumentTypeInfo()); |
| if (!ToArgumentTypeInfoOrErr) |
| return ToArgumentTypeInfoOrErr.takeError(); |
| |
| return new (Importer.getToContext()) UnaryExprOrTypeTraitExpr( |
| E->getKind(), *ToArgumentTypeInfoOrErr, ToType, ToOperatorLoc, |
| ToRParenLoc); |
| } |
| |
| ExpectedExpr ToArgumentExprOrErr = import(E->getArgumentExpr()); |
| if (!ToArgumentExprOrErr) |
| return ToArgumentExprOrErr.takeError(); |
| |
| return new (Importer.getToContext()) UnaryExprOrTypeTraitExpr( |
| E->getKind(), *ToArgumentExprOrErr, ToType, ToOperatorLoc, ToRParenLoc); |
| } |
| |
| ExpectedStmt ASTNodeImporter::VisitBinaryOperator(BinaryOperator *E) { |
| Error Err = Error::success(); |
| auto ToLHS = importChecked(Err, E->getLHS()); |
| auto ToRHS = importChecked(Err, E->getRHS()); |
| auto ToType = importChecked(Err, E->getType()); |
| auto ToOperatorLoc = importChecked(Err, E->getOperatorLoc()); |
| if (Err) |
| return std::move(Err); |
| |
| return BinaryOperator::Create( |
| Importer.getToContext(), ToLHS, ToRHS, E->getOpcode(), ToType, |
| E->getValueKind(), E->getObjectKind(), ToOperatorLoc, |
| E->getFPFeatures(Importer.getFromContext().getLangOpts())); |
| } |
| |
| 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::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(Importer.getFromContext().getLangOpts()), |
| ToComputationLHSType, ToComputationResultType); |
| } |
| |
| Expected<CXXCastPath> |
| ASTNodeImporter::ImportCastPath(CastExpr *CE) { |
| CXXCastPath Path; |
| for (auto I = CE->path_begin(), E = CE->path_end(); I != E; ++I) { |
| if (auto SpecOrErr = import(*I)) |
| Path.push_back(*SpecOrErr); |
| else |
| return SpecOrErr.takeError(); |
| } |
| return Path; |
| } |
| |
| ExpectedStmt ASTNodeImporter::VisitImplicitCastExpr(ImplicitCastExpr *E) { |
| ExpectedType ToTypeOrErr = import(E->getType()); |
| if (!ToTypeOrErr) |
| return ToTypeOrErr.takeError(); |
| |
| ExpectedExpr ToSubExprOrErr = import(E->getSubExpr()); |
| if (!ToSubExprOrErr) |
| return ToSubExprOrErr.takeError(); |
| |
| Expected<CXXCastPath> ToBasePathOrErr = ImportCastPath(E); |
| if (!ToBasePathOrErr) |
| return ToBasePathOrErr.takeError(); |
| |
| return ImplicitCastExpr::Create( |
| Importer.getToContext(), *ToTypeOrErr, E->getCastKind(), *ToSubExprOrErr, |
| &(*ToBasePathOrErr), E->getValueKind(), E->getFPFeatures()); |
| } |
| |
| ExpectedStmt ASTNodeImporter::VisitExplicitCastExpr(ExplicitCastExpr *E) { |
| Error Err = Error::success(); |
| auto ToType = importChecked(Err, E->getType()); |
| auto ToSubExpr = importChecked(Err, E->getSubExpr()); |
| auto ToTypeInfoAsWritten = importChecked(Err, E->getTypeInfoAsWritten()); |
| if (Err) |
| return std::move(Err); |
| |
| Expected<CXXCastPath> ToBasePathOrErr = ImportCastPath(E); |
| if (!ToBasePathOrErr) |
| return ToBasePathOrErr.takeError(); |
| CXXCastPath *ToBasePath = &(*ToBasePathOrErr); |
| |
| switch (E->getStmtClass()) { |
| case Stmt::CStyleCastExprClass: { |
| auto *CCE = cast<CStyleCastExpr>(E); |
| ExpectedSLoc ToLParenLocOrErr = import(CCE->getLParenLoc()); |
| if (!ToLParenLocOrErr) |
| return ToLParenLocOrErr.takeError(); |
| ExpectedSLoc ToRParenLocOrErr = import(CCE->getRParenLoc()); |
| if (!ToRParenLocOrErr) |
| return ToRParenLocOrErr.takeError(); |
| return CStyleCastExpr::Create( |
| Importer.getToContext(), ToType, E->getValueKind(), E->getCastKind(), |
| ToSubExpr, ToBasePath, CCE->getFPFeatures(), ToTypeInfoAsWritten, |
| *ToLParenLocOrErr, *ToRParenLocOrErr); |
| } |
| |
| case Stmt::CXXFunctionalCastExprClass: { |
| auto *FCE = cast<CXXFunctionalCastExpr>(E); |
| ExpectedSLoc ToLParenLocOrErr = import(FCE->getLParenLoc()); |
| if (!ToLParenLocOrErr) |
| return ToLParenLocOrErr.takeError(); |
| ExpectedSLoc ToRParenLocOrErr = import(FCE->getRParenLoc()); |
| if (!ToRParenLocOrErr) |
| return ToRParenLocOrErr.takeError(); |
| return CXXFunctionalCastExpr::Create( |
| Importer.getToContext(), ToType, E->getValueKind(), ToTypeInfoAsWritten, |
| E->getCastKind(), ToSubExpr, ToBasePath, FCE->getFPFeatures(), |
| *ToLParenLocOrErr, *ToRParenLocOrErr); |
| } |
| |
| case Stmt::ObjCBridgedCastExprClass: { |
| auto *OCE = cast<ObjCBridgedCastExpr>(E); |
| ExpectedSLoc ToLParenLocOrErr = import(OCE->getLParenLoc()); |
| if (!ToLParenLocOrErr) |
| return ToLParenLocOrErr.takeError(); |
| ExpectedSLoc ToBridgeKeywordLocOrErr = import(OCE->getBridgeKeywordLoc()); |
| if (!ToBridgeKeywordLocOrErr) |
| return ToBridgeKeywordLocOrErr.takeError(); |
| return new (Importer.getToContext()) ObjCBridgedCastExpr( |
| *ToLParenLocOrErr, OCE->getBridgeKind(), E->getCastKind(), |
| *ToBridgeKeywordLocOrErr, ToTypeInfoAsWritten, ToSubExpr); |
| } |
| default: |
| llvm_unreachable("Cast expression of unsupported type!"); |
| return make_error<ImportError>(ImportError::UnsupportedConstruct); |
| } |
| } |
| |
| ExpectedStmt ASTNodeImporter::VisitOffsetOfExpr(OffsetOfExpr *E) { |
| SmallVector<OffsetOfNode, 4> ToNodes; |
| for (int I = 0, N = E->getNumComponents(); I < N; ++I) { |
| const OffsetOfNode &FromNode = E->getComponent(I); |
| |
| SourceLocation ToBeginLoc, ToEndLoc; |
| |
| if (FromNode.getKind() != OffsetOfNode::Base) { |
| Error Err = Error::success(); |
| ToBeginLoc = importChecked(Err, FromNode.getBeginLoc()); |
| ToEndLoc = importChecked(Err, FromNode.getEndLoc()); |
| if (Err) |
| return std::move(Err); |
| } |
| |
| switch (FromNode.getKind()) { |
| case OffsetOfNode::Array: |
| ToNodes.push_back( |
| OffsetOfNode(ToBeginLoc, FromNode.getArrayExprIndex(), ToEndLoc)); |
| break; |
| case OffsetOfNode::Base: { |
| auto ToBSOrErr = import(FromNode.getBase()); |
| if (!ToBSOrErr) |
| return ToBSOrErr.takeError(); |
| ToNodes.push_back(OffsetOfNode(*ToBSOrErr)); |
| break; |
| } |
| case OffsetOfNode::Field: { |
| auto ToFieldOrErr = import(FromNode.getField()); |
| if (!ToFieldOrErr) |
| return ToFieldOrErr.takeError(); |
| ToNodes.push_back(OffsetOfNode(ToBeginLoc, *ToFieldOrErr, ToEndLoc)); |
| break; |
| } |
| case OffsetOfNode::Identifier: { |
| IdentifierInfo *ToII = Importer.Import(FromNode.getFieldName()); |
| ToNodes.push_back(OffsetOfNode(ToBeginLoc, ToII, ToEndLoc)); |
| break; |
| } |
| } |
| } |
| |
| SmallVector<Expr *, 4> ToExprs(E->getNumExpressions()); |
| for (int I = 0, N = E->getNumExpressions(); I < N; ++I) { |
| ExpectedExpr ToIndexExprOrErr = import(E->getIndexExpr(I)); |
| if (!ToIndexExprOrErr) |
| return ToIndexExprOrErr.takeError(); |
| ToExprs[I] = *ToIndexExprOrErr; |
| } |
| |
| Error Err = Error::success(); |
| auto ToType = importChecked(Err, E->getType()); |
| auto ToTypeSourceInfo = importChecked(Err, E->getTypeSourceInfo()); |
| auto ToOperatorLoc = importChecked(Err, E->getOperatorLoc()); |
| auto ToRParenLoc = importChecked(Err, E->getRParenLoc()); |
| if (Err) |
| return std::move(Err); |
| |
| return OffsetOfExpr::Create( |
| Importer.getToContext(), ToType, ToOperatorLoc, ToTypeSourceInfo, ToNodes, |
| ToExprs, ToRParenLoc); |
| } |
| |
| ExpectedStmt ASTNodeImporter::VisitCXXNoexceptExpr(CXXNoexceptExpr *E) { |
| Error Err = Error::success(); |
| auto ToType = importChecked(Err, E->getType()); |
| auto ToOperand = importChecked(Err, E->getOperand()); |
| auto ToBeginLoc = importChecked(Err, E->getBeginLoc()); |
| auto ToEndLoc = importChecked(Err, E->getEndLoc()); |
| if (Err) |
| return std::move(Err); |
| |
| CanThrowResult ToCanThrow; |
| if (E->isValueDependent()) |
| ToCanThrow = CT_Dependent; |
| else |
| ToCanThrow = E->getValue() ? CT_Can : CT_Cannot; |
| |
| return new (Importer.getToContext()) CXXNoexceptExpr( |
| ToType, ToOperand, ToCanThrow, ToBeginLoc, ToEndLoc); |
| } |
| |
| ExpectedStmt ASTNodeImporter::VisitCXXThrowExpr(CXXThrowExpr *E) { |
| Error Err = Error::success(); |
| auto ToSubExpr = importChecked(Err, E->getSubExpr()); |
| auto ToType = importChecked(Err, E->getType()); |
| auto ToThrowLoc = importChecked(Err, E->getThrowLoc()); |
| if (Err) |
| return std::move(Err); |
| |
| return new (Importer.getToContext()) CXXThrowExpr( |
| ToSubExpr, ToType, ToThrowLoc, E->isThrownVariableInScope()); |
| } |
| |
| ExpectedStmt ASTNodeImporter::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) { |
| ExpectedSLoc ToUsedLocOrErr = import(E->getUsedLocation()); |
| if (!ToUsedLocOrErr) |
| return ToUsedLocOrErr.takeError(); |
| |
| auto ToParamOrErr = import(E->getParam()); |
| if (!ToParamOrErr) |
| return ToParamOrErr.takeError(); |
| |
| auto UsedContextOrErr = Importer.ImportContext(E->getUsedContext()); |
| if (!UsedContextOrErr) |
| return UsedContextOrErr.takeError(); |
| |
| // Import the default arg if it was not imported yet. |
| // This is needed because it can happen that during the import of the |
| // default expression (from VisitParmVarDecl) the same ParmVarDecl is |
| // encountered here. The default argument for a ParmVarDecl is set in the |
| // ParmVarDecl only after it is imported (set in VisitParmVarDecl if not here, |
| // see VisitParmVarDecl). |
| ParmVarDecl *ToParam = *ToParamOrErr; |
| if (!ToParam->getDefaultArg()) { |
| Optional<ParmVarDecl *> FromParam = Importer.getImportedFromDecl(ToParam); |
| assert(FromParam && "ParmVarDecl was not imported?"); |
| |
| if (Error Err = ImportDefaultArgOfParmVarDecl(*FromParam, ToParam)) |
| return std::move(Err); |
| } |
| |
| return CXXDefaultArgExpr::Create(Importer.getToContext(), *ToUsedLocOrErr, |
| *ToParamOrErr, *UsedContextOrErr); |
| } |
| |
| ExpectedStmt |
| ASTNodeImporter::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) { |
| Error Err = Error::success(); |
| auto ToType = importChecked(Err, E->getType()); |
| auto ToTypeSourceInfo = importChecked(Err, E->getTypeSourceInfo()); |
| auto ToRParenLoc = importChecked(Err, E->getRParenLoc()); |
| if (Err) |
| return std::move(Err); |
| |
| return new (Importer.getToContext()) CXXScalarValueInitExpr( |
| ToType, ToTypeSourceInfo, ToRParenLoc); |
| } |
| |
| ExpectedStmt |
| ASTNodeImporter::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) { |
| ExpectedExpr ToSubExprOrErr = import(E->getSubExpr()); |
| if (!ToSubExprOrErr) |
| return ToSubExprOrErr.takeError(); |
| |
| auto ToDtorOrErr = import(E->getTemporary()->getDestructor()); |
| if (!ToDtorOrErr) |
| return ToDtorOrErr.takeError(); |
| |
| ASTContext &ToCtx = Importer.getToContext(); |
| CXXTemporary *Temp = CXXTemporary::Create(ToCtx, *ToDtorOrErr); |
| return CXXBindTemporaryExpr::Create(ToCtx, Temp, *ToSubExprOrErr); |
| } |
| |
| ExpectedStmt |
| |
| ASTNodeImporter::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E) { |
| Error Err = Error::success(); |
| auto ToConstructor = importChecked(Err, E->getConstructor()); |
| auto ToType = importChecked(Err, E->getType()); |
| auto ToTypeSourceInfo = importChecked(Err, E->getTypeSourceInfo()); |
| auto ToParenOrBraceRange = importChecked(Err, E->getParenOrBraceRange()); |
| if (Err) |
| return std::move(Err); |
| |
| SmallVector<Expr *, 8> ToArgs(E->getNumArgs()); |
| if (Error Err = ImportContainerChecked(E->arguments(), ToArgs)) |
| return std::move(Err); |
| |
| return CXXTemporaryObjectExpr::Create( |
| Importer.getToContext(), ToConstructor, ToType, ToTypeSourceInfo, ToArgs, |
| ToParenOrBraceRange, E->hadMultipleCandidates(), |
| E->isListInitialization(), E->isStdInitListInitialization(), |
| E->requiresZeroInitialization()); |
| } |
| |
| ExpectedDecl ASTNodeImporter::VisitLifetimeExtendedTemporaryDecl( |
| LifetimeExtendedTemporaryDecl *D) { |
| DeclContext *DC, *LexicalDC; |
| if (Error Err = ImportDeclContext(D, DC, LexicalDC)) |
| return std::move(Err); |
| |
| Error Err = Error::success(); |
| auto Temporary = importChecked(Err, D->getTemporaryExpr()); |
| auto ExtendingDecl = importChecked(Err, D->getExtendingDecl()); |
| if (Err) |
| return std::move(Err); |
| // FIXME: Should ManglingNumber get numbers associated with 'to' context? |
| |
| LifetimeExtendedTemporaryDecl *To; |
| if (GetImportedOrCreateDecl(To, D, Temporary, ExtendingDecl, |
| D->getManglingNumber())) |
| return To; |
| |
| To->setLexicalDeclContext(LexicalDC); |
| LexicalDC->addDeclInternal(To); |
| return To; |
| } |
| |
| ExpectedStmt |
| ASTNodeImporter::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E) { |
| Error Err = Error::success(); |
| auto ToType = importChecked(Err, E->getType()); |
| Expr *ToTemporaryExpr = importChecked( |
| Err, E->getLifetimeExtendedTemporaryDecl() ? nullptr : E->getSubExpr()); |
| auto ToMaterializedDecl = |
| importChecked(Err, E->getLifetimeExtendedTemporaryDecl()); |
| if (Err) |
| return std::move(Err); |
| |
| if (!ToTemporaryExpr) |
| ToTemporaryExpr = cast<Expr>(ToMaterializedDecl->getTemporaryExpr()); |
| |
| auto *ToMTE = new (Importer.getToContext()) MaterializeTemporaryExpr( |
| ToType, ToTemporaryExpr, E->isBoundToLvalueReference(), |
| ToMaterializedDecl); |
| |
| return ToMTE; |
| } |
| |
| ExpectedStmt ASTNodeImporter::VisitPackExpansionExpr(PackExpansionExpr *E) { |
| Error Err = Error::success(); |
| auto 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); |
| |
| Optional<unsigned> Length; |
| if (!E->isValueDependent()) |
| Length = E->getPackLength(); |
| |
| SmallVector<TemplateArgument, 8> ToPartialArguments; |
| if (E->isPartiallySubstituted()) { |
| if (Error Err = ImportTemplateArguments( |
| E->getPartialArguments().data(), |
| E->getPartialArguments().size(), |
| ToPartialArguments)) |
| return std::move(Err); |
| } |
| |
| return SizeOfPackExpr::Create( |
| Importer.getToContext(), ToOperatorLoc, ToPack, ToPackLoc, ToRParenLoc, |
| Length, ToPartialArguments); |
| } |
| |
| |
| ExpectedStmt ASTNodeImporter::VisitCXXNewExpr(CXXNewExpr *E) { |
| Error Err = Error::success(); |
| auto ToOperatorNew = importChecked(Err, E->getOperatorNew()); |
| auto ToOperatorDelete = importChecked(Err, E->getOperatorDelete()); |
| auto ToTypeIdParens = importChecked(Err, E->getTypeIdParens()); |
| auto ToArraySize = importChecked(Err, E->getArraySize()); |
| auto ToInitializer = importChecked(Err, E->getInitializer()); |
| auto ToType = importChecked(Err, E->getType()); |
| auto ToAllocatedTypeSourceInfo = |
| importChecked(Err, E->getAllocatedTypeSourceInfo()); |
| auto ToSourceRange = importChecked(Err, E->getSourceRange()); |
| auto ToDirectInitRange = importChecked(Err, E->getDirectInitRange()); |
| if (Err) |
| return std::move(Err); |
| |
| SmallVector<Expr *, 4> ToPlacementArgs(E->getNumPlacementArgs()); |
| if (Error Err = |
| ImportContainerChecked(E->placement_arguments(), ToPlacementArgs)) |
| return std::move(Err); |
| |
| return CXXNewExpr::Create( |
| Importer.getToContext(), E->isGlobalNew(), ToOperatorNew, |
| ToOperatorDelete, E->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<Expr *, 6> ToArgs(E->getNumArgs()); |
| if (Error Err = ImportContainerChecked(E->arguments(), ToArgs)) |
| return std::move(Err); |
| |
| return CXXConstructExpr::Create( |
| Importer.getToContext(), ToType, ToLocation, ToConstructor, |
| E->isElidable(), ToArgs, E->hadMultipleCandidates(), |
| E->isListInitialization(), E->isStdInitListInitialization(), |
| E->requiresZeroInitialization(), E->getConstructionKind(), |
| ToParenOrBraceRange); |
| } |
| |
| ExpectedStmt ASTNodeImporter::VisitExprWithCleanups(ExprWithCleanups *E) { |
| ExpectedExpr ToSubExprOrErr = import(E->getSubExpr()); |
| if (!ToSubExprOrErr) |
| return ToSubExprOrErr.takeError(); |
| |
| SmallVector<ExprWithCleanups::CleanupObject, 8> ToObjects(E->getNumObjects()); |
| if (Error Err = ImportContainerChecked(E->getObjects(), ToObjects)) |
| return std::move(Err); |
| |
| return ExprWithCleanups::Create( |
| Importer.getToContext(), *ToSubExprOrErr, E->cleanupsHaveSideEffects(), |
| ToObjects); |
| } |
| |
| ExpectedStmt ASTNodeImporter::VisitCXXMemberCallExpr(CXXMemberCallExpr *E) { |
| Error Err = Error::success(); |
| auto ToCallee = importChecked(Err, E->getCallee()); |
| auto ToType = importChecked(Err, E->getType()); |
| auto ToRParenLoc = importChecked(Err, E->getRParenLoc()); |
| if (Err) |
| return std::move(Err); |
| |
| SmallVector<Expr *, 4> ToArgs(E->getNumArgs()); |
| if (Error Err = ImportContainerChecked(E->arguments(), ToArgs)) |
| return std::move(Err); |
| |
| return CXXMemberCallExpr::Create(Importer.getToContext(), ToCallee, ToArgs, |
| ToType, E->getValueKind(), ToRParenLoc, |
| E->getFPFeatures()); |
| } |
| |
| ExpectedStmt ASTNodeImporter::VisitCXXThisExpr(CXXThisExpr *E) { |
| ExpectedType ToTypeOrErr = import(E->getType()); |
| if (!ToTypeOrErr) |
| return ToTypeOrErr.takeError(); |
| |
| ExpectedSLoc ToLocationOrErr = import(E->getLocation()); |
| if (!ToLocationOrErr) |
| return ToLocationOrErr.takeError(); |
| |
| return new (Importer.getToContext()) CXXThisExpr( |
| *ToLocationOrErr, *ToTypeOrErr, E->isImplicit()); |
| } |
| |
| ExpectedStmt ASTNodeImporter::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) { |
| ExpectedType ToTypeOrErr = import(E->getType()); |
| if (!ToTypeOrErr) |
| return ToTypeOrErr.takeError(); |
| |
| ExpectedSLoc ToLocationOrErr = import(E->getLocation()); |
| if (!ToLocationOrErr) |
| return ToLocationOrErr.takeError(); |
| |
| return new (Importer.getToContext()) CXXBoolLiteralExpr( |
| E->getValue(), *ToTypeOrErr, *ToLocationOrErr); |
| } |
| |
| ExpectedStmt ASTNodeImporter::VisitMemberExpr(MemberExpr *E) { |
| 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 (IdentifierInfo *FromII = E->getDestroyedTypeIdentifier()) { |
| IdentifierInfo *ToII = Importer.Import(FromII); |
| ExpectedSLoc ToDestroyedTypeLocOrErr = import(E->getDestroyedTypeLoc()); |
| if (!ToDestroyedTypeLocOrErr) |
| return ToDestroyedTypeLocOrErr.takeError(); |
| Storage = PseudoDestructorTypeStorage(ToII, *ToDestroyedTypeLocOrErr); |
| } else { |
| if (auto ToTIOrErr = import(E->getDestroyedTypeInfo())) |
| Storage = PseudoDestructorTypeStorage(*ToTIOrErr); |
| else |
| return ToTIOrErr.takeError(); |
| } |
| |
| return new (Importer.getToContext()) CXXPseudoDestructorExpr( |
| Importer.getToContext(), ToBase, E->isArrow(), ToOperatorLoc, |
| ToQualifierLoc, ToScopeTypeInfo, ToColonColonLoc, ToTildeLoc, Storage); |
| } |
| |
| ExpectedStmt ASTNodeImporter::VisitCXXDependentScopeMemberExpr( |
| CXXDependentScopeMemberExpr *E) { |
| Error Err = Error::success(); |
| auto ToType = importChecked(Err, E->getType()); |
| auto ToOperatorLoc = importChecked(Err, E->getOperatorLoc()); |
| auto ToQualifierLoc = importChecked(Err, E->getQualifierLoc()); |
| auto ToTemplateKeywordLoc = importChecked(Err, E->getTemplateKeywordLoc()); |
| auto ToFirstQualifierFoundInScope = |
| importChecked(Err, E->getFirstQualifierFoundInScope()); |
| if (Err) |
| return std::move(Err); |
| |
| Expr *ToBase = nullptr; |
| if (!E->isImplicitAccess()) { |
| if (ExpectedExpr ToBaseOrErr = import(E->getBase())) |
| ToBase = *ToBaseOrErr; |
| else |
| return ToBaseOrErr.takeError(); |
| } |
| |
| TemplateArgumentListInfo ToTAInfo, *ResInfo = nullptr; |
| |
| if (E->hasExplicitTemplateArgs()) { |
| if (Error Err = |
| ImportTemplateArgumentListInfo(E->getLAngleLoc(), E->getRAngleLoc(), |
| E->template_arguments(), ToTAInfo)) |
| return std::move(Err); |
| ResInfo = &ToTAInfo; |
| } |
| auto ToMember = importChecked(Err, E->getMember()); |
| auto ToMemberLoc = importChecked(Err, E->getMemberLoc()); |
| if (Err) |
| return std::move(Err); |
| DeclarationNameInfo ToMemberNameInfo(ToMember, ToMemberLoc); |
| |
| // Import additional name location/type info. |
| if (Error Err = |
| ImportDeclarationNameLoc(E->getMemberNameInfo(), ToMemberNameInfo)) |
| return std::move(Err); |
| |
| return CXXDependentScopeMemberExpr::Create( |
| Importer.getToContext(), ToBase, ToType, E->isArrow(), ToOperatorLoc, |
| ToQualifierLoc, ToTemplateKeywordLoc, ToFirstQualifierFoundInScope, |
| ToMemberNameInfo, ResInfo); |
| } |
| |
| ExpectedStmt |
| ASTNodeImporter::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) { |
| Error Err = Error::success(); |
| auto ToQualifierLoc = importChecked(Err, E->getQualifierLoc()); |
| auto ToTemplateKeywordLoc = importChecked(Err, E->getTemplateKeywordLoc()); |
| auto ToDeclName = importChecked(Err, E->getDeclName()); |
| auto ToNameLoc = importChecked(Err, E->getNameInfo().getLoc()); |
| auto ToLAngleLoc = importChecked(Err, E->getLAngleLoc()); |
| auto ToRAngleLoc = importChecked(Err, E->getRAngleLoc()); |
| if (Err) |
| return std::move(Err); |
| |
| DeclarationNameInfo ToNameInfo(ToDeclName, ToNameLoc); |
| if (Error Err = ImportDeclarationNameLoc(E->getNameInfo(), ToNameInfo)) |
| return std::move(Err); |
| |
| TemplateArgumentListInfo ToTAInfo(ToLAngleLoc, ToRAngleLoc); |
| TemplateArgumentListInfo *ResInfo = nullptr; |
| if (E->hasExplicitTemplateArgs()) { |
| if (Error Err = |
| ImportTemplateArgumentListInfo(E->template_arguments(), ToTAInfo)) |
| return std::move(Err); |
| ResInfo = &ToTAInfo; |
| } |
| |
| return DependentScopeDeclRefExpr::Create( |
| Importer.getToContext(), ToQualifierLoc, ToTemplateKeywordLoc, |
| ToNameInfo, ResInfo); |
| } |
| |
| ExpectedStmt ASTNodeImporter::VisitCXXUnresolvedConstructExpr( |
| CXXUnresolvedConstructExpr *E) { |
| Error Err = Error::success(); |
| auto ToLParenLoc = importChecked(Err, E->getLParenLoc()); |
| auto ToRParenLoc = importChecked(Err, E->getRParenLoc()); |
| auto ToType = importChecked(Err, E->getType()); |
| auto ToTypeSourceInfo = importChecked(Err, E->getTypeSourceInfo()); |
| if (Err) |
| return std::move(Err); |
| |
| SmallVector<Expr *, 8> ToArgs(E->getNumArgs()); |
| if (Error Err = |
| ImportArrayChecked(E->arg_begin(), E->arg_end(), ToArgs.begin())) |
| return std::move(Err); |
| |
| return CXXUnresolvedConstructExpr::Create( |
| Importer.getToContext(), ToType, ToTypeSourceInfo, ToLParenLoc, |
| llvm::makeArrayRef(ToArgs), ToRParenLoc); |
| } |
| |
| ExpectedStmt |
| ASTNodeImporter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) { |
| Expected<CXXRecordDecl *> ToNamingClassOrErr = import(E->getNamingClass()); |
| if (!ToNamingClassOrErr) |
| return ToNamingClassOrErr.takeError(); |
| |
| auto ToQualifierLocOrErr = import(E->getQualifierLoc()); |
| if (!ToQualifierLocOrErr) |
| return ToQualifierLocOrErr.takeError(); |
| |
| Error Err = Error::success(); |
| auto ToName = importChecked(Err, E->getName()); |
| auto ToNameLoc = importChecked(Err, E->getNameLoc()); |
| if (Err) |
| return std::move(Err); |
| DeclarationNameInfo ToNameInfo(ToName, ToNameLoc); |
| |
| // Import additional name location/type info. |
| if (Error Err = ImportDeclarationNameLoc(E->getNameInfo(), ToNameInfo)) |
| return std::move(Err); |
| |
| UnresolvedSet<8> ToDecls; |
| for (auto *D : E->decls()) |
| if (auto ToDOrErr = import(D)) |
| ToDecls.addDecl(cast<NamedDecl>(*ToDOrErr)); |
| else |
| return ToDOrErr.takeError(); |
| |
| if (E->hasExplicitTemplateArgs()) { |
| TemplateArgumentListInfo ToTAInfo; |
| if (Error Err = ImportTemplateArgumentListInfo( |
| E->getLAngleLoc(), E->getRAngleLoc(), E->template_arguments(), |
| ToTAInfo)) |
| return std::move(Err); |
| |
| ExpectedSLoc ToTemplateKeywordLocOrErr = import(E->getTemplateKeywordLoc()); |
| if (!ToTemplateKeywordLocOrErr) |
| return ToTemplateKeywordLocOrErr.takeError(); |
| |
| return UnresolvedLookupExpr::Create( |
| Importer.getToContext(), *ToNamingClassOrErr, *ToQualifierLocOrErr, |
| *ToTemplateKeywordLocOrErr, ToNameInfo, E->requiresADL(), &ToTAInfo, |
| ToDecls.begin(), ToDecls.end()); |
| } |
| |
| return UnresolvedLookupExpr::Create( |
| Importer.getToContext(), *ToNamingClassOrErr, *ToQualifierLocOrErr, |
| ToNameInfo, E->requiresADL(), E->isOverloaded(), ToDecls.begin(), |
| ToDecls.end()); |
| } |
| |
| ExpectedStmt |
| ASTNodeImporter::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E) { |
| Error Err = Error::success(); |
| auto ToType = importChecked(Err, E->getType()); |
| auto ToOperatorLoc = importChecked(Err, E->getOperatorLoc()); |
| auto ToQualifierLoc = importChecked(Err, E->getQualifierLoc()); |
| auto ToTemplateKeywordLoc = importChecked(Err, E->getTemplateKeywordLoc()); |
| auto ToName = importChecked(Err, E->getName()); |
| auto ToNameLoc = importChecked(Err, E->getNameLoc()); |
| if (Err) |
| return std::move(Err); |
| |
| DeclarationNameInfo ToNameInfo(ToName, ToNameLoc); |
| // Import additional name location/type info. |
| if (Error Err = ImportDeclarationNameLoc(E->getNameInfo(), ToNameInfo)) |
| return std::move(Err); |
| |
| UnresolvedSet<8> ToDecls; |
| for (Decl *D : E->decls()) |
| if (auto ToDOrErr = import(D)) |
| ToDecls.addDecl(cast<NamedDecl>(*ToDOrErr)); |
| else |
| return ToDOrErr.takeError(); |
| |
| TemplateArgumentListInfo ToTAInfo; |
| TemplateArgumentListInfo *ResInfo = nullptr; |
| if (E->hasExplicitTemplateArgs()) { |
| TemplateArgumentListInfo FromTAInfo; |
| E->copyTemplateArgumentsInto(FromTAInfo); |
| if (Error Err = ImportTemplateArgumentListInfo(FromTAInfo, ToTAInfo)) |
| return std::move(Err); |
| ResInfo = &ToTAInfo; |
| } |
| |
| Expr *ToBase = nullptr; |
| if (!E->isImplicitAccess()) { |
| if (ExpectedExpr ToBaseOrErr = import(E->getBase())) |
| ToBase = *ToBaseOrErr; |
| else |
| return ToBaseOrErr.takeError(); |
| } |
| |
| return UnresolvedMemberExpr::Create( |
| Importer.getToContext(), E->hasUnresolvedUsing(), ToBase, ToType, |
| E->isArrow(), ToOperatorLoc, ToQualifierLoc, ToTemplateKeywordLoc, |
| ToNameInfo, ResInfo, ToDecls.begin(), ToDecls.end()); |
| } |
| |
| ExpectedStmt ASTNodeImporter::VisitCallExpr(CallExpr *E) { |
| Error Err = Error::success(); |
| auto ToCallee = importChecked(Err, E->getCallee()); |
| auto ToType = importChecked(Err, E->getType()); |
| auto ToRParenLoc = importChecked(Err, E->getRParenLoc()); |
| if (Err) |
| return std::move(Err); |
| |
| unsigned NumArgs = E->getNumArgs(); |
| llvm::SmallVector<Expr *, 2> ToArgs(NumArgs); |
| if (Error Err = ImportContainerChecked(E->arguments(), ToArgs)) |
| return std::move(Err); |
| |
| if (const auto *OCE = dyn_cast<CXXOperatorCallExpr>(E)) { |
| return CXXOperatorCallExpr::Create( |
| Importer.getToContext(), OCE->getOperator(), ToCallee, ToArgs, ToType, |
| OCE->getValueKind(), ToRParenLoc, OCE->getFPFeatures(), |
| OCE->getADLCallKind()); |
| } |
| |
| return CallExpr::Create(Importer.getToContext(), ToCallee, ToArgs, ToType, |
| E->getValueKind(), ToRParenLoc, E->getFPFeatures(), |
| /*MinNumArgs=*/0, E->getADLCallKind()); |
| } |
| |
| ExpectedStmt ASTNodeImporter::VisitLambdaExpr(LambdaExpr *E) { |
| CXXRecordDecl *FromClass = E->getLambdaClass(); |
| auto ToClassOrErr = import(FromClass); |
| if (!ToClassOrErr) |
| return ToClassOrErr.takeError(); |
| CXXRecordDecl *ToClass = *ToClassOrErr; |
| |
| auto ToCallOpOrErr = import(E->getCallOperator()); |
| if (!ToCallOpOrErr) |
| return ToCallOpOrErr.takeError(); |
| |
| SmallVector<Expr *, 8> ToCaptureInits(E->capture_size()); |
| if (Error Err = ImportContainerChecked(E->capture_inits(), ToCaptureInits)) |
| return std::move(Err); |
| |
| Error Err = Error::success(); |
| auto ToIntroducerRange = importChecked(Err, E->getIntroducerRange()); |
| auto ToCaptureDefaultLoc = importChecked(Err, E->getCaptureDefaultLoc()); |
| auto ToEndLoc = importChecked(Err, E->getEndLoc()); |
| if (Err) |
| return std::move(Err); |
| |
| return LambdaExpr::Create(Importer.getToContext(), ToClass, ToIntroducerRange, |
| E->getCaptureDefault(), ToCaptureDefaultLoc, |
| E->hasExplicitParameters(), |
| E->hasExplicitResultType(), ToCaptureInits, |
| ToEndLoc, E->containsUnexpandedParameterPack()); |
| } |
| |
| |
| ExpectedStmt ASTNodeImporter::VisitInitListExpr(InitListExpr *E) { |
| Error Err = Error::success(); |
| auto ToLBraceLoc = importChecked(Err, E->getLBraceLoc()); |
| auto ToRBraceLoc = importChecked(Err, E->getRBraceLoc()); |
| auto ToType = importChecked(Err, E->getType()); |
| if (Err) |
| return std::move(Err); |
| |
| SmallVector<Expr *, 4> ToExprs(E->getNumInits()); |
| if (Error Err = ImportContainerChecked(E->inits(), ToExprs)) |
| return std::move(Err); |
| |
| ASTContext &ToCtx = Importer.getToContext(); |
| InitListExpr *To = new (ToCtx) InitListExpr( |
| ToCtx, ToLBraceLoc, ToExprs, ToRBraceLoc); |
| To->setType(ToType); |
| |
| if (E->hasArrayFiller()) { |
| if (ExpectedExpr ToFillerOrErr = import(E->getArrayFiller())) |
| To->setArrayFiller(*ToFillerOrErr); |
| else |
| return ToFillerOrErr.takeError(); |
| } |
| |
| if (FieldDecl *FromFD = E->getInitializedFieldInUnion()) { |
| if (auto ToFDOrErr = import(FromFD)) |
| To->setInitializedFieldInUnion(*ToFDOrErr); |
| else |
| return ToFDOrErr.takeError(); |
| } |
| |
| if (InitListExpr *SyntForm = E->getSyntacticForm()) { |
| if (auto ToSyntFormOrErr = import(SyntForm)) |
| To->setSyntacticForm(*ToSyntFormOrErr); |
| else |
| return ToSyntFormOrErr.takeError(); |
| } |
| |
| // Copy InitListExprBitfields, which are not handled in the ctor of |
| // InitListExpr. |
| To->sawArrayRangeDesignator(E->hadArrayRangeDesignator()); |
| |
| return To; |
| } |
| |
| ExpectedStmt ASTNodeImporter::VisitCXXStdInitializerListExpr( |
| CXXStdInitializerListExpr *E) { |
| ExpectedType ToTypeOrErr = import(E->getType()); |
| if (!ToTypeOrErr) |
| return ToTypeOrErr.takeError(); |
| |
| ExpectedExpr ToSubExprOrErr = import(E->getSubExpr()); |
| if (!ToSubExprOrErr) |
| return ToSubExprOrErr.takeError(); |
| |
| return new (Importer.getToContext()) CXXStdInitializerListExpr( |
| *ToTypeOrErr, *ToSubExprOrErr); |
| } |
| |
| ExpectedStmt ASTNodeImporter::VisitCXXInheritedCtorInitExpr( |
| CXXInheritedCtorInitExpr *E) { |
| Error Err = Error::success(); |
| auto ToLocation = importChecked(Err, E->getLocation()); |
| auto ToType = importChecked(Err, E->getType()); |
| auto ToConstructor = importChecked(Err, E->getConstructor()); |
| if (Err) |
| return std::move(Err); |
| |
| return new (Importer.getToContext()) CXXInheritedCtorInitExpr( |
| ToLocation, ToType, ToConstructor, E->constructsVBase(), |
| E->inheritedFromVBase()); |
| } |
| |
| ExpectedStmt ASTNodeImporter::VisitArrayInitLoopExpr(ArrayInitLoopExpr *E) { |
| Error Err = Error::success(); |
| auto ToType = importChecked(Err, E->getType()); |
| auto ToCommonExpr = importChecked(Err, E->getCommonExpr()); |
| auto ToSubExpr = importChecked(Err, E->getSubExpr()); |
| if (Err) |
| return std::move(Err); |
| |
| return new (Importer.getToContext()) ArrayInitLoopExpr( |
| ToType, ToCommonExpr, ToSubExpr); |
| } |
| |
| ExpectedStmt ASTNodeImporter::VisitArrayInitIndexExpr(ArrayInitIndexExpr *E) { |
| ExpectedType ToTypeOrErr = import(E->getType()); |
| if (!ToTypeOrErr) |
| return ToTypeOrErr.takeError(); |
| return new (Importer.getToContext()) ArrayInitIndexExpr(*ToTypeOrErr); |
| } |
| |
| ExpectedStmt ASTNodeImporter::VisitCXXDefaultInitExpr(CXXDefaultInitExpr *E) { |
| ExpectedSLoc ToBeginLocOrErr = import(E->getBeginLoc()); |
| if (!ToBeginLocOrErr) |
| return ToBeginLocOrErr.takeError(); |
| |
| auto ToFieldOrErr = import(E->getField()); |
| if (!ToFieldOrErr) |
| return ToFieldOrErr.takeError(); |
| |
| auto UsedContextOrErr = Importer.ImportContext(E->getUsedContext()); |
| if (!UsedContextOrErr) |
| return UsedContextOrErr.takeError(); |
| |
| return CXXDefaultInitExpr::Create( |
| Importer.getToContext(), *ToBeginLocOrErr, *ToFieldOrErr, *UsedContextOrErr); |
| } |
| |
| ExpectedStmt ASTNodeImporter::VisitCXXNamedCastExpr(CXXNamedCastExpr *E) { |
| Error Err = Error::success(); |
| auto ToType = importChecked(Err, E->getType()); |
| auto ToSubExpr = importChecked(Err, E->getSubExpr()); |
| auto ToTypeInfoAsWritten = importChecked(Err, E->getTypeInfoAsWritten()); |
| auto ToOperatorLoc = importChecked(Err, E->getOperatorLoc()); |
| auto ToRParenLoc = importChecked(Err, E->getRParenLoc()); |
| auto ToAngleBrackets = importChecked(Err, E->getAngleBrackets()); |
| if (Err) |
| return std::move(Err); |
| |
| ExprValueKind VK = E->getValueKind(); |
| CastKind CK = E->getCastKind(); |
| auto ToBasePathOrErr = ImportCastPath(E); |
| if (!ToBasePathOrErr) |
| return ToBasePathOrErr.takeError(); |
| |
| if (auto CCE = dyn_cast<CXXStaticCastExpr>(E)) { |
| return CXXStaticCastExpr::Create( |
| Importer.getToContext(), ToType, VK, CK, ToSubExpr, &(*ToBasePathOrErr), |
| ToTypeInfoAsWritten, CCE->getFPFeatures(), ToOperatorLoc, ToRParenLoc, |
| ToAngleBrackets); |
| } else if (isa<CXXDynamicCastExpr>(E)) { |
| return CXXDynamicCastExpr::Create( |
| Importer.getToContext(), ToType, VK, CK, ToSubExpr, &(*ToBasePathOrErr), |
| ToTypeInfoAsWritten, ToOperatorLoc, ToRParenLoc, ToAngleBrackets); |
| } else if (isa<CXXReinterpretCastExpr>(E)) { |
| return CXXReinterpretCastExpr::Create( |
| Importer.getToContext(), ToType, VK, CK, ToSubExpr, &(*ToBasePathOrErr), |
| ToTypeInfoAsWritten, ToOperatorLoc, ToRParenLoc, ToAngleBrackets); |
| } else if (isa<CXXConstCastExpr>(E)) { |
| return CXXConstCastExpr::Create( |
| Importer.getToContext(), ToType, VK, ToSubExpr, ToTypeInfoAsWritten, |
| ToOperatorLoc, ToRParenLoc, ToAngleBrackets); |
| } else { |
| llvm_unreachable("Unknown cast type"); |
| return make_error<ImportError>(); |
| } |
| } |
| |
| ExpectedStmt ASTNodeImporter::VisitSubstNonTypeTemplateParmExpr( |
| SubstNonTypeTemplateParmExpr *E) { |
| Error Err = Error::success(); |
| auto ToType = importChecked(Err, E->getType()); |
| auto ToExprLoc = importChecked(Err, E->getExprLoc()); |
| auto ToParameter = importChecked(Err, E->getParameter()); |
| auto ToReplacement = importChecked(Err, E->getReplacement()); |
| if (Err) |
| return std::move(Err); |
| |
| return new (Importer.getToContext()) SubstNonTypeTemplateParmExpr( |
| ToType, E->getValueKind(), ToExprLoc, ToParameter, |
| E->isReferenceParameter(), ToReplacement); |
| } |
| |
| ExpectedStmt ASTNodeImporter::VisitTypeTraitExpr(TypeTraitExpr *E) { |
| Error Err = Error::success(); |
| auto ToType = importChecked(Err, E->getType()); |
| auto ToBeginLoc = importChecked(Err, E->getBeginLoc()); |
| auto ToEndLoc = importChecked(Err, E->getEndLoc()); |
| if (Err) |
| return std::move(Err); |
| |
| SmallVector<TypeSourceInfo *, 4> ToArgs(E->getNumArgs()); |
| if (Error Err = ImportContainerChecked(E->getArgs(), ToArgs)) |
| return std::move(Err); |
| |
| // 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<CXXMethodDecl>( |
| (*ImportedOrErr)->getCanonicalDecl())); |
| else |
| ImportErrors = |
| joinErrors(std::move(ImportErrors), ImportedOrErr.takeError()); |
| } |
| return ImportErrors; |
| } |
| |
| ASTImporter::ASTImporter(ASTContext &ToContext, FileManager &ToFileManager, |
| ASTContext &FromContext, FileManager &FromFileManager, |
| bool MinimalImport, |
| std::shared_ptr<ASTImporterSharedState> SharedState) |
| : SharedState(SharedState), ToContext(ToContext), FromContext(FromContext), |
| ToFileManager(ToFileManager), FromFileManager(FromFileManager), |
| Minimal(MinimalImport), ODRHandling(ODRHandlingType::Conservative) { |
| |
| // Create a default state without the lookup table: LLDB case. |
| if (!SharedState) { |
| this->SharedState = std::make_shared<ASTImporterSharedState>(); |
| } |
| |
| ImportedDecls[FromContext.getTranslationUnitDecl()] = |
| ToContext.getTranslationUnitDecl(); |
| } |
| |
| ASTImporter::~ASTImporter() = default; |
| |
| Optional<unsigned> ASTImporter::getFieldIndex(Decl *F) { |
| assert(F && (isa<FieldDecl>(*F) || isa<IndirectFieldDecl>(*F)) && |
| "Try to get field index for non-field."); |
| |
| auto *Owner = dyn_cast<RecordDecl>(F->getDeclContext()); |
| if (!Owner) |
| return None; |
| |
| unsigned Index = 0; |
| for (const auto *D : Owner->decls()) { |
| if (D == F) |
| return Index; |
| |
| if (isa<FieldDecl>(*D) || isa<IndirectFieldDecl>(*D)) |
| ++Index; |
| } |
| |
| llvm_unreachable("Field was not found in its parent context."); |
| |
| return None; |
| } |
| |
| ASTImporter::FoundDeclsTy |
| ASTImporter::findDeclsInToCtx(DeclContext *DC, DeclarationName Name) { |
| // We search in the redecl context because of transparent contexts. |
| // E.g. a simple C language enum is a transparent context: |
| // enum E { A, B }; |
| // Now if we had a global variable in the TU |
| // int A; |
| // then the enum constant 'A' and the variable 'A' violates ODR. |
| // We can diagnose this only if we search in the redecl context. |
| DeclContext *ReDC = DC->getRedeclContext(); |
| if (SharedState->getLookupTable()) { |
| ASTImporterLookupTable::LookupResult LookupResult = |
| SharedState->getLookupTable()->lookup(ReDC, Name); |
| return FoundDeclsTy(LookupResult.begin(), LookupResult.end()); |
| } else { |
| DeclContext::lookup_result NoloadLookupResult = ReDC->noload_lookup(Name); |
| FoundDeclsTy Result(NoloadLookupResult.begin(), NoloadLookupResult.end()); |
| // We must search by the slow case of localUncachedLookup because that is |
| // working even if there is no LookupPtr for the DC. We could use |
| // DC::buildLookup() to create the LookupPtr, but that would load external |
| // decls again, we must avoid that case. |
| // Also, even if we had the LookupPtr, we must find Decls which are not |
| // in the LookupPtr, so we need the slow case. |
| // These cases are handled in ASTImporterLookupTable, but we cannot use |
| // that with LLDB since that traverses through the AST which initiates the |
| // load of external decls again via DC::decls(). And again, we must avoid |
| // loading external decls during the import. |
| if (Result.empty()) |
| ReDC->localUncachedLookup(Name, Result); |
| return Result; |
| } |
| } |
| |
| void ASTImporter::AddToLookupTable(Decl *ToD) { |
| SharedState->addDeclToLookup(ToD); |
| } |
| |
| Expected<Decl *> ASTImporter::ImportImpl(Decl *FromD) { |
| // Import the decl using ASTNodeImporter. |
| ASTNodeImporter Importer(*this); |
| return Importer.Visit(FromD); |
| } |
| |
| void ASTImporter::RegisterImportedDecl(Decl *FromD, Decl *ToD) { |
| MapImported(FromD, ToD); |
| } |
| |
| llvm::Expected<ExprWithCleanups::CleanupObject> |
| ASTImporter::Import(ExprWithCleanups::CleanupObject From) { |
| if (auto *CLE = From.dyn_cast<CompoundLiteralExpr *>()) { |
| if (Expected<Expr *> R = Import(CLE)) |
| return ExprWithCleanups::CleanupObject(cast<CompoundLiteralExpr>(*R)); |
| } |
| |
| // FIXME: Handle BlockDecl when we implement importing BlockExpr in |
| // ASTNodeImporter. |
| return make_error<ImportError>(ImportError::UnsupportedConstruct); |
| } |
| |
| Expected<QualType> ASTImporter::Import(QualType FromT) { |
| if (FromT.isNull()) |
| return QualType{}; |
| |
| const Type *FromTy = FromT.getTypePtr(); |
| |
| // Check whether we've already imported this type. |
| llvm::DenseMap<const Type *, const Type *>::iterator Pos |
| = ImportedTypes.find(FromTy); |
| if (Pos != ImportedTypes.end()) |
| return ToContext.getQualifiedType(Pos->second, FromT.getLocalQualifiers()); |
| |
| // Import the type |
| ASTNodeImporter Importer(*this); |
| ExpectedType ToTOrErr = Importer.Visit(FromTy); |
| if (!ToTOrErr) |
| return ToTOrErr.takeError(); |
| |
| // Record the imported type. |
| ImportedTypes[FromTy] = (*ToTOrErr).getTypePtr(); |
| |
| return ToContext.getQualifiedType(*ToTOrErr, FromT.getLocalQualifiers()); |
| } |
| |
| Expected<TypeSourceInfo *> ASTImporter::Import(TypeSourceInfo *FromTSI) { |
| if (!FromTSI) |
| return FromTSI; |
| |
| // FIXME: For now we just create a "trivial" type source info based |
| // on the type and a single location. Implement a real version of this. |
| ExpectedType TOrErr = Import(FromTSI->getType()); |
| if (!TOrErr) |
| return TOrErr.takeError(); |
| ExpectedSLoc BeginLocOrErr = Import(FromTSI->getTypeLoc().getBeginLoc()); |
| if (!BeginLocOrErr) |
| return BeginLocOrErr.takeError(); |
| |
| return ToContext.getTrivialTypeSourceInfo(*TOrErr, *BeginLocOrErr); |
| } |
| |
| Expected<Attr *> ASTImporter::Import(const Attr *FromAttr) { |
| Attr *ToAttr = nullptr; |
| SourceRange ToRange; |
| if (Error Err = importInto(ToRange, FromAttr->getRange())) |
| return std::move(Err); |
| |
| // FIXME: Is there some kind of AttrVisitor to use here? |
| switch (FromAttr->getKind()) { |
| case attr::Aligned: { |
| auto *From = cast<AlignedAttr>(FromAttr); |
| AlignedAttr *To; |
| auto CreateAlign = [&](bool IsAlignmentExpr, void *Alignment) { |
| return AlignedAttr::Create(ToContext, IsAlignmentExpr, Alignment, ToRange, |
| From->getSyntax(), |
| From->getSemanticSpelling()); |
| }; |
| if (From->isAlignmentExpr()) { |
| if (auto ToEOrErr = Import(From->getAlignmentExpr())) |
| To = CreateAlign(true, *ToEOrErr); |
| else |
| return ToEOrErr.takeError(); |
| } else { |
| if (auto ToTOrErr = Import(From->getAlignmentType())) |
| To = CreateAlign(false, *ToTOrErr); |
| else |
| return ToTOrErr.takeError(); |
| } |
| To->setInherited(From->isInherited()); |
| To->setPackExpansion(From->isPackExpansion()); |
| To->setImplicit(From->isImplicit()); |
| ToAttr = To; |
| break; |
| } |
| case attr::Format: { |
| const auto *From = cast<FormatAttr>(FromAttr); |
| FormatAttr *To; |
| IdentifierInfo *ToAttrType = Import(From->getType()); |
| To = FormatAttr::Create(ToContext, ToAttrType, From->getFormatIdx(), |
| From->getFirstArg(), ToRange, From->getSyntax()); |
| To->setInherited(From->isInherited()); |
| ToAttr = To; |
| break; |
| } |
| default: |
| // FIXME: 'clone' copies every member but some of them should be imported. |
| // Handle other Attrs that have parameters that should be imported. |
| ToAttr = FromAttr->clone(ToContext); |
| ToAttr->setRange(ToRange); |
| break; |
| } |
| assert(ToAttr && "Attribute should be created."); |
| |
| return ToAttr; |
| } |
| |
| Decl *ASTImporter::GetAlreadyImportedOrNull(const Decl *FromD) const { |
| auto Pos = ImportedDecls.find(FromD); |
| if (Pos != ImportedDecls.end()) |
| return Pos->second; |
| else |
| return nullptr; |
| } |
| |
| TranslationUnitDecl *ASTImporter::GetFromTU(Decl *ToD) { |
| auto FromDPos = ImportedFromDecls.find(ToD); |
| if (FromDPos == ImportedFromDecls.end()) |
| return nullptr; |
| return FromDPos->second->getTranslationUnitDecl(); |
| } |
| |
| Expected<Decl *> ASTImporter::Import(Decl *FromD) { |
| if (!FromD) |
| return nullptr; |
| |
| // Push FromD to the stack, and remove that when we return. |
| ImportPath.push(FromD); |
| auto ImportPathBuilder = |
| llvm::make_scope_exit([this]() { ImportPath.pop(); }); |
| |
| // Check whether there was a previous failed import. |
| // If yes return the existing error. |
| if (auto Error = getImportDeclErrorIfAny(FromD)) |
| return make_error<ImportError>(*Error); |
| |
| // Check whether we've already imported this declaration. |
| Decl *ToD = GetAlreadyImportedOrNull(FromD); |
| if (ToD) { |
| // Already imported (possibly from another TU) and with an error. |
| if (auto Error = SharedState->getImportDeclErrorIfAny(ToD)) { |
| setImportDeclError(FromD, *Error); |
| return make_error<ImportError>(*Error); |
| } |
| |
| // If FromD has some updated flags after last import, apply it. |
| updateFlags(FromD, ToD); |
| // If we encounter a cycle during an import then we save the relevant part |
| // of the import path associated to the Decl. |
| if (ImportPath.hasCycleAtBack()) |
| SavedImportPaths[FromD].push_back(ImportPath.copyCycleAtBack()); |
| return ToD; |
| } |
| |
| // Import the declaration. |
| ExpectedDecl ToDOrErr = ImportImpl(FromD); |
| if (!ToDOrErr) { |
| // Failed to import. |
| |
| auto Pos = ImportedDecls.find(FromD); |
| if (Pos != ImportedDecls.end()) { |
| // Import failed after the object was created. |
| // Remove all references to it. |
| auto *ToD = Pos->second; |
| ImportedDecls.erase(Pos); |
| |
| // ImportedDecls and ImportedFromDecls are not symmetric. It may happen |
| // (e.g. with namespaces) that several decls from the 'from' context are |
| // mapped to the same decl in the 'to' context. If we removed entries |
| // from the LookupTable here then we may end up removing them multiple |
| // times. |
| |
| // The Lookuptable contains decls only which are in the 'to' context. |
| // Remove from the Lookuptable only if it is *imported* into the 'to' |
| // context (and do not remove it if it was added during the initial |
| // traverse of the 'to' context). |
| auto PosF = ImportedFromDecls.find(ToD); |
| if (PosF != ImportedFromDecls.end()) { |
| SharedState->removeDeclFromLookup(ToD); |
| ImportedFromDecls.erase(PosF); |
| } |
| |
| // FIXME: AST may contain remaining references to the failed object. |
| // However, the ImportDeclErrors in the shared state contains all the |
| // failed objects together with their error. |
| } |
| |
| // Error encountered for the first time. |
| // After takeError the error is not usable any more in ToDOrErr. |
| // Get a copy of the error object (any more simple solution for this?). |
| ImportError ErrOut; |
| handleAllErrors(ToDOrErr.takeError(), |
| [&ErrOut](const ImportError &E) { ErrOut = E; }); |
| setImportDeclError(FromD, ErrOut); |
| // Set the error for the mapped to Decl, which is in the "to" context. |
| if (Pos != ImportedDecls.end()) |
| SharedState->setImportDeclError(Pos->second, ErrOut); |
| |
| // Set the error for all nodes which have been created before we |
| // recognized the error. |
| for (const auto &Path : SavedImportPaths[FromD]) |
| for (Decl *FromDi : Path) { |
| setImportDeclError(FromDi, ErrOut); |
| //FIXME Should we remove these Decls from ImportedDecls? |
| // Set the error for the mapped to Decl, which is in the "to" context. |
| auto Ii = ImportedDecls.find(FromDi); |
| if (Ii != ImportedDecls.end()) |
| SharedState->setImportDeclError(Ii->second, ErrOut); |
| // FIXME Should we remove these Decls from the LookupTable, |
| // and from ImportedFromDecls? |
| } |
| SavedImportPaths.erase(FromD); |
| |
| // Do not return ToDOrErr, error was taken out of it. |
| return make_error<ImportError>(ErrOut); |
| } |
| |
| ToD = *ToDOrErr; |
| |
| // FIXME: Handle the "already imported with error" case. We can get here |
| // nullptr only if GetImportedOrCreateDecl returned nullptr (after a |
| // previously failed create was requested). |
| // Later GetImportedOrCreateDecl can be updated to return the error. |
| if (!ToD) { |
| auto Err = getImportDeclErrorIfAny(FromD); |
| assert(Err); |
| return make_error<ImportError>(*Err); |
| } |
| |
| // We could import from the current TU without error. But previously we |
| // already had imported a Decl as `ToD` from another TU (with another |
| // ASTImporter object) and with an error. |
| if (auto Error = SharedState->getImportDeclErrorIfAny(ToD)) { |
| setImportDeclError(FromD, *Error); |
| return make_error<ImportError>(*Error); |
| } |
| |
| // Make sure that ImportImpl registered the imported decl. |
| assert(ImportedDecls.count(FromD) != 0 && "Missing call to MapImported?"); |
| |
| if (FromD->hasAttrs()) |
| for (const Attr *FromAttr : FromD->getAttrs()) { |
| auto ToAttrOrErr = Import(FromAttr); |
| if (ToAttrOrErr) |
| ToD->addAttr(*ToAttrOrErr); |
| else |
| return ToAttrOrErr.takeError(); |
| } |
| |
| // Notify subclasses. |
| Imported(FromD, ToD); |
| |
| updateFlags(FromD, ToD); |
| SavedImportPaths.erase(FromD); |
| return ToDOrErr; |
| } |
| |
| Expected<DeclContext *> ASTImporter::ImportContext(DeclContext *FromDC) { |
| if (!FromDC) |
| return FromDC; |
| |
| ExpectedDecl ToDCOrErr = Import(cast<Decl>(FromDC)); |
| if (!ToDCOrErr) |
| return ToDCOrErr.takeError(); |
| auto *ToDC = cast<DeclContext>(*ToDCOrErr); |
| |
| // When we're using a record/enum/Objective-C class/protocol as a context, we |
| // need it to have a definition. |
| if (auto *ToRecord = dyn_cast<RecordDecl>(ToDC)) { |
| auto *FromRecord = cast<RecordDecl>(FromDC); |
| if (ToRecord->isCompleteDefinition()) |
| return ToDC; |
| |
| // If FromRecord is not defined we need to force it to be. |
| // Simply calling CompleteDecl(...) for a RecordDecl will break some cases |
| // it will start the definition but we never finish it. |
| // If there are base classes they won't be imported and we will |
| // be missing anything that we inherit from those bases. |
| if (FromRecord->getASTContext().getExternalSource() && |
| !FromRecord->isCompleteDefinition()) |
| FromRecord->getASTContext().getExternalSource()->CompleteType(FromRecord); |
| |
| if (FromRecord->isCompleteDefinition()) |
| if (Error Err = ASTNodeImporter(*this).ImportDefinition( |
| FromRecord, ToRecord, ASTNodeImporter::IDK_Basic)) |
| return std::move(Err); |
| } else if (auto *ToEnum = dyn_cast<EnumDecl>(ToDC)) { |
| auto *FromEnum = cast<EnumDecl>(FromDC); |
| if (ToEnum->isCompleteDefinition()) { |
| // Do nothing. |
| } else if (FromEnum->isCompleteDefinition()) { |
| if (Error Err = ASTNodeImporter(*this).ImportDefinition( |
| FromEnum, ToEnum, ASTNodeImporter::IDK_Basic)) |
| return std::move(Err); |
| } else { |
| CompleteDecl(ToEnum); |
| } |
| } else if (auto *ToClass = dyn_cast<ObjCInterfaceDecl>(ToDC)) { |
| auto *FromClass = cast<ObjCInterfaceDecl>(FromDC); |
| if (ToClass->getDefinition()) { |
| // Do nothing. |
| } else if (ObjCInterfaceDecl *FromDef = FromClass->getDefinition()) { |
| if (Error Err = ASTNodeImporter(*this).ImportDefinition( |
| FromDef, ToClass, ASTNodeImporter::IDK_Basic)) |
| return std::move(Err); |
| } else { |
| CompleteDecl(ToClass); |
| } |
| } else if (auto *ToProto = dyn_cast<ObjCProtocolDecl>(ToDC)) { |
| auto *FromProto = cast<ObjCProtocolDecl>(FromDC); |
| if (ToProto->getDefinition()) { |
| // Do nothing. |
| } else if (ObjCProtocolDecl *FromDef = FromProto->getDefinition()) { |
| if (Error Err = ASTNodeImporter(*this).ImportDefinition( |
| FromDef, ToProto, ASTNodeImporter::IDK_Basic)) |
| return std::move(Err); |
| } else { |
| CompleteDecl(ToProto); |
| } |
| } |
| |
| return ToDC; |
| } |
| |
| Expected<Expr *> ASTImporter::Import(Expr *FromE) { |
| if (ExpectedStmt ToSOrErr = Import(cast_or_null<Stmt>(FromE))) |
| return cast_or_null<Expr>(*ToSOrErr); |
| else |
| return ToSOrErr.takeError(); |
| } |
| |
| Expected<Stmt *> ASTImporter::Import(Stmt *FromS) { |
| if (!FromS) |
| return nullptr; |
| |
| // Check whether we've already imported this statement. |
| llvm::DenseMap<Stmt *, Stmt *>::iterator Pos = ImportedStmts.find(FromS); |
| if (Pos != ImportedStmts.end()) |
| return Pos->second; |
| |
| // Import the statement. |
| ASTNodeImporter Importer(*this); |
| ExpectedStmt ToSOrErr = Importer.Visit(FromS); |
| if (!ToSOrErr) |
| return ToSOrErr; |
| |
| if (auto *ToE = dyn_cast<Expr>(*ToSOrErr)) { |
| auto *FromE = cast<Expr>(FromS); |
| // Copy ExprBitfields, which may not be handled in Expr subclasses |
| // constructors. |
| ToE->setValueKind(FromE->getValueKind()); |
| ToE->setObjectKind(FromE->getObjectKind()); |
| ToE->setDependence(FromE->getDependence()); |
| } |
| |
| // Record the imported statement object. |
| ImportedStmts[FromS] = *ToSOrErr; |
| return ToSOrErr; |
| } |
| |
| Expected<NestedNameSpecifier *> |
| ASTImporter::Import(NestedNameSpecifier *FromNNS) { |
| if (!FromNNS) |
| return nullptr; |
| |
| NestedNameSpecifier *Prefix = nullptr; |
| if (Error Err = importInto(Prefix, FromNNS->getPrefix())) |
| return std::move(Err); |
| |
| switch (FromNNS->getKind()) { |
| case NestedNameSpecifier::Identifier: |
| assert(FromNNS->getAsIdentifier() && "NNS should contain identifier."); |
| return NestedNameSpecifier::Create(ToContext, Prefix, |
| Import(FromNNS->getAsIdentifier())); |
| |
| case NestedNameSpecifier::Namespace: |
| if (ExpectedDecl NSOrErr = Import(FromNNS->getAsNamespace())) { |
| return NestedNameSpecifier::Create(ToContext, Prefix, |
| cast<NamespaceDecl>(*NSOrErr)); |
| } else |
| return NSOrErr.takeError(); |
| |
| case NestedNameSpecifier::NamespaceAlias: |
| if (ExpectedDecl NSADOrErr = Import(FromNNS->getAsNamespaceAlias())) |
| return NestedNameSpecifier::Create(ToContext, Prefix, |
| cast<NamespaceAliasDecl>(*NSADOrErr)); |
| else |
| return NSADOrErr.takeError(); |
| |
| case NestedNameSpecifier::Global: |
| return NestedNameSpecifier::GlobalSpecifier(ToContext); |
| |
| case NestedNameSpecifier::Super: |
| if (ExpectedDecl RDOrErr = Import(FromNNS->getAsRecordDecl())) |
| return NestedNameSpecifier::SuperSpecifier(ToContext, |
| cast<CXXRecordDecl>(*RDOrErr)); |
| else |
| return RDOrErr.takeError(); |
| |
| case NestedNameSpecifier::TypeSpec: |
| case NestedNameSpecifier::TypeSpecWithTemplate: |
| if (Expected<QualType> TyOrErr = |
| Import(QualType(FromNNS->getAsType(), 0u))) { |
| bool TSTemplate = |
| FromNNS->getKind() == NestedNameSpecifier::TypeSpecWithTemplate; |
| return NestedNameSpecifier::Create(ToContext, Prefix, TSTemplate, |
| TyOrErr->getTypePtr()); |
| } else { |
| return TyOrErr.takeError(); |
| } |
| } |
| |
| llvm_unreachable("Invalid nested name specifier kind"); |
| } |
| |
| Expected<NestedNameSpecifierLoc> |
| ASTImporter::Import(NestedNameSpecifierLoc FromNNS) { |
| // Copied from NestedNameSpecifier mostly. |
| SmallVector<NestedNameSpecifierLoc , 8> NestedNames; |
| NestedNameSpecifierLoc NNS = FromNNS; |
| |
| // Push each of the nested-name-specifiers's onto a stack for |
| // serialization in reverse order. |
| while (NNS) { |
| NestedNames.push_back(NNS); |
| NNS = NNS.getPrefix(); |
| } |
| |
| NestedNameSpecifierLocBuilder Builder; |
| |
| while (!NestedNames.empty()) { |
| NNS = NestedNames.pop_back_val(); |
| NestedNameSpecifier *Spec = nullptr; |
| if (Error Err = importInto(Spec, NNS.getNestedNameSpecifier())) |
| return std::move(Err); |
| |
| NestedNameSpecifier::SpecifierKind Kind = Spec->getKind(); |
| |
| SourceLocation ToLocalBeginLoc, ToLocalEndLoc; |
| if (Kind != NestedNameSpecifier::Super) { |
| if (Error Err = importInto(ToLocalBeginLoc, NNS.getLocalBeginLoc())) |
| return std::move(Err); |
| |
| if (Kind != NestedNameSpecifier::Global) |
| if (Error Err = importInto(ToLocalEndLoc, NNS.getLocalEndLoc())) |
| return std::move(Err); |
| } |
| |
| switch (Kind) { |
| case NestedNameSpecifier::Identifier: |
| Builder.Extend(getToContext(), Spec->getAsIdentifier(), ToLocalBeginLoc, |
| ToLocalEndLoc); |
| break; |
| |
| case NestedNameSpecifier::Namespace: |
| Builder.Extend(getToContext(), Spec->getAsNamespace(), ToLocalBeginLoc, |
| ToLocalEndLoc); |
| break; |
| |
| case NestedNameSpecifier::NamespaceAlias: |
| Builder.Extend(getToContext(), Spec->getAsNamespaceAlias(), |
| ToLocalBeginLoc, ToLocalEndLoc); |
| break; |
| |
| case NestedNameSpecifier::TypeSpec: |
| case NestedNameSpecifier::TypeSpecWithTemplate: { |
| SourceLocation ToTLoc; |
| if (Error Err = importInto(ToTLoc, NNS.getTypeLoc().getBeginLoc())) |
| return std::move(Err); |
| TypeSourceInfo *TSI = getToContext().getTrivialTypeSourceInfo( |
| QualType(Spec->getAsType(), 0), ToTLoc); |
| 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<TemplateName> ASTImporter::Import(TemplateName From) { |
| switch (From.getKind()) { |
| case TemplateName::Template: |
| if (ExpectedDecl ToTemplateOrErr = Import(From.getAsTemplateDecl())) |
| return TemplateName(cast<TemplateDecl>(*ToTemplateOrErr)); |
| else |
| return ToTemplateOrErr.takeError(); |
| |
| case TemplateName::OverloadedTemplate: { |
| OverloadedTemplateStorage *FromStorage = From.getAsOverloadedTemplate(); |
| UnresolvedSet<2> ToTemplates; |
| for (auto *I : *FromStorage) { |
| if (auto ToOrErr = Import(I)) |
| ToTemplates.addDecl(cast<NamedDecl>(*ToOrErr)); |
| else |
| return ToOrErr.takeError(); |
| } |
| return ToContext.getOverloadedTemplateName(ToTemplates.begin(), |
| ToTemplates.end()); |
| } |
| |
| case TemplateName::AssumedTemplate: { |
| AssumedTemplateStorage *FromStorage = From.getAsAssumedTemplateName(); |
| auto DeclNameOrErr = Import(FromStorage->getDeclName()); |
| if (!DeclNameOrErr) |
| return DeclNameOrErr.takeError(); |
| return ToContext.getAssumedTemplateName(*DeclNameOrErr); |
| } |
| |
| case TemplateName::QualifiedTemplate: { |
| QualifiedTemplateName *QTN = From.getAsQualifiedTemplateName(); |
| auto QualifierOrErr = Import(QTN->getQualifier()); |
| if (!QualifierOrErr) |
| return QualifierOrErr.takeError(); |
| |
| if (ExpectedDecl ToTemplateOrErr = Import(From.getAsTemplateDecl())) |
| return ToContext.getQualifiedTemplateName( |
| *QualifierOrErr, QTN->hasTemplateKeyword(), |
| cast<TemplateDecl>(*ToTemplateOrErr)); |
| else |
| return ToTemplateOrErr.takeError(); |
| } |
| |
| case TemplateName::DependentTemplate: { |
| DependentTemplateName *DTN = From.getAsDependentTemplateName(); |
| auto QualifierOrErr = Import(DTN->getQualifier()); |
| if (!QualifierOrErr) |
| return QualifierOrErr.takeError(); |
| |
| if (DTN->isIdentifier()) { |
| return ToContext.getDependentTemplateName(*QualifierOrErr, |
| Import(DTN->getIdentifier())); |
| } |
| |
| return ToContext.getDependentTemplateName(*QualifierOrErr, |
| DTN->getOperator()); |
| } |
| |
| case TemplateName::SubstTemplateTemplateParm: { |
| SubstTemplateTemplateParmStorage *Subst = |
| From.getAsSubstTemplateTemplateParm(); |
| ExpectedDecl ParamOrErr = Import(Subst->getParameter()); |
| if (!ParamOrErr) |
| return ParamOrErr.takeError(); |
| |
| auto ReplacementOrErr = Import(Subst->getReplacement()); |
| if (!ReplacementOrErr) |
| return ReplacementOrErr.takeError(); |
| |
| return ToContext.getSubstTemplateTemplateParm( |
| cast<TemplateTemplateParmDecl>(*ParamOrErr), *ReplacementOrErr); |
| } |
| |
| case TemplateName::SubstTemplateTemplateParmPack: { |
| SubstTemplateTemplateParmPackStorage *SubstPack |
| = From.getAsSubstTemplateTemplateParmPack(); |
| ExpectedDecl ParamOrErr = Import(SubstPack->getParameterPack()); |
| if (!ParamOrErr) |
| return ParamOrErr.takeError(); |
| |
| ASTNodeImporter Importer(*this); |
| auto ArgPackOrErr = |
| Importer.ImportTemplateArgument(SubstPack->getArgumentPack()); |
| if (!ArgPackOrErr) |
| return ArgPackOrErr.takeError(); |
| |
| return ToContext.getSubstTemplateTemplateParmPack( |
| cast<TemplateTemplateParmDecl>(*ParamOrErr), *ArgPackOrErr); |
| } |
| } |
| |
| llvm_unreachable("Invalid template name kind"); |
| } |
| |
| Expected<SourceLocation> ASTImporter::Import(SourceLocation FromLoc) { |
| if (FromLoc.isInvalid()) |
| return SourceLocation{}; |
| |
| SourceManager &FromSM = FromContext.getSourceManager(); |
| bool IsBuiltin = FromSM.isWrittenInBuiltinFile(FromLoc); |
| |
| std::pair<FileID, unsigned> Decomposed = FromSM.getDecomposedLoc(FromLoc); |
| Expected<FileID> ToFileIDOrErr = Import(Decomposed.first, IsBuiltin); |
| if (!ToFileIDOrErr) |
| return ToFileIDOrErr.takeError(); |
| SourceManager &ToSM = ToContext.getSourceManager(); |
| return ToSM.getComposedLoc(*ToFileIDOrErr, Decomposed.second); |
| } |
| |
| Expected<SourceRange> ASTImporter::Import(SourceRange FromRange) { |
| SourceLocation ToBegin, ToEnd; |
| if (Error Err = importInto(ToBegin, FromRange.getBegin())) |
| return std::move(Err); |
| if (Error Err = importInto(ToEnd, FromRange.getEnd())) |
| return std::move(Err); |
| |
| return SourceRange(ToBegin, ToEnd); |
| } |
| |
| Expected<FileID> ASTImporter::Import(FileID FromID, bool IsBuiltin) { |
| llvm::DenseMap<FileID, FileID>::iterator Pos = ImportedFileIDs.find(FromID); |
| if (Pos != ImportedFileIDs.end()) |
| return Pos->second; |
| |
| SourceManager &FromSM = FromContext.getSourceManager(); |
| SourceManager &ToSM = ToContext.getSourceManager(); |
| const SrcMgr::SLocEntry &FromSLoc = FromSM.getSLocEntry(FromID); |
| |
| // Map the FromID to the "to" source manager. |
| FileID ToID; |
| if (FromSLoc.isExpansion()) { |
| const SrcMgr::ExpansionInfo &FromEx = FromSLoc.getExpansion(); |
| ExpectedSLoc ToSpLoc = Import(FromEx.getSpellingLoc()); |
| if (!ToSpLoc) |
| return ToSpLoc.takeError(); |
| ExpectedSLoc ToExLocS = Import(FromEx.getExpansionLocStart()); |
| if (!ToExLocS) |
| return ToExLocS.takeError(); |
| unsigned TokenLen = FromSM.getFileIDSize(FromID); |
| SourceLocation MLoc; |
| if (FromEx.isMacroArgExpansion()) { |
| MLoc = ToSM.createMacroArgExpansionLoc(*ToSpLoc, *ToExLocS, TokenLen); |
| } else { |
| if (ExpectedSLoc ToExLocE = Import(FromEx.getExpansionLocEnd())) |
| MLoc = ToSM.createExpansionLoc(*ToSpLoc, *ToExLocS, *ToExLocE, TokenLen, |
| FromEx.isExpansionTokenRange()); |
| else |
| return ToExLocE.takeError(); |
| } |
| ToID = ToSM.getFileID(MLoc); |
| } else { |
| const SrcMgr::ContentCache *Cache = &FromSLoc.getFile().getContentCache(); |
| |
| if (!IsBuiltin && !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! |
| llvm::Optional<llvm::MemoryBufferRef> FromBuf = |
| Cache->getBufferOrNone(FromContext.getDiagnostics(), |
| FromSM.getFileManager(), SourceLocation{}); |
| if (!FromBuf) |
| return llvm::make_error<ImportError>(ImportError::Unknown); |
| |
| std::unique_ptr<llvm::MemoryBuffer> ToBuf = |
| llvm::MemoryBuffer::getMemBufferCopy(FromBuf->getBuffer(), |
| FromBuf->getBufferIdentifier()); |
| ToID = ToSM.createFileID(std::move(ToBuf), |
| FromSLoc.getFile().getFileCharacteristic()); |
| } |
| } |
| |
| assert(ToID.isValid() && "Unexpected invalid fileID was created."); |
| |
| ImportedFileIDs[FromID] = ToID; |
| |
| if (FileIDImportHandler) |
| FileIDImportHandler(ToID, FromID); |
| |
| return ToID; |
| } |
| |
| Expected<CXXCtorInitializer *> ASTImporter::Import(CXXCtorInitializer *From) { |
| ExpectedExpr ToExprOrErr = Import(From->getInit()); |
| if (!ToExprOrErr) |
| return ToExprOrErr.takeError(); |
| |
| auto LParenLocOrErr = Import(From->getLParenLoc()); |
| if (!LParenLocOrErr) |
| return LParenLocOrErr.takeError(); |
| |
| auto RParenLocOrErr = Import(From->getRParenLoc()); |
| if (!RParenLocOrErr) |
| return RParenLocOrErr.takeError(); |
| |
| if (From->isBaseInitializer()) { |
| auto ToTInfoOrErr = Import(From->getTypeSourceInfo()); |
| if (!ToTInfoOrErr) |
| return ToTInfoOrErr.takeError(); |
| |
| SourceLocation EllipsisLoc; |
| if (From->isPackExpansion()) |
| if (Error Err = importInto(EllipsisLoc, From->getEllipsisLoc())) |
| return std::move(Err); |
| |
| return new (ToContext) CXXCtorInitializer( |
| ToContext, *ToTInfoOrErr, From->isBaseVirtual(), *LParenLocOrErr, |
| *ToExprOrErr, *RParenLocOrErr, EllipsisLoc); |
| } else if (From->isMemberInitializer()) { |
| ExpectedDecl ToFieldOrErr = Import(From->getMember()); |
| if (!ToFieldOrErr) |
| return ToFieldOrErr.takeError(); |
| |
| auto MemberLocOrErr = Import(From->getMemberLocation()); |
| if (!MemberLocOrErr) |
| return MemberLocOrErr.takeError(); |
| |
| return new (ToContext) CXXCtorInitializer( |
| ToContext, cast_or_null<FieldDecl>(*ToFieldOrErr), *MemberLocOrErr, |
| *LParenLocOrErr, *ToExprOrErr, *RParenLocOrErr); |
| } else if (From->isIndirectMemberInitializer()) { |
| ExpectedDecl ToIFieldOrErr = Import(From->getIndirectMember()); |
| if (!ToIFieldOrErr) |
| return ToIFieldOrErr.takeError(); |
| |
| auto MemberLocOrErr = Import(From->getMemberLocation()); |
| if (!MemberLocOrErr) |
| return MemberLocOrErr.takeError(); |
| |
| return new (ToContext) CXXCtorInitializer( |
| ToContext, cast_or_null<IndirectFieldDecl>(*ToIFieldOrErr), |
| *MemberLocOrErr, *LParenLocOrErr, *ToExprOrErr, *RParenLocOrErr); |
| } else if (From->isDelegatingInitializer()) { |
| auto ToTInfoOrErr = Import(From->getTypeSourceInfo()); |
| if (!ToTInfoOrErr) |
| return ToTInfoOrErr.takeError(); |
| |
| return new (ToContext) |
| CXXCtorInitializer(ToContext, *ToTInfoOrErr, *LParenLocOrErr, |
| *ToExprOrErr, *RParenLocOrErr); |
| } else { |
| // FIXME: assert? |
| return make_error<ImportError>(); |
| } |
| } |
| |
| Expected<CXXBaseSpecifier *> |
| ASTImporter::Import(const CXXBaseSpecifier *BaseSpec) { |
| auto Pos = ImportedCXXBaseSpecifiers.find(BaseSpec); |
| if (Pos != ImportedCXXBaseSpecifiers.end()) |
| return Pos->second; |
| |
| Expected<SourceRange> ToSourceRange = Import(BaseSpec->getSourceRange()); |
| if (!ToSourceRange) |
| return ToSourceRange.takeError(); |
| Expected<TypeSourceInfo *> ToTSI = Import(BaseSpec->getTypeSourceInfo()); |
| if (!ToTSI) |
| return ToTSI.takeError(); |
| ExpectedSLoc ToEllipsisLoc = Import(BaseSpec->getEllipsisLoc()); |
| if (!ToEllipsisLoc) |
| return ToEllipsisLoc.takeError(); |
| CXXBaseSpecifier *Imported = new (ToContext) CXXBaseSpecifier( |
| *ToSourceRange, BaseSpec->isVirtual(), BaseSpec->isBaseOfClass(), |
| BaseSpec->getAccessSpecifierAsWritten(), *ToTSI, *ToEllipsisLoc); |
| ImportedCXXBaseSpecifiers[BaseSpec] = Imported; |
| return Imported; |
| } |
| |
| llvm::Expected<APValue> ASTImporter::Import(const APValue &FromValue) { |
| ASTNodeImporter Importer(*this); |
| return Importer.ImportAPValue(FromValue); |
| } |
| |
| Error ASTImporter::ImportDefinition(Decl *From) { |
| ExpectedDecl ToOrErr = Import(From); |
| if (!ToOrErr) |
| return ToOrErr.takeError(); |
| Decl *To = *ToOrErr; |
| |
| auto *FromDC = cast<DeclContext>(From); |
| ASTNodeImporter Importer(*this); |
| |
| if (auto *ToRecord = dyn_cast<RecordDecl>(To)) { |
| if (!ToRecord->getDefinition()) { |
| return Importer.ImportDefinition( |
| cast<RecordDecl>(FromDC), ToRecord, |
| ASTNodeImporter::IDK_Everything); |
| } |
| } |
| |
| if (auto *ToEnum = dyn_cast<EnumDecl>(To)) { |
| if (!ToEnum->getDefinition()) { |
| return Importer.ImportDefinition( |
| cast<EnumDecl>(FromDC), ToEnum, ASTNodeImporter::IDK_Everything); |
| } |
| } |
| |
| if (auto *ToIFace = dyn_cast<ObjCInterfaceDecl>(To)) { |
| if (!ToIFace->getDefinition()) { |
| return Importer.ImportDefinition( |
| cast<ObjCInterfaceDecl>(FromDC), ToIFace, |
| ASTNodeImporter::IDK_Everything); |
| } |
| } |
| |
| if (auto *ToProto = dyn_cast<ObjCProtocolDecl>(To)) { |
| if (!ToProto->getDefinition()) { |
| return Importer.ImportDefinition( |
| cast<ObjCProtocolDecl>(FromDC), ToProto, |
| ASTNodeImporter::IDK_Everything); |
| } |
| } |
| |
| return Importer.ImportDeclContext(FromDC, true); |
| } |
| |
| Expected<DeclarationName> ASTImporter::Import(DeclarationName FromName) { |
| if (!FromName) |
| return DeclarationName{}; |
| |
| switch (FromName.getNameKind()) { |
| case DeclarationName::Identifier: |
| return DeclarationName(Import(FromName.getAsIdentifierInfo())); |
| |
| case DeclarationName::ObjCZeroArgSelector: |
| case DeclarationName::ObjCOneArgSelector: |
| case DeclarationName::ObjCMultiArgSelector: |
| if (auto ToSelOrErr = Import(FromName.getObjCSelector())) |
| return DeclarationName(*ToSelOrErr); |
| else |
| return ToSelOrErr.takeError(); |
| |
| case DeclarationName::CXXConstructorName: { |
| if (auto ToTyOrErr = Import(FromName.getCXXNameType())) |
| return ToContext.DeclarationNames.getCXXConstructorName( |
| ToContext.getCanonicalType(*ToTyOrErr)); |
| else |
| return ToTyOrErr.takeError(); |
| } |
| |
| case DeclarationName::CXXDestructorName: { |
| if (auto ToTyOrErr = Import(FromName.getCXXNameType())) |
| return ToContext.DeclarationNames.getCXXDestructorName( |
| ToContext.getCanonicalType(*ToTyOrErr)); |
| else |
| return ToTyOrErr.takeError(); |
| } |
| |
| case DeclarationName::CXXDeductionGuideName: { |
| if (auto ToTemplateOrErr = Import(FromName.getCXXDeductionGuideTemplate())) |
| return ToContext.DeclarationNames.getCXXDeductionGuideName( |
| cast<TemplateDecl>(*ToTemplateOrErr)); |
| else |
| return ToTemplateOrErr.takeError(); |
| } |
| |
| case DeclarationName::CXXConversionFunctionName: { |
| if (auto ToTyOrErr = Import(FromName.getCXXNameType())) |
| return ToContext.DeclarationNames.getCXXConversionFunctionName( |
| ToContext.getCanonicalType(*ToTyOrErr)); |
| else |
| return ToTyOrErr.takeError(); |
| } |
| |
| case DeclarationName::CXXOperatorName: |
| return ToContext.DeclarationNames.getCXXOperatorName( |
| FromName.getCXXOverloadedOperator()); |
| |
| case DeclarationName::CXXLiteralOperatorName: |
| return ToContext.DeclarationNames.getCXXLiteralOperatorName( |
| Import(FromName.getCXXLiteralIdentifier())); |
| |
| case DeclarationName::CXXUsingDirective: |
| // FIXME: STATICS! |
| return DeclarationName::getUsingDirectiveName(); |
| } |
| |
| llvm_unreachable("Invalid DeclarationName Kind!"); |
| } |
| |
| IdentifierInfo *ASTImporter::Import(const IdentifierInfo *FromId) { |
| if (!FromId) |
| return nullptr; |
| |
| IdentifierInfo *ToId = &ToContext.Idents.get(FromId->getName()); |
| |
| if (!ToId->getBuiltinID() && FromId->getBuiltinID()) |
| ToId->setBuiltinID(FromId->getBuiltinID()); |
| |
| return ToId; |
| } |
| |
| Expected<Selector> ASTImporter::Import(Selector FromSel) { |
| if (FromSel.isNull()) |
| return Selector{}; |
| |
| SmallVector<IdentifierInfo *, 4> Idents; |
| Idents.push_back(Import(FromSel.getIdentifierInfoForSlot(0))); |
| for (unsigned I = 1, N = FromSel.getNumArgs(); I < N; ++I) |
| Idents.push_back(Import(FromSel.getIdentifierInfoForSlot(I))); |
| return ToContext.Selectors.getSelector(FromSel.getNumArgs(), Idents.data()); |
| } |
| |
| llvm::Expected<APValue> |
| ASTNodeImporter::ImportAPValue(const APValue &FromValue) { |
| APValue Result; |
| llvm::Error Err = llvm::Error::success(); |
| auto ImportLoop = [&](const APValue *From, APValue *To, unsigned Size) { |
| for (unsigned Idx = 0; Idx < Size; Idx++) { |
| APValue Tmp = importChecked(Err, From[Idx]); |
| To[Idx] = Tmp; |
| } |
| }; |
| switch (FromValue.getKind()) { |
| case APValue::None: |
| case APValue::Indeterminate: |
| case APValue::Int: |
| case APValue::Float: |
| case APValue::FixedPoint: |
| case APValue::ComplexInt: |
| case APValue::ComplexFloat: |
| Result = FromValue; |
| break; |
| case APValue::Vector: { |
| Result.MakeVector(); |
| MutableArrayRef<APValue> Elts = |
| Result.setVectorUninit(FromValue.getVectorLength()); |
| ImportLoop(((const APValue::Vec *)(const char *)&FromValue.Data)->Elts, |
| Elts.data(), FromValue.getVectorLength()); |
| break; |
| } |
| case APValue::Array: |
| Result.MakeArray(FromValue.getArrayInitializedElts(), |
| FromValue.getArraySize()); |
| ImportLoop(((const APValue::Arr *)(const char *)&FromValue.Data)->Elts, |
| ((const APValue::Arr *)(const char *)&Result.Data)->Elts, |
| FromValue.getArrayInitializedElts()); |
| break; |
| case APValue::Struct: |
| Result.MakeStruct(FromValue.getStructNumBases(), |
| FromValue.getStructNumFields()); |
| ImportLoop( |
| ((const APValue::StructData *)(const char *)&FromValue.Data)->Elts, |
| ((const APValue::StructData *)(const char *)&Result.Data)->Elts, |
| FromValue.getStructNumBases() + FromValue.getStructNumFields()); |
| break; |
| case APValue::Union: { |
| Result.MakeUnion(); |
| const Decl *ImpFDecl = importChecked(Err, FromValue.getUnionField()); |
| APValue ImpValue = importChecked(Err, FromValue.getUnionValue()); |
| if (Err) |
| return std::move(Err); |
| Result.setUnion(cast<FieldDecl>(ImpFDecl), ImpValue); |
| break; |
| } |
| case APValue::AddrLabelDiff: { |
| Result.MakeAddrLabelDiff(); |
| const Expr *ImpLHS = importChecked(Err, FromValue.getAddrLabelDiffLHS()); |
| const Expr *ImpRHS = importChecked(Err, FromValue.getAddrLabelDiffRHS()); |
| if (Err) |
| return std::move(Err); |
| Result.setAddrLabelDiff(cast<AddrLabelExpr>(ImpLHS), |
| cast<AddrLabelExpr>(ImpRHS)); |
| break; |
| } |
| case APValue::MemberPointer: { |
| const Decl *ImpMemPtrDecl = |
| importChecked(Err, FromValue.getMemberPointerDecl()); |
| if (Err) |
| return std::move(Err); |
| MutableArrayRef<const CXXRecordDecl *> ToPath = |
| Result.setMemberPointerUninit( |
| cast<const ValueDecl>(ImpMemPtrDecl), |
| FromValue.isMemberPointerToDerivedMember(), |
| FromValue.getMemberPointerPath().size()); |
| llvm::ArrayRef<const CXXRecordDecl *> FromPath = |
| Result.getMemberPointerPath(); |
| for (unsigned Idx = 0; Idx < FromValue.getMemberPointerPath().size(); |
| Idx++) { |
| const Decl *ImpDecl = importChecked(Err, FromPath[Idx]); |
| if (Err) |
| return std::move(Err); |
| ToPath[Idx] = cast<const CXXRecordDecl>(ImpDecl->getCanonicalDecl()); |
| } |
| break; |
| } |
| case APValue::LValue: |
| APValue::LValueBase Base; |
| QualType FromElemTy; |
| if (FromValue.getLValueBase()) { |
| assert(!FromValue.getLValueBase().is<DynamicAllocLValue>() && |
| "in C++20 dynamic allocation are transient so they shouldn't " |
| "appear in the AST"); |
| if (!FromValue.getLValueBase().is<TypeInfoLValue>()) { |
| if (const auto *E = |
| FromValue.getLValueBase().dyn_cast<const Expr *>()) { |
| FromElemTy = E->getType(); |
| const Expr *ImpExpr = importChecked(Err, E); |
| if (Err) |
| return std::move(Err); |
| Base = APValue::LValueBase(ImpExpr, |
| FromValue.getLValueBase().getCallIndex(), |
| FromValue.getLValueBase().getVersion()); |
| } else { |
| FromElemTy = |
| FromValue.getLValueBase().get<const ValueDecl *>()->getType(); |
| const Decl *ImpDecl = importChecked( |
| Err, FromValue.getLValueBase().get<const ValueDecl *>()); |
| if (Err) |
| return std::move(Err); |
| Base = APValue::LValueBase(cast<ValueDecl>(ImpDecl), |
| FromValue.getLValueBase().getCallIndex(), |
| FromValue.getLValueBase().getVersion()); |
| } |
| } else { |
| FromElemTy = FromValue.getLValueBase().getTypeInfoType(); |
| QualType ImpTypeInfo = importChecked( |
| Err, |
| QualType(FromValue.getLValueBase().get<TypeInfoLValue>().getType(), |
| 0)); |
| QualType ImpType = |
| importChecked(Err, FromValue.getLValueBase().getTypeInfoType()); |
| if (Err) |
| return std::move(Err); |
| Base = APValue::LValueBase::getTypeInfo( |
| TypeInfoLValue(ImpTypeInfo.getTypePtr()), ImpType); |
| } |
| } |
| CharUnits Offset = FromValue.getLValueOffset(); |
| unsigned PathLength = FromValue.getLValuePath().size(); |
| Result.MakeLValue(); |
| if (FromValue.hasLValuePath()) { |
| MutableArrayRef<APValue::LValuePathEntry> ToPath = Result.setLValueUninit( |
| Base, Offset, PathLength, FromValue.isLValueOnePastTheEnd(), |
| FromValue.isNullPointer()); |
| llvm::ArrayRef<APValue::LValuePathEntry> FromPath = |
| FromValue.getLValuePath(); |
| for (unsigned LoopIdx = 0; LoopIdx < PathLength; LoopIdx++) { |
| if (FromElemTy->isRecordType()) { |
| const Decl *FromDecl = |
| FromPath[LoopIdx].getAsBaseOrMember().getPointer(); |
| const Decl *ImpDecl = importChecked(Err, FromDecl); |
| if (Err) |
| return std::move(Err); |
| if (auto *RD = dyn_cast<CXXRecordDecl>(FromDecl)) |
| FromElemTy = Importer.FromContext.getRecordType(RD); |
| else |
| FromElemTy = cast<ValueDecl>(FromDecl)->getType(); |
| ToPath[LoopIdx] = APValue::LValuePathEntry(APValue::BaseOrMemberType( |
| ImpDecl, FromPath[LoopIdx].getAsBaseOrMember().getInt())); |
| } else { |
| FromElemTy = |
| Importer.FromContext.getAsArrayType(FromElemTy)->getElementType(); |
| ToPath[LoopIdx] = APValue::LValuePathEntry::ArrayIndex( |
| FromPath[LoopIdx].getAsArrayIndex()); |
| } |
| } |
| } else |
| Result.setLValue(Base, Offset, APValue::NoLValuePath{}, |
| FromValue.isNullPointer()); |
| } |
| if (Err) |
| return std::move(Err); |
| return Result; |
| } |
| |
| Expected<DeclarationName> ASTImporter::HandleNameConflict(DeclarationName Name, |
| DeclContext *DC, |
| unsigned IDNS, |
| NamedDecl **Decls, |
| unsigned NumDecls) { |
| if (ODRHandling == ODRHandlingType::Conservative) |
| // Report error at any name conflict. |
| return make_error<ImportError>(ImportError::NameConflict); |
| else |
| // Allow to create the new Decl with the same name. |
| return Name; |
| } |
| |
| DiagnosticBuilder ASTImporter::ToDiag(SourceLocation Loc, unsigned DiagID) { |
| if (LastDiagFromFrom) |
| ToContext.getDiagnostics().notePriorDiagnosticFrom( |
| FromContext.getDiagnostics()); |
| LastDiagFromFrom = false; |
| return ToContext.getDiagnostics().Report(Loc, DiagID); |
| } |
| |
| DiagnosticBuilder ASTImporter::FromDiag(SourceLocation Loc, unsigned DiagID) { |
| if (!LastDiagFromFrom) |
| FromContext.getDiagnostics().notePriorDiagnosticFrom( |
| ToContext.getDiagnostics()); |
| LastDiagFromFrom = true; |
| return FromContext.getDiagnostics().Report(Loc, DiagID); |
| } |
| |
| void ASTImporter::CompleteDecl (Decl *D) { |
| if (auto *ID = dyn_cast<ObjCInterfaceDecl>(D)) { |
| if (!ID->getDefinition()) |
| ID->startDefinition(); |
| } |
| else if (auto *PD = dyn_cast<ObjCProtocolDecl>(D)) { |
| if (!PD->getDefinition()) |
| PD->startDefinition(); |
| } |
| else if (auto *TD = dyn_cast<TagDecl>(D)) { |
| if (!TD->getDefinition() && !TD->isBeingDefined()) { |
| TD->startDefinition(); |
| TD->setCompleteDefinition(true); |
| } |
| } |
| else { |
| assert(0 && "CompleteDecl called on a Decl that can't be completed"); |
| } |
| } |
| |
| Decl *ASTImporter::MapImported(Decl *From, Decl *To) { |
| llvm::DenseMap<Decl *, Decl *>::iterator Pos = ImportedDecls.find(From); |
| assert((Pos == ImportedDecls.end() || Pos->second == To) && |
| "Try to import an already imported Decl"); |
| if (Pos != ImportedDecls.end()) |
| return Pos->second; |
| ImportedDecls[From] = To; |
| // This mapping should be maintained only in this function. Therefore do not |
| // check for additional consistency. |
| ImportedFromDecls[To] = From; |
| // 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; |
| } |
| |
| llvm::Optional<ImportError> |
| ASTImporter::getImportDeclErrorIfAny(Decl *FromD) const { |
| auto Pos = ImportDeclErrors.find(FromD); |
| if (Pos != ImportDeclErrors.end()) |
| return Pos->second; |
| else |
| return Optional<ImportError>(); |
| } |
| |
| void ASTImporter::setImportDeclError(Decl *From, ImportError Error) { |
| auto InsertRes = ImportDeclErrors.insert({From, Error}); |
| (void)InsertRes; |
| // Either we set the error for the first time, or we already had set one and |
| // now we want to set the same error. |
| assert(InsertRes.second || InsertRes.first->second.Error == Error.Error); |
| } |
| |
| bool ASTImporter::IsStructurallyEquivalent(QualType From, QualType To, |
| bool Complain) { |
| llvm::DenseMap<const Type *, const Type *>::iterator Pos = |
| ImportedTypes.find(From.getTypePtr()); |
| if (Pos != ImportedTypes.end()) { |
| if (ExpectedType ToFromOrErr = Import(From)) { |
| if (ToContext.hasSameType(*ToFromOrErr, To)) |
| return true; |
| } else { |
| llvm::consumeError(ToFromOrErr.takeError()); |
| } |
| } |
| |
| StructuralEquivalenceContext Ctx(FromContext, ToContext, NonEquivalentDecls, |
| getStructuralEquivalenceKind(*this), false, |
| Complain); |
| return Ctx.IsEquivalent(From, To); |
| } |