8915 lines
		
	
	
		
			320 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			8915 lines
		
	
	
		
			320 KiB
		
	
	
	
		
			C++
		
	
	
	
| //===- 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;
 | |
|     }
 | |
| 
 | |
|     // 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->hasAttrs())
 | |
|         for (const Attr *FromAttr : FromD->getAttrs()) {
 | |
|           // FIXME: Return of the error here is not possible until store of
 | |
|           // import errors is implemented.
 | |
|           auto ToAttrOrErr = import(FromAttr);
 | |
|           if (ToAttrOrErr)
 | |
|             ToD->addAttr(*ToAttrOrErr);
 | |
|           else
 | |
|             llvm::consumeError(ToAttrOrErr.takeError());
 | |
|         }
 | |
|       if (FromD->isUsed())
 | |
|         ToD->setIsUsed();
 | |
|       if (FromD->isImplicit())
 | |
|         ToD->setImplicit();
 | |
|     }
 | |
| 
 | |
|     // Check if we have found an existing definition.  Returns with that
 | |
|     // definition if yes, otherwise returns null.
 | |
|     Decl *FindAndMapDefinition(FunctionDecl *D, FunctionDecl *FoundFunction) {
 | |
|       const FunctionDecl *Definition = nullptr;
 | |
|       if (D->doesThisDeclarationHaveABody() &&
 | |
|           FoundFunction->hasBody(Definition))
 | |
|         return Importer.MapImported(D, const_cast<FunctionDecl *>(Definition));
 | |
|       return nullptr;
 | |
|     }
 | |
| 
 | |
|     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, DeclContext *&DC, DeclContext *&LexicalDC,
 | |
|         DeclarationName &Name, NamedDecl *&ToD, SourceLocation &Loc);
 | |
|     Error ImportDefinitionIfNeeded(Decl *FromD, Decl *ToD = nullptr);
 | |
|     Error ImportDeclarationNameLoc(
 | |
|         const DeclarationNameInfo &From, DeclarationNameInfo &To);
 | |
|     Error ImportDeclContext(DeclContext *FromDC, bool ForceImport = false);
 | |
|     Error ImportDeclContext(
 | |
|         Decl *From, DeclContext *&ToDC, DeclContext *&ToLexicalDC);
 | |
|     Error ImportImplicitMethods(const CXXRecordDecl *From, CXXRecordDecl *To);
 | |
| 
 | |
|     Expected<CXXCastPath> ImportCastPath(CastExpr *E);
 | |
| 
 | |
|     using Designator = DesignatedInitExpr::Designator;
 | |
| 
 | |
|     /// What we should import from the definition.
 | |
|     enum ImportDefinitionKind {
 | |
|       /// Import the default subset of the definition, which might be
 | |
|       /// nothing (if minimal import is set) or might be everything (if minimal
 | |
|       /// import is not set).
 | |
|       IDK_Default,
 | |
|       /// Import everything.
 | |
|       IDK_Everything,
 | |
|       /// Import only the bare bones needed to establish a valid
 | |
|       /// DeclContext.
 | |
|       IDK_Basic
 | |
|     };
 | |
| 
 | |
|     bool shouldForceImportDeclContext(ImportDefinitionKind IDK) {
 | |
|       return IDK == IDK_Everything ||
 | |
|              (IDK == IDK_Default && !Importer.isMinimalImport());
 | |
|     }
 | |
| 
 | |
|     Error ImportInitializer(VarDecl *From, VarDecl *To);
 | |
|     Error ImportDefinition(
 | |
|         RecordDecl *From, RecordDecl *To,
 | |
|         ImportDefinitionKind Kind = IDK_Default);
 | |
|     Error ImportDefinition(
 | |
|         EnumDecl *From, EnumDecl *To,
 | |
|         ImportDefinitionKind Kind = IDK_Default);
 | |
|     Error ImportDefinition(
 | |
|         ObjCInterfaceDecl *From, ObjCInterfaceDecl *To,
 | |
|         ImportDefinitionKind Kind = IDK_Default);
 | |
|     Error ImportDefinition(
 | |
|         ObjCProtocolDecl *From, ObjCProtocolDecl *To,
 | |
|         ImportDefinitionKind Kind = IDK_Default);
 | |
|     Error ImportTemplateArguments(
 | |
|         const TemplateArgument *FromArgs, unsigned NumFromArgs,
 | |
|         SmallVectorImpl<TemplateArgument> &ToArgs);
 | |
|     Expected<TemplateArgument>
 | |
|     ImportTemplateArgument(const TemplateArgument &From);
 | |
| 
 | |
|     template <typename InContainerTy>
 | |
|     Error ImportTemplateArgumentListInfo(
 | |
|         const InContainerTy &Container, TemplateArgumentListInfo &ToTAInfo);
 | |
| 
 | |
|     template<typename InContainerTy>
 | |
|     Error ImportTemplateArgumentListInfo(
 | |
|       SourceLocation FromLAngleLoc, SourceLocation FromRAngleLoc,
 | |
|       const InContainerTy &Container, TemplateArgumentListInfo &Result);
 | |
| 
 | |
|     using TemplateArgsTy = SmallVector<TemplateArgument, 8>;
 | |
|     using FunctionTemplateAndArgsTy =
 | |
|         std::tuple<FunctionTemplateDecl *, TemplateArgsTy>;
 | |
|     Expected<FunctionTemplateAndArgsTy>
 | |
|     ImportFunctionTemplateWithTemplateArgsFromSpecialization(
 | |
|         FunctionDecl *FromFD);
 | |
|     Error ImportTemplateParameterLists(const DeclaratorDecl *FromD,
 | |
|                                        DeclaratorDecl *ToD);
 | |
| 
 | |
|     Error ImportTemplateInformation(FunctionDecl *FromFD, FunctionDecl *ToFD);
 | |
| 
 | |
|     Error ImportFunctionDeclBody(FunctionDecl *FromFD, FunctionDecl *ToFD);
 | |
| 
 | |
|     Error ImportDefaultArgOfParmVarDecl(const ParmVarDecl *FromParam,
 | |
|                                         ParmVarDecl *ToParam);
 | |
| 
 | |
|     template <typename T>
 | |
|     bool 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 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 VisitPredefinedExpr(PredefinedExpr *E);
 | |
|     ExpectedStmt VisitDeclRefExpr(DeclRefExpr *E);
 | |
|     ExpectedStmt VisitImplicitValueInitExpr(ImplicitValueInitExpr *E);
 | |
|     ExpectedStmt VisitDesignatedInitExpr(DesignatedInitExpr *E);
 | |
|     ExpectedStmt VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E);
 | |
|     ExpectedStmt VisitIntegerLiteral(IntegerLiteral *E);
 | |
|     ExpectedStmt VisitFloatingLiteral(FloatingLiteral *E);
 | |
|     ExpectedStmt VisitImaginaryLiteral(ImaginaryLiteral *E);
 | |
|     ExpectedStmt VisitCharacterLiteral(CharacterLiteral *E);
 | |
|     ExpectedStmt VisitStringLiteral(StringLiteral *E);
 | |
|     ExpectedStmt VisitCompoundLiteralExpr(CompoundLiteralExpr *E);
 | |
|     ExpectedStmt VisitAtomicExpr(AtomicExpr *E);
 | |
|     ExpectedStmt VisitAddrLabelExpr(AddrLabelExpr *E);
 | |
|     ExpectedStmt VisitConstantExpr(ConstantExpr *E);
 | |
|     ExpectedStmt VisitParenExpr(ParenExpr *E);
 | |
|     ExpectedStmt VisitParenListExpr(ParenListExpr *E);
 | |
|     ExpectedStmt VisitStmtExpr(StmtExpr *E);
 | |
|     ExpectedStmt VisitUnaryOperator(UnaryOperator *E);
 | |
|     ExpectedStmt VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E);
 | |
|     ExpectedStmt VisitBinaryOperator(BinaryOperator *E);
 | |
|     ExpectedStmt VisitConditionalOperator(ConditionalOperator *E);
 | |
|     ExpectedStmt VisitBinaryConditionalOperator(BinaryConditionalOperator *E);
 | |
|     ExpectedStmt VisitOpaqueValueExpr(OpaqueValueExpr *E);
 | |
|     ExpectedStmt VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E);
 | |
|     ExpectedStmt VisitExpressionTraitExpr(ExpressionTraitExpr *E);
 | |
|     ExpectedStmt VisitArraySubscriptExpr(ArraySubscriptExpr *E);
 | |
|     ExpectedStmt VisitCompoundAssignOperator(CompoundAssignOperator *E);
 | |
|     ExpectedStmt VisitImplicitCastExpr(ImplicitCastExpr *E);
 | |
|     ExpectedStmt VisitExplicitCastExpr(ExplicitCastExpr *E);
 | |
|     ExpectedStmt VisitOffsetOfExpr(OffsetOfExpr *OE);
 | |
|     ExpectedStmt VisitCXXThrowExpr(CXXThrowExpr *E);
 | |
|     ExpectedStmt VisitCXXNoexceptExpr(CXXNoexceptExpr *E);
 | |
|     ExpectedStmt VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E);
 | |
|     ExpectedStmt VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E);
 | |
|     ExpectedStmt VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E);
 | |
|     ExpectedStmt VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E);
 | |
|     ExpectedStmt VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E);
 | |
|     ExpectedStmt VisitPackExpansionExpr(PackExpansionExpr *E);
 | |
|     ExpectedStmt VisitSizeOfPackExpr(SizeOfPackExpr *E);
 | |
|     ExpectedStmt VisitCXXNewExpr(CXXNewExpr *E);
 | |
|     ExpectedStmt VisitCXXDeleteExpr(CXXDeleteExpr *E);
 | |
|     ExpectedStmt VisitCXXConstructExpr(CXXConstructExpr *E);
 | |
|     ExpectedStmt VisitCXXMemberCallExpr(CXXMemberCallExpr *E);
 | |
|     ExpectedStmt VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E);
 | |
|     ExpectedStmt VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E);
 | |
|     ExpectedStmt VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *E);
 | |
|     ExpectedStmt VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E);
 | |
|     ExpectedStmt VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E);
 | |
|     ExpectedStmt VisitExprWithCleanups(ExprWithCleanups *E);
 | |
|     ExpectedStmt VisitCXXThisExpr(CXXThisExpr *E);
 | |
|     ExpectedStmt VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E);
 | |
|     ExpectedStmt VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E);
 | |
|     ExpectedStmt VisitMemberExpr(MemberExpr *E);
 | |
|     ExpectedStmt VisitCallExpr(CallExpr *E);
 | |
|     ExpectedStmt VisitLambdaExpr(LambdaExpr *LE);
 | |
|     ExpectedStmt VisitInitListExpr(InitListExpr *E);
 | |
|     ExpectedStmt VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *E);
 | |
|     ExpectedStmt VisitCXXInheritedCtorInitExpr(CXXInheritedCtorInitExpr *E);
 | |
|     ExpectedStmt VisitArrayInitLoopExpr(ArrayInitLoopExpr *E);
 | |
|     ExpectedStmt VisitArrayInitIndexExpr(ArrayInitIndexExpr *E);
 | |
|     ExpectedStmt VisitCXXDefaultInitExpr(CXXDefaultInitExpr *E);
 | |
|     ExpectedStmt VisitCXXNamedCastExpr(CXXNamedCastExpr *E);
 | |
|     ExpectedStmt VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *E);
 | |
|     ExpectedStmt VisitTypeTraitExpr(TypeTraitExpr *E);
 | |
|     ExpectedStmt VisitCXXTypeidExpr(CXXTypeidExpr *E);
 | |
| 
 | |
|     template<typename IIter, typename OIter>
 | |
|     Error ImportArrayChecked(IIter Ibegin, IIter Iend, OIter Obegin) {
 | |
|       using ItemT = 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(
 | |
|           *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 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());
 | |
| }
 | |
| 
 | |
| 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::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) {
 | |
|         const RecordType *RecordFrom = FieldFrom->getType()->getAs<RecordType>();
 | |
|         const RecordType *RecordTo = FieldTo->getType()->getAs<RecordType>();
 | |
|         if (RecordFrom && RecordTo) {
 | |
|           RecordDecl *FromRecordDecl = RecordFrom->getDecl();
 | |
|           RecordDecl *ToRecordDecl = RecordTo->getDecl();
 | |
| 
 | |
|           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))) {
 | |
|       Error Result = ImportDeclContext(From, /*ForceImport=*/true);
 | |
|       // Finish the definition of the lambda, set isBeingDefined to false.
 | |
|       if (To->isLambda())
 | |
|         DefinitionCompleter();
 | |
|       return Result;
 | |
|     }
 | |
| 
 | |
|     return Error::success();
 | |
|   }
 | |
| 
 | |
|   To->startDefinition();
 | |
|   // Complete the definition even if error is returned.
 | |
|   // The RecordDecl may be already part of the AST so it is better to
 | |
|   // have it in complete state even if something is wrong with it.
 | |
|   auto DefinitionCompleterScopeExit =
 | |
|       llvm::make_scope_exit(DefinitionCompleter);
 | |
| 
 | |
|   if (Error Err = setTypedefNameForAnonDecl(From, To, Importer))
 | |
|     return Err;
 | |
| 
 | |
|   // Add base classes.
 | |
|   auto *ToCXX = dyn_cast<CXXRecordDecl>(To);
 | |
|   auto *FromCXX = dyn_cast<CXXRecordDecl>(From);
 | |
|   if (ToCXX && FromCXX && ToCXX->dataPtr() && FromCXX->dataPtr()) {
 | |
| 
 | |
|     struct CXXRecordDecl::DefinitionData &ToData = ToCXX->data();
 | |
|     struct CXXRecordDecl::DefinitionData &FromData = FromCXX->data();
 | |
| 
 | |
|     #define FIELD(Name, Width, Merge) \
 | |
|     ToData.Name = FromData.Name;
 | |
|     #include "clang/AST/CXXRecordDeclDefinitionBits.def"
 | |
| 
 | |
|     // Copy over the data stored in RecordDeclBits
 | |
|     ToCXX->setArgPassingRestrictions(FromCXX->getArgPassingRestrictions());
 | |
| 
 | |
|     SmallVector<CXXBaseSpecifier *, 4> Bases;
 | |
|     for (const auto &Base1 : FromCXX->bases()) {
 | |
|       ExpectedType TyOrErr = import(Base1.getType());
 | |
|       if (!TyOrErr)
 | |
|         return TyOrErr.takeError();
 | |
| 
 | |
|       SourceLocation EllipsisLoc;
 | |
|       if (Base1.isPackExpansion()) {
 | |
|         if (ExpectedSLoc LocOrErr = import(Base1.getEllipsisLoc()))
 | |
|           EllipsisLoc = *LocOrErr;
 | |
|         else
 | |
|           return LocOrErr.takeError();
 | |
|       }
 | |
| 
 | |
|       // Ensure that we have a definition for the base.
 | |
|       if (Error Err =
 | |
|           ImportDefinitionIfNeeded(Base1.getType()->getAsCXXRecordDecl()))
 | |
|         return Err;
 | |
| 
 | |
|       auto RangeOrErr = import(Base1.getSourceRange());
 | |
|       if (!RangeOrErr)
 | |
|         return RangeOrErr.takeError();
 | |
| 
 | |
|       auto TSIOrErr = import(Base1.getTypeSourceInfo());
 | |
|       if (!TSIOrErr)
 | |
|         return TSIOrErr.takeError();
 | |
| 
 | |
|       Bases.push_back(
 | |
|           new (Importer.getToContext()) CXXBaseSpecifier(
 | |
|               *RangeOrErr,
 | |
|               Base1.isVirtual(),
 | |
|               Base1.isBaseOfClass(),
 | |
|               Base1.getAccessSpecifierAsWritten(),
 | |
|               *TSIOrErr,
 | |
|               EllipsisLoc));
 | |
|     }
 | |
|     if (!Bases.empty())
 | |
|       ToCXX->setBases(Bases.data(), Bases.size());
 | |
|   }
 | |
| 
 | |
|   if (shouldForceImportDeclContext(Kind))
 | |
|     if (Error Err = ImportDeclContext(From, /*ForceImport=*/true))
 | |
|       return Err;
 | |
| 
 | |
|   return Error::success();
 | |
| }
 | |
| 
 | |
| Error ASTNodeImporter::ImportInitializer(VarDecl *From, VarDecl *To) {
 | |
|   if (To->getAnyInitializer())
 | |
|     return Error::success();
 | |
| 
 | |
|   Expr *FromInit = From->getInit();
 | |
|   if (!FromInit)
 | |
|     return Error::success();
 | |
| 
 | |
|   ExpectedExpr ToInitOrErr = import(FromInit);
 | |
|   if (!ToInitOrErr)
 | |
|     return ToInitOrErr.takeError();
 | |
| 
 | |
|   To->setInit(*ToInitOrErr);
 | |
|   if (From->isInitKnownICE()) {
 | |
|     EvaluatedStmt *Eval = To->ensureEvaluatedStmt();
 | |
|     Eval->CheckedICE = true;
 | |
|     Eval->IsICE = From->isInitICE();
 | |
|   }
 | |
| 
 | |
|   // FIXME: Other bits to merge?
 | |
|   return Error::success();
 | |
| }
 | |
| 
 | |
| Error ASTNodeImporter::ImportDefinition(
 | |
|     EnumDecl *From, EnumDecl *To, ImportDefinitionKind Kind) {
 | |
|   if (To->getDefinition() || To->isBeingDefined()) {
 | |
|     if (Kind == IDK_Everything)
 | |
|       return ImportDeclContext(From, /*ForceImport=*/true);
 | |
|     return Error::success();
 | |
|   }
 | |
| 
 | |
|   To->startDefinition();
 | |
| 
 | |
|   if (Error Err = setTypedefNameForAnonDecl(From, To, Importer))
 | |
|     return Err;
 | |
| 
 | |
|   ExpectedType ToTypeOrErr =
 | |
|       import(Importer.getFromContext().getTypeDeclType(From));
 | |
|   if (!ToTypeOrErr)
 | |
|     return ToTypeOrErr.takeError();
 | |
| 
 | |
|   ExpectedType ToPromotionTypeOrErr = import(From->getPromotionType());
 | |
|   if (!ToPromotionTypeOrErr)
 | |
|     return ToPromotionTypeOrErr.takeError();
 | |
| 
 | |
|   if (shouldForceImportDeclContext(Kind))
 | |
|     if (Error Err = ImportDeclContext(From, /*ForceImport=*/true))
 | |
|       return Err;
 | |
| 
 | |
|   // FIXME: we might need to merge the number of positive or negative bits
 | |
|   // if the enumerator lists don't match.
 | |
|   To->completeDefinition(*ToTypeOrErr, *ToPromotionTypeOrErr,
 | |
|                          From->getNumPositiveBits(),
 | |
|                          From->getNumNegativeBits());
 | |
|   return Error::success();
 | |
| }
 | |
| 
 | |
| Error ASTNodeImporter::ImportTemplateArguments(
 | |
|     const TemplateArgument *FromArgs, unsigned NumFromArgs,
 | |
|     SmallVectorImpl<TemplateArgument> &ToArgs) {
 | |
|   for (unsigned I = 0; I != NumFromArgs; ++I) {
 | |
|     if (auto ToOrErr = import(FromArgs[I]))
 | |
|       ToArgs.push_back(*ToOrErr);
 | |
|     else
 | |
|       return ToOrErr.takeError();
 | |
|   }
 | |
| 
 | |
|   return Error::success();
 | |
| }
 | |
| 
 | |
| // FIXME: Do not forget to remove this and use only 'import'.
 | |
| Expected<TemplateArgument>
 | |
| ASTNodeImporter::ImportTemplateArgument(const TemplateArgument &From) {
 | |
|   return import(From);
 | |
| }
 | |
| 
 | |
| template <typename InContainerTy>
 | |
| Error ASTNodeImporter::ImportTemplateArgumentListInfo(
 | |
|     const InContainerTy &Container, TemplateArgumentListInfo &ToTAInfo) {
 | |
|   for (const auto &FromLoc : Container) {
 | |
|     if (auto ToLocOrErr = import(FromLoc))
 | |
|       ToTAInfo.addArgument(*ToLocOrErr);
 | |
|     else
 | |
|       return ToLocOrErr.takeError();
 | |
|   }
 | |
|   return Error::success();
 | |
| }
 | |
| 
 | |
| static StructuralEquivalenceKind
 | |
| getStructuralEquivalenceKind(const ASTImporter &Importer) {
 | |
|   return Importer.isMinimalImport() ? StructuralEquivalenceKind::Minimal
 | |
|                                     : StructuralEquivalenceKind::Default;
 | |
| }
 | |
| 
 | |
| bool ASTNodeImporter::IsStructuralMatch(Decl *From, Decl *To, bool Complain) {
 | |
|   StructuralEquivalenceContext Ctx(
 | |
|       Importer.getFromContext(), Importer.getToContext(),
 | |
|       Importer.getNonEquivalentDecls(), getStructuralEquivalenceKind(Importer),
 | |
|       false, Complain);
 | |
|   return Ctx.IsEquivalent(From, To);
 | |
| }
 | |
| 
 | |
| bool ASTNodeImporter::IsStructuralMatch(RecordDecl *FromRecord,
 | |
|                                         RecordDecl *ToRecord, bool Complain) {
 | |
|   // Eliminate a potential failure point where we attempt to re-import
 | |
|   // something we're trying to import while completing ToRecord.
 | |
|   Decl *ToOrigin = Importer.GetOriginalDecl(ToRecord);
 | |
|   if (ToOrigin) {
 | |
|     auto *ToOriginRecord = dyn_cast<RecordDecl>(ToOrigin);
 | |
|     if (ToOriginRecord)
 | |
|       ToRecord = ToOriginRecord;
 | |
|   }
 | |
| 
 | |
|   StructuralEquivalenceContext Ctx(Importer.getFromContext(),
 | |
|                                    ToRecord->getASTContext(),
 | |
|                                    Importer.getNonEquivalentDecls(),
 | |
|                                    getStructuralEquivalenceKind(Importer),
 | |
|                                    false, Complain);
 | |
|   return Ctx.IsEquivalent(FromRecord, ToRecord);
 | |
| }
 | |
| 
 | |
| bool ASTNodeImporter::IsStructuralMatch(VarDecl *FromVar, VarDecl *ToVar,
 | |
|                                         bool Complain) {
 | |
|   StructuralEquivalenceContext Ctx(
 | |
|       Importer.getFromContext(), Importer.getToContext(),
 | |
|       Importer.getNonEquivalentDecls(), getStructuralEquivalenceKind(Importer),
 | |
|       false, Complain);
 | |
|   return Ctx.IsEquivalent(FromVar, ToVar);
 | |
| }
 | |
| 
 | |
| bool ASTNodeImporter::IsStructuralMatch(EnumDecl *FromEnum, EnumDecl *ToEnum) {
 | |
|   // Eliminate a potential failure point where we attempt to re-import
 | |
|   // something we're trying to import while completing ToEnum.
 | |
|   if (Decl *ToOrigin = Importer.GetOriginalDecl(ToEnum))
 | |
|     if (auto *ToOriginEnum = dyn_cast<EnumDecl>(ToOrigin))
 | |
|         ToEnum = ToOriginEnum;
 | |
| 
 | |
|   StructuralEquivalenceContext Ctx(
 | |
|       Importer.getFromContext(), Importer.getToContext(),
 | |
|       Importer.getNonEquivalentDecls(), getStructuralEquivalenceKind(Importer));
 | |
|   return Ctx.IsEquivalent(FromEnum, ToEnum);
 | |
| }
 | |
| 
 | |
| bool ASTNodeImporter::IsStructuralMatch(FunctionTemplateDecl *From,
 | |
|                                         FunctionTemplateDecl *To) {
 | |
|   StructuralEquivalenceContext Ctx(
 | |
|       Importer.getFromContext(), Importer.getToContext(),
 | |
|       Importer.getNonEquivalentDecls(), getStructuralEquivalenceKind(Importer),
 | |
|       false, false);
 | |
|   return Ctx.IsEquivalent(From, To);
 | |
| }
 | |
| 
 | |
| bool ASTNodeImporter::IsStructuralMatch(FunctionDecl *From, FunctionDecl *To) {
 | |
|   StructuralEquivalenceContext Ctx(
 | |
|       Importer.getFromContext(), Importer.getToContext(),
 | |
|       Importer.getNonEquivalentDecls(), getStructuralEquivalenceKind(Importer),
 | |
|       false, false);
 | |
|   return Ctx.IsEquivalent(From, To);
 | |
| }
 | |
| 
 | |
| bool ASTNodeImporter::IsStructuralMatch(EnumConstantDecl *FromEC,
 | |
|                                         EnumConstantDecl *ToEC) {
 | |
|   const llvm::APSInt &FromVal = FromEC->getInitVal();
 | |
|   const llvm::APSInt &ToVal = ToEC->getInitVal();
 | |
| 
 | |
|   return FromVal.isSigned() == ToVal.isSigned() &&
 | |
|          FromVal.getBitWidth() == ToVal.getBitWidth() &&
 | |
|          FromVal == ToVal;
 | |
| }
 | |
| 
 | |
| bool ASTNodeImporter::IsStructuralMatch(ClassTemplateDecl *From,
 | |
|                                         ClassTemplateDecl *To) {
 | |
|   StructuralEquivalenceContext Ctx(Importer.getFromContext(),
 | |
|                                    Importer.getToContext(),
 | |
|                                    Importer.getNonEquivalentDecls(),
 | |
|                                    getStructuralEquivalenceKind(Importer));
 | |
|   return Ctx.IsEquivalent(From, To);
 | |
| }
 | |
| 
 | |
| bool ASTNodeImporter::IsStructuralMatch(VarTemplateDecl *From,
 | |
|                                         VarTemplateDecl *To) {
 | |
|   StructuralEquivalenceContext Ctx(Importer.getFromContext(),
 | |
|                                    Importer.getToContext(),
 | |
|                                    Importer.getNonEquivalentDecls(),
 | |
|                                    getStructuralEquivalenceKind(Importer));
 | |
|   return Ctx.IsEquivalent(From, To);
 | |
| }
 | |
| 
 | |
| ExpectedDecl ASTNodeImporter::VisitDecl(Decl *D) {
 | |
|   Importer.FromDiag(D->getLocation(), diag::err_unsupported_ast_node)
 | |
|     << D->getDeclKindName();
 | |
|   return make_error<ImportError>(ImportError::UnsupportedConstruct);
 | |
| }
 | |
| 
 | |
| ExpectedDecl ASTNodeImporter::VisitImportDecl(ImportDecl *D) {
 | |
|   Importer.FromDiag(D->getLocation(), diag::err_unsupported_ast_node)
 | |
|       << D->getDeclKindName();
 | |
|   return make_error<ImportError>(ImportError::UnsupportedConstruct);
 | |
| }
 | |
| 
 | |
| ExpectedDecl ASTNodeImporter::VisitEmptyDecl(EmptyDecl *D) {
 | |
|   // Import the context of this declaration.
 | |
|   DeclContext *DC, *LexicalDC;
 | |
|   if (Error Err = ImportDeclContext(D, DC, LexicalDC))
 | |
|     return std::move(Err);
 | |
| 
 | |
|   // Import the location of this declaration.
 | |
|   ExpectedSLoc LocOrErr = import(D->getLocation());
 | |
|   if (!LocOrErr)
 | |
|     return LocOrErr.takeError();
 | |
| 
 | |
|   EmptyDecl *ToD;
 | |
|   if (GetImportedOrCreateDecl(ToD, D, Importer.getToContext(), DC, *LocOrErr))
 | |
|     return ToD;
 | |
| 
 | |
|   ToD->setLexicalDeclContext(LexicalDC);
 | |
|   LexicalDC->addDeclInternal(ToD);
 | |
|   return ToD;
 | |
| }
 | |
| 
 | |
| ExpectedDecl ASTNodeImporter::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
 | |
|   TranslationUnitDecl *ToD =
 | |
|     Importer.getToContext().getTranslationUnitDecl();
 | |
| 
 | |
|   Importer.MapImported(D, ToD);
 | |
| 
 | |
|   return ToD;
 | |
| }
 | |
| 
 | |
| ExpectedDecl ASTNodeImporter::VisitAccessSpecDecl(AccessSpecDecl *D) {
 | |
|   ExpectedSLoc LocOrErr = import(D->getLocation());
 | |
|   if (!LocOrErr)
 | |
|     return LocOrErr.takeError();
 | |
|   auto ColonLocOrErr = import(D->getColonLoc());
 | |
|   if (!ColonLocOrErr)
 | |
|     return ColonLocOrErr.takeError();
 | |
| 
 | |
|   // Import the context of this declaration.
 | |
|   auto DCOrErr = Importer.ImportContext(D->getDeclContext());
 | |
|   if (!DCOrErr)
 | |
|     return DCOrErr.takeError();
 | |
|   DeclContext *DC = *DCOrErr;
 | |
| 
 | |
|   AccessSpecDecl *ToD;
 | |
|   if (GetImportedOrCreateDecl(ToD, D, Importer.getToContext(), D->getAccess(),
 | |
|                               DC, *LocOrErr, *ColonLocOrErr))
 | |
|     return ToD;
 | |
| 
 | |
|   // Lexical DeclContext and Semantic DeclContext
 | |
|   // is always the same for the accessSpec.
 | |
|   ToD->setLexicalDeclContext(DC);
 | |
|   DC->addDeclInternal(ToD);
 | |
| 
 | |
|   return ToD;
 | |
| }
 | |
| 
 | |
| ExpectedDecl ASTNodeImporter::VisitStaticAssertDecl(StaticAssertDecl *D) {
 | |
|   auto DCOrErr = Importer.ImportContext(D->getDeclContext());
 | |
|   if (!DCOrErr)
 | |
|     return DCOrErr.takeError();
 | |
|   DeclContext *DC = *DCOrErr;
 | |
|   DeclContext *LexicalDC = DC;
 | |
| 
 | |
|   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.
 | |
|   DeclContext *DC, *LexicalDC;
 | |
|   DeclarationName Name;
 | |
|   SourceLocation Loc;
 | |
|   NamedDecl *ToD;
 | |
|   if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
 | |
|     return std::move(Err);
 | |
|   if (ToD)
 | |
|     return ToD;
 | |
| 
 | |
|   // If this typedef is not in block scope, determine whether we've
 | |
|   // seen a typedef with the same name (that we can merge with) or any
 | |
|   // other entity by that name (which name lookup could conflict with).
 | |
|   // Note: Repeated typedefs are not valid in C99:
 | |
|   // 'typedef int T; typedef int T;' is invalid
 | |
|   // We do not care about this now.
 | |
|   if (!DC->isFunctionOrMethod()) {
 | |
|     SmallVector<NamedDecl *, 4> ConflictingDecls;
 | |
|     unsigned IDNS = Decl::IDNS_Ordinary;
 | |
|     auto FoundDecls = Importer.findDeclsInToCtx(DC, Name);
 | |
|     for (auto *FoundDecl : FoundDecls) {
 | |
|       if (!FoundDecl->isInIdentifierNamespace(IDNS))
 | |
|         continue;
 | |
|       if (auto *FoundTypedef = dyn_cast<TypedefNameDecl>(FoundDecl)) {
 | |
|         if (!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;
 | |
| 
 | |
|   ToTypedef->setAccess(D->getAccess());
 | |
|   ToTypedef->setLexicalDeclContext(LexicalDC);
 | |
| 
 | |
|   // Templated declarations should not appear in DeclContext.
 | |
|   TypeAliasDecl *FromAlias = IsAlias ? cast<TypeAliasDecl>(D) : nullptr;
 | |
|   if (!FromAlias || !FromAlias->getDescribedAliasTemplate())
 | |
|     LexicalDC->addDeclInternal(ToTypedef);
 | |
| 
 | |
|   return ToTypedef;
 | |
| }
 | |
| 
 | |
| ExpectedDecl ASTNodeImporter::VisitTypedefDecl(TypedefDecl *D) {
 | |
|   return VisitTypedefNameDecl(D, /*IsAlias=*/false);
 | |
| }
 | |
| 
 | |
| ExpectedDecl ASTNodeImporter::VisitTypeAliasDecl(TypeAliasDecl *D) {
 | |
|   return VisitTypedefNameDecl(D, /*IsAlias=*/true);
 | |
| }
 | |
| 
 | |
| ExpectedDecl
 | |
| ASTNodeImporter::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) {
 | |
|   // Import the major distinguishing characteristics of this typedef.
 | |
|   DeclContext *DC, *LexicalDC;
 | |
|   DeclarationName Name;
 | |
|   SourceLocation Loc;
 | |
|   NamedDecl *FoundD;
 | |
|   if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, FoundD, Loc))
 | |
|     return std::move(Err);
 | |
|   if (FoundD)
 | |
|     return FoundD;
 | |
| 
 | |
|   // If this typedef is not in block scope, determine whether we've
 | |
|   // seen a typedef with the same name (that we can merge with) or any
 | |
|   // other entity by that name (which name lookup could conflict with).
 | |
|   if (!DC->isFunctionOrMethod()) {
 | |
|     SmallVector<NamedDecl *, 4> ConflictingDecls;
 | |
|     unsigned IDNS = Decl::IDNS_Ordinary;
 | |
|     auto FoundDecls = Importer.findDeclsInToCtx(DC, Name);
 | |
|     for (auto *FoundDecl : FoundDecls) {
 | |
|       if (!FoundDecl->isInIdentifierNamespace(IDNS))
 | |
|         continue;
 | |
|       if (auto *FoundAlias = dyn_cast<TypeAliasTemplateDecl>(FoundDecl))
 | |
|         return Importer.MapImported(D, FoundAlias);
 | |
|       ConflictingDecls.push_back(FoundDecl);
 | |
|     }
 | |
| 
 | |
|     if (!ConflictingDecls.empty()) {
 | |
|       ExpectedName NameOrErr = Importer.HandleNameConflict(
 | |
|           Name, DC, IDNS, ConflictingDecls.data(), ConflictingDecls.size());
 | |
|       if (NameOrErr)
 | |
|         Name = NameOrErr.get();
 | |
|       else
 | |
|         return NameOrErr.takeError();
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   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());
 | |
|     } 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;
 | |
| }
 | |
| 
 | |
| 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)) {
 | |
|     Expr *ExplicitExpr = nullptr;
 | |
|     if (FromConstructor->getExplicitSpecifier().getExpr()) {
 | |
|       auto Imp = import(FromConstructor->getExplicitSpecifier().getExpr());
 | |
|       if (!Imp)
 | |
|         return Imp.takeError();
 | |
|       ExplicitExpr = *Imp;
 | |
|     }
 | |
|     if (GetImportedOrCreateDecl<CXXConstructorDecl>(
 | |
|             ToFunction, D, Importer.getToContext(), cast<CXXRecordDecl>(DC),
 | |
|             ToInnerLocStart, NameInfo, T, TInfo,
 | |
|             ExplicitSpecifier(
 | |
|                 ExplicitExpr,
 | |
|                 FromConstructor->getExplicitSpecifier().getKind()),
 | |
|             D->isInlineSpecified(), D->isImplicit(), D->getConstexprKind(),
 | |
|             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)) {
 | |
|     Expr *ExplicitExpr = nullptr;
 | |
|     if (FromConversion->getExplicitSpecifier().getExpr()) {
 | |
|       auto Imp = import(FromConversion->getExplicitSpecifier().getExpr());
 | |
|       if (!Imp)
 | |
|         return Imp.takeError();
 | |
|       ExplicitExpr = *Imp;
 | |
|     }
 | |
|     if (GetImportedOrCreateDecl<CXXConversionDecl>(
 | |
|             ToFunction, D, Importer.getToContext(), cast<CXXRecordDecl>(DC),
 | |
|             ToInnerLocStart, NameInfo, T, TInfo, D->isInlineSpecified(),
 | |
|             ExplicitSpecifier(ExplicitExpr,
 | |
|                               FromConversion->getExplicitSpecifier().getKind()),
 | |
|             D->getConstexprKind(), SourceLocation(), 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 (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::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;
 | |
| }
 | |
| 
 | |
| ExpectedDecl ASTNodeImporter::VisitFriendDecl(FriendDecl *D) {
 | |
|   // Import the major distinguishing characteristics of a declaration.
 | |
|   DeclContext *DC, *LexicalDC;
 | |
|   if (Error Err = ImportDeclContext(D, DC, LexicalDC))
 | |
|     return std::move(Err);
 | |
| 
 | |
|   // Determine whether we've already imported this decl.
 | |
|   // FriendDecl is not a NamedDecl so we cannot use lookup.
 | |
|   auto *RD = cast<CXXRecordDecl>(DC);
 | |
|   FriendDecl *ImportedFriend = RD->getFirstFriend();
 | |
| 
 | |
|   while (ImportedFriend) {
 | |
|     if (D->getFriendDecl() && ImportedFriend->getFriendDecl()) {
 | |
|       if (IsStructuralMatch(D->getFriendDecl(), ImportedFriend->getFriendDecl(),
 | |
|                             /*Complain=*/false))
 | |
|         return Importer.MapImported(D, ImportedFriend);
 | |
| 
 | |
|     } else if (D->getFriendType() && ImportedFriend->getFriendType()) {
 | |
|       if (Importer.IsStructurallyEquivalent(
 | |
|             D->getFriendType()->getType(),
 | |
|             ImportedFriend->getFriendType()->getType(), true))
 | |
|         return Importer.MapImported(D, ImportedFriend);
 | |
|     }
 | |
|     ImportedFriend = ImportedFriend->getNextFriend();
 | |
|   }
 | |
| 
 | |
|   // Not found. Create it.
 | |
|   FriendDecl::FriendUnion ToFU;
 | |
|   if (NamedDecl *FriendD = D->getFriendDecl()) {
 | |
|     NamedDecl *ToFriendD;
 | |
|     if (Error Err = importInto(ToFriendD, FriendD))
 | |
|       return std::move(Err);
 | |
| 
 | |
|     if (FriendD->getFriendObjectKind() != Decl::FOK_None &&
 | |
|         !(FriendD->isInIdentifierNamespace(Decl::IDNS_NonMemberOperator)))
 | |
|       ToFriendD->setObjectOfFriendDecl(false);
 | |
| 
 | |
|     ToFU = ToFriendD;
 | |
|   } else { // The friend is a type, not a decl.
 | |
|     if (auto TSIOrErr = import(D->getFriendType()))
 | |
|       ToFU = *TSIOrErr;
 | |
|     else
 | |
|       return TSIOrErr.takeError();
 | |
|   }
 | |
| 
 | |
|   SmallVector<TemplateParameterList *, 1> ToTPLists(D->NumTPLists);
 | |
|   auto **FromTPLists = D->getTrailingObjects<TemplateParameterList *>();
 | |
|   for (unsigned I = 0; I < D->NumTPLists; I++) {
 | |
|     if (auto ListOrErr = import(FromTPLists[I]))
 | |
|       ToTPLists[I] = *ListOrErr;
 | |
|     else
 | |
|       return ListOrErr.takeError();
 | |
|   }
 | |
| 
 | |
|   auto LocationOrErr = import(D->getLocation());
 | |
|   if (!LocationOrErr)
 | |
|     return LocationOrErr.takeError();
 | |
|   auto FriendLocOrErr = import(D->getFriendLoc());
 | |
|   if (!FriendLocOrErr)
 | |
|     return FriendLocOrErr.takeError();
 | |
| 
 | |
|   FriendDecl *FrD;
 | |
|   if (GetImportedOrCreateDecl(FrD, D, Importer.getToContext(), DC,
 | |
|                               *LocationOrErr, ToFU,
 | |
|                               *FriendLocOrErr, ToTPLists))
 | |
|     return FrD;
 | |
| 
 | |
|   FrD->setAccess(D->getAccess());
 | |
|   FrD->setLexicalDeclContext(LexicalDC);
 | |
|   LexicalDC->addDeclInternal(FrD);
 | |
|   return FrD;
 | |
| }
 | |
| 
 | |
| ExpectedDecl ASTNodeImporter::VisitObjCIvarDecl(ObjCIvarDecl *D) {
 | |
|   // Import the major distinguishing characteristics of an ivar.
 | |
|   DeclContext *DC, *LexicalDC;
 | |
|   DeclarationName Name;
 | |
|   SourceLocation Loc;
 | |
|   NamedDecl *ToD;
 | |
|   if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
 | |
|     return std::move(Err);
 | |
|   if (ToD)
 | |
|     return ToD;
 | |
| 
 | |
|   // Determine whether we've already imported this ivar
 | |
|   auto FoundDecls = Importer.findDeclsInToCtx(DC, Name);
 | |
|   for (auto *FoundDecl : FoundDecls) {
 | |
|     if (ObjCIvarDecl *FoundIvar = dyn_cast<ObjCIvarDecl>(FoundDecl)) {
 | |
|       if (Importer.IsStructurallyEquivalent(D->getType(),
 | |
|                                             FoundIvar->getType())) {
 | |
|         Importer.MapImported(D, FoundIvar);
 | |
|         return FoundIvar;
 | |
|       }
 | |
| 
 | |
|       Importer.ToDiag(Loc, diag::warn_odr_ivar_type_inconsistent)
 | |
|         << Name << D->getType() << FoundIvar->getType();
 | |
|       Importer.ToDiag(FoundIvar->getLocation(), diag::note_odr_value_here)
 | |
|         << FoundIvar->getType();
 | |
| 
 | |
|       return make_error<ImportError>(ImportError::NameConflict);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   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();
 | |
|   }
 | |
| 
 | |
|   if (shouldForceImportDeclContext(Kind)) {
 | |
|     // Import all of the members of this class.
 | |
|     if (Error Err = ImportDeclContext(From, /*ForceImport=*/true))
 | |
|       return Err;
 | |
|   }
 | |
|   return Error::success();
 | |
| }
 | |
| 
 | |
| Expected<ObjCTypeParamList *>
 | |
| ASTNodeImporter::ImportObjCTypeParamList(ObjCTypeParamList *list) {
 | |
|   if (!list)
 | |
|     return nullptr;
 | |
| 
 | |
|   SmallVector<ObjCTypeParamDecl *, 4> toTypeParams;
 | |
|   for (auto *fromTypeParam : *list) {
 | |
|     if (auto toTypeParamOrErr = import(fromTypeParam))
 | |
|       toTypeParams.push_back(*toTypeParamOrErr);
 | |
|     else
 | |
|       return toTypeParamOrErr.takeError();
 | |
|   }
 | |
| 
 | |
|   auto LAngleLocOrErr = import(list->getLAngleLoc());
 | |
|   if (!LAngleLocOrErr)
 | |
|     return LAngleLocOrErr.takeError();
 | |
| 
 | |
|   auto RAngleLocOrErr = import(list->getRAngleLoc());
 | |
|   if (!RAngleLocOrErr)
 | |
|     return RAngleLocOrErr.takeError();
 | |
| 
 | |
|   return ObjCTypeParamList::create(Importer.getToContext(),
 | |
|                                    *LAngleLocOrErr,
 | |
|                                    toTypeParams,
 | |
|                                    *RAngleLocOrErr);
 | |
| }
 | |
| 
 | |
| ExpectedDecl ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
 | |
|   // If this class has a definition in the translation unit we're coming from,
 | |
|   // but this particular declaration is not that definition, import the
 | |
|   // definition and map to that.
 | |
|   ObjCInterfaceDecl *Definition = D->getDefinition();
 | |
|   if (Definition && Definition != D) {
 | |
|     if (ExpectedDecl ImportedDefOrErr = import(Definition))
 | |
|       return Importer.MapImported(D, *ImportedDefOrErr);
 | |
|     else
 | |
|       return ImportedDefOrErr.takeError();
 | |
|   }
 | |
| 
 | |
|   // Import the major distinguishing characteristics of an @interface.
 | |
|   DeclContext *DC, *LexicalDC;
 | |
|   DeclarationName Name;
 | |
|   SourceLocation Loc;
 | |
|   NamedDecl *ToD;
 | |
|   if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
 | |
|     return std::move(Err);
 | |
|   if (ToD)
 | |
|     return ToD;
 | |
| 
 | |
|   // Look for an existing interface with the same name.
 | |
|   ObjCInterfaceDecl *MergeWithIface = nullptr;
 | |
|   auto FoundDecls = Importer.findDeclsInToCtx(DC, Name);
 | |
|   for (auto *FoundDecl : FoundDecls) {
 | |
|     if (!FoundDecl->isInIdentifierNamespace(Decl::IDNS_Ordinary))
 | |
|       continue;
 | |
| 
 | |
|     if ((MergeWithIface = dyn_cast<ObjCInterfaceDecl>(FoundDecl)))
 | |
|       break;
 | |
|   }
 | |
| 
 | |
|   // Create an interface declaration, if one does not already exist.
 | |
|   ObjCInterfaceDecl *ToIface = MergeWithIface;
 | |
|   if (!ToIface) {
 | |
|     ExpectedSLoc AtBeginLocOrErr = import(D->getAtStartLoc());
 | |
|     if (!AtBeginLocOrErr)
 | |
|       return AtBeginLocOrErr.takeError();
 | |
| 
 | |
|     if (GetImportedOrCreateDecl(
 | |
|             ToIface, D, Importer.getToContext(), DC,
 | |
|             *AtBeginLocOrErr, Name.getAsIdentifierInfo(),
 | |
|             /*TypeParamList=*/nullptr,
 | |
|             /*PrevDecl=*/nullptr, Loc, D->isImplicitInterfaceDecl()))
 | |
|       return ToIface;
 | |
|     ToIface->setLexicalDeclContext(LexicalDC);
 | |
|     LexicalDC->addDeclInternal(ToIface);
 | |
|   }
 | |
|   Importer.MapImported(D, ToIface);
 | |
|   // Import the type parameter list after MapImported, to avoid
 | |
|   // loops when bringing in their DeclContext.
 | |
|   if (auto ToPListOrErr =
 | |
|       ImportObjCTypeParamList(D->getTypeParamListAsWritten()))
 | |
|     ToIface->setTypeParamList(*ToPListOrErr);
 | |
|   else
 | |
|     return ToPListOrErr.takeError();
 | |
| 
 | |
|   if (D->isThisDeclarationADefinition())
 | |
|     if (Error Err = ImportDefinition(D, ToIface))
 | |
|       return std::move(Err);
 | |
| 
 | |
|   return ToIface;
 | |
| }
 | |
| 
 | |
| ExpectedDecl
 | |
| ASTNodeImporter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) {
 | |
|   ObjCCategoryDecl *Category;
 | |
|   if (Error Err = importInto(Category, D->getCategoryDecl()))
 | |
|     return std::move(Err);
 | |
| 
 | |
|   ObjCCategoryImplDecl *ToImpl = Category->getImplementation();
 | |
|   if (!ToImpl) {
 | |
|     DeclContext *DC, *LexicalDC;
 | |
|     if (Error Err = ImportDeclContext(D, DC, LexicalDC))
 | |
|       return std::move(Err);
 | |
| 
 | |
|     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.
 | |
| 
 | |
|   // FIXME: Import default argument  and constraint expression.
 | |
| 
 | |
|   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);
 | |
|   }
 | |
| 
 | |
|   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);
 | |
| 
 | |
|   // FIXME: Import default argument.
 | |
| 
 | |
|   NonTypeTemplateParmDecl *ToD = nullptr;
 | |
|   (void)GetImportedOrCreateDecl(
 | |
|       ToD, D, Importer.getToContext(),
 | |
|       Importer.getToContext().getTranslationUnitDecl(),
 | |
|       ToInnerLocStart, ToLocation, D->getDepth(),
 | |
|       D->getPosition(), ToDeclName.getAsIdentifierInfo(), ToType,
 | |
|       D->isParameterPack(), ToTypeSourceInfo);
 | |
|   return ToD;
 | |
| }
 | |
| 
 | |
| ExpectedDecl
 | |
| ASTNodeImporter::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
 | |
|   // Import the name of this declaration.
 | |
|   auto NameOrErr = import(D->getDeclName());
 | |
|   if (!NameOrErr)
 | |
|     return NameOrErr.takeError();
 | |
| 
 | |
|   // Import the location of this declaration.
 | |
|   ExpectedSLoc LocationOrErr = import(D->getLocation());
 | |
|   if (!LocationOrErr)
 | |
|     return LocationOrErr.takeError();
 | |
| 
 | |
|   // Import template parameters.
 | |
|   auto TemplateParamsOrErr = import(D->getTemplateParameters());
 | |
|   if (!TemplateParamsOrErr)
 | |
|     return TemplateParamsOrErr.takeError();
 | |
| 
 | |
|   // FIXME: Import default argument.
 | |
| 
 | |
|   TemplateTemplateParmDecl *ToD = nullptr;
 | |
|   (void)GetImportedOrCreateDecl(
 | |
|       ToD, D, Importer.getToContext(),
 | |
|       Importer.getToContext().getTranslationUnitDecl(), *LocationOrErr,
 | |
|       D->getDepth(), D->getPosition(), D->isParameterPack(),
 | |
|       (*NameOrErr).getAsIdentifierInfo(),
 | |
|       *TemplateParamsOrErr);
 | |
|   return ToD;
 | |
| }
 | |
| 
 | |
| // Returns the definition for a (forward) declaration of a TemplateDecl, if
 | |
| // it has any definition in the redecl chain.
 | |
| template <typename T> static auto getTemplateDefinition(T *D) -> T * {
 | |
|   assert(D->getTemplatedDecl() && "Should be called on templates only");
 | |
|   auto *ToTemplatedDef = D->getTemplatedDecl()->getDefinition();
 | |
|   if (!ToTemplatedDef)
 | |
|     return nullptr;
 | |
|   auto *TemplateWithDef = ToTemplatedDef->getDescribedTemplate();
 | |
|   return cast_or_null<T>(TemplateWithDef);
 | |
| }
 | |
| 
 | |
| ExpectedDecl ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
 | |
| 
 | |
|   // 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();
 | |
| 
 | |
|   // Create the declaration that is being templated.
 | |
|   CXXRecordDecl *ToTemplated;
 | |
|   if (Error Err = importInto(ToTemplated, FromTemplated))
 | |
|     return std::move(Err);
 | |
| 
 | |
|   // Create the class template declaration itself.
 | |
|   auto TemplateParamsOrErr = import(D->getTemplateParameters());
 | |
|   if (!TemplateParamsOrErr)
 | |
|     return TemplateParamsOrErr.takeError();
 | |
| 
 | |
|   ClassTemplateDecl *D2;
 | |
|   if (GetImportedOrCreateDecl(D2, D, Importer.getToContext(), DC, Loc, Name,
 | |
|                               *TemplateParamsOrErr, ToTemplated))
 | |
|     return D2;
 | |
| 
 | |
|   ToTemplated->setDescribedClassTemplate(D2);
 | |
| 
 | |
|   D2->setAccess(D->getAccess());
 | |
|   D2->setLexicalDeclContext(LexicalDC);
 | |
| 
 | |
|   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)) {
 | |
|       if (D->isThisDeclarationADefinition() && PrevDecl->getDefinition()) {
 | |
|         Importer.MapImported(D, PrevDecl->getDefinition());
 | |
|         // Import those default field initializers which have been
 | |
|         // instantiated in the "From" context, but not in the "To" context.
 | |
|         for (auto *FromField : D->fields()) {
 | |
|           auto ToOrErr = import(FromField);
 | |
|           if (!ToOrErr)
 | |
|             return ToOrErr.takeError();
 | |
|         }
 | |
| 
 | |
|         // Import those methods which have been instantiated in the
 | |
|         // "From" context, but not in the "To" context.
 | |
|         for (CXXMethodDecl *FromM : D->methods()) {
 | |
|           auto ToOrErr = import(FromM);
 | |
|           if (!ToOrErr)
 | |
|             return ToOrErr.takeError();
 | |
|         }
 | |
| 
 | |
|         // TODO Import instantiated default arguments.
 | |
|         // TODO Import instantiated exception specifications.
 | |
|         //
 | |
|         // Generally, ASTCommon.h/DeclUpdateKind enum gives a very good hint
 | |
|         // what else could be fused during an AST merge.
 | |
|         return PrevDecl;
 | |
|       }
 | |
|     } else { // ODR violation.
 | |
|       // FIXME HandleNameConflict
 | |
|       return make_error<ImportError>(ImportError::NameConflict);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   // Import the location of this declaration.
 | |
|   ExpectedSLoc BeginLocOrErr = import(D->getBeginLoc());
 | |
|   if (!BeginLocOrErr)
 | |
|     return BeginLocOrErr.takeError();
 | |
|   ExpectedSLoc IdLocOrErr = import(D->getLocation());
 | |
|   if (!IdLocOrErr)
 | |
|     return IdLocOrErr.takeError();
 | |
| 
 | |
|   // Create the specialization.
 | |
|   ClassTemplateSpecializationDecl *D2 = nullptr;
 | |
|   if (PartialSpec) {
 | |
|     // Import TemplateArgumentListInfo.
 | |
|     TemplateArgumentListInfo ToTAInfo;
 | |
|     const auto &ASTTemplateArgs = *PartialSpec->getTemplateArgsAsWritten();
 | |
|     if (Error Err = ImportTemplateArgumentListInfo(ASTTemplateArgs, ToTAInfo))
 | |
|       return std::move(Err);
 | |
| 
 | |
|     QualType CanonInjType;
 | |
|     if (Error Err = importInto(
 | |
|         CanonInjType, PartialSpec->getInjectedSpecializationType()))
 | |
|       return std::move(Err);
 | |
|     CanonInjType = CanonInjType.getCanonicalType();
 | |
| 
 | |
|     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 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, 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 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);
 | |
|   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());
 | |
|   if (Err)
 | |
|     return std::move(Err);
 | |
| 
 | |
|   return WhileStmt::Create(Importer.getToContext(), ToConditionVariable, ToCond,
 | |
|                            ToBody, ToWhileLoc);
 | |
| }
 | |
| 
 | |
| 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();
 | |
| 
 | |
|   bool TypeDependent = ToCond->isTypeDependent();
 | |
|   bool ValueDependent = ToCond->isValueDependent();
 | |
| 
 | |
|   // The value of CondIsTrue only matters if the value is not
 | |
|   // condition-dependent.
 | |
|   bool CondIsTrue = !E->isConditionDependent() && E->isConditionTrue();
 | |
| 
 | |
|   return new (Importer.getToContext())
 | |
|       ChooseExpr(ToBuiltinLoc, ToCond, ToLHS, ToRHS, ToType, VK, OK,
 | |
|                  ToRParenLoc, CondIsTrue, TypeDependent, ValueDependent);
 | |
| }
 | |
| 
 | |
| ExpectedStmt ASTNodeImporter::VisitGNUNullExpr(GNUNullExpr *E) {
 | |
|   ExpectedType TypeOrErr = import(E->getType());
 | |
|   if (!TypeOrErr)
 | |
|     return TypeOrErr.takeError();
 | |
| 
 | |
|   ExpectedSLoc BeginLocOrErr = import(E->getBeginLoc());
 | |
|   if (!BeginLocOrErr)
 | |
|     return BeginLocOrErr.takeError();
 | |
| 
 | |
|   return new (Importer.getToContext()) GNUNullExpr(*TypeOrErr, *BeginLocOrErr);
 | |
| }
 | |
| 
 | |
| ExpectedStmt ASTNodeImporter::VisitPredefinedExpr(PredefinedExpr *E) {
 | |
| 
 | |
|   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::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());
 | |
|   if (Err)
 | |
|     return std::move(Err);
 | |
| 
 | |
|   // TODO : Handle APValue::ValueKind that require importing.
 | |
| 
 | |
|   APValue::ValueKind Kind = E->getResultAPValueKind();
 | |
|   if (Kind == APValue::Int || Kind == APValue::Float ||
 | |
|       Kind == APValue::FixedPoint || Kind == APValue::ComplexFloat ||
 | |
|       Kind == APValue::ComplexInt)
 | |
|     return ConstantExpr::Create(Importer.getToContext(), ToSubExpr,
 | |
|                                 E->getAPValueResult());
 | |
|   return ConstantExpr::Create(Importer.getToContext(), ToSubExpr);
 | |
| }
 | |
| ExpectedStmt ASTNodeImporter::VisitParenExpr(ParenExpr *E) {
 | |
|   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 new (Importer.getToContext()) UnaryOperator(
 | |
|       ToSubExpr, E->getOpcode(), ToType, E->getValueKind(), E->getObjectKind(),
 | |
|       ToOperatorLoc, E->canOverflow());
 | |
| }
 | |
| 
 | |
| 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 new (Importer.getToContext()) BinaryOperator(
 | |
|       ToLHS, ToRHS, E->getOpcode(), ToType, E->getValueKind(),
 | |
|       E->getObjectKind(), ToOperatorLoc, E->getFPFeatures());
 | |
| }
 | |
| 
 | |
| ExpectedStmt ASTNodeImporter::VisitConditionalOperator(ConditionalOperator *E) {
 | |
|   Error Err = Error::success();
 | |
|   auto ToCond = importChecked(Err, E->getCond());
 | |
|   auto ToQuestionLoc = importChecked(Err, E->getQuestionLoc());
 | |
|   auto ToLHS = importChecked(Err, E->getLHS());
 | |
|   auto ToColonLoc = importChecked(Err, E->getColonLoc());
 | |
|   auto ToRHS = importChecked(Err, E->getRHS());
 | |
|   auto ToType = importChecked(Err, E->getType());
 | |
|   if (Err)
 | |
|     return std::move(Err);
 | |
| 
 | |
|   return new (Importer.getToContext()) ConditionalOperator(
 | |
|       ToCond, ToQuestionLoc, ToLHS, ToColonLoc, ToRHS, ToType,
 | |
|       E->getValueKind(), E->getObjectKind());
 | |
| }
 | |
| 
 | |
| ExpectedStmt
 | |
| ASTNodeImporter::VisitBinaryConditionalOperator(BinaryConditionalOperator *E) {
 | |
|   Error Err = Error::success();
 | |
|   auto ToCommon = importChecked(Err, E->getCommon());
 | |
|   auto ToOpaqueValue = importChecked(Err, E->getOpaqueValue());
 | |
|   auto ToCond = importChecked(Err, E->getCond());
 | |
|   auto ToTrueExpr = importChecked(Err, E->getTrueExpr());
 | |
|   auto ToFalseExpr = importChecked(Err, E->getFalseExpr());
 | |
|   auto ToQuestionLoc = importChecked(Err, E->getQuestionLoc());
 | |
|   auto ToColonLoc = importChecked(Err, E->getColonLoc());
 | |
|   auto ToType = importChecked(Err, E->getType());
 | |
|   if (Err)
 | |
|     return std::move(Err);
 | |
| 
 | |
|   return new (Importer.getToContext()) BinaryConditionalOperator(
 | |
|       ToCommon, ToOpaqueValue, ToCond, ToTrueExpr, ToFalseExpr,
 | |
|       ToQuestionLoc, ToColonLoc, ToType, E->getValueKind(),
 | |
|       E->getObjectKind());
 | |
| }
 | |
| 
 | |
| ExpectedStmt ASTNodeImporter::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 new (Importer.getToContext()) CompoundAssignOperator(
 | |
|       ToLHS, ToRHS, E->getOpcode(), ToType, E->getValueKind(),
 | |
|       E->getObjectKind(), ToComputationLHSType, ToComputationResultType,
 | |
|       ToOperatorLoc, E->getFPFeatures());
 | |
| }
 | |
| 
 | |
| Expected<CXXCastPath>
 | |
| ASTNodeImporter::ImportCastPath(CastExpr *CE) {
 | |
|   CXXCastPath Path;
 | |
|   for (auto I = CE->path_begin(), E = CE->path_end(); I != E; ++I) {
 | |
|     if (auto SpecOrErr = import(*I))
 | |
|       Path.push_back(*SpecOrErr);
 | |
|     else
 | |
|       return SpecOrErr.takeError();
 | |
|   }
 | |
|   return Path;
 | |
| }
 | |
| 
 | |
| ExpectedStmt ASTNodeImporter::VisitImplicitCastExpr(ImplicitCastExpr *E) {
 | |
|   ExpectedType ToTypeOrErr = import(E->getType());
 | |
|   if (!ToTypeOrErr)
 | |
|     return ToTypeOrErr.takeError();
 | |
| 
 | |
|   ExpectedExpr ToSubExprOrErr = import(E->getSubExpr());
 | |
|   if (!ToSubExprOrErr)
 | |
|     return ToSubExprOrErr.takeError();
 | |
| 
 | |
|   Expected<CXXCastPath> ToBasePathOrErr = ImportCastPath(E);
 | |
|   if (!ToBasePathOrErr)
 | |
|     return ToBasePathOrErr.takeError();
 | |
| 
 | |
|   return ImplicitCastExpr::Create(
 | |
|       Importer.getToContext(), *ToTypeOrErr, E->getCastKind(), *ToSubExprOrErr,
 | |
|       &(*ToBasePathOrErr), E->getValueKind());
 | |
| }
 | |
| 
 | |
| ExpectedStmt ASTNodeImporter::VisitExplicitCastExpr(ExplicitCastExpr *E) {
 | |
|   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, ToTypeInfoAsWritten, *ToLParenLocOrErr,
 | |
|         *ToRParenLocOrErr);
 | |
|   }
 | |
| 
 | |
|   case Stmt::CXXFunctionalCastExprClass: {
 | |
|     auto *FCE = cast<CXXFunctionalCastExpr>(E);
 | |
|     ExpectedSLoc ToLParenLocOrErr = import(FCE->getLParenLoc());
 | |
|     if (!ToLParenLocOrErr)
 | |
|       return ToLParenLocOrErr.takeError();
 | |
|     ExpectedSLoc ToRParenLocOrErr = import(FCE->getRParenLoc());
 | |
|     if (!ToRParenLocOrErr)
 | |
|       return ToRParenLocOrErr.takeError();
 | |
|     return CXXFunctionalCastExpr::Create(
 | |
|         Importer.getToContext(), ToType, E->getValueKind(), ToTypeInfoAsWritten,
 | |
|         E->getCastKind(), ToSubExpr, ToBasePath, *ToLParenLocOrErr,
 | |
|         *ToRParenLocOrErr);
 | |
|   }
 | |
| 
 | |
|   case Stmt::ObjCBridgedCastExprClass: {
 | |
|     auto *OCE = cast<ObjCBridgedCastExpr>(E);
 | |
|     ExpectedSLoc ToLParenLocOrErr = import(OCE->getLParenLoc());
 | |
|     if (!ToLParenLocOrErr)
 | |
|       return ToLParenLocOrErr.takeError();
 | |
|     ExpectedSLoc ToBridgeKeywordLocOrErr = import(OCE->getBridgeKeywordLoc());
 | |
|     if (!ToBridgeKeywordLocOrErr)
 | |
|       return ToBridgeKeywordLocOrErr.takeError();
 | |
|     return new (Importer.getToContext()) ObjCBridgedCastExpr(
 | |
|         *ToLParenLocOrErr, OCE->getBridgeKind(), E->getCastKind(),
 | |
|         *ToBridgeKeywordLocOrErr, ToTypeInfoAsWritten, ToSubExpr);
 | |
|   }
 | |
|   default:
 | |
|     llvm_unreachable("Cast expression of unsupported type!");
 | |
|     return make_error<ImportError>(ImportError::UnsupportedConstruct);
 | |
|   }
 | |
| }
 | |
| 
 | |
| ExpectedStmt ASTNodeImporter::VisitOffsetOfExpr(OffsetOfExpr *E) {
 | |
|   SmallVector<OffsetOfNode, 4> ToNodes;
 | |
|   for (int I = 0, N = E->getNumComponents(); I < N; ++I) {
 | |
|     const OffsetOfNode &FromNode = E->getComponent(I);
 | |
| 
 | |
|     SourceLocation ToBeginLoc, ToEndLoc;
 | |
| 
 | |
|     if (FromNode.getKind() != OffsetOfNode::Base) {
 | |
|       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);
 | |
| }
 | |
| 
 | |
| 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 ToTypeSourceInfo = importChecked(Err, E->getTypeSourceInfo());
 | |
|   if (Err)
 | |
|     return std::move(Err);
 | |
| 
 | |
|   SmallVector<Expr *, 8> ToArgs(E->arg_size());
 | |
|   if (Error Err =
 | |
|       ImportArrayChecked(E->arg_begin(), E->arg_end(), ToArgs.begin()))
 | |
|     return std::move(Err);
 | |
| 
 | |
|   return CXXUnresolvedConstructExpr::Create(
 | |
|       Importer.getToContext(), ToTypeSourceInfo, ToLParenLoc,
 | |
|       llvm::makeArrayRef(ToArgs), ToRParenLoc);
 | |
| }
 | |
| 
 | |
| ExpectedStmt
 | |
| ASTNodeImporter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) {
 | |
|   Expected<CXXRecordDecl *> ToNamingClassOrErr = import(E->getNamingClass());
 | |
|   if (!ToNamingClassOrErr)
 | |
|     return ToNamingClassOrErr.takeError();
 | |
| 
 | |
|   auto ToQualifierLocOrErr = import(E->getQualifierLoc());
 | |
|   if (!ToQualifierLocOrErr)
 | |
|     return ToQualifierLocOrErr.takeError();
 | |
| 
 | |
|   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, /*MinNumArgs=*/0,
 | |
|                           E->getADLCallKind());
 | |
| }
 | |
| 
 | |
| ExpectedStmt ASTNodeImporter::VisitLambdaExpr(LambdaExpr *E) {
 | |
|   CXXRecordDecl *FromClass = E->getLambdaClass();
 | |
|   auto ToClassOrErr = import(FromClass);
 | |
|   if (!ToClassOrErr)
 | |
|     return ToClassOrErr.takeError();
 | |
|   CXXRecordDecl *ToClass = *ToClassOrErr;
 | |
| 
 | |
|   auto ToCallOpOrErr = import(E->getCallOperator());
 | |
|   if (!ToCallOpOrErr)
 | |
|     return ToCallOpOrErr.takeError();
 | |
| 
 | |
|   SmallVector<LambdaCapture, 8> ToCaptures;
 | |
|   ToCaptures.reserve(E->capture_size());
 | |
|   for (const auto &FromCapture : E->captures()) {
 | |
|     if (auto ToCaptureOrErr = import(FromCapture))
 | |
|       ToCaptures.push_back(*ToCaptureOrErr);
 | |
|     else
 | |
|       return ToCaptureOrErr.takeError();
 | |
|   }
 | |
| 
 | |
|   SmallVector<Expr *, 8> ToCaptureInits(E->capture_size());
 | |
|   if (Error Err = ImportContainerChecked(E->capture_inits(), ToCaptureInits))
 | |
|     return std::move(Err);
 | |
| 
 | |
|   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, ToCaptures,
 | |
|       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 (isa<CXXStaticCastExpr>(E)) {
 | |
|     return CXXStaticCastExpr::Create(
 | |
|         Importer.getToContext(), ToType, VK, CK, ToSubExpr, &(*ToBasePathOrErr),
 | |
|         ToTypeInfoAsWritten, ToOperatorLoc, ToRParenLoc, ToAngleBrackets);
 | |
|   } else if (isa<CXXDynamicCastExpr>(E)) {
 | |
|     return CXXDynamicCastExpr::Create(
 | |
|         Importer.getToContext(), ToType, VK, CK, ToSubExpr, &(*ToBasePathOrErr),
 | |
|         ToTypeInfoAsWritten, ToOperatorLoc, ToRParenLoc, ToAngleBrackets);
 | |
|   } else if (isa<CXXReinterpretCastExpr>(E)) {
 | |
|     return CXXReinterpretCastExpr::Create(
 | |
|         Importer.getToContext(), ToType, VK, CK, ToSubExpr, &(*ToBasePathOrErr),
 | |
|         ToTypeInfoAsWritten, ToOperatorLoc, ToRParenLoc, ToAngleBrackets);
 | |
|   } else if (isa<CXXConstCastExpr>(E)) {
 | |
|     return CXXConstCastExpr::Create(
 | |
|         Importer.getToContext(), ToType, VK, ToSubExpr, ToTypeInfoAsWritten,
 | |
|         ToOperatorLoc, ToRParenLoc, ToAngleBrackets);
 | |
|   } else {
 | |
|     llvm_unreachable("Unknown cast type");
 | |
|     return make_error<ImportError>();
 | |
|   }
 | |
| }
 | |
| 
 | |
| ExpectedStmt ASTNodeImporter::VisitSubstNonTypeTemplateParmExpr(
 | |
|     SubstNonTypeTemplateParmExpr *E) {
 | |
|   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, 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);
 | |
| }
 | |
| 
 | |
| 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;
 | |
|   }
 | |
|   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?");
 | |
| 
 | |
|   // 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()) {
 | |
|       // Do nothing.
 | |
|     } else if (FromRecord->isCompleteDefinition()) {
 | |
|       if (Error Err = ASTNodeImporter(*this).ImportDefinition(
 | |
|           FromRecord, ToRecord, ASTNodeImporter::IDK_Basic))
 | |
|         return std::move(Err);
 | |
|     } else {
 | |
|       CompleteDecl(ToRecord);
 | |
|     }
 | |
|   } else if (auto *ToEnum = dyn_cast<EnumDecl>(ToDC)) {
 | |
|     auto *FromEnum = cast<EnumDecl>(FromDC);
 | |
|     if (ToEnum->isCompleteDefinition()) {
 | |
|       // Do nothing.
 | |
|     } else if (FromEnum->isCompleteDefinition()) {
 | |
|       if (Error Err = ASTNodeImporter(*this).ImportDefinition(
 | |
|           FromEnum, ToEnum, ASTNodeImporter::IDK_Basic))
 | |
|         return std::move(Err);
 | |
|     } else {
 | |
|       CompleteDecl(ToEnum);
 | |
|     }
 | |
|   } else if (auto *ToClass = dyn_cast<ObjCInterfaceDecl>(ToDC)) {
 | |
|     auto *FromClass = cast<ObjCInterfaceDecl>(FromDC);
 | |
|     if (ToClass->getDefinition()) {
 | |
|       // Do nothing.
 | |
|     } else if (ObjCInterfaceDecl *FromDef = FromClass->getDefinition()) {
 | |
|       if (Error Err = ASTNodeImporter(*this).ImportDefinition(
 | |
|           FromDef, ToClass, ASTNodeImporter::IDK_Basic))
 | |
|         return std::move(Err);
 | |
|     } else {
 | |
|       CompleteDecl(ToClass);
 | |
|     }
 | |
|   } else if (auto *ToProto = dyn_cast<ObjCProtocolDecl>(ToDC)) {
 | |
|     auto *FromProto = cast<ObjCProtocolDecl>(FromDC);
 | |
|     if (ToProto->getDefinition()) {
 | |
|       // Do nothing.
 | |
|     } else if (ObjCProtocolDecl *FromDef = FromProto->getDefinition()) {
 | |
|       if (Error Err = ASTNodeImporter(*this).ImportDefinition(
 | |
|           FromDef, ToProto, ASTNodeImporter::IDK_Basic))
 | |
|         return std::move(Err);
 | |
|     } else {
 | |
|       CompleteDecl(ToProto);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return ToDC;
 | |
| }
 | |
| 
 | |
| Expected<Expr *> ASTImporter::Import(Expr *FromE) {
 | |
|   if (ExpectedStmt ToSOrErr = Import(cast_or_null<Stmt>(FromE)))
 | |
|     return cast_or_null<Expr>(*ToSOrErr);
 | |
|   else
 | |
|     return ToSOrErr.takeError();
 | |
| }
 | |
| 
 | |
| Expected<Stmt *> ASTImporter::Import(Stmt *FromS) {
 | |
|   if (!FromS)
 | |
|     return nullptr;
 | |
| 
 | |
|   // Check whether we've already imported this statement.
 | |
|   llvm::DenseMap<Stmt *, Stmt *>::iterator Pos = ImportedStmts.find(FromS);
 | |
|   if (Pos != ImportedStmts.end())
 | |
|     return Pos->second;
 | |
| 
 | |
|   // Import the statement.
 | |
|   ASTNodeImporter Importer(*this);
 | |
|   ExpectedStmt ToSOrErr = Importer.Visit(FromS);
 | |
|   if (!ToSOrErr)
 | |
|     return ToSOrErr;
 | |
| 
 | |
|   if (auto *ToE = dyn_cast<Expr>(*ToSOrErr)) {
 | |
|     auto *FromE = cast<Expr>(FromS);
 | |
|     // Copy ExprBitfields, which may not be handled in Expr subclasses
 | |
|     // constructors.
 | |
|     ToE->setValueKind(FromE->getValueKind());
 | |
|     ToE->setObjectKind(FromE->getObjectKind());
 | |
|     ToE->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) {
 | |
|       // 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.getFile(Cache->OrigEntry->getName());
 | |
|         // FIXME: The filename may be a virtual name that does probably not
 | |
|         // point to a valid file and we get no Entry here. In this case try with
 | |
|         // the memory buffer below.
 | |
|         if (Entry)
 | |
|           ToID = ToSM.createFileID(*Entry, ToIncludeLocOrFakeLoc,
 | |
|                                    FromSLoc.getFile().getFileCharacteristic());
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     if (ToID.isInvalid() || IsBuiltin) {
 | |
|       // FIXME: We want to re-use the existing MemoryBuffer!
 | |
|       bool Invalid = true;
 | |
|       const llvm::MemoryBuffer *FromBuf =
 | |
|           Cache->getBuffer(FromContext.getDiagnostics(),
 | |
|                            FromSM.getFileManager(), SourceLocation{}, &Invalid);
 | |
|       if (!FromBuf || Invalid)
 | |
|         // FIXME: Use a new error kind?
 | |
|         return llvm::make_error<ImportError>(ImportError::Unknown);
 | |
| 
 | |
|       std::unique_ptr<llvm::MemoryBuffer> ToBuf =
 | |
|           llvm::MemoryBuffer::getMemBufferCopy(FromBuf->getBuffer(),
 | |
|                                                FromBuf->getBufferIdentifier());
 | |
|       ToID = ToSM.createFileID(std::move(ToBuf),
 | |
|                                FromSLoc.getFile().getFileCharacteristic());
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   assert(ToID.isValid() && "Unexpected invalid fileID was created.");
 | |
| 
 | |
|   ImportedFileIDs[FromID] = ToID;
 | |
| 
 | |
|   if (FileIDImportHandler)
 | |
|     FileIDImportHandler(ToID, FromID);
 | |
| 
 | |
|   return ToID;
 | |
| }
 | |
| 
 | |
| Expected<CXXCtorInitializer *> ASTImporter::Import(CXXCtorInitializer *From) {
 | |
|   ExpectedExpr ToExprOrErr = Import(From->getInit());
 | |
|   if (!ToExprOrErr)
 | |
|     return ToExprOrErr.takeError();
 | |
| 
 | |
|   auto LParenLocOrErr = Import(From->getLParenLoc());
 | |
|   if (!LParenLocOrErr)
 | |
|     return LParenLocOrErr.takeError();
 | |
| 
 | |
|   auto RParenLocOrErr = Import(From->getRParenLoc());
 | |
|   if (!RParenLocOrErr)
 | |
|     return RParenLocOrErr.takeError();
 | |
| 
 | |
|   if (From->isBaseInitializer()) {
 | |
|     auto ToTInfoOrErr = Import(From->getTypeSourceInfo());
 | |
|     if (!ToTInfoOrErr)
 | |
|       return ToTInfoOrErr.takeError();
 | |
| 
 | |
|     SourceLocation EllipsisLoc;
 | |
|     if (From->isPackExpansion())
 | |
|       if (Error Err = importInto(EllipsisLoc, From->getEllipsisLoc()))
 | |
|         return std::move(Err);
 | |
| 
 | |
|     return new (ToContext) CXXCtorInitializer(
 | |
|         ToContext, *ToTInfoOrErr, From->isBaseVirtual(), *LParenLocOrErr,
 | |
|         *ToExprOrErr, *RParenLocOrErr, EllipsisLoc);
 | |
|   } else if (From->isMemberInitializer()) {
 | |
|     ExpectedDecl ToFieldOrErr = Import(From->getMember());
 | |
|     if (!ToFieldOrErr)
 | |
|       return ToFieldOrErr.takeError();
 | |
| 
 | |
|     auto MemberLocOrErr = Import(From->getMemberLocation());
 | |
|     if (!MemberLocOrErr)
 | |
|       return MemberLocOrErr.takeError();
 | |
| 
 | |
|     return new (ToContext) CXXCtorInitializer(
 | |
|         ToContext, cast_or_null<FieldDecl>(*ToFieldOrErr), *MemberLocOrErr,
 | |
|         *LParenLocOrErr, *ToExprOrErr, *RParenLocOrErr);
 | |
|   } else if (From->isIndirectMemberInitializer()) {
 | |
|     ExpectedDecl ToIFieldOrErr = Import(From->getIndirectMember());
 | |
|     if (!ToIFieldOrErr)
 | |
|       return ToIFieldOrErr.takeError();
 | |
| 
 | |
|     auto MemberLocOrErr = Import(From->getMemberLocation());
 | |
|     if (!MemberLocOrErr)
 | |
|       return MemberLocOrErr.takeError();
 | |
| 
 | |
|     return new (ToContext) CXXCtorInitializer(
 | |
|         ToContext, cast_or_null<IndirectFieldDecl>(*ToIFieldOrErr),
 | |
|         *MemberLocOrErr, *LParenLocOrErr, *ToExprOrErr, *RParenLocOrErr);
 | |
|   } else if (From->isDelegatingInitializer()) {
 | |
|     auto ToTInfoOrErr = Import(From->getTypeSourceInfo());
 | |
|     if (!ToTInfoOrErr)
 | |
|       return ToTInfoOrErr.takeError();
 | |
| 
 | |
|     return new (ToContext)
 | |
|         CXXCtorInitializer(ToContext, *ToTInfoOrErr, *LParenLocOrErr,
 | |
|                            *ToExprOrErr, *RParenLocOrErr);
 | |
|   } else {
 | |
|     // FIXME: assert?
 | |
|     return make_error<ImportError>();
 | |
|   }
 | |
| }
 | |
| 
 | |
| Expected<CXXBaseSpecifier *>
 | |
| ASTImporter::Import(const CXXBaseSpecifier *BaseSpec) {
 | |
|   auto Pos = ImportedCXXBaseSpecifiers.find(BaseSpec);
 | |
|   if (Pos != ImportedCXXBaseSpecifiers.end())
 | |
|     return Pos->second;
 | |
| 
 | |
|   Expected<SourceRange> ToSourceRange = Import(BaseSpec->getSourceRange());
 | |
|   if (!ToSourceRange)
 | |
|     return ToSourceRange.takeError();
 | |
|   Expected<TypeSourceInfo *> ToTSI = Import(BaseSpec->getTypeSourceInfo());
 | |
|   if (!ToTSI)
 | |
|     return ToTSI.takeError();
 | |
|   ExpectedSLoc ToEllipsisLoc = Import(BaseSpec->getEllipsisLoc());
 | |
|   if (!ToEllipsisLoc)
 | |
|     return ToEllipsisLoc.takeError();
 | |
|   CXXBaseSpecifier *Imported = new (ToContext) CXXBaseSpecifier(
 | |
|       *ToSourceRange, BaseSpec->isVirtual(), BaseSpec->isBaseOfClass(),
 | |
|       BaseSpec->getAccessSpecifierAsWritten(), *ToTSI, *ToEllipsisLoc);
 | |
|   ImportedCXXBaseSpecifiers[BaseSpec] = Imported;
 | |
|   return Imported;
 | |
| }
 | |
| 
 | |
| Error ASTImporter::ImportDefinition(Decl *From) {
 | |
|   ExpectedDecl ToOrErr = Import(From);
 | |
|   if (!ToOrErr)
 | |
|     return ToOrErr.takeError();
 | |
|   Decl *To = *ToOrErr;
 | |
| 
 | |
|   auto *FromDC = cast<DeclContext>(From);
 | |
|   ASTNodeImporter Importer(*this);
 | |
| 
 | |
|   if (auto *ToRecord = dyn_cast<RecordDecl>(To)) {
 | |
|     if (!ToRecord->getDefinition()) {
 | |
|       return Importer.ImportDefinition(
 | |
|           cast<RecordDecl>(FromDC), ToRecord,
 | |
|           ASTNodeImporter::IDK_Everything);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (auto *ToEnum = dyn_cast<EnumDecl>(To)) {
 | |
|     if (!ToEnum->getDefinition()) {
 | |
|       return Importer.ImportDefinition(
 | |
|           cast<EnumDecl>(FromDC), ToEnum, ASTNodeImporter::IDK_Everything);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (auto *ToIFace = dyn_cast<ObjCInterfaceDecl>(To)) {
 | |
|     if (!ToIFace->getDefinition()) {
 | |
|       return Importer.ImportDefinition(
 | |
|           cast<ObjCInterfaceDecl>(FromDC), ToIFace,
 | |
|           ASTNodeImporter::IDK_Everything);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (auto *ToProto = dyn_cast<ObjCProtocolDecl>(To)) {
 | |
|     if (!ToProto->getDefinition()) {
 | |
|       return Importer.ImportDefinition(
 | |
|           cast<ObjCProtocolDecl>(FromDC), ToProto,
 | |
|           ASTNodeImporter::IDK_Everything);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return Importer.ImportDeclContext(FromDC, true);
 | |
| }
 | |
| 
 | |
| Expected<DeclarationName> ASTImporter::Import(DeclarationName FromName) {
 | |
|   if (!FromName)
 | |
|     return DeclarationName{};
 | |
| 
 | |
|   switch (FromName.getNameKind()) {
 | |
|   case DeclarationName::Identifier:
 | |
|     return DeclarationName(Import(FromName.getAsIdentifierInfo()));
 | |
| 
 | |
|   case DeclarationName::ObjCZeroArgSelector:
 | |
|   case DeclarationName::ObjCOneArgSelector:
 | |
|   case DeclarationName::ObjCMultiArgSelector:
 | |
|     if (auto ToSelOrErr = Import(FromName.getObjCSelector()))
 | |
|       return DeclarationName(*ToSelOrErr);
 | |
|     else
 | |
|       return ToSelOrErr.takeError();
 | |
| 
 | |
|   case DeclarationName::CXXConstructorName: {
 | |
|     if (auto ToTyOrErr = Import(FromName.getCXXNameType()))
 | |
|       return ToContext.DeclarationNames.getCXXConstructorName(
 | |
|           ToContext.getCanonicalType(*ToTyOrErr));
 | |
|     else
 | |
|       return ToTyOrErr.takeError();
 | |
|   }
 | |
| 
 | |
|   case DeclarationName::CXXDestructorName: {
 | |
|     if (auto ToTyOrErr = Import(FromName.getCXXNameType()))
 | |
|       return ToContext.DeclarationNames.getCXXDestructorName(
 | |
|           ToContext.getCanonicalType(*ToTyOrErr));
 | |
|     else
 | |
|       return ToTyOrErr.takeError();
 | |
|   }
 | |
| 
 | |
|   case DeclarationName::CXXDeductionGuideName: {
 | |
|     if (auto ToTemplateOrErr = Import(FromName.getCXXDeductionGuideTemplate()))
 | |
|       return ToContext.DeclarationNames.getCXXDeductionGuideName(
 | |
|           cast<TemplateDecl>(*ToTemplateOrErr));
 | |
|     else
 | |
|       return ToTemplateOrErr.takeError();
 | |
|   }
 | |
| 
 | |
|   case DeclarationName::CXXConversionFunctionName: {
 | |
|     if (auto ToTyOrErr = Import(FromName.getCXXNameType()))
 | |
|       return ToContext.DeclarationNames.getCXXConversionFunctionName(
 | |
|           ToContext.getCanonicalType(*ToTyOrErr));
 | |
|     else
 | |
|       return ToTyOrErr.takeError();
 | |
|   }
 | |
| 
 | |
|   case DeclarationName::CXXOperatorName:
 | |
|     return ToContext.DeclarationNames.getCXXOperatorName(
 | |
|                                           FromName.getCXXOverloadedOperator());
 | |
| 
 | |
|   case DeclarationName::CXXLiteralOperatorName:
 | |
|     return ToContext.DeclarationNames.getCXXLiteralOperatorName(
 | |
|         Import(FromName.getCXXLiteralIdentifier()));
 | |
| 
 | |
|   case DeclarationName::CXXUsingDirective:
 | |
|     // FIXME: STATICS!
 | |
|     return DeclarationName::getUsingDirectiveName();
 | |
|   }
 | |
| 
 | |
|   llvm_unreachable("Invalid DeclarationName Kind!");
 | |
| }
 | |
| 
 | |
| IdentifierInfo *ASTImporter::Import(const IdentifierInfo *FromId) {
 | |
|   if (!FromId)
 | |
|     return nullptr;
 | |
| 
 | |
|   IdentifierInfo *ToId = &ToContext.Idents.get(FromId->getName());
 | |
| 
 | |
|   if (!ToId->getBuiltinID() && FromId->getBuiltinID())
 | |
|     ToId->setBuiltinID(FromId->getBuiltinID());
 | |
| 
 | |
|   return ToId;
 | |
| }
 | |
| 
 | |
| Expected<Selector> ASTImporter::Import(Selector FromSel) {
 | |
|   if (FromSel.isNull())
 | |
|     return Selector{};
 | |
| 
 | |
|   SmallVector<IdentifierInfo *, 4> Idents;
 | |
|   Idents.push_back(Import(FromSel.getIdentifierInfoForSlot(0)));
 | |
|   for (unsigned I = 1, N = FromSel.getNumArgs(); I < N; ++I)
 | |
|     Idents.push_back(Import(FromSel.getIdentifierInfoForSlot(I)));
 | |
|   return ToContext.Selectors.getSelector(FromSel.getNumArgs(), Idents.data());
 | |
| }
 | |
| 
 | |
| Expected<DeclarationName> ASTImporter::HandleNameConflict(DeclarationName Name,
 | |
|                                                           DeclContext *DC,
 | |
|                                                           unsigned IDNS,
 | |
|                                                           NamedDecl **Decls,
 | |
|                                                           unsigned NumDecls) {
 | |
|   if (ODRHandling == ODRHandlingType::Conservative)
 | |
|     // Report error at any name conflict.
 | |
|     return make_error<ImportError>(ImportError::NameConflict);
 | |
|   else
 | |
|     // Allow to create the new Decl with the same name.
 | |
|     return Name;
 | |
| }
 | |
| 
 | |
| DiagnosticBuilder ASTImporter::ToDiag(SourceLocation Loc, unsigned DiagID) {
 | |
|   if (LastDiagFromFrom)
 | |
|     ToContext.getDiagnostics().notePriorDiagnosticFrom(
 | |
|       FromContext.getDiagnostics());
 | |
|   LastDiagFromFrom = false;
 | |
|   return ToContext.getDiagnostics().Report(Loc, DiagID);
 | |
| }
 | |
| 
 | |
| DiagnosticBuilder ASTImporter::FromDiag(SourceLocation Loc, unsigned DiagID) {
 | |
|   if (!LastDiagFromFrom)
 | |
|     FromContext.getDiagnostics().notePriorDiagnosticFrom(
 | |
|       ToContext.getDiagnostics());
 | |
|   LastDiagFromFrom = true;
 | |
|   return FromContext.getDiagnostics().Report(Loc, DiagID);
 | |
| }
 | |
| 
 | |
| void ASTImporter::CompleteDecl (Decl *D) {
 | |
|   if (auto *ID = dyn_cast<ObjCInterfaceDecl>(D)) {
 | |
|     if (!ID->getDefinition())
 | |
|       ID->startDefinition();
 | |
|   }
 | |
|   else if (auto *PD = dyn_cast<ObjCProtocolDecl>(D)) {
 | |
|     if (!PD->getDefinition())
 | |
|       PD->startDefinition();
 | |
|   }
 | |
|   else if (auto *TD = dyn_cast<TagDecl>(D)) {
 | |
|     if (!TD->getDefinition() && !TD->isBeingDefined()) {
 | |
|       TD->startDefinition();
 | |
|       TD->setCompleteDefinition(true);
 | |
|     }
 | |
|   }
 | |
|   else {
 | |
|     assert(0 && "CompleteDecl called on a Decl that can't be completed");
 | |
|   }
 | |
| }
 | |
| 
 | |
| Decl *ASTImporter::MapImported(Decl *From, Decl *To) {
 | |
|   llvm::DenseMap<Decl *, Decl *>::iterator Pos = ImportedDecls.find(From);
 | |
|   assert((Pos == ImportedDecls.end() || Pos->second == To) &&
 | |
|       "Try to import an already imported Decl");
 | |
|   if (Pos != ImportedDecls.end())
 | |
|     return Pos->second;
 | |
|   ImportedDecls[From] = To;
 | |
|   // This mapping should be maintained only in this function. Therefore do not
 | |
|   // check for additional consistency.
 | |
|   ImportedFromDecls[To] = From;
 | |
|   AddToLookupTable(To);
 | |
|   return To;
 | |
| }
 | |
| 
 | |
| llvm::Optional<ImportError>
 | |
| ASTImporter::getImportDeclErrorIfAny(Decl *FromD) const {
 | |
|   auto Pos = ImportDeclErrors.find(FromD);
 | |
|   if (Pos != ImportDeclErrors.end())
 | |
|     return Pos->second;
 | |
|   else
 | |
|     return Optional<ImportError>();
 | |
| }
 | |
| 
 | |
| void ASTImporter::setImportDeclError(Decl *From, ImportError Error) {
 | |
|   auto InsertRes = ImportDeclErrors.insert({From, Error});
 | |
|   (void)InsertRes;
 | |
|   // Either we set the error for the first time, or we already had set one and
 | |
|   // now we want to set the same error.
 | |
|   assert(InsertRes.second || InsertRes.first->second.Error == Error.Error);
 | |
| }
 | |
| 
 | |
| bool ASTImporter::IsStructurallyEquivalent(QualType From, QualType To,
 | |
|                                            bool Complain) {
 | |
|   llvm::DenseMap<const Type *, const Type *>::iterator Pos =
 | |
|       ImportedTypes.find(From.getTypePtr());
 | |
|   if (Pos != ImportedTypes.end()) {
 | |
|     if (ExpectedType ToFromOrErr = Import(From)) {
 | |
|       if (ToContext.hasSameType(*ToFromOrErr, To))
 | |
|         return true;
 | |
|     } else {
 | |
|       llvm::consumeError(ToFromOrErr.takeError());
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   StructuralEquivalenceContext Ctx(FromContext, ToContext, NonEquivalentDecls,
 | |
|                                    getStructuralEquivalenceKind(*this), false,
 | |
|                                    Complain);
 | |
|   return Ctx.IsEquivalent(From, To);
 | |
| }
 |