diff options
Diffstat (limited to 'lib/AST/ASTImporter.cpp')
-rw-r--r-- | lib/AST/ASTImporter.cpp | 2911 |
1 files changed, 1872 insertions, 1039 deletions
diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index 0d1d9807549f5..6668067233e44 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -1,4 +1,4 @@ -//===--- ASTImporter.cpp - Importing ASTs from other Contexts ---*- C++ -*-===// +//===- ASTImporter.cpp - Importing ASTs from other Contexts ---------------===// // // The LLVM Compiler Infrastructure // @@ -11,29 +11,165 @@ // context into another context. // //===----------------------------------------------------------------------===// + #include "clang/AST/ASTImporter.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ASTDiagnostic.h" #include "clang/AST/ASTStructuralEquivalence.h" +#include "clang/AST/Attr.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclAccessPair.h" +#include "clang/AST/DeclBase.h" #include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclFriend.h" +#include "clang/AST/DeclGroup.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclTemplate.h" #include "clang/AST/DeclVisitor.h" +#include "clang/AST/DeclarationName.h" +#include "clang/AST/Expr.h" +#include "clang/AST/ExprCXX.h" +#include "clang/AST/ExprObjC.h" +#include "clang/AST/ExternalASTSource.h" +#include "clang/AST/LambdaCapture.h" +#include "clang/AST/NestedNameSpecifier.h" +#include "clang/AST/OperationKinds.h" +#include "clang/AST/Stmt.h" +#include "clang/AST/StmtCXX.h" +#include "clang/AST/StmtObjC.h" #include "clang/AST/StmtVisitor.h" +#include "clang/AST/TemplateBase.h" +#include "clang/AST/TemplateName.h" +#include "clang/AST/Type.h" +#include "clang/AST/TypeLoc.h" #include "clang/AST/TypeVisitor.h" +#include "clang/AST/UnresolvedSet.h" +#include "clang/Basic/ExceptionSpecificationType.h" #include "clang/Basic/FileManager.h" +#include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/LangOptions.h" +#include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManager.h" +#include "clang/Basic/Specifiers.h" +#include "llvm/ADT/APSInt.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/None.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MemoryBuffer.h" -#include <deque> +#include <algorithm> +#include <cassert> +#include <cstddef> +#include <memory> +#include <type_traits> +#include <utility> namespace clang { + + 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) { + // Currently only FunctionDecl is supported + auto FD = cast<FunctionDecl>(D); + return getCanonicalForwardRedeclChain<FunctionDecl>(FD); + } + + 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, QualType>, public DeclVisitor<ASTNodeImporter, Decl *>, public StmtVisitor<ASTNodeImporter, Stmt *> { ASTImporter &Importer; + // Wrapper for an overload set. + template <typename ToDeclT> struct CallOverloadedCreateFun { + template <typename... Args> + auto operator()(Args &&... args) + -> decltype(ToDeclT::Create(std::forward<Args>(args)...)) { + return ToDeclT::Create(std::forward<Args>(args)...); + } + }; + + // Always use these functions to create a Decl during import. There are + // certain tasks which must be done after the Decl was created, e.g. we + // must immediately register that as an imported Decl. The parameter `ToD` + // will be set to the newly created Decl or if had been imported before + // then to the already imported Decl. Returns a bool value set to true if + // the `FromD` had been imported before. + template <typename ToDeclT, typename FromDeclT, typename... Args> + LLVM_NODISCARD bool GetImportedOrCreateDecl(ToDeclT *&ToD, FromDeclT *FromD, + Args &&... args) { + // There may be several overloads of ToDeclT::Create. We must make sure + // to call the one which would be chosen by the arguments, thus we use a + // wrapper for the overload set. + CallOverloadedCreateFun<ToDeclT> OC; + return GetImportedOrCreateSpecialDecl(ToD, OC, FromD, + std::forward<Args>(args)...); + } + // Use this overload if a special Type is needed to be created. E.g if we + // want to create a `TypeAliasDecl` and assign that to a `TypedefNameDecl` + // then: + // TypedefNameDecl *ToTypedef; + // GetImportedOrCreateDecl<TypeAliasDecl>(ToTypedef, FromD, ...); + template <typename NewDeclT, typename ToDeclT, typename FromDeclT, + typename... Args> + LLVM_NODISCARD bool GetImportedOrCreateDecl(ToDeclT *&ToD, FromDeclT *FromD, + Args &&... args) { + CallOverloadedCreateFun<NewDeclT> OC; + return GetImportedOrCreateSpecialDecl(ToD, OC, FromD, + std::forward<Args>(args)...); + } + // Use this version if a special create function must be + // used, e.g. CXXRecordDecl::CreateLambda . + template <typename ToDeclT, typename CreateFunT, typename FromDeclT, + typename... Args> + LLVM_NODISCARD bool + GetImportedOrCreateSpecialDecl(ToDeclT *&ToD, CreateFunT CreateFun, + FromDeclT *FromD, Args &&... args) { + ToD = cast_or_null<ToDeclT>(Importer.GetAlreadyImportedOrNull(FromD)); + if (ToD) + return true; // Already imported. + ToD = CreateFun(std::forward<Args>(args)...); + InitializeImportedDecl(FromD, ToD); + return false; // A new Decl is created. + } + + void InitializeImportedDecl(Decl *FromD, Decl *ToD) { + Importer.MapImported(FromD, ToD); + ToD->IdentifierNamespace = FromD->IdentifierNamespace; + if (FromD->hasAttrs()) + for (const Attr *FromAttr : FromD->getAttrs()) + ToD->addAttr(Importer.Import(FromAttr)); + if (FromD->isUsed()) + ToD->setIsUsed(); + if (FromD->isImplicit()) + ToD->setImplicit(); + } + public: - explicit ASTNodeImporter(ASTImporter &Importer) : Importer(Importer) { } - + explicit ASTNodeImporter(ASTImporter &Importer) : Importer(Importer) {} + using TypeVisitor<ASTNodeImporter, QualType>::Visit; using DeclVisitor<ASTNodeImporter, Decl *>::Visit; using StmtVisitor<ASTNodeImporter, Stmt *>::Visit; @@ -52,7 +188,7 @@ namespace clang { QualType VisitConstantArrayType(const ConstantArrayType *T); QualType VisitIncompleteArrayType(const IncompleteArrayType *T); QualType VisitVariableArrayType(const VariableArrayType *T); - // FIXME: DependentSizedArrayType + QualType VisitDependentSizedArrayType(const DependentSizedArrayType *T); // FIXME: DependentSizedExtVectorType QualType VisitVectorType(const VectorType *T); QualType VisitExtVectorType(const ExtVectorType *T); @@ -76,14 +212,15 @@ namespace clang { QualType VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T); QualType VisitTemplateSpecializationType(const TemplateSpecializationType *T); QualType VisitElaboratedType(const ElaboratedType *T); - // FIXME: DependentNameType + QualType VisitDependentNameType(const DependentNameType *T); QualType VisitPackExpansionType(const PackExpansionType *T); - // FIXME: DependentTemplateSpecializationType + QualType VisitDependentTemplateSpecializationType( + const DependentTemplateSpecializationType *T); QualType VisitObjCInterfaceType(const ObjCInterfaceType *T); QualType VisitObjCObjectType(const ObjCObjectType *T); QualType VisitObjCObjectPointerType(const ObjCObjectPointerType *T); - - // Importing declarations + + // Importing declarations bool ImportDeclParts(NamedDecl *D, DeclContext *&DC, DeclContext *&LexicalDC, DeclarationName &Name, NamedDecl *&ToD, SourceLocation &Loc); @@ -91,22 +228,27 @@ namespace clang { void ImportDeclarationNameLoc(const DeclarationNameInfo &From, DeclarationNameInfo& To); void ImportDeclContext(DeclContext *FromDC, bool ForceImport = false); + void ImportImplicitMethods(const CXXRecordDecl *From, CXXRecordDecl *To); bool ImportCastPath(CastExpr *E, CXXCastPath &Path); - typedef DesignatedInitExpr::Designator Designator; + using Designator = DesignatedInitExpr::Designator; + Designator ImportDesignator(const Designator &D); + Optional<LambdaCapture> ImportLambdaCapture(const LambdaCapture &From); - /// \brief What we should import from the definition. + /// What we should import from the definition. enum ImportDefinitionKind { - /// \brief Import the default subset of the definition, which might be + /// 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, - /// \brief Import everything. + + /// Import everything. IDK_Everything, - /// \brief Import only the bare bones needed to establish a valid + + /// Import only the bare bones needed to establish a valid /// DeclContext. IDK_Basic }; @@ -127,16 +269,33 @@ namespace clang { bool ImportDefinition(ObjCProtocolDecl *From, ObjCProtocolDecl *To, ImportDefinitionKind Kind = IDK_Default); TemplateParameterList *ImportTemplateParameterList( - TemplateParameterList *Params); + TemplateParameterList *Params); TemplateArgument ImportTemplateArgument(const TemplateArgument &From); Optional<TemplateArgumentLoc> ImportTemplateArgumentLoc( const TemplateArgumentLoc &TALoc); bool ImportTemplateArguments(const TemplateArgument *FromArgs, unsigned NumFromArgs, - SmallVectorImpl<TemplateArgument> &ToArgs); + SmallVectorImpl<TemplateArgument> &ToArgs); + template <typename InContainerTy> bool ImportTemplateArgumentListInfo(const InContainerTy &Container, TemplateArgumentListInfo &ToTAInfo); + + template<typename InContainerTy> + bool ImportTemplateArgumentListInfo(SourceLocation FromLAngleLoc, + SourceLocation FromRAngleLoc, + const InContainerTy &Container, + TemplateArgumentListInfo &Result); + + using TemplateArgsTy = SmallVector<TemplateArgument, 8>; + using OptionalTemplateArgsTy = Optional<TemplateArgsTy>; + std::tuple<FunctionTemplateDecl *, OptionalTemplateArgsTy> + ImportFunctionTemplateWithTemplateArgsFromSpecialization( + FunctionDecl *FromFD); + + bool ImportTemplateInformation(FunctionDecl *FromFD, FunctionDecl *ToFD); + + bool IsStructuralMatch(Decl *From, Decl *To, bool Complain); bool IsStructuralMatch(RecordDecl *FromRecord, RecordDecl *ToRecord, bool Complain = true); bool IsStructuralMatch(VarDecl *FromVar, VarDecl *ToVar, @@ -145,6 +304,7 @@ namespace clang { 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); Decl *VisitDecl(Decl *D); @@ -185,7 +345,6 @@ namespace clang { Decl *VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D); Decl *VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D); - ObjCTypeParamList *ImportObjCTypeParamList(ObjCTypeParamList *list); Decl *VisitObjCInterfaceDecl(ObjCInterfaceDecl *D); Decl *VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D); @@ -282,29 +441,38 @@ namespace clang { Expr *VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *CE); Expr *VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E); Expr *VisitPackExpansionExpr(PackExpansionExpr *E); + Expr *VisitSizeOfPackExpr(SizeOfPackExpr *E); Expr *VisitCXXNewExpr(CXXNewExpr *CE); Expr *VisitCXXDeleteExpr(CXXDeleteExpr *E); Expr *VisitCXXConstructExpr(CXXConstructExpr *E); Expr *VisitCXXMemberCallExpr(CXXMemberCallExpr *E); Expr *VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E); + Expr *VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E); + Expr *VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *CE); + Expr *VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E); + Expr *VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E); Expr *VisitExprWithCleanups(ExprWithCleanups *EWC); Expr *VisitCXXThisExpr(CXXThisExpr *E); Expr *VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E); Expr *VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E); Expr *VisitMemberExpr(MemberExpr *E); Expr *VisitCallExpr(CallExpr *E); + Expr *VisitLambdaExpr(LambdaExpr *LE); Expr *VisitInitListExpr(InitListExpr *E); + Expr *VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *E); + Expr *VisitCXXInheritedCtorInitExpr(CXXInheritedCtorInitExpr *E); Expr *VisitArrayInitLoopExpr(ArrayInitLoopExpr *E); Expr *VisitArrayInitIndexExpr(ArrayInitIndexExpr *E); Expr *VisitCXXDefaultInitExpr(CXXDefaultInitExpr *E); Expr *VisitCXXNamedCastExpr(CXXNamedCastExpr *E); Expr *VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *E); Expr *VisitTypeTraitExpr(TypeTraitExpr *E); - + Expr *VisitCXXTypeidExpr(CXXTypeidExpr *E); template<typename IIter, typename OIter> void ImportArray(IIter Ibegin, IIter Iend, OIter Obegin) { - typedef typename std::remove_reference<decltype(*Obegin)>::type ItemT; + using ItemT = typename std::remove_reference<decltype(*Obegin)>::type; + ASTImporter &ImporterRef = Importer; std::transform(Ibegin, Iend, Obegin, [&ImporterRef](ItemT From) -> ItemT { @@ -314,13 +482,13 @@ namespace clang { template<typename IIter, typename OIter> bool ImportArrayChecked(IIter Ibegin, IIter Iend, OIter Obegin) { - typedef typename std::remove_reference<decltype(**Obegin)>::type ItemT; + using ItemT = typename std::remove_reference<decltype(**Obegin)>::type; + ASTImporter &ImporterRef = Importer; bool Failed = false; std::transform(Ibegin, Iend, Obegin, [&ImporterRef, &Failed](ItemT *From) -> ItemT * { - ItemT *To = cast_or_null<ItemT>( - ImporterRef.Import(From)); + auto *To = cast_or_null<ItemT>(ImporterRef.Import(From)); if (!To && From) Failed = true; return To; @@ -342,9 +510,58 @@ namespace clang { // Importing overrides. void ImportOverrides(CXXMethodDecl *ToMethod, CXXMethodDecl *FromMethod); + + FunctionDecl *FindFunctionTemplateSpecialization(FunctionDecl *FromFD); }; + +template <typename InContainerTy> +bool ASTNodeImporter::ImportTemplateArgumentListInfo( + SourceLocation FromLAngleLoc, SourceLocation FromRAngleLoc, + const InContainerTy &Container, TemplateArgumentListInfo &Result) { + TemplateArgumentListInfo ToTAInfo(Importer.Import(FromLAngleLoc), + Importer.Import(FromRAngleLoc)); + if (ImportTemplateArgumentListInfo(Container, ToTAInfo)) + return true; + Result = ToTAInfo; + return false; +} + +template <> +bool ASTNodeImporter::ImportTemplateArgumentListInfo<TemplateArgumentListInfo>( + const TemplateArgumentListInfo &From, TemplateArgumentListInfo &Result) { + return ImportTemplateArgumentListInfo( + From.getLAngleLoc(), From.getRAngleLoc(), From.arguments(), Result); +} + +template <> +bool ASTNodeImporter::ImportTemplateArgumentListInfo< + ASTTemplateArgumentListInfo>(const ASTTemplateArgumentListInfo &From, + TemplateArgumentListInfo &Result) { + return ImportTemplateArgumentListInfo(From.LAngleLoc, From.RAngleLoc, + From.arguments(), Result); +} + +std::tuple<FunctionTemplateDecl *, ASTNodeImporter::OptionalTemplateArgsTy> +ASTNodeImporter::ImportFunctionTemplateWithTemplateArgsFromSpecialization( + FunctionDecl *FromFD) { + assert(FromFD->getTemplatedKind() == + FunctionDecl::TK_FunctionTemplateSpecialization); + auto *FTSInfo = FromFD->getTemplateSpecializationInfo(); + auto *Template = cast_or_null<FunctionTemplateDecl>( + Importer.Import(FTSInfo->getTemplate())); + + // Import template arguments. + auto TemplArgs = FTSInfo->TemplateArguments->asArray(); + TemplateArgsTy ToTemplArgs; + if (ImportTemplateArguments(TemplArgs.data(), TemplArgs.size(), + ToTemplArgs)) // Error during import. + return std::make_tuple(Template, OptionalTemplateArgsTy()); + + return std::make_tuple(Template, ToTemplArgs); } +} // namespace clang + //---------------------------------------------------------------------------- // Import Types //---------------------------------------------------------------------------- @@ -354,13 +571,13 @@ using namespace clang; QualType ASTNodeImporter::VisitType(const Type *T) { Importer.FromDiag(SourceLocation(), diag::err_unsupported_ast_node) << T->getTypeClassName(); - return QualType(); + return {}; } QualType ASTNodeImporter::VisitAtomicType(const AtomicType *T){ QualType UnderlyingType = Importer.Import(T->getValueType()); if(UnderlyingType.isNull()) - return QualType(); + return {}; return Importer.getToContext().getAtomicType(UnderlyingType); } @@ -413,7 +630,7 @@ QualType ASTNodeImporter::VisitBuiltinType(const BuiltinType *T) { QualType ASTNodeImporter::VisitDecayedType(const DecayedType *T) { QualType OrigT = Importer.Import(T->getOriginalType()); if (OrigT.isNull()) - return QualType(); + return {}; return Importer.getToContext().getDecayedType(OrigT); } @@ -421,7 +638,7 @@ QualType ASTNodeImporter::VisitDecayedType(const DecayedType *T) { QualType ASTNodeImporter::VisitComplexType(const ComplexType *T) { QualType ToElementType = Importer.Import(T->getElementType()); if (ToElementType.isNull()) - return QualType(); + return {}; return Importer.getToContext().getComplexType(ToElementType); } @@ -429,7 +646,7 @@ QualType ASTNodeImporter::VisitComplexType(const ComplexType *T) { QualType ASTNodeImporter::VisitPointerType(const PointerType *T) { QualType ToPointeeType = Importer.Import(T->getPointeeType()); if (ToPointeeType.isNull()) - return QualType(); + return {}; return Importer.getToContext().getPointerType(ToPointeeType); } @@ -438,7 +655,7 @@ QualType ASTNodeImporter::VisitBlockPointerType(const BlockPointerType *T) { // FIXME: Check for blocks support in "to" context. QualType ToPointeeType = Importer.Import(T->getPointeeType()); if (ToPointeeType.isNull()) - return QualType(); + return {}; return Importer.getToContext().getBlockPointerType(ToPointeeType); } @@ -448,7 +665,7 @@ ASTNodeImporter::VisitLValueReferenceType(const LValueReferenceType *T) { // FIXME: Check for C++ support in "to" context. QualType ToPointeeType = Importer.Import(T->getPointeeTypeAsWritten()); if (ToPointeeType.isNull()) - return QualType(); + return {}; return Importer.getToContext().getLValueReferenceType(ToPointeeType); } @@ -458,7 +675,7 @@ ASTNodeImporter::VisitRValueReferenceType(const RValueReferenceType *T) { // FIXME: Check for C++0x support in "to" context. QualType ToPointeeType = Importer.Import(T->getPointeeTypeAsWritten()); if (ToPointeeType.isNull()) - return QualType(); + return {}; return Importer.getToContext().getRValueReferenceType(ToPointeeType); } @@ -467,7 +684,7 @@ QualType ASTNodeImporter::VisitMemberPointerType(const MemberPointerType *T) { // FIXME: Check for C++ support in "to" context. QualType ToPointeeType = Importer.Import(T->getPointeeType()); if (ToPointeeType.isNull()) - return QualType(); + return {}; QualType ClassType = Importer.Import(QualType(T->getClass(), 0)); return Importer.getToContext().getMemberPointerType(ToPointeeType, @@ -477,7 +694,7 @@ QualType ASTNodeImporter::VisitMemberPointerType(const MemberPointerType *T) { QualType ASTNodeImporter::VisitConstantArrayType(const ConstantArrayType *T) { QualType ToElementType = Importer.Import(T->getElementType()); if (ToElementType.isNull()) - return QualType(); + return {}; return Importer.getToContext().getConstantArrayType(ToElementType, T->getSize(), @@ -489,7 +706,7 @@ QualType ASTNodeImporter::VisitIncompleteArrayType(const IncompleteArrayType *T) { QualType ToElementType = Importer.Import(T->getElementType()); if (ToElementType.isNull()) - return QualType(); + return {}; return Importer.getToContext().getIncompleteArrayType(ToElementType, T->getSizeModifier(), @@ -499,11 +716,11 @@ ASTNodeImporter::VisitIncompleteArrayType(const IncompleteArrayType *T) { QualType ASTNodeImporter::VisitVariableArrayType(const VariableArrayType *T) { QualType ToElementType = Importer.Import(T->getElementType()); if (ToElementType.isNull()) - return QualType(); + return {}; Expr *Size = Importer.Import(T->getSizeExpr()); if (!Size) - return QualType(); + return {}; SourceRange Brackets = Importer.Import(T->getBracketsRange()); return Importer.getToContext().getVariableArrayType(ToElementType, Size, @@ -512,10 +729,28 @@ QualType ASTNodeImporter::VisitVariableArrayType(const VariableArrayType *T) { Brackets); } +QualType ASTNodeImporter::VisitDependentSizedArrayType( + const DependentSizedArrayType *T) { + QualType ToElementType = Importer.Import(T->getElementType()); + if (ToElementType.isNull()) + return {}; + + // SizeExpr may be null if size is not specified directly. + // For example, 'int a[]'. + Expr *Size = Importer.Import(T->getSizeExpr()); + if (!Size && T->getSizeExpr()) + return {}; + + SourceRange Brackets = Importer.Import(T->getBracketsRange()); + return Importer.getToContext().getDependentSizedArrayType( + ToElementType, Size, T->getSizeModifier(), T->getIndexTypeCVRQualifiers(), + Brackets); +} + QualType ASTNodeImporter::VisitVectorType(const VectorType *T) { QualType ToElementType = Importer.Import(T->getElementType()); if (ToElementType.isNull()) - return QualType(); + return {}; return Importer.getToContext().getVectorType(ToElementType, T->getNumElements(), @@ -525,7 +760,7 @@ QualType ASTNodeImporter::VisitVectorType(const VectorType *T) { QualType ASTNodeImporter::VisitExtVectorType(const ExtVectorType *T) { QualType ToElementType = Importer.Import(T->getElementType()); if (ToElementType.isNull()) - return QualType(); + return {}; return Importer.getToContext().getExtVectorType(ToElementType, T->getNumElements()); @@ -537,7 +772,7 @@ ASTNodeImporter::VisitFunctionNoProtoType(const FunctionNoProtoType *T) { // into C++? Should we make it variadic? QualType ToResultType = Importer.Import(T->getReturnType()); if (ToResultType.isNull()) - return QualType(); + return {}; return Importer.getToContext().getFunctionNoProtoType(ToResultType, T->getExtInfo()); @@ -546,14 +781,14 @@ ASTNodeImporter::VisitFunctionNoProtoType(const FunctionNoProtoType *T) { QualType ASTNodeImporter::VisitFunctionProtoType(const FunctionProtoType *T) { QualType ToResultType = Importer.Import(T->getReturnType()); if (ToResultType.isNull()) - return QualType(); + return {}; // Import argument types SmallVector<QualType, 4> ArgTypes; for (const auto &A : T->param_types()) { QualType ArgType = Importer.Import(A); if (ArgType.isNull()) - return QualType(); + return {}; ArgTypes.push_back(ArgType); } @@ -562,7 +797,7 @@ QualType ASTNodeImporter::VisitFunctionProtoType(const FunctionProtoType *T) { for (const auto &E : T->exceptions()) { QualType ExceptionType = Importer.Import(E); if (ExceptionType.isNull()) - return QualType(); + return {}; ExceptionTypes.push_back(ExceptionType); } @@ -588,16 +823,16 @@ QualType ASTNodeImporter::VisitFunctionProtoType(const FunctionProtoType *T) { QualType ASTNodeImporter::VisitUnresolvedUsingType( const UnresolvedUsingType *T) { - UnresolvedUsingTypenameDecl *ToD = cast_or_null<UnresolvedUsingTypenameDecl>( - Importer.Import(T->getDecl())); + const auto *ToD = + cast_or_null<UnresolvedUsingTypenameDecl>(Importer.Import(T->getDecl())); if (!ToD) - return QualType(); + return {}; - UnresolvedUsingTypenameDecl *ToPrevD = + auto *ToPrevD = cast_or_null<UnresolvedUsingTypenameDecl>( Importer.Import(T->getDecl()->getPreviousDecl())); if (!ToPrevD && T->getDecl()->getPreviousDecl()) - return QualType(); + return {}; return Importer.getToContext().getTypeDeclType(ToD, ToPrevD); } @@ -605,16 +840,16 @@ QualType ASTNodeImporter::VisitUnresolvedUsingType( QualType ASTNodeImporter::VisitParenType(const ParenType *T) { QualType ToInnerType = Importer.Import(T->getInnerType()); if (ToInnerType.isNull()) - return QualType(); + return {}; return Importer.getToContext().getParenType(ToInnerType); } QualType ASTNodeImporter::VisitTypedefType(const TypedefType *T) { - TypedefNameDecl *ToDecl - = dyn_cast_or_null<TypedefNameDecl>(Importer.Import(T->getDecl())); + auto *ToDecl = + dyn_cast_or_null<TypedefNameDecl>(Importer.Import(T->getDecl())); if (!ToDecl) - return QualType(); + return {}; return Importer.getToContext().getTypeDeclType(ToDecl); } @@ -622,7 +857,7 @@ QualType ASTNodeImporter::VisitTypedefType(const TypedefType *T) { QualType ASTNodeImporter::VisitTypeOfExprType(const TypeOfExprType *T) { Expr *ToExpr = Importer.Import(T->getUnderlyingExpr()); if (!ToExpr) - return QualType(); + return {}; return Importer.getToContext().getTypeOfExprType(ToExpr); } @@ -630,7 +865,7 @@ QualType ASTNodeImporter::VisitTypeOfExprType(const TypeOfExprType *T) { QualType ASTNodeImporter::VisitTypeOfType(const TypeOfType *T) { QualType ToUnderlyingType = Importer.Import(T->getUnderlyingType()); if (ToUnderlyingType.isNull()) - return QualType(); + return {}; return Importer.getToContext().getTypeOfType(ToUnderlyingType); } @@ -639,11 +874,11 @@ QualType ASTNodeImporter::VisitDecltypeType(const DecltypeType *T) { // FIXME: Make sure that the "to" context supports C++0x! Expr *ToExpr = Importer.Import(T->getUnderlyingExpr()); if (!ToExpr) - return QualType(); + return {}; QualType UnderlyingType = Importer.Import(T->getUnderlyingType()); if (UnderlyingType.isNull()) - return QualType(); + return {}; return Importer.getToContext().getDecltypeType(ToExpr, UnderlyingType); } @@ -652,7 +887,7 @@ QualType ASTNodeImporter::VisitUnaryTransformType(const UnaryTransformType *T) { QualType ToBaseType = Importer.Import(T->getBaseType()); QualType ToUnderlyingType = Importer.Import(T->getUnderlyingType()); if (ToBaseType.isNull() || ToUnderlyingType.isNull()) - return QualType(); + return {}; return Importer.getToContext().getUnaryTransformType(ToBaseType, ToUnderlyingType, @@ -666,7 +901,7 @@ QualType ASTNodeImporter::VisitAutoType(const AutoType *T) { if (!FromDeduced.isNull()) { ToDeduced = Importer.Import(FromDeduced); if (ToDeduced.isNull()) - return QualType(); + return {}; } return Importer.getToContext().getAutoType(ToDeduced, T->getKeyword(), @@ -675,13 +910,13 @@ QualType ASTNodeImporter::VisitAutoType(const AutoType *T) { QualType ASTNodeImporter::VisitInjectedClassNameType( const InjectedClassNameType *T) { - CXXRecordDecl *D = cast_or_null<CXXRecordDecl>(Importer.Import(T->getDecl())); + auto *D = cast_or_null<CXXRecordDecl>(Importer.Import(T->getDecl())); if (!D) - return QualType(); + return {}; QualType InjType = Importer.Import(T->getInjectedSpecializationType()); if (InjType.isNull()) - return QualType(); + return {}; // FIXME: ASTContext::getInjectedClassNameType is not suitable for AST reading // See comments in InjectedClassNameType definition for details @@ -696,19 +931,17 @@ QualType ASTNodeImporter::VisitInjectedClassNameType( } QualType ASTNodeImporter::VisitRecordType(const RecordType *T) { - RecordDecl *ToDecl - = dyn_cast_or_null<RecordDecl>(Importer.Import(T->getDecl())); + auto *ToDecl = dyn_cast_or_null<RecordDecl>(Importer.Import(T->getDecl())); if (!ToDecl) - return QualType(); + return {}; return Importer.getToContext().getTagDeclType(ToDecl); } QualType ASTNodeImporter::VisitEnumType(const EnumType *T) { - EnumDecl *ToDecl - = dyn_cast_or_null<EnumDecl>(Importer.Import(T->getDecl())); + auto *ToDecl = dyn_cast_or_null<EnumDecl>(Importer.Import(T->getDecl())); if (!ToDecl) - return QualType(); + return {}; return Importer.getToContext().getTagDeclType(ToDecl); } @@ -722,25 +955,24 @@ QualType ASTNodeImporter::VisitAttributedType(const AttributedType *T) { if (!FromModifiedType.isNull()) { ToModifiedType = Importer.Import(FromModifiedType); if (ToModifiedType.isNull()) - return QualType(); + return {}; } if (!FromEquivalentType.isNull()) { ToEquivalentType = Importer.Import(FromEquivalentType); if (ToEquivalentType.isNull()) - return QualType(); + return {}; } return Importer.getToContext().getAttributedType(T->getAttrKind(), ToModifiedType, ToEquivalentType); } - QualType ASTNodeImporter::VisitTemplateTypeParmType( const TemplateTypeParmType *T) { - TemplateTypeParmDecl *ParmDecl = + auto *ParmDecl = cast_or_null<TemplateTypeParmDecl>(Importer.Import(T->getDecl())); if (!ParmDecl && T->getDecl()) - return QualType(); + return {}; return Importer.getToContext().getTemplateTypeParmType( T->getDepth(), T->getIndex(), T->isParameterPack(), ParmDecl); @@ -748,15 +980,15 @@ QualType ASTNodeImporter::VisitTemplateTypeParmType( QualType ASTNodeImporter::VisitSubstTemplateTypeParmType( const SubstTemplateTypeParmType *T) { - const TemplateTypeParmType *Replaced = + const auto *Replaced = cast_or_null<TemplateTypeParmType>(Importer.Import( QualType(T->getReplacedParameter(), 0)).getTypePtr()); if (!Replaced) - return QualType(); + return {}; QualType Replacement = Importer.Import(T->getReplacementType()); if (Replacement.isNull()) - return QualType(); + return {}; Replacement = Replacement.getCanonicalType(); return Importer.getToContext().getSubstTemplateTypeParmType( @@ -767,11 +999,11 @@ QualType ASTNodeImporter::VisitTemplateSpecializationType( const TemplateSpecializationType *T) { TemplateName ToTemplate = Importer.Import(T->getTemplateName()); if (ToTemplate.isNull()) - return QualType(); + return {}; SmallVector<TemplateArgument, 2> ToTemplateArgs; if (ImportTemplateArguments(T->getArgs(), T->getNumArgs(), ToTemplateArgs)) - return QualType(); + return {}; QualType ToCanonType; if (!QualType(T, 0).isCanonical()) { @@ -779,7 +1011,7 @@ QualType ASTNodeImporter::VisitTemplateSpecializationType( = Importer.getFromContext().getCanonicalType(QualType(T, 0)); ToCanonType =Importer.Import(FromCanonType); if (ToCanonType.isNull()) - return QualType(); + return {}; } return Importer.getToContext().getTemplateSpecializationType(ToTemplate, ToTemplateArgs, @@ -792,31 +1024,75 @@ QualType ASTNodeImporter::VisitElaboratedType(const ElaboratedType *T) { if (T->getQualifier()) { ToQualifier = Importer.Import(T->getQualifier()); if (!ToQualifier) - return QualType(); + return {}; } QualType ToNamedType = Importer.Import(T->getNamedType()); if (ToNamedType.isNull()) - return QualType(); + return {}; + + TagDecl *OwnedTagDecl = + cast_or_null<TagDecl>(Importer.Import(T->getOwnedTagDecl())); + if (!OwnedTagDecl && T->getOwnedTagDecl()) + return {}; return Importer.getToContext().getElaboratedType(T->getKeyword(), - ToQualifier, ToNamedType); + ToQualifier, ToNamedType, + OwnedTagDecl); } QualType ASTNodeImporter::VisitPackExpansionType(const PackExpansionType *T) { QualType Pattern = Importer.Import(T->getPattern()); if (Pattern.isNull()) - return QualType(); + return {}; return Importer.getToContext().getPackExpansionType(Pattern, T->getNumExpansions()); } +QualType ASTNodeImporter::VisitDependentTemplateSpecializationType( + const DependentTemplateSpecializationType *T) { + NestedNameSpecifier *Qualifier = Importer.Import(T->getQualifier()); + if (!Qualifier && T->getQualifier()) + return {}; + + IdentifierInfo *Name = Importer.Import(T->getIdentifier()); + if (!Name && T->getIdentifier()) + return {}; + + SmallVector<TemplateArgument, 2> ToPack; + ToPack.reserve(T->getNumArgs()); + if (ImportTemplateArguments(T->getArgs(), T->getNumArgs(), ToPack)) + return {}; + + return Importer.getToContext().getDependentTemplateSpecializationType( + T->getKeyword(), Qualifier, Name, ToPack); +} + +QualType ASTNodeImporter::VisitDependentNameType(const DependentNameType *T) { + NestedNameSpecifier *NNS = Importer.Import(T->getQualifier()); + if (!NNS && T->getQualifier()) + return QualType(); + + IdentifierInfo *Name = Importer.Import(T->getIdentifier()); + if (!Name && T->getIdentifier()) + return QualType(); + + QualType Canon = (T == T->getCanonicalTypeInternal().getTypePtr()) + ? QualType() + : Importer.Import(T->getCanonicalTypeInternal()); + if (!Canon.isNull()) + Canon = Canon.getCanonicalType(); + + return Importer.getToContext().getDependentNameType(T->getKeyword(), NNS, + Name, Canon); +} + QualType ASTNodeImporter::VisitObjCInterfaceType(const ObjCInterfaceType *T) { - ObjCInterfaceDecl *Class - = dyn_cast_or_null<ObjCInterfaceDecl>(Importer.Import(T->getDecl())); + auto *Class = + dyn_cast_or_null<ObjCInterfaceDecl>(Importer.Import(T->getDecl())); if (!Class) - return QualType(); + return {}; return Importer.getToContext().getObjCInterfaceType(Class); } @@ -824,23 +1100,22 @@ QualType ASTNodeImporter::VisitObjCInterfaceType(const ObjCInterfaceType *T) { QualType ASTNodeImporter::VisitObjCObjectType(const ObjCObjectType *T) { QualType ToBaseType = Importer.Import(T->getBaseType()); if (ToBaseType.isNull()) - return QualType(); + return {}; SmallVector<QualType, 4> TypeArgs; for (auto TypeArg : T->getTypeArgsAsWritten()) { QualType ImportedTypeArg = Importer.Import(TypeArg); if (ImportedTypeArg.isNull()) - return QualType(); + return {}; TypeArgs.push_back(ImportedTypeArg); } SmallVector<ObjCProtocolDecl *, 4> Protocols; for (auto *P : T->quals()) { - ObjCProtocolDecl *Protocol - = dyn_cast_or_null<ObjCProtocolDecl>(Importer.Import(P)); + auto *Protocol = dyn_cast_or_null<ObjCProtocolDecl>(Importer.Import(P)); if (!Protocol) - return QualType(); + return {}; Protocols.push_back(Protocol); } @@ -853,7 +1128,7 @@ QualType ASTNodeImporter::VisitObjCObjectPointerType(const ObjCObjectPointerType *T) { QualType ToPointeeType = Importer.Import(T->getPointeeType()); if (ToPointeeType.isNull()) - return QualType(); + return {}; return Importer.getToContext().getObjCObjectPointerType(ToPointeeType); } @@ -866,8 +1141,26 @@ bool ASTNodeImporter::ImportDeclParts(NamedDecl *D, DeclContext *&DC, DeclarationName &Name, NamedDecl *&ToD, SourceLocation &Loc) { + // Check if RecordDecl is in FunctionDecl parameters to avoid infinite loop. + // example: int struct_in_proto(struct data_t{int a;int b;} *d); + DeclContext *OrigDC = D->getDeclContext(); + FunctionDecl *FunDecl; + if (isa<RecordDecl>(D) && (FunDecl = dyn_cast<FunctionDecl>(OrigDC)) && + FunDecl->hasBody()) { + SourceRange RecR = D->getSourceRange(); + SourceRange BodyR = FunDecl->getBody()->getSourceRange(); + // If RecordDecl is not in Body (it is a param), we bail out. + if (RecR.isValid() && BodyR.isValid() && + (RecR.getBegin() < BodyR.getBegin() || + BodyR.getEnd() < RecR.getEnd())) { + Importer.FromDiag(D->getLocation(), diag::err_unsupported_ast_node) + << D->getDeclKindName(); + return true; + } + } + // Import the context of this declaration. - DC = Importer.ImportContext(D->getDeclContext()); + DC = Importer.ImportContext(OrigDC); if (!DC) return true; @@ -899,8 +1192,8 @@ void ASTNodeImporter::ImportDefinitionIfNeeded(Decl *FromD, Decl *ToD) { return; } - if (RecordDecl *FromRecord = dyn_cast<RecordDecl>(FromD)) { - if (RecordDecl *ToRecord = cast_or_null<RecordDecl>(ToD)) { + if (auto *FromRecord = dyn_cast<RecordDecl>(FromD)) { + if (auto *ToRecord = cast_or_null<RecordDecl>(ToD)) { if (FromRecord->getDefinition() && FromRecord->isCompleteDefinition() && !ToRecord->getDefinition()) { ImportDefinition(FromRecord, ToRecord); } @@ -908,8 +1201,8 @@ void ASTNodeImporter::ImportDefinitionIfNeeded(Decl *FromD, Decl *ToD) { return; } - if (EnumDecl *FromEnum = dyn_cast<EnumDecl>(FromD)) { - if (EnumDecl *ToEnum = cast_or_null<EnumDecl>(ToD)) { + if (auto *FromEnum = dyn_cast<EnumDecl>(FromD)) { + if (auto *ToEnum = cast_or_null<EnumDecl>(ToD)) { if (FromEnum->getDefinition() && !ToEnum->getDefinition()) { ImportDefinition(FromEnum, ToEnum); } @@ -963,6 +1256,27 @@ void ASTNodeImporter::ImportDeclContext(DeclContext *FromDC, bool ForceImport) { Importer.Import(From); } +void 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()) + Importer.Import(FromM); +} + +static void setTypedefNameForAnonDecl(TagDecl *From, TagDecl *To, + ASTImporter &Importer) { + if (TypedefNameDecl *FromTypedef = From->getTypedefNameForAnonDecl()) { + auto *ToTypedef = + cast_or_null<TypedefNameDecl>(Importer.Import(FromTypedef)); + assert (ToTypedef && "Failed to import typedef of an anonymous structure"); + + To->setTypedefNameForAnonDecl(ToTypedef); + } +} + bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To, ImportDefinitionKind Kind) { if (To->getDefinition() || To->isBeingDefined()) { @@ -973,10 +1287,12 @@ bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To, } To->startDefinition(); + + setTypedefNameForAnonDecl(From, To, Importer); // Add base classes. - if (CXXRecordDecl *ToCXX = dyn_cast<CXXRecordDecl>(To)) { - CXXRecordDecl *FromCXX = cast<CXXRecordDecl>(From); + if (auto *ToCXX = dyn_cast<CXXRecordDecl>(To)) { + auto *FromCXX = cast<CXXRecordDecl>(From); struct CXXRecordDecl::DefinitionData &ToData = ToCXX->data(); struct CXXRecordDecl::DefinitionData &FromData = FromCXX->data(); @@ -988,7 +1304,10 @@ bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To, ToData.Polymorphic = FromData.Polymorphic; ToData.Abstract = FromData.Abstract; ToData.IsStandardLayout = FromData.IsStandardLayout; - ToData.HasNoNonEmptyBases = FromData.HasNoNonEmptyBases; + ToData.IsCXX11StandardLayout = FromData.IsCXX11StandardLayout; + ToData.HasBasesWithFields = FromData.HasBasesWithFields; + ToData.HasBasesWithNonStaticDataMembers = + FromData.HasBasesWithNonStaticDataMembers; ToData.HasPrivateFields = FromData.HasPrivateFields; ToData.HasProtectedFields = FromData.HasProtectedFields; ToData.HasPublicFields = FromData.HasPublicFields; @@ -1022,7 +1341,6 @@ bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To, = FromData.HasConstexprNonCopyMoveConstructor; ToData.HasDefaultedDefaultConstructor = FromData.HasDefaultedDefaultConstructor; - ToData.CanPassInRegisters = FromData.CanPassInRegisters; ToData.DefaultedDefaultConstructorIsConstexpr = FromData.DefaultedDefaultConstructorIsConstexpr; ToData.HasConstexprDefaultConstructor @@ -1043,7 +1361,6 @@ bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To, = FromData.HasDeclaredCopyConstructorWithConstParam; ToData.HasDeclaredCopyAssignmentWithConstParam = FromData.HasDeclaredCopyAssignmentWithConstParam; - ToData.IsLambda = FromData.IsLambda; SmallVector<CXXBaseSpecifier *, 4> Bases; for (const auto &Base1 : FromCXX->bases()) { @@ -1103,6 +1420,8 @@ bool ASTNodeImporter::ImportDefinition(EnumDecl *From, EnumDecl *To, To->startDefinition(); + setTypedefNameForAnonDecl(From, To, Importer); + QualType T = Importer.Import(Importer.getFromContext().getTypeDeclType(From)); if (T.isNull()) return true; @@ -1154,36 +1473,36 @@ ASTNodeImporter::ImportTemplateArgument(const TemplateArgument &From) { case TemplateArgument::Type: { QualType ToType = Importer.Import(From.getAsType()); if (ToType.isNull()) - return TemplateArgument(); + return {}; return TemplateArgument(ToType); } case TemplateArgument::Integral: { QualType ToType = Importer.Import(From.getIntegralType()); if (ToType.isNull()) - return TemplateArgument(); + return {}; return TemplateArgument(From, ToType); } case TemplateArgument::Declaration: { - ValueDecl *To = cast_or_null<ValueDecl>(Importer.Import(From.getAsDecl())); + auto *To = cast_or_null<ValueDecl>(Importer.Import(From.getAsDecl())); QualType ToType = Importer.Import(From.getParamTypeForDecl()); if (!To || ToType.isNull()) - return TemplateArgument(); + return {}; return TemplateArgument(To, ToType); } case TemplateArgument::NullPtr: { QualType ToType = Importer.Import(From.getNullPtrType()); if (ToType.isNull()) - return TemplateArgument(); + return {}; return TemplateArgument(ToType, /*isNullPtr*/true); } case TemplateArgument::Template: { TemplateName ToTemplate = Importer.Import(From.getAsTemplate()); if (ToTemplate.isNull()) - return TemplateArgument(); + return {}; return TemplateArgument(ToTemplate); } @@ -1192,7 +1511,7 @@ ASTNodeImporter::ImportTemplateArgument(const TemplateArgument &From) { TemplateName ToTemplate = Importer.Import(From.getAsTemplateOrTemplatePattern()); if (ToTemplate.isNull()) - return TemplateArgument(); + return {}; return TemplateArgument(ToTemplate, From.getNumTemplateExpansions()); } @@ -1206,7 +1525,7 @@ ASTNodeImporter::ImportTemplateArgument(const TemplateArgument &From) { SmallVector<TemplateArgument, 2> ToPack; ToPack.reserve(From.pack_size()); if (ImportTemplateArguments(From.pack_begin(), From.pack_size(), ToPack)) - return TemplateArgument(); + return {}; return TemplateArgument( llvm::makeArrayRef(ToPack).copy(Importer.getToContext())); @@ -1254,6 +1573,9 @@ bool ASTNodeImporter::ImportTemplateArguments(const TemplateArgument *FromArgs, return false; } +// We cannot use Optional<> pattern here and below because +// TemplateArgumentListInfo's operator new is declared as deleted so it cannot +// be stored in Optional. template <typename InContainerTy> bool ASTNodeImporter::ImportTemplateArgumentListInfo( const InContainerTy &Container, TemplateArgumentListInfo &ToTAInfo) { @@ -1266,13 +1588,27 @@ bool ASTNodeImporter::ImportTemplateArgumentListInfo( return false; } -bool ASTNodeImporter::IsStructuralMatch(RecordDecl *FromRecord, +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) { - RecordDecl *ToOriginRecord = dyn_cast<RecordDecl>(ToOrigin); + auto *ToOriginRecord = dyn_cast<RecordDecl>(ToOrigin); if (ToOriginRecord) ToRecord = ToOriginRecord; } @@ -1280,36 +1616,46 @@ bool ASTNodeImporter::IsStructuralMatch(RecordDecl *FromRecord, StructuralEquivalenceContext Ctx(Importer.getFromContext(), ToRecord->getASTContext(), Importer.getNonEquivalentDecls(), + getStructuralEquivalenceKind(Importer), false, Complain); - return Ctx.IsStructurallyEquivalent(FromRecord, ToRecord); + return Ctx.IsEquivalent(FromRecord, ToRecord); } bool ASTNodeImporter::IsStructuralMatch(VarDecl *FromVar, VarDecl *ToVar, bool Complain) { StructuralEquivalenceContext Ctx( Importer.getFromContext(), Importer.getToContext(), - Importer.getNonEquivalentDecls(), false, Complain); - return Ctx.IsStructurallyEquivalent(FromVar, ToVar); + Importer.getNonEquivalentDecls(), getStructuralEquivalenceKind(Importer), + false, Complain); + return Ctx.IsEquivalent(FromVar, ToVar); } bool ASTNodeImporter::IsStructuralMatch(EnumDecl *FromEnum, EnumDecl *ToEnum) { - StructuralEquivalenceContext Ctx(Importer.getFromContext(), - Importer.getToContext(), - Importer.getNonEquivalentDecls()); - return Ctx.IsStructurallyEquivalent(FromEnum, ToEnum); + 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(), false, false); - return Ctx.IsStructurallyEquivalent(From, To); + 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) -{ + EnumConstantDecl *ToEC) { const llvm::APSInt &FromVal = FromEC->getInitVal(); const llvm::APSInt &ToVal = ToEC->getInitVal(); @@ -1322,16 +1668,18 @@ bool ASTNodeImporter::IsStructuralMatch(ClassTemplateDecl *From, ClassTemplateDecl *To) { StructuralEquivalenceContext Ctx(Importer.getFromContext(), Importer.getToContext(), - Importer.getNonEquivalentDecls()); - return Ctx.IsStructurallyEquivalent(From, To); + Importer.getNonEquivalentDecls(), + getStructuralEquivalenceKind(Importer)); + return Ctx.IsEquivalent(From, To); } bool ASTNodeImporter::IsStructuralMatch(VarTemplateDecl *From, VarTemplateDecl *To) { StructuralEquivalenceContext Ctx(Importer.getFromContext(), Importer.getToContext(), - Importer.getNonEquivalentDecls()); - return Ctx.IsStructurallyEquivalent(From, To); + Importer.getNonEquivalentDecls(), + getStructuralEquivalenceKind(Importer)); + return Ctx.IsEquivalent(From, To); } Decl *ASTNodeImporter::VisitDecl(Decl *D) { @@ -1356,9 +1704,11 @@ Decl *ASTNodeImporter::VisitEmptyDecl(EmptyDecl *D) { // Import the location of this declaration. SourceLocation Loc = Importer.Import(D->getLocation()); - EmptyDecl *ToD = EmptyDecl::Create(Importer.getToContext(), DC, Loc); + EmptyDecl *ToD; + if (GetImportedOrCreateDecl(ToD, D, Importer.getToContext(), DC, Loc)) + return ToD; + ToD->setLexicalDeclContext(LexicalDC); - Importer.Imported(D, ToD); LexicalDC->addDeclInternal(ToD); return ToD; } @@ -1367,13 +1717,12 @@ Decl *ASTNodeImporter::VisitTranslationUnitDecl(TranslationUnitDecl *D) { TranslationUnitDecl *ToD = Importer.getToContext().getTranslationUnitDecl(); - Importer.Imported(D, ToD); + Importer.MapImported(D, ToD); return ToD; } Decl *ASTNodeImporter::VisitAccessSpecDecl(AccessSpecDecl *D) { - SourceLocation Loc = Importer.Import(D->getLocation()); SourceLocation ColonLoc = Importer.Import(D->getColonLoc()); @@ -1382,19 +1731,17 @@ Decl *ASTNodeImporter::VisitAccessSpecDecl(AccessSpecDecl *D) { if (!DC) return nullptr; - AccessSpecDecl *accessSpecDecl - = AccessSpecDecl::Create(Importer.getToContext(), D->getAccess(), - DC, Loc, ColonLoc); - - if (!accessSpecDecl) - return nullptr; + AccessSpecDecl *ToD; + if (GetImportedOrCreateDecl(ToD, D, Importer.getToContext(), D->getAccess(), + DC, Loc, ColonLoc)) + return ToD; // Lexical DeclContext and Semantic DeclContext // is always the same for the accessSpec. - accessSpecDecl->setLexicalDeclContext(DC); - DC->addDeclInternal(accessSpecDecl); + ToD->setLexicalDeclContext(DC); + DC->addDeclInternal(ToD); - return accessSpecDecl; + return ToD; } Decl *ASTNodeImporter::VisitStaticAssertDecl(StaticAssertDecl *D) { @@ -1412,17 +1759,18 @@ Decl *ASTNodeImporter::VisitStaticAssertDecl(StaticAssertDecl *D) { return nullptr; StringLiteral *FromMsg = D->getMessage(); - StringLiteral *ToMsg = cast_or_null<StringLiteral>(Importer.Import(FromMsg)); + auto *ToMsg = cast_or_null<StringLiteral>(Importer.Import(FromMsg)); if (!ToMsg && FromMsg) return nullptr; - StaticAssertDecl *ToD = StaticAssertDecl::Create( - Importer.getToContext(), DC, Loc, AssertExpr, ToMsg, - Importer.Import(D->getRParenLoc()), D->isFailed()); + StaticAssertDecl *ToD; + if (GetImportedOrCreateDecl( + ToD, D, Importer.getToContext(), DC, Loc, AssertExpr, ToMsg, + Importer.Import(D->getRParenLoc()), D->isFailed())) + return ToD; ToD->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToD); - Importer.Imported(D, ToD); return ToD; } @@ -1442,7 +1790,7 @@ Decl *ASTNodeImporter::VisitNamespaceDecl(NamespaceDecl *D) { // This is an anonymous namespace. Adopt an existing anonymous // namespace if we can. // FIXME: Not testable. - if (TranslationUnitDecl *TU = dyn_cast<TranslationUnitDecl>(DC)) + if (auto *TU = dyn_cast<TranslationUnitDecl>(DC)) MergeWithNamespace = TU->getAnonymousNamespace(); else MergeWithNamespace = cast<NamespaceDecl>(DC)->getAnonymousNamespace(); @@ -1450,17 +1798,17 @@ Decl *ASTNodeImporter::VisitNamespaceDecl(NamespaceDecl *D) { SmallVector<NamedDecl *, 4> ConflictingDecls; SmallVector<NamedDecl *, 2> FoundDecls; DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls); - for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { - if (!FoundDecls[I]->isInIdentifierNamespace(Decl::IDNS_Namespace)) + for (auto *FoundDecl : FoundDecls) { + if (!FoundDecl->isInIdentifierNamespace(Decl::IDNS_Namespace)) continue; - if (NamespaceDecl *FoundNS = dyn_cast<NamespaceDecl>(FoundDecls[I])) { + if (auto *FoundNS = dyn_cast<NamespaceDecl>(FoundDecl)) { MergeWithNamespace = FoundNS; ConflictingDecls.clear(); break; } - ConflictingDecls.push_back(FoundDecls[I]); + ConflictingDecls.push_back(FoundDecl); } if (!ConflictingDecls.empty()) { @@ -1473,24 +1821,24 @@ Decl *ASTNodeImporter::VisitNamespaceDecl(NamespaceDecl *D) { // Create the "to" namespace, if needed. NamespaceDecl *ToNamespace = MergeWithNamespace; if (!ToNamespace) { - ToNamespace = NamespaceDecl::Create(Importer.getToContext(), DC, - D->isInline(), - Importer.Import(D->getLocStart()), - Loc, Name.getAsIdentifierInfo(), - /*PrevDecl=*/nullptr); + if (GetImportedOrCreateDecl( + ToNamespace, D, Importer.getToContext(), DC, D->isInline(), + Importer.Import(D->getLocStart()), Loc, Name.getAsIdentifierInfo(), + /*PrevDecl=*/nullptr)) + return ToNamespace; ToNamespace->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToNamespace); // If this is an anonymous namespace, register it as the anonymous // namespace within its context. if (!Name) { - if (TranslationUnitDecl *TU = dyn_cast<TranslationUnitDecl>(DC)) + if (auto *TU = dyn_cast<TranslationUnitDecl>(DC)) TU->setAnonymousNamespace(ToNamespace); else cast<NamespaceDecl>(DC)->setAnonymousNamespace(ToNamespace); } } - Importer.Imported(D, ToNamespace); + Importer.MapImported(D, ToNamespace); ImportDeclContext(D); @@ -1510,8 +1858,8 @@ Decl *ASTNodeImporter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { // NOTE: No conflict resolution is done for namespace aliases now. - NamespaceDecl *TargetDecl = cast_or_null<NamespaceDecl>( - Importer.Import(D->getNamespace())); + auto *TargetDecl = cast_or_null<NamespaceDecl>( + Importer.Import(D->getNamespace())); if (!TargetDecl) return nullptr; @@ -1523,13 +1871,15 @@ Decl *ASTNodeImporter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { if (D->getQualifierLoc() && !ToQLoc) return nullptr; - NamespaceAliasDecl *ToD = NamespaceAliasDecl::Create( - Importer.getToContext(), DC, Importer.Import(D->getNamespaceLoc()), - Importer.Import(D->getAliasLoc()), ToII, ToQLoc, - Importer.Import(D->getTargetNameLoc()), TargetDecl); + NamespaceAliasDecl *ToD; + if (GetImportedOrCreateDecl(ToD, D, Importer.getToContext(), DC, + Importer.Import(D->getNamespaceLoc()), + Importer.Import(D->getAliasLoc()), ToII, ToQLoc, + Importer.Import(D->getTargetNameLoc()), + TargetDecl)) + return ToD; ToD->setLexicalDeclContext(LexicalDC); - Importer.Imported(D, ToD); LexicalDC->addDeclInternal(ToD); return ToD; @@ -1554,17 +1904,16 @@ Decl *ASTNodeImporter::VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias) { unsigned IDNS = Decl::IDNS_Ordinary; SmallVector<NamedDecl *, 2> FoundDecls; DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls); - for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { - if (!FoundDecls[I]->isInIdentifierNamespace(IDNS)) + for (auto *FoundDecl : FoundDecls) { + if (!FoundDecl->isInIdentifierNamespace(IDNS)) continue; - if (TypedefNameDecl *FoundTypedef = - dyn_cast<TypedefNameDecl>(FoundDecls[I])) { + if (auto *FoundTypedef = dyn_cast<TypedefNameDecl>(FoundDecl)) { if (Importer.IsStructurallyEquivalent(D->getUnderlyingType(), FoundTypedef->getUnderlyingType())) - return Importer.Imported(D, FoundTypedef); + return Importer.MapImported(D, FoundTypedef); } - ConflictingDecls.push_back(FoundDecls[I]); + ConflictingDecls.push_back(FoundDecl); } if (!ConflictingDecls.empty()) { @@ -1584,22 +1933,25 @@ Decl *ASTNodeImporter::VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias) { // Create the new typedef node. TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo()); SourceLocation StartL = Importer.Import(D->getLocStart()); + TypedefNameDecl *ToTypedef; - if (IsAlias) - ToTypedef = TypeAliasDecl::Create(Importer.getToContext(), DC, - StartL, Loc, - Name.getAsIdentifierInfo(), - TInfo); - else - ToTypedef = TypedefDecl::Create(Importer.getToContext(), DC, - StartL, Loc, - Name.getAsIdentifierInfo(), - TInfo); + if (IsAlias) { + if (GetImportedOrCreateDecl<TypeAliasDecl>( + ToTypedef, D, Importer.getToContext(), DC, StartL, Loc, + Name.getAsIdentifierInfo(), TInfo)) + return ToTypedef; + } else if (GetImportedOrCreateDecl<TypedefDecl>( + ToTypedef, D, Importer.getToContext(), DC, StartL, Loc, + Name.getAsIdentifierInfo(), TInfo)) + return ToTypedef; ToTypedef->setAccess(D->getAccess()); ToTypedef->setLexicalDeclContext(LexicalDC); - Importer.Imported(D, ToTypedef); - LexicalDC->addDeclInternal(ToTypedef); + + // Templated declarations should not appear in DeclContext. + TypeAliasDecl *FromAlias = IsAlias ? cast<TypeAliasDecl>(D) : nullptr; + if (!FromAlias || !FromAlias->getDescribedAliasTemplate()) + LexicalDC->addDeclInternal(ToTypedef); return ToTypedef; } @@ -1617,11 +1969,11 @@ Decl *ASTNodeImporter::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) { DeclContext *DC, *LexicalDC; DeclarationName Name; SourceLocation Loc; - NamedDecl *ToD; - if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) + NamedDecl *FoundD; + if (ImportDeclParts(D, DC, LexicalDC, Name, FoundD, Loc)) return nullptr; - if (ToD) - return ToD; + 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 @@ -1631,13 +1983,12 @@ Decl *ASTNodeImporter::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) { unsigned IDNS = Decl::IDNS_Ordinary; SmallVector<NamedDecl *, 2> FoundDecls; DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls); - for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { - if (!FoundDecls[I]->isInIdentifierNamespace(IDNS)) + for (auto *FoundDecl : FoundDecls) { + if (!FoundDecl->isInIdentifierNamespace(IDNS)) continue; - if (auto *FoundAlias = - dyn_cast<TypeAliasTemplateDecl>(FoundDecls[I])) - return Importer.Imported(D, FoundAlias); - ConflictingDecls.push_back(FoundDecls[I]); + if (auto *FoundAlias = dyn_cast<TypeAliasTemplateDecl>(FoundDecl)) + return Importer.MapImported(D, FoundAlias); + ConflictingDecls.push_back(FoundDecl); } if (!ConflictingDecls.empty()) { @@ -1654,19 +2005,22 @@ Decl *ASTNodeImporter::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) { if (!Params) return nullptr; - NamedDecl *TemplDecl = cast_or_null<NamedDecl>( + auto *TemplDecl = cast_or_null<TypeAliasDecl>( Importer.Import(D->getTemplatedDecl())); if (!TemplDecl) return nullptr; - TypeAliasTemplateDecl *ToAlias = TypeAliasTemplateDecl::Create( - Importer.getToContext(), DC, Loc, Name, Params, TemplDecl); + TypeAliasTemplateDecl *ToAlias; + if (GetImportedOrCreateDecl(ToAlias, D, Importer.getToContext(), DC, Loc, + Name, Params, TemplDecl)) + return ToAlias; + + TemplDecl->setDescribedAliasTemplate(ToAlias); ToAlias->setAccess(D->getAccess()); ToAlias->setLexicalDeclContext(LexicalDC); - Importer.Imported(D, ToAlias); LexicalDC->addDeclInternal(ToAlias); - return ToD; + return ToAlias; } Decl *ASTNodeImporter::VisitLabelDecl(LabelDecl *D) { @@ -1682,17 +2036,18 @@ Decl *ASTNodeImporter::VisitLabelDecl(LabelDecl *D) { assert(LexicalDC->isFunctionOrMethod()); - LabelDecl *ToLabel = D->isGnuLocal() - ? LabelDecl::Create(Importer.getToContext(), - DC, Importer.Import(D->getLocation()), - Name.getAsIdentifierInfo(), - Importer.Import(D->getLocStart())) - : LabelDecl::Create(Importer.getToContext(), - DC, Importer.Import(D->getLocation()), - Name.getAsIdentifierInfo()); - Importer.Imported(D, ToLabel); - - LabelStmt *Label = cast_or_null<LabelStmt>(Importer.Import(D->getStmt())); + LabelDecl *ToLabel; + if (D->isGnuLocal() + ? GetImportedOrCreateDecl(ToLabel, D, Importer.getToContext(), DC, + Importer.Import(D->getLocation()), + Name.getAsIdentifierInfo(), + Importer.Import(D->getLocStart())) + : GetImportedOrCreateDecl(ToLabel, D, Importer.getToContext(), DC, + Importer.Import(D->getLocation()), + Name.getAsIdentifierInfo())) + return ToLabel; + + auto *Label = cast_or_null<LabelStmt>(Importer.Import(D->getStmt())); if (!Label) return nullptr; @@ -1727,22 +2082,22 @@ Decl *ASTNodeImporter::VisitEnumDecl(EnumDecl *D) { SmallVector<NamedDecl *, 4> ConflictingDecls; SmallVector<NamedDecl *, 2> FoundDecls; DC->getRedeclContext()->localUncachedLookup(SearchName, FoundDecls); - for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { - if (!FoundDecls[I]->isInIdentifierNamespace(IDNS)) + for (auto *FoundDecl : FoundDecls) { + if (!FoundDecl->isInIdentifierNamespace(IDNS)) continue; - Decl *Found = FoundDecls[I]; - if (TypedefNameDecl *Typedef = dyn_cast<TypedefNameDecl>(Found)) { - if (const TagType *Tag = Typedef->getUnderlyingType()->getAs<TagType>()) + Decl *Found = FoundDecl; + if (auto *Typedef = dyn_cast<TypedefNameDecl>(Found)) { + if (const auto *Tag = Typedef->getUnderlyingType()->getAs<TagType>()) Found = Tag->getDecl(); } - if (EnumDecl *FoundEnum = dyn_cast<EnumDecl>(Found)) { + if (auto *FoundEnum = dyn_cast<EnumDecl>(Found)) { if (IsStructuralMatch(D, FoundEnum)) - return Importer.Imported(D, FoundEnum); + return Importer.MapImported(D, FoundEnum); } - ConflictingDecls.push_back(FoundDecls[I]); + ConflictingDecls.push_back(FoundDecl); } if (!ConflictingDecls.empty()) { @@ -1751,18 +2106,19 @@ Decl *ASTNodeImporter::VisitEnumDecl(EnumDecl *D) { ConflictingDecls.size()); } } - + // Create the enum declaration. - EnumDecl *D2 = EnumDecl::Create(Importer.getToContext(), DC, - Importer.Import(D->getLocStart()), - Loc, Name.getAsIdentifierInfo(), nullptr, - D->isScoped(), D->isScopedUsingClassTag(), - D->isFixed()); + EnumDecl *D2; + if (GetImportedOrCreateDecl( + D2, D, Importer.getToContext(), DC, Importer.Import(D->getLocStart()), + Loc, Name.getAsIdentifierInfo(), nullptr, D->isScoped(), + D->isScopedUsingClassTag(), D->isFixed())) + return D2; + // Import the qualifier, if any. D2->setQualifierInfo(Importer.Import(D->getQualifierLoc())); D2->setAccess(D->getAccess()); D2->setLexicalDeclContext(LexicalDC); - Importer.Imported(D, D2); LexicalDC->addDeclInternal(D2); // Import the integer type. @@ -1783,14 +2139,20 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { // but this particular declaration is not that definition, import the // definition and map to that. TagDecl *Definition = D->getDefinition(); - if (Definition && Definition != D) { + if (Definition && Definition != D && + // In contrast to a normal CXXRecordDecl, the implicit + // CXXRecordDecl of ClassTemplateSpecializationDecl is its redeclaration. + // The definition of the implicit CXXRecordDecl in this case is the + // ClassTemplateSpecializationDecl itself. Thus, we start with an extra + // condition in order to be able to import the implict Decl. + !D->isImplicit()) { Decl *ImportedDef = Importer.Import(Definition); if (!ImportedDef) return nullptr; - return Importer.Imported(D, ImportedDef); + return Importer.MapImported(D, ImportedDef); } - + // Import the major distinguishing characteristics of this record. DeclContext *DC, *LexicalDC; DeclarationName Name; @@ -1824,30 +2186,27 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { D->getASTContext().getExternalSource()->CompleteType(D); } - for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { - if (!FoundDecls[I]->isInIdentifierNamespace(IDNS)) + for (auto *FoundDecl : FoundDecls) { + if (!FoundDecl->isInIdentifierNamespace(IDNS)) continue; - Decl *Found = FoundDecls[I]; - if (TypedefNameDecl *Typedef = dyn_cast<TypedefNameDecl>(Found)) { - if (const TagType *Tag = Typedef->getUnderlyingType()->getAs<TagType>()) + Decl *Found = FoundDecl; + if (auto *Typedef = dyn_cast<TypedefNameDecl>(Found)) { + if (const auto *Tag = Typedef->getUnderlyingType()->getAs<TagType>()) Found = Tag->getDecl(); } - - if (RecordDecl *FoundRecord = dyn_cast<RecordDecl>(Found)) { - if (D->isAnonymousStructOrUnion() && - FoundRecord->isAnonymousStructOrUnion()) { - // If both anonymous structs/unions are in a record context, make sure - // they occur in the same location in the context records. - if (Optional<unsigned> Index1 = - StructuralEquivalenceContext::findUntaggedStructOrUnionIndex( - D)) { - if (Optional<unsigned> Index2 = StructuralEquivalenceContext:: - findUntaggedStructOrUnionIndex(FoundRecord)) { - if (*Index1 != *Index2) - continue; - } - } + + if (D->getDescribedTemplate()) { + if (auto *Template = dyn_cast<ClassTemplateDecl>(Found)) + Found = Template->getTemplatedDecl(); + else + continue; + } + + if (auto *FoundRecord = dyn_cast<RecordDecl>(Found)) { + if (!SearchName) { + if (!IsStructuralMatch(D, FoundRecord, false)) + continue; } PrevDecl = FoundRecord; @@ -1861,8 +2220,19 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { // The record types structurally match, or the "from" translation // unit only had a forward declaration anyway; call it the same // function. - // FIXME: For C++, we should also merge methods here. - return Importer.Imported(D, 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 (D->isCompleteDefinition() && !Importer.isMinimalImport()) + // FoundDef may not have every implicit method that D has + // because implicit methods are created only if they are used. + ImportImplicitMethods(DCXX, FoundCXX); + } + return FoundDef; } } else if (!D->isCompleteDefinition()) { // We have a forward declaration of this type, so adopt that forward @@ -1889,7 +2259,7 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { } } - ConflictingDecls.push_back(FoundDecls[I]); + ConflictingDecls.push_back(FoundDecl); } if (!ConflictingDecls.empty() && SearchName) { @@ -1904,53 +2274,80 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { SourceLocation StartLoc = Importer.Import(D->getLocStart()); if (!D2) { CXXRecordDecl *D2CXX = nullptr; - if (CXXRecordDecl *DCXX = llvm::dyn_cast<CXXRecordDecl>(D)) { + if (auto *DCXX = dyn_cast<CXXRecordDecl>(D)) { if (DCXX->isLambda()) { TypeSourceInfo *TInfo = Importer.Import(DCXX->getLambdaTypeInfo()); - D2CXX = CXXRecordDecl::CreateLambda(Importer.getToContext(), - DC, TInfo, Loc, - DCXX->isDependentLambda(), - DCXX->isGenericLambda(), - DCXX->getLambdaCaptureDefault()); + if (GetImportedOrCreateSpecialDecl( + D2CXX, CXXRecordDecl::CreateLambda, D, Importer.getToContext(), + DC, TInfo, Loc, DCXX->isDependentLambda(), + DCXX->isGenericLambda(), DCXX->getLambdaCaptureDefault())) + return D2CXX; Decl *CDecl = Importer.Import(DCXX->getLambdaContextDecl()); if (DCXX->getLambdaContextDecl() && !CDecl) return nullptr; D2CXX->setLambdaMangling(DCXX->getLambdaManglingNumber(), CDecl); - } else if (DCXX->isInjectedClassName()) { - // We have to be careful to do a similar dance to the one in - // Sema::ActOnStartCXXMemberDeclarations - CXXRecordDecl *const PrevDecl = nullptr; - const bool DelayTypeCreation = true; - D2CXX = CXXRecordDecl::Create( - Importer.getToContext(), D->getTagKind(), DC, StartLoc, Loc, - Name.getAsIdentifierInfo(), PrevDecl, DelayTypeCreation); - Importer.getToContext().getTypeDeclType( - D2CXX, llvm::dyn_cast<CXXRecordDecl>(DC)); + } else if (DCXX->isInjectedClassName()) { + // We have to be careful to do a similar dance to the one in + // Sema::ActOnStartCXXMemberDeclarations + CXXRecordDecl *const PrevDecl = nullptr; + const bool DelayTypeCreation = true; + if (GetImportedOrCreateDecl(D2CXX, D, Importer.getToContext(), + D->getTagKind(), DC, StartLoc, Loc, + Name.getAsIdentifierInfo(), PrevDecl, + DelayTypeCreation)) + return D2CXX; + Importer.getToContext().getTypeDeclType( + D2CXX, dyn_cast<CXXRecordDecl>(DC)); } else { - D2CXX = CXXRecordDecl::Create(Importer.getToContext(), - D->getTagKind(), - DC, StartLoc, Loc, - Name.getAsIdentifierInfo()); + if (GetImportedOrCreateDecl(D2CXX, D, Importer.getToContext(), + D->getTagKind(), DC, StartLoc, Loc, + Name.getAsIdentifierInfo(), + cast_or_null<CXXRecordDecl>(PrevDecl))) + return D2CXX; } + D2 = D2CXX; D2->setAccess(D->getAccess()); - - Importer.Imported(D, D2); + D2->setLexicalDeclContext(LexicalDC); + if (!DCXX->getDescribedClassTemplate() || DCXX->isImplicit()) + LexicalDC->addDeclInternal(D2); if (ClassTemplateDecl *FromDescribed = DCXX->getDescribedClassTemplate()) { - ClassTemplateDecl *ToDescribed = cast_or_null<ClassTemplateDecl>( - Importer.Import(FromDescribed)); + auto *ToDescribed = cast_or_null<ClassTemplateDecl>( + Importer.Import(FromDescribed)); if (!ToDescribed) return nullptr; D2CXX->setDescribedClassTemplate(ToDescribed); - + if (!DCXX->isInjectedClassName()) { + // 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; + } + } + D2CXX->setTypeForDecl(nullptr); + Importer.getToContext().getInjectedClassNameType(D2CXX, + ToDescribed->getInjectedClassNameSpecialization()); + if (Injected) { + Injected->setTypeForDecl(nullptr); + Importer.getToContext().getTypeDeclType(Injected, D2CXX); + } + } } else if (MemberSpecializationInfo *MemberInfo = DCXX->getMemberSpecializationInfo()) { TemplateSpecializationKind SK = MemberInfo->getTemplateSpecializationKind(); CXXRecordDecl *FromInst = DCXX->getInstantiatedFromMemberClass(); - CXXRecordDecl *ToInst = + auto *ToInst = cast_or_null<CXXRecordDecl>(Importer.Import(FromInst)); if (FromInst && !ToInst) return nullptr; @@ -1958,24 +2355,21 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { D2CXX->getMemberSpecializationInfo()->setPointOfInstantiation( Importer.Import(MemberInfo->getPointOfInstantiation())); } - } else { - D2 = RecordDecl::Create(Importer.getToContext(), D->getTagKind(), - DC, StartLoc, Loc, Name.getAsIdentifierInfo()); + if (GetImportedOrCreateDecl(D2, D, Importer.getToContext(), + D->getTagKind(), DC, StartLoc, Loc, + Name.getAsIdentifierInfo(), PrevDecl)) + return D2; + D2->setLexicalDeclContext(LexicalDC); + LexicalDC->addDeclInternal(D2); } - + D2->setQualifierInfo(Importer.Import(D->getQualifierLoc())); - D2->setLexicalDeclContext(LexicalDC); - LexicalDC->addDeclInternal(D2); if (D->isAnonymousStructOrUnion()) D2->setAnonymousStructOrUnion(true); - if (PrevDecl) { - // FIXME: do this for all Redeclarables, not just RecordDecls. - D2->setPreviousDecl(PrevDecl); - } } - - Importer.Imported(D, D2); + + Importer.MapImported(D, D2); if (D->isCompleteDefinition() && ImportDefinition(D, D2, IDK_Default)) return nullptr; @@ -2005,17 +2399,16 @@ Decl *ASTNodeImporter::VisitEnumConstantDecl(EnumConstantDecl *D) { unsigned IDNS = Decl::IDNS_Ordinary; SmallVector<NamedDecl *, 2> FoundDecls; DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls); - for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { - if (!FoundDecls[I]->isInIdentifierNamespace(IDNS)) + for (auto *FoundDecl : FoundDecls) { + if (!FoundDecl->isInIdentifierNamespace(IDNS)) continue; - if (EnumConstantDecl *FoundEnumConstant - = dyn_cast<EnumConstantDecl>(FoundDecls[I])) { + if (auto *FoundEnumConstant = dyn_cast<EnumConstantDecl>(FoundDecl)) { if (IsStructuralMatch(D, FoundEnumConstant)) - return Importer.Imported(D, FoundEnumConstant); + return Importer.MapImported(D, FoundEnumConstant); } - ConflictingDecls.push_back(FoundDecls[I]); + ConflictingDecls.push_back(FoundDecl); } if (!ConflictingDecls.empty()) { @@ -2031,18 +2424,120 @@ Decl *ASTNodeImporter::VisitEnumConstantDecl(EnumConstantDecl *D) { if (D->getInitExpr() && !Init) return nullptr; - EnumConstantDecl *ToEnumerator - = EnumConstantDecl::Create(Importer.getToContext(), cast<EnumDecl>(DC), Loc, - Name.getAsIdentifierInfo(), T, - Init, D->getInitVal()); + EnumConstantDecl *ToEnumerator; + if (GetImportedOrCreateDecl( + ToEnumerator, D, Importer.getToContext(), cast<EnumDecl>(DC), Loc, + Name.getAsIdentifierInfo(), T, Init, D->getInitVal())) + return ToEnumerator; + ToEnumerator->setAccess(D->getAccess()); ToEnumerator->setLexicalDeclContext(LexicalDC); - Importer.Imported(D, ToEnumerator); LexicalDC->addDeclInternal(ToEnumerator); return ToEnumerator; } +bool ASTNodeImporter::ImportTemplateInformation(FunctionDecl *FromFD, + FunctionDecl *ToFD) { + switch (FromFD->getTemplatedKind()) { + case FunctionDecl::TK_NonTemplate: + case FunctionDecl::TK_FunctionTemplate: + return false; + + case FunctionDecl::TK_MemberSpecialization: { + auto *InstFD = cast_or_null<FunctionDecl>( + Importer.Import(FromFD->getInstantiatedFromMemberFunction())); + if (!InstFD) + return true; + + TemplateSpecializationKind TSK = FromFD->getTemplateSpecializationKind(); + SourceLocation POI = Importer.Import( + FromFD->getMemberSpecializationInfo()->getPointOfInstantiation()); + ToFD->setInstantiationOfMemberFunction(InstFD, TSK); + ToFD->getMemberSpecializationInfo()->setPointOfInstantiation(POI); + return false; + } + + case FunctionDecl::TK_FunctionTemplateSpecialization: { + FunctionTemplateDecl* Template; + OptionalTemplateArgsTy ToTemplArgs; + std::tie(Template, ToTemplArgs) = + ImportFunctionTemplateWithTemplateArgsFromSpecialization(FromFD); + if (!Template || !ToTemplArgs) + return true; + + TemplateArgumentList *ToTAList = TemplateArgumentList::CreateCopy( + Importer.getToContext(), *ToTemplArgs); + + auto *FTSInfo = FromFD->getTemplateSpecializationInfo(); + TemplateArgumentListInfo ToTAInfo; + const auto *FromTAArgsAsWritten = FTSInfo->TemplateArgumentsAsWritten; + if (FromTAArgsAsWritten) + if (ImportTemplateArgumentListInfo(*FromTAArgsAsWritten, ToTAInfo)) + return true; + + SourceLocation POI = Importer.Import(FTSInfo->getPointOfInstantiation()); + + TemplateSpecializationKind TSK = FTSInfo->getTemplateSpecializationKind(); + ToFD->setFunctionTemplateSpecialization( + Template, ToTAList, /* InsertPos= */ nullptr, + TSK, FromTAArgsAsWritten ? &ToTAInfo : nullptr, POI); + return false; + } + + case FunctionDecl::TK_DependentFunctionTemplateSpecialization: { + auto *FromInfo = FromFD->getDependentSpecializationInfo(); + UnresolvedSet<8> TemplDecls; + unsigned NumTemplates = FromInfo->getNumTemplates(); + for (unsigned I = 0; I < NumTemplates; I++) { + if (auto *ToFTD = cast_or_null<FunctionTemplateDecl>( + Importer.Import(FromInfo->getTemplate(I)))) + TemplDecls.addDecl(ToFTD); + else + return true; + } + + // Import TemplateArgumentListInfo. + TemplateArgumentListInfo ToTAInfo; + if (ImportTemplateArgumentListInfo( + FromInfo->getLAngleLoc(), FromInfo->getRAngleLoc(), + llvm::makeArrayRef(FromInfo->getTemplateArgs(), + FromInfo->getNumTemplateArgs()), + ToTAInfo)) + return true; + + ToFD->setDependentTemplateSpecialization(Importer.getToContext(), + TemplDecls, ToTAInfo); + return false; + } + } + llvm_unreachable("All cases should be covered!"); +} + +FunctionDecl * +ASTNodeImporter::FindFunctionTemplateSpecialization(FunctionDecl *FromFD) { + FunctionTemplateDecl* Template; + OptionalTemplateArgsTy ToTemplArgs; + std::tie(Template, ToTemplArgs) = + ImportFunctionTemplateWithTemplateArgsFromSpecialization(FromFD); + if (!Template || !ToTemplArgs) + return nullptr; + + void *InsertPos = nullptr; + auto *FoundSpec = Template->findSpecialization(*ToTemplArgs, InsertPos); + return FoundSpec; +} + Decl *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) + if (!Importer.Import(*RedeclIt)) + return nullptr; + assert(*RedeclIt == D); + // Import the major distinguishing characteristics of this function. DeclContext *DC, *LexicalDC; DeclarationName Name; @@ -2053,33 +2548,54 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { if (ToD) return ToD; - const FunctionDecl *FoundWithoutBody = nullptr; - + const 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 localUncachedLookup + // 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) { + if (FunctionDecl *FoundFunction = FindFunctionTemplateSpecialization(D)) { + if (D->doesThisDeclarationHaveABody() && + FoundFunction->hasBody()) + return Importer.Imported(D, FoundFunction); + 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. - if (!LexicalDC->isFunctionOrMethod()) { + else if (!LexicalDC->isFunctionOrMethod()) { SmallVector<NamedDecl *, 4> ConflictingDecls; - unsigned IDNS = Decl::IDNS_Ordinary; + unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_OrdinaryFriend; SmallVector<NamedDecl *, 2> FoundDecls; DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls); - for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { - if (!FoundDecls[I]->isInIdentifierNamespace(IDNS)) + for (auto *FoundDecl : FoundDecls) { + if (!FoundDecl->isInIdentifierNamespace(IDNS)) continue; - if (FunctionDecl *FoundFunction = dyn_cast<FunctionDecl>(FoundDecls[I])) { + // If template was found, look at the templated function. + if (FromFT) { + if (auto *Template = dyn_cast<FunctionTemplateDecl>(FoundDecl)) + FoundDecl = Template->getTemplatedDecl(); + else + continue; + } + + if (auto *FoundFunction = dyn_cast<FunctionDecl>(FoundDecl)) { if (FoundFunction->hasExternalFormalLinkage() && D->hasExternalFormalLinkage()) { - if (Importer.IsStructurallyEquivalent(D->getType(), - FoundFunction->getType())) { - // FIXME: Actually try to merge the body and other attributes. - const FunctionDecl *FromBodyDecl = nullptr; - D->hasBody(FromBodyDecl); - if (D == FromBodyDecl && !FoundFunction->hasBody()) { - // This function is needed to merge completely. - FoundWithoutBody = FoundFunction; - break; + if (IsStructuralMatch(D, FoundFunction)) { + const FunctionDecl *Definition = nullptr; + if (D->doesThisDeclarationHaveABody() && + FoundFunction->hasBody(Definition)) { + return Importer.MapImported( + D, const_cast<FunctionDecl *>(Definition)); } - return Importer.Imported(D, FoundFunction); + FoundByLookup = FoundFunction; + break; } // FIXME: Check for overloading more carefully, e.g., by boosting @@ -2098,7 +2614,7 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { } } - ConflictingDecls.push_back(FoundDecls[I]); + ConflictingDecls.push_back(FoundDecl); } if (!ConflictingDecls.empty()) { @@ -2117,8 +2633,7 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { QualType FromTy = D->getType(); bool usedDifferentExceptionSpec = false; - if (const FunctionProtoType * - FromFPT = D->getType()->getAs<FunctionProtoType>()) { + if (const auto *FromFPT = D->getType()->getAs<FunctionProtoType>()) { FunctionProtoType::ExtProtoInfo FromEPI = FromFPT->getExtProtoInfo(); // FunctionProtoType::ExtProtoInfo's ExceptionSpecDecl can point to the // FunctionDecl that we are importing the FunctionProtoType for. @@ -2142,75 +2657,66 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { // Import the function parameters. SmallVector<ParmVarDecl *, 8> Parameters; for (auto P : D->parameters()) { - ParmVarDecl *ToP = cast_or_null<ParmVarDecl>(Importer.Import(P)); + auto *ToP = cast_or_null<ParmVarDecl>(Importer.Import(P)); if (!ToP) return nullptr; Parameters.push_back(ToP); } - // Create the imported function. TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo()); + if (D->getTypeSourceInfo() && !TInfo) + return nullptr; + + // Create the imported function. FunctionDecl *ToFunction = nullptr; SourceLocation InnerLocStart = Importer.Import(D->getInnerLocStart()); - if (CXXConstructorDecl *FromConstructor = dyn_cast<CXXConstructorDecl>(D)) { - ToFunction = CXXConstructorDecl::Create(Importer.getToContext(), - cast<CXXRecordDecl>(DC), - InnerLocStart, - NameInfo, T, TInfo, - FromConstructor->isExplicit(), - D->isInlineSpecified(), - D->isImplicit(), - D->isConstexpr()); + if (auto *FromConstructor = dyn_cast<CXXConstructorDecl>(D)) { + if (GetImportedOrCreateDecl<CXXConstructorDecl>( + ToFunction, D, Importer.getToContext(), cast<CXXRecordDecl>(DC), + InnerLocStart, NameInfo, T, TInfo, FromConstructor->isExplicit(), + D->isInlineSpecified(), D->isImplicit(), D->isConstexpr())) + return ToFunction; if (unsigned NumInitializers = FromConstructor->getNumCtorInitializers()) { SmallVector<CXXCtorInitializer *, 4> CtorInitializers; - for (CXXCtorInitializer *I : FromConstructor->inits()) { - CXXCtorInitializer *ToI = - cast_or_null<CXXCtorInitializer>(Importer.Import(I)); + for (auto *I : FromConstructor->inits()) { + auto *ToI = cast_or_null<CXXCtorInitializer>(Importer.Import(I)); if (!ToI && I) return nullptr; CtorInitializers.push_back(ToI); } - CXXCtorInitializer **Memory = + auto **Memory = new (Importer.getToContext()) CXXCtorInitializer *[NumInitializers]; std::copy(CtorInitializers.begin(), CtorInitializers.end(), Memory); - CXXConstructorDecl *ToCtor = llvm::cast<CXXConstructorDecl>(ToFunction); + auto *ToCtor = cast<CXXConstructorDecl>(ToFunction); ToCtor->setCtorInitializers(Memory); ToCtor->setNumCtorInitializers(NumInitializers); } } else if (isa<CXXDestructorDecl>(D)) { - ToFunction = CXXDestructorDecl::Create(Importer.getToContext(), - cast<CXXRecordDecl>(DC), - InnerLocStart, - NameInfo, T, TInfo, - D->isInlineSpecified(), - D->isImplicit()); - } else if (CXXConversionDecl *FromConversion - = dyn_cast<CXXConversionDecl>(D)) { - ToFunction = CXXConversionDecl::Create(Importer.getToContext(), - cast<CXXRecordDecl>(DC), - InnerLocStart, - NameInfo, T, TInfo, - D->isInlineSpecified(), - FromConversion->isExplicit(), - D->isConstexpr(), - Importer.Import(D->getLocEnd())); - } else if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) { - ToFunction = CXXMethodDecl::Create(Importer.getToContext(), - cast<CXXRecordDecl>(DC), - InnerLocStart, - NameInfo, T, TInfo, - Method->getStorageClass(), - Method->isInlineSpecified(), - D->isConstexpr(), - Importer.Import(D->getLocEnd())); + if (GetImportedOrCreateDecl<CXXDestructorDecl>( + ToFunction, D, Importer.getToContext(), cast<CXXRecordDecl>(DC), + InnerLocStart, NameInfo, T, TInfo, D->isInlineSpecified(), + D->isImplicit())) + return ToFunction; + } else if (CXXConversionDecl *FromConversion = + dyn_cast<CXXConversionDecl>(D)) { + if (GetImportedOrCreateDecl<CXXConversionDecl>( + ToFunction, D, Importer.getToContext(), cast<CXXRecordDecl>(DC), + InnerLocStart, NameInfo, T, TInfo, D->isInlineSpecified(), + FromConversion->isExplicit(), D->isConstexpr(), SourceLocation())) + return ToFunction; + } else if (auto *Method = dyn_cast<CXXMethodDecl>(D)) { + if (GetImportedOrCreateDecl<CXXMethodDecl>( + ToFunction, D, Importer.getToContext(), cast<CXXRecordDecl>(DC), + InnerLocStart, NameInfo, T, TInfo, Method->getStorageClass(), + Method->isInlineSpecified(), D->isConstexpr(), SourceLocation())) + return ToFunction; } else { - ToFunction = FunctionDecl::Create(Importer.getToContext(), DC, - InnerLocStart, - NameInfo, T, TInfo, D->getStorageClass(), - D->isInlineSpecified(), - D->hasWrittenPrototype(), - D->isConstexpr()); + if (GetImportedOrCreateDecl(ToFunction, D, Importer.getToContext(), DC, + InnerLocStart, NameInfo, T, TInfo, + D->getStorageClass(), D->isInlineSpecified(), + D->hasWrittenPrototype(), D->isConstexpr())) + return ToFunction; } // Import the qualifier, if any. @@ -2220,21 +2726,31 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { ToFunction->setVirtualAsWritten(D->isVirtualAsWritten()); ToFunction->setTrivial(D->isTrivial()); ToFunction->setPure(D->isPure()); - Importer.Imported(D, ToFunction); + ToFunction->setRangeEnd(Importer.Import(D->getLocEnd())); // Set the parameters. - for (unsigned I = 0, N = Parameters.size(); I != N; ++I) { - Parameters[I]->setOwningFunction(ToFunction); - ToFunction->addDeclInternal(Parameters[I]); + for (auto *Param : Parameters) { + Param->setOwningFunction(ToFunction); + ToFunction->addDeclInternal(Param); } ToFunction->setParams(Parameters); - if (FoundWithoutBody) { + if (FoundByLookup) { auto *Recent = const_cast<FunctionDecl *>( - FoundWithoutBody->getMostRecentDecl()); + FoundByLookup->getMostRecentDecl()); ToFunction->setPreviousDecl(Recent); } + // We need to complete creation of FunctionProtoTypeLoc manually with setting + // params it refers to. + if (TInfo) { + if (auto ProtoLoc = + TInfo->getTypeLoc().IgnoreParens().getAs<FunctionProtoTypeLoc>()) { + for (unsigned I = 0, N = Parameters.size(); I != N; ++I) + ProtoLoc.setParam(I, Parameters[I]); + } + } + if (usedDifferentExceptionSpec) { // Update FunctionProtoType::ExtProtoInfo. QualType T = Importer.Import(D->getType()); @@ -2243,17 +2759,47 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { ToFunction->setType(T); } - // Import the body, if any. - if (Stmt *FromBody = D->getBody()) { - if (Stmt *ToBody = Importer.Import(FromBody)) { - ToFunction->setBody(ToBody); + // Import the describing template function, if any. + if (FromFT) + if (!Importer.Import(FromFT)) + return nullptr; + + if (D->doesThisDeclarationHaveABody()) { + if (Stmt *FromBody = D->getBody()) { + if (Stmt *ToBody = Importer.Import(FromBody)) { + ToFunction->setBody(ToBody); + } } } // FIXME: Other bits to merge? - // Add this function to the lexical context. - LexicalDC->addDeclInternal(ToFunction); + // If it is a template, import all related things. + if (ImportTemplateInformation(D, ToFunction)) + return nullptr; + + bool IsFriend = D->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend); + + // TODO Can we generalize this approach to other AST nodes as well? + if (D->getDeclContext()->containsDeclAndLoad(D)) + DC->addDeclInternal(ToFunction); + if (DC != LexicalDC && D->getLexicalDeclContext()->containsDeclAndLoad(D)) + LexicalDC->addDeclInternal(ToFunction); + + // Friend declaration's lexical context is the befriending class, but the + // semantic context is the enclosing scope of the befriending class. + // We want the friend functions to be found in the semantic context by lookup. + // FIXME should we handle this generically in VisitFriendDecl? + // In Other cases when LexicalDC != DC we don't want it to be added, + // e.g out-of-class definitions like void B::f() {} . + if (LexicalDC != DC && IsFriend) { + DC->makeDeclVisibleInContext(ToFunction); + } + + // Import the rest of the chain. I.e. import all subsequent declarations. + for (++RedeclIt; RedeclIt != Redecls.end(); ++RedeclIt) + if (!Importer.Import(*RedeclIt)) + return nullptr; if (auto *FromCXXMethod = dyn_cast<CXXMethodDecl>(D)) ImportOverrides(cast<CXXMethodDecl>(ToFunction), FromCXXMethod); @@ -2278,7 +2824,7 @@ Decl *ASTNodeImporter::VisitCXXConversionDecl(CXXConversionDecl *D) { } static unsigned getFieldIndex(Decl *F) { - RecordDecl *Owner = dyn_cast<RecordDecl>(F->getDeclContext()); + auto *Owner = dyn_cast<RecordDecl>(F->getDeclContext()); if (!Owner) return 0; @@ -2308,15 +2854,15 @@ Decl *ASTNodeImporter::VisitFieldDecl(FieldDecl *D) { // Determine whether we've already imported this field. SmallVector<NamedDecl *, 2> FoundDecls; DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls); - for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { - if (FieldDecl *FoundField = dyn_cast<FieldDecl>(FoundDecls[I])) { + for (auto *FoundDecl : FoundDecls) { + if (auto *FoundField = dyn_cast<FieldDecl>(FoundDecl)) { // For anonymous fields, match up by index. if (!Name && getFieldIndex(D) != getFieldIndex(FoundField)) continue; if (Importer.IsStructurallyEquivalent(D->getType(), FoundField->getType())) { - Importer.Imported(D, FoundField); + Importer.MapImported(D, FoundField); return FoundField; } @@ -2338,11 +2884,13 @@ Decl *ASTNodeImporter::VisitFieldDecl(FieldDecl *D) { if (!BitWidth && D->getBitWidth()) return nullptr; - FieldDecl *ToField = FieldDecl::Create(Importer.getToContext(), DC, - Importer.Import(D->getInnerLocStart()), - Loc, Name.getAsIdentifierInfo(), - T, TInfo, BitWidth, D->isMutable(), - D->getInClassInitStyle()); + FieldDecl *ToField; + if (GetImportedOrCreateDecl(ToField, D, Importer.getToContext(), DC, + Importer.Import(D->getInnerLocStart()), Loc, + Name.getAsIdentifierInfo(), T, TInfo, BitWidth, + D->isMutable(), D->getInClassInitStyle())) + return ToField; + ToField->setAccess(D->getAccess()); ToField->setLexicalDeclContext(LexicalDC); if (Expr *FromInitializer = D->getInClassInitializer()) { @@ -2353,7 +2901,6 @@ Decl *ASTNodeImporter::VisitFieldDecl(FieldDecl *D) { return nullptr; } ToField->setImplicit(D->isImplicit()); - Importer.Imported(D, ToField); LexicalDC->addDeclInternal(ToField); return ToField; } @@ -2373,8 +2920,7 @@ Decl *ASTNodeImporter::VisitIndirectFieldDecl(IndirectFieldDecl *D) { SmallVector<NamedDecl *, 2> FoundDecls; DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls); for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { - if (IndirectFieldDecl *FoundField - = dyn_cast<IndirectFieldDecl>(FoundDecls[I])) { + if (auto *FoundField = dyn_cast<IndirectFieldDecl>(FoundDecls[I])) { // For anonymous indirect fields, match up by index. if (!Name && getFieldIndex(D) != getFieldIndex(FoundField)) continue; @@ -2382,7 +2928,7 @@ Decl *ASTNodeImporter::VisitIndirectFieldDecl(IndirectFieldDecl *D) { if (Importer.IsStructurallyEquivalent(D->getType(), FoundField->getType(), !Name.isEmpty())) { - Importer.Imported(D, FoundField); + Importer.MapImported(D, FoundField); return FoundField; } @@ -2403,8 +2949,8 @@ Decl *ASTNodeImporter::VisitIndirectFieldDecl(IndirectFieldDecl *D) { if (T.isNull()) return nullptr; - NamedDecl **NamedChain = - new (Importer.getToContext())NamedDecl*[D->getChainingSize()]; + auto **NamedChain = + new (Importer.getToContext()) NamedDecl*[D->getChainingSize()]; unsigned i = 0; for (auto *PI : D->chain()) { @@ -2414,16 +2960,18 @@ Decl *ASTNodeImporter::VisitIndirectFieldDecl(IndirectFieldDecl *D) { NamedChain[i++] = cast<NamedDecl>(D); } - IndirectFieldDecl *ToIndirectField = IndirectFieldDecl::Create( - Importer.getToContext(), DC, Loc, Name.getAsIdentifierInfo(), T, - {NamedChain, D->getChainingSize()}); + llvm::MutableArrayRef<NamedDecl *> CH = {NamedChain, D->getChainingSize()}; + IndirectFieldDecl *ToIndirectField; + if (GetImportedOrCreateDecl(ToIndirectField, D, Importer.getToContext(), DC, + Loc, Name.getAsIdentifierInfo(), T, CH)) + // FIXME here we leak `NamedChain` which is allocated before + return ToIndirectField; - for (const auto *Attr : D->attrs()) - ToIndirectField->addAttr(Attr->clone(Importer.getToContext())); + for (const auto *A : D->attrs()) + ToIndirectField->addAttr(Importer.Import(A)); ToIndirectField->setAccess(D->getAccess()); ToIndirectField->setLexicalDeclContext(LexicalDC); - Importer.Imported(D, ToIndirectField); LexicalDC->addDeclInternal(ToIndirectField); return ToIndirectField; } @@ -2440,37 +2988,38 @@ Decl *ASTNodeImporter::VisitFriendDecl(FriendDecl *D) { // FriendDecl is not a NamedDecl so we cannot use localUncachedLookup. auto *RD = cast<CXXRecordDecl>(DC); FriendDecl *ImportedFriend = RD->getFirstFriend(); - StructuralEquivalenceContext Context( - Importer.getFromContext(), Importer.getToContext(), - Importer.getNonEquivalentDecls(), false, false); while (ImportedFriend) { if (D->getFriendDecl() && ImportedFriend->getFriendDecl()) { - if (Context.IsStructurallyEquivalent(D->getFriendDecl(), - ImportedFriend->getFriendDecl())) - return Importer.Imported(D, ImportedFriend); + 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.Imported(D, ImportedFriend); + return Importer.MapImported(D, ImportedFriend); } ImportedFriend = ImportedFriend->getNextFriend(); } // Not found. Create it. FriendDecl::FriendUnion ToFU; - if (NamedDecl *FriendD = D->getFriendDecl()) - ToFU = cast_or_null<NamedDecl>(Importer.Import(FriendD)); - else + if (NamedDecl *FriendD = D->getFriendDecl()) { + auto *ToFriendD = cast_or_null<NamedDecl>(Importer.Import(FriendD)); + if (ToFriendD && FriendD->getFriendObjectKind() != Decl::FOK_None && + !(FriendD->isInIdentifierNamespace(Decl::IDNS_NonMemberOperator))) + ToFriendD->setObjectOfFriendDecl(false); + + ToFU = ToFriendD; + } else // The friend is a type, not a decl. ToFU = Importer.Import(D->getFriendType()); if (!ToFU) return nullptr; SmallVector<TemplateParameterList *, 1> ToTPLists(D->NumTPLists); - TemplateParameterList **FromTPLists = - D->getTrailingObjects<TemplateParameterList *>(); + auto **FromTPLists = D->getTrailingObjects<TemplateParameterList *>(); for (unsigned I = 0; I < D->NumTPLists; I++) { TemplateParameterList *List = ImportTemplateParameterList(FromTPLists[I]); if (!List) @@ -2478,13 +3027,11 @@ Decl *ASTNodeImporter::VisitFriendDecl(FriendDecl *D) { ToTPLists[I] = List; } - FriendDecl *FrD = FriendDecl::Create(Importer.getToContext(), DC, - Importer.Import(D->getLocation()), - ToFU, Importer.Import(D->getFriendLoc()), - ToTPLists); - - Importer.Imported(D, FrD); - RD->pushFriendDecl(FrD); + FriendDecl *FrD; + if (GetImportedOrCreateDecl(FrD, D, Importer.getToContext(), DC, + Importer.Import(D->getLocation()), ToFU, + Importer.Import(D->getFriendLoc()), ToTPLists)) + return FrD; FrD->setAccess(D->getAccess()); FrD->setLexicalDeclContext(LexicalDC); @@ -2506,11 +3053,11 @@ Decl *ASTNodeImporter::VisitObjCIvarDecl(ObjCIvarDecl *D) { // Determine whether we've already imported this ivar SmallVector<NamedDecl *, 2> FoundDecls; DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls); - for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { - if (ObjCIvarDecl *FoundIvar = dyn_cast<ObjCIvarDecl>(FoundDecls[I])) { + for (auto *FoundDecl : FoundDecls) { + if (auto *FoundIvar = dyn_cast<ObjCIvarDecl>(FoundDecl)) { if (Importer.IsStructurallyEquivalent(D->getType(), FoundIvar->getType())) { - Importer.Imported(D, FoundIvar); + Importer.MapImported(D, FoundIvar); return FoundIvar; } @@ -2532,17 +3079,17 @@ Decl *ASTNodeImporter::VisitObjCIvarDecl(ObjCIvarDecl *D) { if (!BitWidth && D->getBitWidth()) return nullptr; - ObjCIvarDecl *ToIvar = ObjCIvarDecl::Create(Importer.getToContext(), - cast<ObjCContainerDecl>(DC), - Importer.Import(D->getInnerLocStart()), - Loc, Name.getAsIdentifierInfo(), - T, TInfo, D->getAccessControl(), - BitWidth, D->getSynthesize()); + ObjCIvarDecl *ToIvar; + if (GetImportedOrCreateDecl( + ToIvar, D, Importer.getToContext(), cast<ObjCContainerDecl>(DC), + Importer.Import(D->getInnerLocStart()), Loc, + Name.getAsIdentifierInfo(), T, TInfo, D->getAccessControl(), BitWidth, + D->getSynthesize())) + return ToIvar; + ToIvar->setLexicalDeclContext(LexicalDC); - Importer.Imported(D, ToIvar); LexicalDC->addDeclInternal(ToIvar); return ToIvar; - } Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) { @@ -2564,11 +3111,11 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) { unsigned IDNS = Decl::IDNS_Ordinary; SmallVector<NamedDecl *, 2> FoundDecls; DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls); - for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { - if (!FoundDecls[I]->isInIdentifierNamespace(IDNS)) + for (auto *FoundDecl : FoundDecls) { + if (!FoundDecl->isInIdentifierNamespace(IDNS)) continue; - if (VarDecl *FoundVar = dyn_cast<VarDecl>(FoundDecls[I])) { + if (auto *FoundVar = dyn_cast<VarDecl>(FoundDecl)) { // We have found a variable that we may need to merge with. Check it. if (FoundVar->hasExternalFormalLinkage() && D->hasExternalFormalLinkage()) { @@ -2607,14 +3154,15 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) { } } - ConflictingDecls.push_back(FoundDecls[I]); + ConflictingDecls.push_back(FoundDecl); } if (MergeWithVar) { - // An equivalent variable with external linkage has been found. Link + // An equivalent variable with external linkage has been found. Link // the two declarations, then merge them. - Importer.Imported(D, MergeWithVar); - + Importer.MapImported(D, MergeWithVar); + updateFlags(D, MergeWithVar); + if (VarDecl *DDef = D->getDefinition()) { if (VarDecl *ExistingDef = MergeWithVar->getDefinition()) { Importer.ToDiag(ExistingDef->getLocation(), @@ -2651,20 +3199,20 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) { // Create the imported variable. TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo()); - VarDecl *ToVar = VarDecl::Create(Importer.getToContext(), DC, - Importer.Import(D->getInnerLocStart()), - Loc, Name.getAsIdentifierInfo(), - T, TInfo, - D->getStorageClass()); + VarDecl *ToVar; + if (GetImportedOrCreateDecl(ToVar, D, Importer.getToContext(), DC, + Importer.Import(D->getInnerLocStart()), Loc, + Name.getAsIdentifierInfo(), T, TInfo, + D->getStorageClass())) + return ToVar; + ToVar->setQualifierInfo(Importer.Import(D->getQualifierLoc())); ToVar->setAccess(D->getAccess()); ToVar->setLexicalDeclContext(LexicalDC); - Importer.Imported(D, ToVar); - LexicalDC->addDeclInternal(ToVar); - if (!D->isFileVarDecl() && - D->isUsed()) - ToVar->setIsUsed(); + // Templated declarations should never appear in the enclosing DeclContext. + if (!D->getDescribedVarTemplate()) + LexicalDC->addDeclInternal(ToVar); // Merge the initializer. if (ImportDefinition(D, ToVar)) @@ -2695,10 +3243,12 @@ Decl *ASTNodeImporter::VisitImplicitParamDecl(ImplicitParamDecl *D) { return nullptr; // Create the imported parameter. - auto *ToParm = ImplicitParamDecl::Create(Importer.getToContext(), DC, Loc, - Name.getAsIdentifierInfo(), T, - D->getParameterKind()); - return Importer.Imported(D, ToParm); + ImplicitParamDecl *ToParm = nullptr; + if (GetImportedOrCreateDecl(ToParm, D, Importer.getToContext(), DC, Loc, + Name.getAsIdentifierInfo(), T, + D->getParameterKind())) + return ToParm; + return ToParm; } Decl *ASTNodeImporter::VisitParmVarDecl(ParmVarDecl *D) { @@ -2721,11 +3271,13 @@ Decl *ASTNodeImporter::VisitParmVarDecl(ParmVarDecl *D) { // Create the imported parameter. TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo()); - ParmVarDecl *ToParm = ParmVarDecl::Create(Importer.getToContext(), DC, - Importer.Import(D->getInnerLocStart()), - Loc, Name.getAsIdentifierInfo(), - T, TInfo, D->getStorageClass(), - /*DefaultArg*/ nullptr); + ParmVarDecl *ToParm; + if (GetImportedOrCreateDecl(ToParm, D, Importer.getToContext(), DC, + Importer.Import(D->getInnerLocStart()), Loc, + Name.getAsIdentifierInfo(), T, TInfo, + D->getStorageClass(), + /*DefaultArg*/ nullptr)) + return ToParm; // Set the default argument. ToParm->setHasInheritedDefaultArg(D->hasInheritedDefaultArg()); @@ -2747,10 +3299,15 @@ Decl *ASTNodeImporter::VisitParmVarDecl(ParmVarDecl *D) { if (FromDefArg && !ToDefArg) return nullptr; - if (D->isUsed()) - ToParm->setIsUsed(); + if (D->isObjCMethodParameter()) { + ToParm->setObjCMethodScopeInfo(D->getFunctionScopeIndex()); + ToParm->setObjCDeclQualifier(D->getObjCDeclQualifier()); + } else { + ToParm->setScopeInfo(D->getFunctionScopeDepth(), + D->getFunctionScopeIndex()); + } - return Importer.Imported(D, ToParm); + return ToParm; } Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { @@ -2766,8 +3323,8 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { SmallVector<NamedDecl *, 2> FoundDecls; DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls); - for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { - if (ObjCMethodDecl *FoundMethod = dyn_cast<ObjCMethodDecl>(FoundDecls[I])) { + for (auto *FoundDecl : FoundDecls) { + if (auto *FoundMethod = dyn_cast<ObjCMethodDecl>(FoundDecl)) { if (FoundMethod->isInstanceMethod() != D->isInstanceMethod()) continue; @@ -2822,7 +3379,7 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { } // FIXME: Any other bits we need to merge? - return Importer.Imported(D, FoundMethod); + return Importer.MapImported(D, FoundMethod); } } @@ -2833,11 +3390,14 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { TypeSourceInfo *ReturnTInfo = Importer.Import(D->getReturnTypeSourceInfo()); - ObjCMethodDecl *ToMethod = ObjCMethodDecl::Create( - Importer.getToContext(), Loc, Importer.Import(D->getLocEnd()), - Name.getObjCSelector(), ResultTy, ReturnTInfo, DC, D->isInstanceMethod(), - D->isVariadic(), D->isPropertyAccessor(), D->isImplicit(), D->isDefined(), - D->getImplementationControl(), D->hasRelatedResultType()); + ObjCMethodDecl *ToMethod; + if (GetImportedOrCreateDecl( + ToMethod, D, Importer.getToContext(), Loc, + Importer.Import(D->getLocEnd()), Name.getObjCSelector(), ResultTy, + ReturnTInfo, DC, D->isInstanceMethod(), D->isVariadic(), + D->isPropertyAccessor(), D->isImplicit(), D->isDefined(), + D->getImplementationControl(), D->hasRelatedResultType())) + return ToMethod; // FIXME: When we decide to merge method definitions, we'll need to // deal with implicit parameters. @@ -2845,7 +3405,7 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { // Import the parameters SmallVector<ParmVarDecl *, 5> ToParams; for (auto *FromP : D->parameters()) { - ParmVarDecl *ToP = cast_or_null<ParmVarDecl>(Importer.Import(FromP)); + auto *ToP = cast_or_null<ParmVarDecl>(Importer.Import(FromP)); if (!ToP) return nullptr; @@ -2853,16 +3413,19 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { } // Set the parameters. - for (unsigned I = 0, N = ToParams.size(); I != N; ++I) { - ToParams[I]->setOwningFunction(ToMethod); - ToMethod->addDeclInternal(ToParams[I]); + for (auto *ToParam : ToParams) { + ToParam->setOwningFunction(ToMethod); + ToMethod->addDeclInternal(ToParam); } + SmallVector<SourceLocation, 12> SelLocs; D->getSelectorLocs(SelLocs); - ToMethod->setMethodParams(Importer.getToContext(), ToParams, SelLocs); + for (auto &Loc : SelLocs) + Loc = Importer.Import(Loc); + + ToMethod->setMethodParams(Importer.getToContext(), ToParams, SelLocs); ToMethod->setLexicalDeclContext(LexicalDC); - Importer.Imported(D, ToMethod); LexicalDC->addDeclInternal(ToMethod); return ToMethod; } @@ -2882,16 +3445,14 @@ Decl *ASTNodeImporter::VisitObjCTypeParamDecl(ObjCTypeParamDecl *D) { if (!BoundInfo) return nullptr; - ObjCTypeParamDecl *Result = ObjCTypeParamDecl::Create( - Importer.getToContext(), DC, - D->getVariance(), - Importer.Import(D->getVarianceLoc()), - D->getIndex(), - Importer.Import(D->getLocation()), - Name.getAsIdentifierInfo(), - Importer.Import(D->getColonLoc()), - BoundInfo); - Importer.Imported(D, Result); + ObjCTypeParamDecl *Result; + if (GetImportedOrCreateDecl( + Result, D, Importer.getToContext(), DC, D->getVariance(), + Importer.Import(D->getVarianceLoc()), D->getIndex(), + Importer.Import(D->getLocation()), Name.getAsIdentifierInfo(), + Importer.Import(D->getColonLoc()), BoundInfo)) + return Result; + Result->setLexicalDeclContext(LexicalDC); return Result; } @@ -2907,8 +3468,8 @@ Decl *ASTNodeImporter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) { if (ToD) return ToD; - ObjCInterfaceDecl *ToInterface - = cast_or_null<ObjCInterfaceDecl>(Importer.Import(D->getClassInterface())); + auto *ToInterface = + cast_or_null<ObjCInterfaceDecl>(Importer.Import(D->getClassInterface())); if (!ToInterface) return nullptr; @@ -2917,18 +3478,18 @@ Decl *ASTNodeImporter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) { = ToInterface->FindCategoryDeclaration(Name.getAsIdentifierInfo()); ObjCCategoryDecl *ToCategory = MergeWithCategory; if (!ToCategory) { - ToCategory = ObjCCategoryDecl::Create(Importer.getToContext(), DC, - Importer.Import(D->getAtStartLoc()), - Loc, - Importer.Import(D->getCategoryNameLoc()), - Name.getAsIdentifierInfo(), - ToInterface, - /*TypeParamList=*/nullptr, - Importer.Import(D->getIvarLBraceLoc()), - Importer.Import(D->getIvarRBraceLoc())); + + if (GetImportedOrCreateDecl(ToCategory, D, Importer.getToContext(), DC, + Importer.Import(D->getAtStartLoc()), Loc, + Importer.Import(D->getCategoryNameLoc()), + Name.getAsIdentifierInfo(), ToInterface, + /*TypeParamList=*/nullptr, + Importer.Import(D->getIvarLBraceLoc()), + Importer.Import(D->getIvarRBraceLoc()))) + return ToCategory; + ToCategory->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToCategory); - Importer.Imported(D, ToCategory); // Import the type parameter list after calling Imported, to avoid // loops when bringing in their DeclContext. ToCategory->setTypeParamList(ImportObjCTypeParamList( @@ -2943,8 +3504,8 @@ Decl *ASTNodeImporter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) { FromProtoEnd = D->protocol_end(); FromProto != FromProtoEnd; ++FromProto, ++FromProtoLoc) { - ObjCProtocolDecl *ToProto - = cast_or_null<ObjCProtocolDecl>(Importer.Import(*FromProto)); + auto *ToProto = + cast_or_null<ObjCProtocolDecl>(Importer.Import(*FromProto)); if (!ToProto) return nullptr; Protocols.push_back(ToProto); @@ -2954,9 +3515,8 @@ Decl *ASTNodeImporter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) { // 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.Imported(D, ToCategory); + Importer.MapImported(D, ToCategory); } // Import all of the members of this category. @@ -2964,8 +3524,8 @@ Decl *ASTNodeImporter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) { // If we have an implementation, import it as well. if (D->getImplementation()) { - ObjCCategoryImplDecl *Impl - = cast_or_null<ObjCCategoryImplDecl>( + auto *Impl = + cast_or_null<ObjCCategoryImplDecl>( Importer.Import(D->getImplementation())); if (!Impl) return nullptr; @@ -2997,8 +3557,7 @@ bool ASTNodeImporter::ImportDefinition(ObjCProtocolDecl *From, FromProtoEnd = From->protocol_end(); FromProto != FromProtoEnd; ++FromProto, ++FromProtoLoc) { - ObjCProtocolDecl *ToProto - = cast_or_null<ObjCProtocolDecl>(Importer.Import(*FromProto)); + auto *ToProto = cast_or_null<ObjCProtocolDecl>(Importer.Import(*FromProto)); if (!ToProto) return true; Protocols.push_back(ToProto); @@ -3026,7 +3585,7 @@ Decl *ASTNodeImporter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) { if (!ImportedDef) return nullptr; - return Importer.Imported(D, ImportedDef); + return Importer.MapImported(D, ImportedDef); } // Import the major distinguishing characteristics of a protocol. @@ -3042,25 +3601,26 @@ Decl *ASTNodeImporter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) { ObjCProtocolDecl *MergeWithProtocol = nullptr; SmallVector<NamedDecl *, 2> FoundDecls; DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls); - for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { - if (!FoundDecls[I]->isInIdentifierNamespace(Decl::IDNS_ObjCProtocol)) + for (auto *FoundDecl : FoundDecls) { + if (!FoundDecl->isInIdentifierNamespace(Decl::IDNS_ObjCProtocol)) continue; - if ((MergeWithProtocol = dyn_cast<ObjCProtocolDecl>(FoundDecls[I]))) + if ((MergeWithProtocol = dyn_cast<ObjCProtocolDecl>(FoundDecl))) break; } ObjCProtocolDecl *ToProto = MergeWithProtocol; if (!ToProto) { - ToProto = ObjCProtocolDecl::Create(Importer.getToContext(), DC, - Name.getAsIdentifierInfo(), Loc, - Importer.Import(D->getAtStartLoc()), - /*PrevDecl=*/nullptr); + if (GetImportedOrCreateDecl(ToProto, D, Importer.getToContext(), DC, + Name.getAsIdentifierInfo(), Loc, + Importer.Import(D->getAtStartLoc()), + /*PrevDecl=*/nullptr)) + return ToProto; ToProto->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToProto); } - - Importer.Imported(D, ToProto); + + Importer.MapImported(D, ToProto); if (D->isThisDeclarationADefinition() && ImportDefinition(D, ToProto)) return nullptr; @@ -3076,14 +3636,11 @@ Decl *ASTNodeImporter::VisitLinkageSpecDecl(LinkageSpecDecl *D) { SourceLocation LangLoc = Importer.Import(D->getLocation()); bool HasBraces = D->hasBraces(); - - LinkageSpecDecl *ToLinkageSpec = - LinkageSpecDecl::Create(Importer.getToContext(), - DC, - ExternLoc, - LangLoc, - D->getLanguage(), - HasBraces); + + LinkageSpecDecl *ToLinkageSpec; + if (GetImportedOrCreateDecl(ToLinkageSpec, D, Importer.getToContext(), DC, + ExternLoc, LangLoc, D->getLanguage(), HasBraces)) + return ToLinkageSpec; if (HasBraces) { SourceLocation RBraceLoc = Importer.Import(D->getRBraceLoc()); @@ -3093,8 +3650,6 @@ Decl *ASTNodeImporter::VisitLinkageSpecDecl(LinkageSpecDecl *D) { ToLinkageSpec->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToLinkageSpec); - Importer.Imported(D, ToLinkageSpec); - return ToLinkageSpec; } @@ -3112,26 +3667,28 @@ Decl *ASTNodeImporter::VisitUsingDecl(UsingDecl *D) { Importer.Import(D->getNameInfo().getLoc())); ImportDeclarationNameLoc(D->getNameInfo(), NameInfo); - UsingDecl *ToUsing = UsingDecl::Create(Importer.getToContext(), DC, - Importer.Import(D->getUsingLoc()), - Importer.Import(D->getQualifierLoc()), - NameInfo, D->hasTypename()); + UsingDecl *ToUsing; + if (GetImportedOrCreateDecl(ToUsing, D, Importer.getToContext(), DC, + Importer.Import(D->getUsingLoc()), + Importer.Import(D->getQualifierLoc()), NameInfo, + D->hasTypename())) + return ToUsing; + ToUsing->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToUsing); - Importer.Imported(D, ToUsing); if (NamedDecl *FromPattern = Importer.getFromContext().getInstantiatedFromUsingDecl(D)) { - if (NamedDecl *ToPattern = - dyn_cast_or_null<NamedDecl>(Importer.Import(FromPattern))) + if (auto *ToPattern = + dyn_cast_or_null<NamedDecl>(Importer.Import(FromPattern))) Importer.getToContext().setInstantiatedFromUsingDecl(ToUsing, ToPattern); else return nullptr; } - for (UsingShadowDecl *FromShadow : D->shadows()) { - if (UsingShadowDecl *ToShadow = - dyn_cast_or_null<UsingShadowDecl>(Importer.Import(FromShadow))) + for (auto *FromShadow : D->shadows()) { + if (auto *ToShadow = + dyn_cast_or_null<UsingShadowDecl>(Importer.Import(FromShadow))) ToUsing->addShadowDecl(ToShadow); else // FIXME: We return a nullptr here but the definition is already created @@ -3151,27 +3708,28 @@ Decl *ASTNodeImporter::VisitUsingShadowDecl(UsingShadowDecl *D) { if (ToD) return ToD; - UsingDecl *ToUsing = dyn_cast_or_null<UsingDecl>( - Importer.Import(D->getUsingDecl())); + auto *ToUsing = dyn_cast_or_null<UsingDecl>( + Importer.Import(D->getUsingDecl())); if (!ToUsing) return nullptr; - NamedDecl *ToTarget = dyn_cast_or_null<NamedDecl>( - Importer.Import(D->getTargetDecl())); + auto *ToTarget = dyn_cast_or_null<NamedDecl>( + Importer.Import(D->getTargetDecl())); if (!ToTarget) return nullptr; - UsingShadowDecl *ToShadow = UsingShadowDecl::Create( - Importer.getToContext(), DC, Loc, ToUsing, ToTarget); + UsingShadowDecl *ToShadow; + if (GetImportedOrCreateDecl(ToShadow, D, Importer.getToContext(), DC, Loc, + ToUsing, ToTarget)) + return ToShadow; ToShadow->setLexicalDeclContext(LexicalDC); ToShadow->setAccess(D->getAccess()); - Importer.Imported(D, ToShadow); if (UsingShadowDecl *FromPattern = Importer.getFromContext().getInstantiatedFromUsingShadowDecl(D)) { - if (UsingShadowDecl *ToPattern = - dyn_cast_or_null<UsingShadowDecl>(Importer.Import(FromPattern))) + if (auto *ToPattern = + dyn_cast_or_null<UsingShadowDecl>(Importer.Import(FromPattern))) Importer.getToContext().setInstantiatedFromUsingShadowDecl(ToShadow, ToPattern); else @@ -3185,7 +3743,6 @@ Decl *ASTNodeImporter::VisitUsingShadowDecl(UsingShadowDecl *D) { return ToShadow; } - Decl *ASTNodeImporter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) { DeclContext *DC, *LexicalDC; DeclarationName Name; @@ -3200,19 +3757,22 @@ Decl *ASTNodeImporter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) { if (!ToComAncestor) return nullptr; - NamespaceDecl *ToNominated = cast_or_null<NamespaceDecl>( - Importer.Import(D->getNominatedNamespace())); + auto *ToNominated = cast_or_null<NamespaceDecl>( + Importer.Import(D->getNominatedNamespace())); if (!ToNominated) return nullptr; - UsingDirectiveDecl *ToUsingDir = UsingDirectiveDecl::Create( - Importer.getToContext(), DC, Importer.Import(D->getUsingLoc()), - Importer.Import(D->getNamespaceKeyLocation()), - Importer.Import(D->getQualifierLoc()), - Importer.Import(D->getIdentLocation()), ToNominated, ToComAncestor); + UsingDirectiveDecl *ToUsingDir; + if (GetImportedOrCreateDecl(ToUsingDir, D, Importer.getToContext(), DC, + Importer.Import(D->getUsingLoc()), + Importer.Import(D->getNamespaceKeyLocation()), + Importer.Import(D->getQualifierLoc()), + Importer.Import(D->getIdentLocation()), + ToNominated, ToComAncestor)) + return ToUsingDir; + ToUsingDir->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToUsingDir); - Importer.Imported(D, ToUsingDir); return ToUsingDir; } @@ -3231,12 +3791,13 @@ Decl *ASTNodeImporter::VisitUnresolvedUsingValueDecl( DeclarationNameInfo NameInfo(Name, Importer.Import(D->getNameInfo().getLoc())); ImportDeclarationNameLoc(D->getNameInfo(), NameInfo); - UnresolvedUsingValueDecl *ToUsingValue = UnresolvedUsingValueDecl::Create( - Importer.getToContext(), DC, Importer.Import(D->getUsingLoc()), - Importer.Import(D->getQualifierLoc()), NameInfo, - Importer.Import(D->getEllipsisLoc())); + UnresolvedUsingValueDecl *ToUsingValue; + if (GetImportedOrCreateDecl(ToUsingValue, D, Importer.getToContext(), DC, + Importer.Import(D->getUsingLoc()), + Importer.Import(D->getQualifierLoc()), NameInfo, + Importer.Import(D->getEllipsisLoc()))) + return ToUsingValue; - Importer.Imported(D, ToUsingValue); ToUsingValue->setAccess(D->getAccess()); ToUsingValue->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToUsingValue); @@ -3255,13 +3816,14 @@ Decl *ASTNodeImporter::VisitUnresolvedUsingTypenameDecl( if (ToD) return ToD; - UnresolvedUsingTypenameDecl *ToUsing = UnresolvedUsingTypenameDecl::Create( - Importer.getToContext(), DC, Importer.Import(D->getUsingLoc()), - Importer.Import(D->getTypenameLoc()), - Importer.Import(D->getQualifierLoc()), Loc, Name, - Importer.Import(D->getEllipsisLoc())); + UnresolvedUsingTypenameDecl *ToUsing; + if (GetImportedOrCreateDecl(ToUsing, D, Importer.getToContext(), DC, + Importer.Import(D->getUsingLoc()), + Importer.Import(D->getTypenameLoc()), + Importer.Import(D->getQualifierLoc()), Loc, Name, + Importer.Import(D->getEllipsisLoc()))) + return ToUsing; - Importer.Imported(D, ToUsing); ToUsing->setAccess(D->getAccess()); ToUsing->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToUsing); @@ -3269,7 +3831,6 @@ Decl *ASTNodeImporter::VisitUnresolvedUsingTypenameDecl( return ToUsing; } - bool ASTNodeImporter::ImportDefinition(ObjCInterfaceDecl *From, ObjCInterfaceDecl *To, ImportDefinitionKind Kind) { @@ -3330,8 +3891,7 @@ bool ASTNodeImporter::ImportDefinition(ObjCInterfaceDecl *From, FromProtoEnd = From->protocol_end(); FromProto != FromProtoEnd; ++FromProto, ++FromProtoLoc) { - ObjCProtocolDecl *ToProto - = cast_or_null<ObjCProtocolDecl>(Importer.Import(*FromProto)); + auto *ToProto = cast_or_null<ObjCProtocolDecl>(Importer.Import(*FromProto)); if (!ToProto) return true; Protocols.push_back(ToProto); @@ -3349,8 +3909,8 @@ bool ASTNodeImporter::ImportDefinition(ObjCInterfaceDecl *From, // If we have an @implementation, import it as well. if (From->getImplementation()) { - ObjCImplementationDecl *Impl = cast_or_null<ObjCImplementationDecl>( - Importer.Import(From->getImplementation())); + auto *Impl = cast_or_null<ObjCImplementationDecl>( + Importer.Import(From->getImplementation())); if (!Impl) return true; @@ -3371,8 +3931,8 @@ ASTNodeImporter::ImportObjCTypeParamList(ObjCTypeParamList *list) { SmallVector<ObjCTypeParamDecl *, 4> toTypeParams; for (auto fromTypeParam : *list) { - auto toTypeParam = cast_or_null<ObjCTypeParamDecl>( - Importer.Import(fromTypeParam)); + auto *toTypeParam = cast_or_null<ObjCTypeParamDecl>( + Importer.Import(fromTypeParam)); if (!toTypeParam) return nullptr; @@ -3395,7 +3955,7 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { if (!ImportedDef) return nullptr; - return Importer.Imported(D, ImportedDef); + return Importer.MapImported(D, ImportedDef); } // Import the major distinguishing characteristics of an @interface. @@ -3412,27 +3972,27 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { ObjCInterfaceDecl *MergeWithIface = nullptr; SmallVector<NamedDecl *, 2> FoundDecls; DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls); - for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { - if (!FoundDecls[I]->isInIdentifierNamespace(Decl::IDNS_Ordinary)) + for (auto *FoundDecl : FoundDecls) { + if (!FoundDecl->isInIdentifierNamespace(Decl::IDNS_Ordinary)) continue; - if ((MergeWithIface = dyn_cast<ObjCInterfaceDecl>(FoundDecls[I]))) + if ((MergeWithIface = dyn_cast<ObjCInterfaceDecl>(FoundDecl))) break; } // Create an interface declaration, if one does not already exist. ObjCInterfaceDecl *ToIface = MergeWithIface; if (!ToIface) { - ToIface = ObjCInterfaceDecl::Create(Importer.getToContext(), DC, - Importer.Import(D->getAtStartLoc()), - Name.getAsIdentifierInfo(), - /*TypeParamList=*/nullptr, - /*PrevDecl=*/nullptr, Loc, - D->isImplicitInterfaceDecl()); + if (GetImportedOrCreateDecl( + ToIface, D, Importer.getToContext(), DC, + Importer.Import(D->getAtStartLoc()), Name.getAsIdentifierInfo(), + /*TypeParamList=*/nullptr, + /*PrevDecl=*/nullptr, Loc, D->isImplicitInterfaceDecl())) + return ToIface; ToIface->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToIface); } - Importer.Imported(D, ToIface); + Importer.MapImported(D, ToIface); // Import the type parameter list after calling Imported, to avoid // loops when bringing in their DeclContext. ToIface->setTypeParamList(ImportObjCTypeParamList( @@ -3445,8 +4005,8 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { } Decl *ASTNodeImporter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) { - ObjCCategoryDecl *Category = cast_or_null<ObjCCategoryDecl>( - Importer.Import(D->getCategoryDecl())); + auto *Category = cast_or_null<ObjCCategoryDecl>( + Importer.Import(D->getCategoryDecl())); if (!Category) return nullptr; @@ -3457,13 +4017,13 @@ Decl *ASTNodeImporter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) { return nullptr; SourceLocation CategoryNameLoc = Importer.Import(D->getCategoryNameLoc()); - ToImpl = ObjCCategoryImplDecl::Create(Importer.getToContext(), DC, - Importer.Import(D->getIdentifier()), - Category->getClassInterface(), - Importer.Import(D->getLocation()), - Importer.Import(D->getAtStartLoc()), - CategoryNameLoc); - + if (GetImportedOrCreateDecl( + ToImpl, D, Importer.getToContext(), DC, + Importer.Import(D->getIdentifier()), Category->getClassInterface(), + Importer.Import(D->getLocation()), + Importer.Import(D->getAtStartLoc()), CategoryNameLoc)) + return ToImpl; + DeclContext *LexicalDC = DC; if (D->getDeclContext() != D->getLexicalDeclContext()) { LexicalDC = Importer.ImportContext(D->getLexicalDeclContext()); @@ -3477,15 +4037,15 @@ Decl *ASTNodeImporter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) { Category->setImplementation(ToImpl); } - Importer.Imported(D, ToImpl); + Importer.MapImported(D, ToImpl); ImportDeclContext(D); return ToImpl; } Decl *ASTNodeImporter::VisitObjCImplementationDecl(ObjCImplementationDecl *D) { // Find the corresponding interface. - ObjCInterfaceDecl *Iface = cast_or_null<ObjCInterfaceDecl>( - Importer.Import(D->getClassInterface())); + auto *Iface = cast_or_null<ObjCInterfaceDecl>( + Importer.Import(D->getClassInterface())); if (!Iface) return nullptr; @@ -3502,15 +4062,15 @@ Decl *ASTNodeImporter::VisitObjCImplementationDecl(ObjCImplementationDecl *D) { if (!Impl) { // We haven't imported an implementation yet. Create a new @implementation // now. - Impl = ObjCImplementationDecl::Create(Importer.getToContext(), - Importer.ImportContext(D->getDeclContext()), - Iface, Super, - Importer.Import(D->getLocation()), - Importer.Import(D->getAtStartLoc()), - Importer.Import(D->getSuperClassLoc()), - Importer.Import(D->getIvarLBraceLoc()), - Importer.Import(D->getIvarRBraceLoc())); - + if (GetImportedOrCreateDecl(Impl, D, Importer.getToContext(), + Importer.ImportContext(D->getDeclContext()), + Iface, Super, Importer.Import(D->getLocation()), + Importer.Import(D->getAtStartLoc()), + Importer.Import(D->getSuperClassLoc()), + Importer.Import(D->getIvarLBraceLoc()), + Importer.Import(D->getIvarRBraceLoc()))) + return Impl; + if (D->getDeclContext() != D->getLexicalDeclContext()) { DeclContext *LexicalDC = Importer.ImportContext(D->getLexicalDeclContext()); @@ -3518,12 +4078,12 @@ Decl *ASTNodeImporter::VisitObjCImplementationDecl(ObjCImplementationDecl *D) { return nullptr; Impl->setLexicalDeclContext(LexicalDC); } - + // Associate the implementation with the class it implements. Iface->setImplementation(Impl); - Importer.Imported(D, Iface->getImplementation()); + Importer.MapImported(D, Iface->getImplementation()); } else { - Importer.Imported(D, Iface->getImplementation()); + Importer.MapImported(D, Iface->getImplementation()); // Verify that the existing @implementation has the same superclass. if ((Super && !Impl->getSuperClass()) || @@ -3574,9 +4134,8 @@ Decl *ASTNodeImporter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) { // Check whether we have already imported this property. SmallVector<NamedDecl *, 2> FoundDecls; DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls); - for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { - if (ObjCPropertyDecl *FoundProp - = dyn_cast<ObjCPropertyDecl>(FoundDecls[I])) { + for (auto *FoundDecl : FoundDecls) { + if (auto *FoundProp = dyn_cast<ObjCPropertyDecl>(FoundDecl)) { // Check property types. if (!Importer.IsStructurallyEquivalent(D->getType(), FoundProp->getType())) { @@ -3590,7 +4149,7 @@ Decl *ASTNodeImporter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) { // FIXME: Check property attributes, getters, setters, etc.? // Consider these properties to be equivalent. - Importer.Imported(D, FoundProp); + Importer.MapImported(D, FoundProp); return FoundProp; } } @@ -3601,15 +4160,14 @@ Decl *ASTNodeImporter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) { return nullptr; // Create the new property. - ObjCPropertyDecl *ToProperty - = ObjCPropertyDecl::Create(Importer.getToContext(), DC, Loc, - Name.getAsIdentifierInfo(), - Importer.Import(D->getAtLoc()), - Importer.Import(D->getLParenLoc()), - Importer.Import(D->getType()), - TSI, - D->getPropertyImplementation()); - Importer.Imported(D, ToProperty); + ObjCPropertyDecl *ToProperty; + if (GetImportedOrCreateDecl( + ToProperty, D, Importer.getToContext(), DC, Loc, + Name.getAsIdentifierInfo(), Importer.Import(D->getAtLoc()), + Importer.Import(D->getLParenLoc()), Importer.Import(D->getType()), + TSI, D->getPropertyImplementation())) + return ToProperty; + ToProperty->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToProperty); @@ -3630,8 +4188,8 @@ Decl *ASTNodeImporter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) { } Decl *ASTNodeImporter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) { - ObjCPropertyDecl *Property = cast_or_null<ObjCPropertyDecl>( - Importer.Import(D->getPropertyDecl())); + auto *Property = cast_or_null<ObjCPropertyDecl>( + Importer.Import(D->getPropertyDecl())); if (!Property) return nullptr; @@ -3647,7 +4205,7 @@ Decl *ASTNodeImporter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) { return nullptr; } - ObjCImplDecl *InImpl = dyn_cast<ObjCImplDecl>(LexicalDC); + auto *InImpl = dyn_cast<ObjCImplDecl>(LexicalDC); if (!InImpl) return nullptr; @@ -3663,16 +4221,15 @@ Decl *ASTNodeImporter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) { ObjCPropertyImplDecl *ToImpl = InImpl->FindPropertyImplDecl(Property->getIdentifier(), Property->getQueryKind()); - if (!ToImpl) { - ToImpl = ObjCPropertyImplDecl::Create(Importer.getToContext(), DC, - Importer.Import(D->getLocStart()), - Importer.Import(D->getLocation()), - Property, - D->getPropertyImplementation(), - Ivar, - Importer.Import(D->getPropertyIvarDeclLoc())); + if (!ToImpl) { + if (GetImportedOrCreateDecl(ToImpl, D, Importer.getToContext(), DC, + Importer.Import(D->getLocStart()), + Importer.Import(D->getLocation()), Property, + D->getPropertyImplementation(), Ivar, + Importer.Import(D->getPropertyIvarDeclLoc()))) + return ToImpl; + ToImpl->setLexicalDeclContext(LexicalDC); - Importer.Imported(D, ToImpl); LexicalDC->addDeclInternal(ToImpl); } else { // Check that we have the same kind of property implementation (@synthesize @@ -3705,7 +4262,7 @@ Decl *ASTNodeImporter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) { } // Merge the existing implementation with the new implementation. - Importer.Imported(D, ToImpl); + Importer.MapImported(D, ToImpl); } return ToImpl; @@ -3717,15 +4274,14 @@ Decl *ASTNodeImporter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) { // is created. // FIXME: Import default argument. - return TemplateTypeParmDecl::Create(Importer.getToContext(), - Importer.getToContext().getTranslationUnitDecl(), - Importer.Import(D->getLocStart()), - Importer.Import(D->getLocation()), - D->getDepth(), - D->getIndex(), - Importer.Import(D->getIdentifier()), - D->wasDeclaredWithTypename(), - D->isParameterPack()); + TemplateTypeParmDecl *ToD = nullptr; + (void)GetImportedOrCreateDecl( + ToD, D, Importer.getToContext(), + Importer.getToContext().getTranslationUnitDecl(), + Importer.Import(D->getLocStart()), Importer.Import(D->getLocation()), + D->getDepth(), D->getIndex(), Importer.Import(D->getIdentifier()), + D->wasDeclaredWithTypename(), D->isParameterPack()); + return ToD; } Decl * @@ -3749,13 +4305,15 @@ ASTNodeImporter::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) { return nullptr; // FIXME: Import default argument. - - return NonTypeTemplateParmDecl::Create(Importer.getToContext(), - Importer.getToContext().getTranslationUnitDecl(), - Importer.Import(D->getInnerLocStart()), - Loc, D->getDepth(), D->getPosition(), - Name.getAsIdentifierInfo(), - T, D->isParameterPack(), TInfo); + + NonTypeTemplateParmDecl *ToD = nullptr; + (void)GetImportedOrCreateDecl( + ToD, D, Importer.getToContext(), + Importer.getToContext().getTranslationUnitDecl(), + Importer.Import(D->getInnerLocStart()), Loc, D->getDepth(), + D->getPosition(), Name.getAsIdentifierInfo(), T, D->isParameterPack(), + TInfo); + return ToD; } Decl * @@ -3767,7 +4325,7 @@ ASTNodeImporter::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) { // Import the location of this declaration. SourceLocation Loc = Importer.Import(D->getLocation()); - + // Import template parameters. TemplateParameterList *TemplateParams = ImportTemplateParameterList(D->getTemplateParameters()); @@ -3775,30 +4333,42 @@ ASTNodeImporter::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) { return nullptr; // FIXME: Import default argument. - - return TemplateTemplateParmDecl::Create(Importer.getToContext(), - Importer.getToContext().getTranslationUnitDecl(), - Loc, D->getDepth(), D->getPosition(), - D->isParameterPack(), - Name.getAsIdentifierInfo(), - TemplateParams); + + TemplateTemplateParmDecl *ToD = nullptr; + (void)GetImportedOrCreateDecl( + ToD, D, Importer.getToContext(), + Importer.getToContext().getTranslationUnitDecl(), Loc, D->getDepth(), + D->getPosition(), D->isParameterPack(), Name.getAsIdentifierInfo(), + TemplateParams); + return ToD; +} + +// Returns the definition for a (forward) declaration of a ClassTemplateDecl, if +// it has any definition in the redecl chain. +static ClassTemplateDecl *getDefinition(ClassTemplateDecl *D) { + CXXRecordDecl *ToTemplatedDef = D->getTemplatedDecl()->getDefinition(); + if (!ToTemplatedDef) + return nullptr; + ClassTemplateDecl *TemplateWithDef = + ToTemplatedDef->getDescribedClassTemplate(); + return TemplateWithDef; } Decl *ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *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. - CXXRecordDecl *Definition - = cast_or_null<CXXRecordDecl>(D->getTemplatedDecl()->getDefinition()); + auto *Definition = + cast_or_null<CXXRecordDecl>(D->getTemplatedDecl()->getDefinition()); if (Definition && Definition != D->getTemplatedDecl()) { Decl *ImportedDef = Importer.Import(Definition->getDescribedClassTemplate()); if (!ImportedDef) return nullptr; - return Importer.Imported(D, ImportedDef); + return Importer.MapImported(D, ImportedDef); } - + // Import the major distinguishing characteristics of this class template. DeclContext *DC, *LexicalDC; DeclarationName Name; @@ -3814,69 +4384,73 @@ Decl *ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) { SmallVector<NamedDecl *, 4> ConflictingDecls; SmallVector<NamedDecl *, 2> FoundDecls; DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls); - for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { - if (!FoundDecls[I]->isInIdentifierNamespace(Decl::IDNS_Ordinary)) + for (auto *FoundDecl : FoundDecls) { + if (!FoundDecl->isInIdentifierNamespace(Decl::IDNS_Ordinary)) continue; - - Decl *Found = FoundDecls[I]; - if (ClassTemplateDecl *FoundTemplate - = dyn_cast<ClassTemplateDecl>(Found)) { + + Decl *Found = FoundDecl; + if (auto *FoundTemplate = dyn_cast<ClassTemplateDecl>(Found)) { + + // The class to be imported is a definition. + if (D->isThisDeclarationADefinition()) { + // Lookup will find the fwd decl only if that is more recent than the + // definition. So, try to get the definition if that is available in + // the redecl chain. + ClassTemplateDecl *TemplateWithDef = getDefinition(FoundTemplate); + if (!TemplateWithDef) + continue; + FoundTemplate = TemplateWithDef; // Continue with the definition. + } + if (IsStructuralMatch(D, FoundTemplate)) { // The class templates structurally match; call it the same template. - // FIXME: We may be filling in a forward declaration here. Handle - // this case! - Importer.Imported(D->getTemplatedDecl(), - FoundTemplate->getTemplatedDecl()); - return Importer.Imported(D, FoundTemplate); - } + + Importer.MapImported(D->getTemplatedDecl(), + FoundTemplate->getTemplatedDecl()); + return Importer.MapImported(D, FoundTemplate); + } } - - ConflictingDecls.push_back(FoundDecls[I]); + + ConflictingDecls.push_back(FoundDecl); } - + if (!ConflictingDecls.empty()) { Name = Importer.HandleNameConflict(Name, DC, Decl::IDNS_Ordinary, - ConflictingDecls.data(), + ConflictingDecls.data(), ConflictingDecls.size()); } - + if (!Name) return nullptr; } - CXXRecordDecl *DTemplated = D->getTemplatedDecl(); - + CXXRecordDecl *FromTemplated = D->getTemplatedDecl(); + // Create the declaration that is being templated. - CXXRecordDecl *D2Templated = cast_or_null<CXXRecordDecl>( - Importer.Import(DTemplated)); - if (!D2Templated) + auto *ToTemplated = cast_or_null<CXXRecordDecl>( + Importer.Import(FromTemplated)); + if (!ToTemplated) return nullptr; - // Resolve possible cyclic import. - if (Decl *AlreadyImported = Importer.GetAlreadyImportedOrNull(D)) - return AlreadyImported; - // Create the class template declaration itself. - TemplateParameterList *TemplateParams - = ImportTemplateParameterList(D->getTemplateParameters()); + TemplateParameterList *TemplateParams = + ImportTemplateParameterList(D->getTemplateParameters()); if (!TemplateParams) return nullptr; - ClassTemplateDecl *D2 = ClassTemplateDecl::Create(Importer.getToContext(), DC, - Loc, Name, TemplateParams, - D2Templated); - D2Templated->setDescribedClassTemplate(D2); + ClassTemplateDecl *D2; + if (GetImportedOrCreateDecl(D2, D, Importer.getToContext(), DC, Loc, Name, + TemplateParams, ToTemplated)) + return D2; + + ToTemplated->setDescribedClassTemplate(D2); D2->setAccess(D->getAccess()); D2->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(D2); - // Note the relationship between the class templates. - Importer.Imported(D, D2); - Importer.Imported(DTemplated, D2Templated); - - if (DTemplated->isCompleteDefinition() && - !D2Templated->isCompleteDefinition()) { + if (FromTemplated->isCompleteDefinition() && + !ToTemplated->isCompleteDefinition()) { // FIXME: Import definition! } @@ -3894,11 +4468,11 @@ Decl *ASTNodeImporter::VisitClassTemplateSpecializationDecl( if (!ImportedDef) return nullptr; - return Importer.Imported(D, ImportedDef); + return Importer.MapImported(D, ImportedDef); } - ClassTemplateDecl *ClassTemplate - = cast_or_null<ClassTemplateDecl>(Importer.Import( + auto *ClassTemplate = + cast_or_null<ClassTemplateDecl>(Importer.Import( D->getSpecializedTemplate())); if (!ClassTemplate) return nullptr; @@ -3941,23 +4515,18 @@ Decl *ASTNodeImporter::VisitClassTemplateSpecializationDecl( // The record types structurally match, or the "from" translation // unit only had a forward declaration anyway; call it the same // function. - return Importer.Imported(D, FoundDef); + return Importer.MapImported(D, FoundDef); } } } else { // Create a new specialization. - if (ClassTemplatePartialSpecializationDecl *PartialSpec = - dyn_cast<ClassTemplatePartialSpecializationDecl>(D)) { - + if (auto *PartialSpec = + dyn_cast<ClassTemplatePartialSpecializationDecl>(D)) { // Import TemplateArgumentListInfo TemplateArgumentListInfo ToTAInfo; - auto &ASTTemplateArgs = *PartialSpec->getTemplateArgsAsWritten(); - for (unsigned I = 0, E = ASTTemplateArgs.NumTemplateArgs; I < E; ++I) { - if (auto ToLoc = ImportTemplateArgumentLoc(ASTTemplateArgs[I])) - ToTAInfo.addArgument(*ToLoc); - else - return nullptr; - } + const auto &ASTTemplateArgs = *PartialSpec->getTemplateArgsAsWritten(); + if (ImportTemplateArgumentListInfo(ASTTemplateArgs, ToTAInfo)) + return nullptr; QualType CanonInjType = Importer.Import( PartialSpec->getInjectedSpecializationType()); @@ -3970,19 +4539,18 @@ Decl *ASTNodeImporter::VisitClassTemplateSpecializationDecl( if (!ToTPList && PartialSpec->getTemplateParameters()) return nullptr; - D2 = ClassTemplatePartialSpecializationDecl::Create( - Importer.getToContext(), D->getTagKind(), DC, StartLoc, IdLoc, - ToTPList, ClassTemplate, - llvm::makeArrayRef(TemplateArgs.data(), TemplateArgs.size()), - ToTAInfo, CanonInjType, nullptr); + if (GetImportedOrCreateDecl<ClassTemplatePartialSpecializationDecl>( + D2, D, Importer.getToContext(), D->getTagKind(), DC, StartLoc, + IdLoc, ToTPList, ClassTemplate, + llvm::makeArrayRef(TemplateArgs.data(), TemplateArgs.size()), + ToTAInfo, CanonInjType, nullptr)) + return D2; } else { - D2 = ClassTemplateSpecializationDecl::Create(Importer.getToContext(), - D->getTagKind(), DC, - StartLoc, IdLoc, - ClassTemplate, - TemplateArgs, - /*PrevDecl=*/nullptr); + if (GetImportedOrCreateDecl( + D2, D, Importer.getToContext(), D->getTagKind(), DC, StartLoc, + IdLoc, ClassTemplate, TemplateArgs, /*PrevDecl=*/nullptr)) + return D2; } D2->setSpecializationKind(D->getSpecializationKind()); @@ -3993,8 +4561,6 @@ Decl *ASTNodeImporter::VisitClassTemplateSpecializationDecl( // Import the qualifier, if any. D2->setQualifierInfo(Importer.Import(D->getQualifierLoc())); - Importer.Imported(D, D2); - if (auto *TSI = D->getTypeAsWritten()) { TypeSourceInfo *TInfo = Importer.Import(TSI); if (!TInfo) @@ -4012,11 +4578,14 @@ Decl *ASTNodeImporter::VisitClassTemplateSpecializationDecl( D2->setTemplateSpecializationKind(D->getTemplateSpecializationKind()); - // Add the specialization to this context. + // Set the context of this specialization/instantiation. D2->setLexicalDeclContext(LexicalDC); - LexicalDC->addDeclInternal(D2); + + // Add to the DC only if it was an explicit specialization/instantiation. + if (D2->isExplicitInstantiationOrSpecialization()) { + LexicalDC->addDeclInternal(D2); + } } - Importer.Imported(D, D2); if (D->isCompleteDefinition() && ImportDefinition(D, D2)) return nullptr; @@ -4028,14 +4597,14 @@ Decl *ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) { // from, // but this particular declaration is not that definition, import the // definition and map to that. - VarDecl *Definition = + auto *Definition = cast_or_null<VarDecl>(D->getTemplatedDecl()->getDefinition()); if (Definition && Definition != D->getTemplatedDecl()) { Decl *ImportedDef = Importer.Import(Definition->getDescribedVarTemplate()); if (!ImportedDef) return nullptr; - return Importer.Imported(D, ImportedDef); + return Importer.MapImported(D, ImportedDef); } // Import the major distinguishing characteristics of this variable template. @@ -4054,21 +4623,21 @@ Decl *ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) { SmallVector<NamedDecl *, 4> ConflictingDecls; SmallVector<NamedDecl *, 2> FoundDecls; DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls); - for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { - if (!FoundDecls[I]->isInIdentifierNamespace(Decl::IDNS_Ordinary)) + for (auto *FoundDecl : FoundDecls) { + if (!FoundDecl->isInIdentifierNamespace(Decl::IDNS_Ordinary)) continue; - Decl *Found = FoundDecls[I]; - if (VarTemplateDecl *FoundTemplate = dyn_cast<VarTemplateDecl>(Found)) { + Decl *Found = FoundDecl; + if (auto *FoundTemplate = dyn_cast<VarTemplateDecl>(Found)) { if (IsStructuralMatch(D, FoundTemplate)) { // The variable templates structurally match; call it the same template. - Importer.Imported(D->getTemplatedDecl(), - FoundTemplate->getTemplatedDecl()); - return Importer.Imported(D, FoundTemplate); + Importer.MapImported(D->getTemplatedDecl(), + FoundTemplate->getTemplatedDecl()); + return Importer.MapImported(D, FoundTemplate); } } - ConflictingDecls.push_back(FoundDecls[I]); + ConflictingDecls.push_back(FoundDecl); } if (!ConflictingDecls.empty()) { @@ -4088,21 +4657,8 @@ Decl *ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) { return nullptr; // Create the declaration that is being templated. - SourceLocation StartLoc = Importer.Import(DTemplated->getLocStart()); - SourceLocation IdLoc = Importer.Import(DTemplated->getLocation()); - TypeSourceInfo *TInfo = Importer.Import(DTemplated->getTypeSourceInfo()); - VarDecl *D2Templated = VarDecl::Create(Importer.getToContext(), DC, StartLoc, - IdLoc, Name.getAsIdentifierInfo(), T, - TInfo, DTemplated->getStorageClass()); - D2Templated->setAccess(DTemplated->getAccess()); - D2Templated->setQualifierInfo(Importer.Import(DTemplated->getQualifierLoc())); - D2Templated->setLexicalDeclContext(LexicalDC); - - // Importer.Imported(DTemplated, D2Templated); - // LexicalDC->addDeclInternal(D2Templated); - - // Merge the initializer. - if (ImportDefinition(DTemplated, D2Templated)) + auto *ToTemplated = dyn_cast_or_null<VarDecl>(Importer.Import(DTemplated)); + if (!ToTemplated) return nullptr; // Create the variable template declaration itself. @@ -4111,24 +4667,23 @@ Decl *ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) { if (!TemplateParams) return nullptr; - VarTemplateDecl *D2 = VarTemplateDecl::Create( - Importer.getToContext(), DC, Loc, Name, TemplateParams, D2Templated); - D2Templated->setDescribedVarTemplate(D2); + VarTemplateDecl *ToVarTD; + if (GetImportedOrCreateDecl(ToVarTD, D, Importer.getToContext(), DC, Loc, + Name, TemplateParams, ToTemplated)) + return ToVarTD; - D2->setAccess(D->getAccess()); - D2->setLexicalDeclContext(LexicalDC); - LexicalDC->addDeclInternal(D2); + ToTemplated->setDescribedVarTemplate(ToVarTD); - // Note the relationship between the variable templates. - Importer.Imported(D, D2); - Importer.Imported(DTemplated, D2Templated); + ToVarTD->setAccess(D->getAccess()); + ToVarTD->setLexicalDeclContext(LexicalDC); + LexicalDC->addDeclInternal(ToVarTD); if (DTemplated->isThisDeclarationADefinition() && - !D2Templated->isThisDeclarationADefinition()) { + !ToTemplated->isThisDeclarationADefinition()) { // FIXME: Import definition! } - return D2; + return ToVarTD; } Decl *ASTNodeImporter::VisitVarTemplateSpecializationDecl( @@ -4142,10 +4697,10 @@ Decl *ASTNodeImporter::VisitVarTemplateSpecializationDecl( if (!ImportedDef) return nullptr; - return Importer.Imported(D, ImportedDef); + return Importer.MapImported(D, ImportedDef); } - VarTemplateDecl *VarTemplate = cast_or_null<VarTemplateDecl>( + auto *VarTemplate = cast_or_null<VarTemplateDecl>( Importer.Import(D->getSpecializedTemplate())); if (!VarTemplate) return nullptr; @@ -4188,23 +4743,68 @@ Decl *ASTNodeImporter::VisitVarTemplateSpecializationDecl( // The record types structurally match, or the "from" translation // unit only had a forward declaration anyway; call it the same // variable. - return Importer.Imported(D, FoundDef); + return Importer.MapImported(D, FoundDef); } } } else { - // Import the type. QualType T = Importer.Import(D->getType()); if (T.isNull()) return nullptr; + TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo()); + if (D->getTypeSourceInfo() && !TInfo) + return nullptr; + + TemplateArgumentListInfo ToTAInfo; + if (ImportTemplateArgumentListInfo(D->getTemplateArgsInfo(), ToTAInfo)) + return nullptr; + using PartVarSpecDecl = VarTemplatePartialSpecializationDecl; // Create a new specialization. - D2 = VarTemplateSpecializationDecl::Create( - Importer.getToContext(), DC, StartLoc, IdLoc, VarTemplate, T, TInfo, - D->getStorageClass(), TemplateArgs); + 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 (ImportTemplateArgumentListInfo(*FromTAArgsAsWritten, ArgInfos)) + return nullptr; + + TemplateParameterList *ToTPList = ImportTemplateParameterList( + FromPartial->getTemplateParameters()); + if (!ToTPList) + return nullptr; + + PartVarSpecDecl *ToPartial; + if (GetImportedOrCreateDecl(ToPartial, D, Importer.getToContext(), DC, + StartLoc, IdLoc, ToTPList, VarTemplate, T, + TInfo, D->getStorageClass(), TemplateArgs, + ArgInfos)) + return ToPartial; + + auto *FromInst = FromPartial->getInstantiatedFromMember(); + auto *ToInst = cast_or_null<PartVarSpecDecl>(Importer.Import(FromInst)); + if (FromInst && !ToInst) + return nullptr; + + ToPartial->setInstantiatedFromMember(ToInst); + if (FromPartial->isMemberSpecialization()) + ToPartial->setMemberSpecialization(); + + D2 = ToPartial; + } else { // Full specialization + if (GetImportedOrCreateDecl(D2, D, Importer.getToContext(), DC, StartLoc, + IdLoc, VarTemplate, T, TInfo, + D->getStorageClass(), TemplateArgs)) + return D2; + } + + SourceLocation POI = D->getPointOfInstantiation(); + if (POI.isValid()) + D2->setPointOfInstantiation(Importer.Import(POI)); + D2->setSpecializationKind(D->getSpecializationKind()); - D2->setTemplateArgsInfo(D->getTemplateArgsInfo()); + D2->setTemplateArgsInfo(ToTAInfo); // Add this specialization to the class template. VarTemplate->AddSpecialization(D2, InsertPos); @@ -4212,13 +4812,22 @@ Decl *ASTNodeImporter::VisitVarTemplateSpecializationDecl( // Import the qualifier, if any. D2->setQualifierInfo(Importer.Import(D->getQualifierLoc())); + if (D->isConstexpr()) + D2->setConstexpr(true); + // Add the specialization to this context. D2->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(D2); + + D2->setAccess(D->getAccess()); } - Importer.Imported(D, D2); - if (D->isThisDeclarationADefinition() && ImportDefinition(D, D2)) + // NOTE: isThisDeclarationADefinition() can return DeclarationOnly even if + // declaration has initializer. Should this be fixed in the AST?.. Anyway, + // we have to check the declaration for initializer - otherwise, it won't be + // imported. + if ((D->isThisDeclarationADefinition() || D->hasInit()) && + ImportDefinition(D, D2)) return nullptr; return D2; @@ -4242,16 +4851,15 @@ Decl *ASTNodeImporter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { unsigned IDNS = Decl::IDNS_Ordinary; SmallVector<NamedDecl *, 2> FoundDecls; DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls); - for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { - if (!FoundDecls[I]->isInIdentifierNamespace(IDNS)) + for (auto *FoundDecl : FoundDecls) { + if (!FoundDecl->isInIdentifierNamespace(IDNS)) continue; - if (FunctionTemplateDecl *FoundFunction = - dyn_cast<FunctionTemplateDecl>(FoundDecls[I])) { + if (auto *FoundFunction = dyn_cast<FunctionTemplateDecl>(FoundDecl)) { if (FoundFunction->hasExternalFormalLinkage() && D->hasExternalFormalLinkage()) { if (IsStructuralMatch(D, FoundFunction)) { - Importer.Imported(D, FoundFunction); + Importer.MapImported(D, FoundFunction); // FIXME: Actually try to merge the body and other attributes. return FoundFunction; } @@ -4265,18 +4873,19 @@ Decl *ASTNodeImporter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { if (!Params) return nullptr; - FunctionDecl *TemplatedFD = + auto *TemplatedFD = cast_or_null<FunctionDecl>(Importer.Import(D->getTemplatedDecl())); if (!TemplatedFD) return nullptr; - FunctionTemplateDecl *ToFunc = FunctionTemplateDecl::Create( - Importer.getToContext(), DC, Loc, Name, Params, TemplatedFD); + FunctionTemplateDecl *ToFunc; + if (GetImportedOrCreateDecl(ToFunc, D, Importer.getToContext(), DC, Loc, Name, + Params, TemplatedFD)) + return ToFunc; TemplatedFD->setDescribedFunctionTemplate(ToFunc); ToFunc->setAccess(D->getAccess()); ToFunc->setLexicalDeclContext(LexicalDC); - Importer.Imported(D, ToFunc); LexicalDC->addDeclInternal(ToFunc); return ToFunc; @@ -4301,12 +4910,11 @@ DeclGroupRef ASTNodeImporter::ImportDeclGroup(DeclGroupRef DG) { NumDecls); } - Stmt *ASTNodeImporter::VisitStmt(Stmt *S) { - Importer.FromDiag(S->getLocStart(), diag::err_unsupported_ast_node) - << S->getStmtClassName(); - return nullptr; - } - +Stmt *ASTNodeImporter::VisitStmt(Stmt *S) { + Importer.FromDiag(S->getLocStart(), diag::err_unsupported_ast_node) + << S->getStmtClassName(); + return nullptr; +} Stmt *ASTNodeImporter::VisitGCCAsmStmt(GCCAsmStmt *S) { SmallVector<IdentifierInfo *, 4> Names; @@ -4329,8 +4937,8 @@ Stmt *ASTNodeImporter::VisitGCCAsmStmt(GCCAsmStmt *S) { SmallVector<StringLiteral *, 4> Clobbers; for (unsigned I = 0, E = S->getNumClobbers(); I != E; I++) { - StringLiteral *Clobber = cast_or_null<StringLiteral>( - Importer.Import(S->getClobberStringLiteral(I))); + auto *Clobber = cast_or_null<StringLiteral>( + Importer.Import(S->getClobberStringLiteral(I))); if (!Clobber) return nullptr; Clobbers.push_back(Clobber); @@ -4338,16 +4946,16 @@ Stmt *ASTNodeImporter::VisitGCCAsmStmt(GCCAsmStmt *S) { SmallVector<StringLiteral *, 4> Constraints; for (unsigned I = 0, E = S->getNumOutputs(); I != E; I++) { - StringLiteral *Output = cast_or_null<StringLiteral>( - Importer.Import(S->getOutputConstraintLiteral(I))); + auto *Output = cast_or_null<StringLiteral>( + Importer.Import(S->getOutputConstraintLiteral(I))); if (!Output) return nullptr; Constraints.push_back(Output); } for (unsigned I = 0, E = S->getNumInputs(); I != E; I++) { - StringLiteral *Input = cast_or_null<StringLiteral>( - Importer.Import(S->getInputConstraintLiteral(I))); + auto *Input = cast_or_null<StringLiteral>( + Importer.Import(S->getInputConstraintLiteral(I))); if (!Input) return nullptr; Constraints.push_back(Input); @@ -4360,8 +4968,8 @@ Stmt *ASTNodeImporter::VisitGCCAsmStmt(GCCAsmStmt *S) { if (ImportArrayChecked(S->inputs(), Exprs.begin() + S->getNumOutputs())) return nullptr; - StringLiteral *AsmStr = cast_or_null<StringLiteral>( - Importer.Import(S->getAsmString())); + auto *AsmStr = cast_or_null<StringLiteral>( + Importer.Import(S->getAsmString())); if (!AsmStr) return nullptr; @@ -4383,7 +4991,7 @@ Stmt *ASTNodeImporter::VisitGCCAsmStmt(GCCAsmStmt *S) { Stmt *ASTNodeImporter::VisitDeclStmt(DeclStmt *S) { DeclGroupRef ToDG = ImportDeclGroup(S->getDeclGroup()); - for (Decl *ToD : ToDG) { + for (auto *ToD : ToDG) { if (!ToD) return nullptr; } @@ -4399,7 +5007,7 @@ Stmt *ASTNodeImporter::VisitNullStmt(NullStmt *S) { } Stmt *ASTNodeImporter::VisitCompoundStmt(CompoundStmt *S) { - llvm::SmallVector<Stmt *, 8> ToStmts(S->size()); + SmallVector<Stmt *, 8> ToStmts(S->size()); if (ImportContainerChecked(S->body(), ToStmts)) return nullptr; @@ -4423,7 +5031,7 @@ Stmt *ASTNodeImporter::VisitCaseStmt(CaseStmt *S) { SourceLocation ToCaseLoc = Importer.Import(S->getCaseLoc()); SourceLocation ToEllipsisLoc = Importer.Import(S->getEllipsisLoc()); SourceLocation ToColonLoc = Importer.Import(S->getColonLoc()); - CaseStmt *ToStmt = new (Importer.getToContext()) + auto *ToStmt = new (Importer.getToContext()) CaseStmt(ToLHS, ToRHS, ToCaseLoc, ToEllipsisLoc, ToColonLoc); ToStmt->setSubStmt(ToSubStmt); return ToStmt; @@ -4441,8 +5049,7 @@ Stmt *ASTNodeImporter::VisitDefaultStmt(DefaultStmt *S) { Stmt *ASTNodeImporter::VisitLabelStmt(LabelStmt *S) { SourceLocation ToIdentLoc = Importer.Import(S->getIdentLoc()); - LabelDecl *ToLabelDecl = - cast_or_null<LabelDecl>(Importer.Import(S->getDecl())); + auto *ToLabelDecl = cast_or_null<LabelDecl>(Importer.Import(S->getDecl())); if (!ToLabelDecl && S->getDecl()) return nullptr; Stmt *ToSubStmt = Importer.Import(S->getSubStmt()); @@ -4456,15 +5063,8 @@ Stmt *ASTNodeImporter::VisitAttributedStmt(AttributedStmt *S) { SourceLocation ToAttrLoc = Importer.Import(S->getAttrLoc()); ArrayRef<const Attr*> FromAttrs(S->getAttrs()); SmallVector<const Attr *, 1> ToAttrs(FromAttrs.size()); - ASTContext &_ToContext = Importer.getToContext(); - std::transform(FromAttrs.begin(), FromAttrs.end(), ToAttrs.begin(), - [&_ToContext](const Attr *A) -> const Attr * { - return A->clone(_ToContext); - }); - for (const Attr *ToA : ToAttrs) { - if (!ToA) - return nullptr; - } + if (ImportContainerChecked(FromAttrs, ToAttrs)) + return nullptr; Stmt *ToSubStmt = Importer.Import(S->getSubStmt()); if (!ToSubStmt && S->getSubStmt()) return nullptr; @@ -4516,7 +5116,7 @@ Stmt *ASTNodeImporter::VisitSwitchStmt(SwitchStmt *S) { Expr *ToCondition = Importer.Import(S->getCond()); if (!ToCondition && S->getCond()) return nullptr; - SwitchStmt *ToStmt = new (Importer.getToContext()) SwitchStmt( + auto *ToStmt = new (Importer.getToContext()) SwitchStmt( Importer.getToContext(), ToInit, ToConditionVariable, ToCondition); Stmt *ToBody = Importer.Import(S->getBody()); @@ -4528,7 +5128,7 @@ Stmt *ASTNodeImporter::VisitSwitchStmt(SwitchStmt *S) { SwitchCase *LastChainedSwitchCase = nullptr; for (SwitchCase *SC = S->getSwitchCaseList(); SC != nullptr; SC = SC->getNextSwitchCase()) { - SwitchCase *ToSC = dyn_cast_or_null<SwitchCase>(Importer.Import(SC)); + auto *ToSC = dyn_cast_or_null<SwitchCase>(Importer.Import(SC)); if (!ToSC) return nullptr; if (LastChainedSwitchCase) @@ -4645,8 +5245,8 @@ Stmt *ASTNodeImporter::VisitReturnStmt(ReturnStmt *S) { Expr *ToRetExpr = Importer.Import(S->getRetValue()); if (!ToRetExpr && S->getRetValue()) return nullptr; - VarDecl *NRVOCandidate = const_cast<VarDecl*>(S->getNRVOCandidate()); - VarDecl *ToNRVOCandidate = cast_or_null<VarDecl>(Importer.Import(NRVOCandidate)); + auto *NRVOCandidate = const_cast<VarDecl *>(S->getNRVOCandidate()); + auto *ToNRVOCandidate = cast_or_null<VarDecl>(Importer.Import(NRVOCandidate)); if (!ToNRVOCandidate && NRVOCandidate) return nullptr; return new (Importer.getToContext()) ReturnStmt(ToRetLoc, ToRetExpr, @@ -4688,15 +5288,15 @@ Stmt *ASTNodeImporter::VisitCXXTryStmt(CXXTryStmt *S) { } Stmt *ASTNodeImporter::VisitCXXForRangeStmt(CXXForRangeStmt *S) { - DeclStmt *ToRange = + auto *ToRange = dyn_cast_or_null<DeclStmt>(Importer.Import(S->getRangeStmt())); if (!ToRange && S->getRangeStmt()) return nullptr; - DeclStmt *ToBegin = + auto *ToBegin = dyn_cast_or_null<DeclStmt>(Importer.Import(S->getBeginStmt())); if (!ToBegin && S->getBeginStmt()) return nullptr; - DeclStmt *ToEnd = + auto *ToEnd = dyn_cast_or_null<DeclStmt>(Importer.Import(S->getEndStmt())); if (!ToEnd && S->getEndStmt()) return nullptr; @@ -4706,7 +5306,7 @@ Stmt *ASTNodeImporter::VisitCXXForRangeStmt(CXXForRangeStmt *S) { Expr *ToInc = Importer.Import(S->getInc()); if (!ToInc && S->getInc()) return nullptr; - DeclStmt *ToLoopVar = + auto *ToLoopVar = dyn_cast_or_null<DeclStmt>(Importer.Import(S->getLoopVarStmt())); if (!ToLoopVar && S->getLoopVarStmt()) return nullptr; @@ -4851,7 +5451,6 @@ Expr *ASTNodeImporter::VisitVAArgExpr(VAArgExpr *E) { Importer.Import(E->getRParenLoc()), T, E->isMicrosoftABI()); } - Expr *ASTNodeImporter::VisitGNUNullExpr(GNUNullExpr *E) { QualType T = Importer.Import(E->getType()); if (T.isNull()) @@ -4866,8 +5465,7 @@ Expr *ASTNodeImporter::VisitPredefinedExpr(PredefinedExpr *E) { if (T.isNull()) return nullptr; - StringLiteral *SL = cast_or_null<StringLiteral>( - Importer.Import(E->getFunctionName())); + auto *SL = cast_or_null<StringLiteral>(Importer.Import(E->getFunctionName())); if (!SL && E->getFunctionName()) return nullptr; @@ -4876,7 +5474,7 @@ Expr *ASTNodeImporter::VisitPredefinedExpr(PredefinedExpr *E) { } Expr *ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) { - ValueDecl *ToD = cast_or_null<ValueDecl>(Importer.Import(E->getDecl())); + auto *ToD = cast_or_null<ValueDecl>(Importer.Import(E->getDecl())); if (!ToD) return nullptr; @@ -4891,16 +5489,11 @@ Expr *ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) { if (T.isNull()) return nullptr; - TemplateArgumentListInfo ToTAInfo; TemplateArgumentListInfo *ResInfo = nullptr; if (E->hasExplicitTemplateArgs()) { - for (const auto &FromLoc : E->template_arguments()) { - if (auto ToTALoc = ImportTemplateArgumentLoc(FromLoc)) - ToTAInfo.addArgument(*ToTALoc); - else - return nullptr; - } + if (ImportTemplateArgumentListInfo(E->template_arguments(), ToTAInfo)) + return nullptr; ResInfo = &ToTAInfo; } @@ -4947,14 +5540,14 @@ ASTNodeImporter::ImportDesignator(const Designator &D) { Expr *ASTNodeImporter::VisitDesignatedInitExpr(DesignatedInitExpr *DIE) { - Expr *Init = cast_or_null<Expr>(Importer.Import(DIE->getInit())); + auto *Init = cast_or_null<Expr>(Importer.Import(DIE->getInit())); if (!Init) return nullptr; SmallVector<Expr *, 4> IndexExprs(DIE->getNumSubExprs() - 1); // List elements from the second, the first is Init itself for (unsigned I = 1, E = DIE->getNumSubExprs(); I < E; I++) { - if (Expr *Arg = cast_or_null<Expr>(Importer.Import(DIE->getSubExpr(I)))) + if (auto *Arg = cast_or_null<Expr>(Importer.Import(DIE->getSubExpr(I)))) IndexExprs[I - 1] = Arg; else return nullptr; @@ -4966,7 +5559,7 @@ Expr *ASTNodeImporter::VisitDesignatedInitExpr(DesignatedInitExpr *DIE) { return ImportDesignator(D); }); - for (const Designator &D : DIE->designators()) + for (const auto &D : DIE->designators()) if (D.isFieldDesignator() && !D.getFieldName()) return nullptr; @@ -5067,7 +5660,7 @@ Expr *ASTNodeImporter::VisitAddrLabelExpr(AddrLabelExpr *E) { if (T.isNull()) return nullptr; - LabelDecl *ToLabel = cast_or_null<LabelDecl>(Importer.Import(E->getLabel())); + auto *ToLabel = cast_or_null<LabelDecl>(Importer.Import(E->getLabel())); if (!ToLabel) return nullptr; @@ -5102,8 +5695,8 @@ Expr *ASTNodeImporter::VisitStmtExpr(StmtExpr *E) { if (T.isNull()) return nullptr; - CompoundStmt *ToSubStmt = cast_or_null<CompoundStmt>( - Importer.Import(E->getSubStmt())); + auto *ToSubStmt = cast_or_null<CompoundStmt>( + Importer.Import(E->getSubStmt())); if (!ToSubStmt && E->getSubStmt()) return nullptr; @@ -5120,14 +5713,13 @@ Expr *ASTNodeImporter::VisitUnaryOperator(UnaryOperator *E) { if (!SubExpr) return nullptr; - return new (Importer.getToContext()) UnaryOperator(SubExpr, E->getOpcode(), - T, E->getValueKind(), - E->getObjectKind(), - Importer.Import(E->getOperatorLoc())); + return new (Importer.getToContext()) UnaryOperator( + SubExpr, E->getOpcode(), T, E->getValueKind(), E->getObjectKind(), + Importer.Import(E->getOperatorLoc()), E->canOverflow()); } -Expr *ASTNodeImporter::VisitUnaryExprOrTypeTraitExpr( - UnaryExprOrTypeTraitExpr *E) { +Expr * +ASTNodeImporter::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E) { QualType ResultType = Importer.Import(E->getType()); if (E->isArgumentType()) { @@ -5208,8 +5800,8 @@ Expr *ASTNodeImporter::VisitBinaryConditionalOperator( if (!Cond) return nullptr; - OpaqueValueExpr *OpaqueValue = cast_or_null<OpaqueValueExpr>( - Importer.Import(E->getOpaqueValue())); + auto *OpaqueValue = cast_or_null<OpaqueValueExpr>( + Importer.Import(E->getOpaqueValue())); if (!OpaqueValue) return nullptr; @@ -5367,7 +5959,7 @@ Expr *ASTNodeImporter::VisitExplicitCastExpr(ExplicitCastExpr *E) { switch (E->getStmtClass()) { case Stmt::CStyleCastExprClass: { - CStyleCastExpr *CCE = cast<CStyleCastExpr>(E); + auto *CCE = cast<CStyleCastExpr>(E); return CStyleCastExpr::Create(Importer.getToContext(), T, E->getValueKind(), E->getCastKind(), SubExpr, &BasePath, TInfo, @@ -5376,7 +5968,7 @@ Expr *ASTNodeImporter::VisitExplicitCastExpr(ExplicitCastExpr *E) { } case Stmt::CXXFunctionalCastExprClass: { - CXXFunctionalCastExpr *FCE = cast<CXXFunctionalCastExpr>(E); + auto *FCE = cast<CXXFunctionalCastExpr>(E); return CXXFunctionalCastExpr::Create(Importer.getToContext(), T, E->getValueKind(), TInfo, E->getCastKind(), SubExpr, &BasePath, @@ -5385,7 +5977,7 @@ Expr *ASTNodeImporter::VisitExplicitCastExpr(ExplicitCastExpr *E) { } case Stmt::ObjCBridgedCastExprClass: { - ObjCBridgedCastExpr *OCE = cast<ObjCBridgedCastExpr>(E); + auto *OCE = cast<ObjCBridgedCastExpr>(E); return new (Importer.getToContext()) ObjCBridgedCastExpr( Importer.Import(OCE->getLParenLoc()), OCE->getBridgeKind(), E->getCastKind(), Importer.Import(OCE->getBridgeKeywordLoc()), @@ -5395,7 +5987,7 @@ Expr *ASTNodeImporter::VisitExplicitCastExpr(ExplicitCastExpr *E) { break; // just fall through } - CXXNamedCastExpr *Named = cast<CXXNamedCastExpr>(E); + auto *Named = cast<CXXNamedCastExpr>(E); SourceLocation ExprLoc = Importer.Import(Named->getOperatorLoc()), RParenLoc = Importer.Import(Named->getRParenLoc()); SourceRange Brackets = Importer.Import(Named->getAngleBrackets()); @@ -5453,7 +6045,7 @@ Expr *ASTNodeImporter::VisitOffsetOfExpr(OffsetOfExpr *OE) { break; } case OffsetOfNode::Field: { - FieldDecl *FD = cast_or_null<FieldDecl>(Importer.Import(Node.getField())); + auto *FD = cast_or_null<FieldDecl>(Importer.Import(Node.getField())); if (!FD) return nullptr; Nodes.push_back(OffsetOfNode(Importer.Import(Node.getLocStart()), FD, @@ -5524,8 +6116,7 @@ Expr *ASTNodeImporter::VisitCXXThrowExpr(CXXThrowExpr *E) { } Expr *ASTNodeImporter::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) { - ParmVarDecl *Param = cast_or_null<ParmVarDecl>( - Importer.Import(E->getParam())); + auto *Param = cast_or_null<ParmVarDecl>(Importer.Import(E->getParam())); if (!Param) return nullptr; @@ -5567,6 +6158,10 @@ Expr *ASTNodeImporter::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *CE) { if (T.isNull()) return nullptr; + TypeSourceInfo *TInfo = Importer.Import(CE->getTypeSourceInfo()); + if (!TInfo) + return nullptr; + SmallVector<Expr *, 8> Args(CE->getNumArgs()); if (ImportContainerChecked(CE->arguments(), Args)) return nullptr; @@ -5576,18 +6171,11 @@ Expr *ASTNodeImporter::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *CE) { if (!Ctor) return nullptr; - return CXXTemporaryObjectExpr::Create( - Importer.getToContext(), T, - Importer.Import(CE->getLocStart()), - Ctor, - CE->isElidable(), - Args, - CE->hadMultipleCandidates(), - CE->isListInitialization(), - CE->isStdInitListInitialization(), - CE->requiresZeroInitialization(), - CE->getConstructionKind(), - Importer.Import(CE->getParenOrBraceRange())); + return new (Importer.getToContext()) CXXTemporaryObjectExpr( + Importer.getToContext(), Ctor, T, TInfo, Args, + Importer.Import(CE->getParenOrBraceRange()), CE->hadMultipleCandidates(), + CE->isListInitialization(), CE->isStdInitListInitialization(), + CE->requiresZeroInitialization()); } Expr * @@ -5600,7 +6188,7 @@ ASTNodeImporter::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E) { if (!TempE) return nullptr; - ValueDecl *ExtendedBy = cast_or_null<ValueDecl>( + auto *ExtendedBy = cast_or_null<ValueDecl>( Importer.Import(const_cast<ValueDecl *>(E->getExtendingDecl()))); if (!ExtendedBy && E->getExtendingDecl()) return nullptr; @@ -5627,6 +6215,30 @@ Expr *ASTNodeImporter::VisitPackExpansionExpr(PackExpansionExpr *E) { E->getNumExpansions()); } +Expr *ASTNodeImporter::VisitSizeOfPackExpr(SizeOfPackExpr *E) { + auto *Pack = cast_or_null<NamedDecl>(Importer.Import(E->getPack())); + if (!Pack) + return nullptr; + + Optional<unsigned> Length; + + if (!E->isValueDependent()) + Length = E->getPackLength(); + + SmallVector<TemplateArgument, 8> PartialArguments; + if (E->isPartiallySubstituted()) { + if (ImportTemplateArguments(E->getPartialArguments().data(), + E->getPartialArguments().size(), + PartialArguments)) + return nullptr; + } + + return SizeOfPackExpr::Create( + Importer.getToContext(), Importer.Import(E->getOperatorLoc()), Pack, + Importer.Import(E->getPackLoc()), Importer.Import(E->getRParenLoc()), + Length, PartialArguments); +} + Expr *ASTNodeImporter::VisitCXXNewExpr(CXXNewExpr *CE) { QualType T = Importer.Import(CE->getType()); if (T.isNull()) @@ -5636,12 +6248,12 @@ Expr *ASTNodeImporter::VisitCXXNewExpr(CXXNewExpr *CE) { if (ImportContainerChecked(CE->placement_arguments(), PlacementArgs)) return nullptr; - FunctionDecl *OperatorNewDecl = cast_or_null<FunctionDecl>( + auto *OperatorNewDecl = cast_or_null<FunctionDecl>( Importer.Import(CE->getOperatorNew())); if (!OperatorNewDecl && CE->getOperatorNew()) return nullptr; - FunctionDecl *OperatorDeleteDecl = cast_or_null<FunctionDecl>( + auto *OperatorDeleteDecl = cast_or_null<FunctionDecl>( Importer.Import(CE->getOperatorDelete())); if (!OperatorDeleteDecl && CE->getOperatorDelete()) return nullptr; @@ -5676,7 +6288,7 @@ Expr *ASTNodeImporter::VisitCXXDeleteExpr(CXXDeleteExpr *E) { if (T.isNull()) return nullptr; - FunctionDecl *OperatorDeleteDecl = cast_or_null<FunctionDecl>( + auto *OperatorDeleteDecl = cast_or_null<FunctionDecl>( Importer.Import(E->getOperatorDelete())); if (!OperatorDeleteDecl && E->getOperatorDelete()) return nullptr; @@ -5700,7 +6312,7 @@ Expr *ASTNodeImporter::VisitCXXConstructExpr(CXXConstructExpr *E) { if (T.isNull()) return nullptr; - CXXConstructorDecl *ToCCD = + auto *ToCCD = dyn_cast_or_null<CXXConstructorDecl>(Importer.Import(E->getConstructor())); if (!ToCCD) return nullptr; @@ -5784,13 +6396,17 @@ Expr *ASTNodeImporter::VisitMemberExpr(MemberExpr *E) { if (!ToBase && E->getBase()) return nullptr; - ValueDecl *ToMember = dyn_cast<ValueDecl>(Importer.Import(E->getMemberDecl())); + auto *ToMember = dyn_cast<ValueDecl>(Importer.Import(E->getMemberDecl())); if (!ToMember && E->getMemberDecl()) return nullptr; - DeclAccessPair ToFoundDecl = DeclAccessPair::make( - dyn_cast<NamedDecl>(Importer.Import(E->getFoundDecl().getDecl())), - E->getFoundDecl().getAccess()); + auto *ToDecl = + dyn_cast_or_null<NamedDecl>(Importer.Import(E->getFoundDecl().getDecl())); + if (!ToDecl && E->getFoundDecl().getDecl()) + return nullptr; + + DeclAccessPair ToFoundDecl = + DeclAccessPair::make(ToDecl, E->getFoundDecl().getAccess()); DeclarationNameInfo ToMemberNameInfo( Importer.Import(E->getMemberNameInfo().getName()), @@ -5812,7 +6428,6 @@ Expr *ASTNodeImporter::VisitMemberExpr(MemberExpr *E) { Expr *ASTNodeImporter::VisitCXXPseudoDestructorExpr( CXXPseudoDestructorExpr *E) { - Expr *BaseE = Importer.Import(E->getBase()); if (!BaseE) return nullptr; @@ -5856,11 +6471,10 @@ Expr *ASTNodeImporter::VisitCXXDependentScopeMemberExpr( if (BaseType.isNull()) return nullptr; - TemplateArgumentListInfo ToTAInfo(Importer.Import(E->getLAngleLoc()), - Importer.Import(E->getRAngleLoc())); - TemplateArgumentListInfo *ResInfo = nullptr; + TemplateArgumentListInfo ToTAInfo, *ResInfo = nullptr; if (E->hasExplicitTemplateArgs()) { - if (ImportTemplateArgumentListInfo(E->template_arguments(), ToTAInfo)) + if (ImportTemplateArgumentListInfo(E->getLAngleLoc(), E->getRAngleLoc(), + E->template_arguments(), ToTAInfo)) return nullptr; ResInfo = &ToTAInfo; } @@ -5884,6 +6498,127 @@ Expr *ASTNodeImporter::VisitCXXDependentScopeMemberExpr( cast_or_null<NamedDecl>(ToFQ), MemberNameInfo, ResInfo); } +Expr * +ASTNodeImporter::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) { + DeclarationName Name = Importer.Import(E->getDeclName()); + if (!E->getDeclName().isEmpty() && Name.isEmpty()) + return nullptr; + + DeclarationNameInfo NameInfo(Name, Importer.Import(E->getExprLoc())); + ImportDeclarationNameLoc(E->getNameInfo(), NameInfo); + + TemplateArgumentListInfo ToTAInfo(Importer.Import(E->getLAngleLoc()), + Importer.Import(E->getRAngleLoc())); + TemplateArgumentListInfo *ResInfo = nullptr; + if (E->hasExplicitTemplateArgs()) { + if (ImportTemplateArgumentListInfo(E->template_arguments(), ToTAInfo)) + return nullptr; + ResInfo = &ToTAInfo; + } + + return DependentScopeDeclRefExpr::Create( + Importer.getToContext(), Importer.Import(E->getQualifierLoc()), + Importer.Import(E->getTemplateKeywordLoc()), NameInfo, ResInfo); +} + +Expr *ASTNodeImporter::VisitCXXUnresolvedConstructExpr( + CXXUnresolvedConstructExpr *CE) { + unsigned NumArgs = CE->arg_size(); + + SmallVector<Expr *, 8> ToArgs(NumArgs); + if (ImportArrayChecked(CE->arg_begin(), CE->arg_end(), ToArgs.begin())) + return nullptr; + + return CXXUnresolvedConstructExpr::Create( + Importer.getToContext(), Importer.Import(CE->getTypeSourceInfo()), + Importer.Import(CE->getLParenLoc()), llvm::makeArrayRef(ToArgs), + Importer.Import(CE->getRParenLoc())); +} + +Expr *ASTNodeImporter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) { + auto *NamingClass = + cast_or_null<CXXRecordDecl>(Importer.Import(E->getNamingClass())); + if (E->getNamingClass() && !NamingClass) + return nullptr; + + DeclarationName Name = Importer.Import(E->getName()); + if (E->getName() && !Name) + return nullptr; + + DeclarationNameInfo NameInfo(Name, Importer.Import(E->getNameLoc())); + // Import additional name location/type info. + ImportDeclarationNameLoc(E->getNameInfo(), NameInfo); + + UnresolvedSet<8> ToDecls; + for (auto *D : E->decls()) { + if (auto *To = cast_or_null<NamedDecl>(Importer.Import(D))) + ToDecls.addDecl(To); + else + return nullptr; + } + + TemplateArgumentListInfo ToTAInfo, *ResInfo = nullptr; + if (E->hasExplicitTemplateArgs()) { + if (ImportTemplateArgumentListInfo(E->getLAngleLoc(), E->getRAngleLoc(), + E->template_arguments(), ToTAInfo)) + return nullptr; + ResInfo = &ToTAInfo; + } + + if (ResInfo || E->getTemplateKeywordLoc().isValid()) + return UnresolvedLookupExpr::Create( + Importer.getToContext(), NamingClass, + Importer.Import(E->getQualifierLoc()), + Importer.Import(E->getTemplateKeywordLoc()), NameInfo, E->requiresADL(), + ResInfo, ToDecls.begin(), ToDecls.end()); + + return UnresolvedLookupExpr::Create( + Importer.getToContext(), NamingClass, + Importer.Import(E->getQualifierLoc()), NameInfo, E->requiresADL(), + E->isOverloaded(), ToDecls.begin(), ToDecls.end()); +} + +Expr *ASTNodeImporter::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E) { + DeclarationName Name = Importer.Import(E->getName()); + if (!E->getName().isEmpty() && Name.isEmpty()) + return nullptr; + DeclarationNameInfo NameInfo(Name, Importer.Import(E->getNameLoc())); + // Import additional name location/type info. + ImportDeclarationNameLoc(E->getNameInfo(), NameInfo); + + QualType BaseType = Importer.Import(E->getType()); + if (!E->getType().isNull() && BaseType.isNull()) + return nullptr; + + UnresolvedSet<8> ToDecls; + for (Decl *D : E->decls()) { + if (NamedDecl *To = cast_or_null<NamedDecl>(Importer.Import(D))) + ToDecls.addDecl(To); + else + return nullptr; + } + + TemplateArgumentListInfo ToTAInfo; + TemplateArgumentListInfo *ResInfo = nullptr; + if (E->hasExplicitTemplateArgs()) { + if (ImportTemplateArgumentListInfo(E->template_arguments(), ToTAInfo)) + return nullptr; + ResInfo = &ToTAInfo; + } + + Expr *BaseE = E->isImplicitAccess() ? nullptr : Importer.Import(E->getBase()); + if (!BaseE && !E->isImplicitAccess() && E->getBase()) { + return nullptr; + } + + return UnresolvedMemberExpr::Create( + Importer.getToContext(), E->hasUnresolvedUsing(), BaseE, BaseType, + E->isArrow(), Importer.Import(E->getOperatorLoc()), + Importer.Import(E->getQualifierLoc()), + Importer.Import(E->getTemplateKeywordLoc()), NameInfo, ResInfo, + ToDecls.begin(), ToDecls.end()); +} + Expr *ASTNodeImporter::VisitCallExpr(CallExpr *E) { QualType T = Importer.Import(E->getType()); if (T.isNull()) @@ -5894,35 +6629,100 @@ Expr *ASTNodeImporter::VisitCallExpr(CallExpr *E) { return nullptr; unsigned NumArgs = E->getNumArgs(); + SmallVector<Expr *, 2> ToArgs(NumArgs); + if (ImportContainerChecked(E->arguments(), ToArgs)) + return nullptr; - llvm::SmallVector<Expr *, 2> ToArgs(NumArgs); - - for (unsigned ai = 0, ae = NumArgs; ai != ae; ++ai) { - Expr *FromArg = E->getArg(ai); - Expr *ToArg = Importer.Import(FromArg); - if (!ToArg) - return nullptr; - ToArgs[ai] = ToArg; - } - - Expr **ToArgs_Copied = new (Importer.getToContext()) - Expr*[NumArgs]; + auto **ToArgs_Copied = new (Importer.getToContext()) Expr*[NumArgs]; for (unsigned ai = 0, ae = NumArgs; ai != ae; ++ai) ToArgs_Copied[ai] = ToArgs[ai]; + if (const auto *OCE = dyn_cast<CXXOperatorCallExpr>(E)) { + return new (Importer.getToContext()) CXXOperatorCallExpr( + Importer.getToContext(), OCE->getOperator(), ToCallee, ToArgs, T, + OCE->getValueKind(), Importer.Import(OCE->getRParenLoc()), + OCE->getFPFeatures()); + } + return new (Importer.getToContext()) CallExpr(Importer.getToContext(), ToCallee, llvm::makeArrayRef(ToArgs_Copied, NumArgs), T, E->getValueKind(), Importer.Import(E->getRParenLoc())); } +Optional<LambdaCapture> +ASTNodeImporter::ImportLambdaCapture(const LambdaCapture &From) { + VarDecl *Var = nullptr; + if (From.capturesVariable()) { + Var = cast_or_null<VarDecl>(Importer.Import(From.getCapturedVar())); + if (!Var) + return None; + } + + return LambdaCapture(Importer.Import(From.getLocation()), From.isImplicit(), + From.getCaptureKind(), Var, + From.isPackExpansion() + ? Importer.Import(From.getEllipsisLoc()) + : SourceLocation()); +} + +Expr *ASTNodeImporter::VisitLambdaExpr(LambdaExpr *LE) { + CXXRecordDecl *FromClass = LE->getLambdaClass(); + auto *ToClass = dyn_cast_or_null<CXXRecordDecl>(Importer.Import(FromClass)); + if (!ToClass) + return nullptr; + + // NOTE: lambda classes are created with BeingDefined flag set up. + // It means that ImportDefinition doesn't work for them and we should fill it + // manually. + if (ToClass->isBeingDefined()) { + for (auto FromField : FromClass->fields()) { + auto *ToField = cast_or_null<FieldDecl>(Importer.Import(FromField)); + if (!ToField) + return nullptr; + } + } + + auto *ToCallOp = dyn_cast_or_null<CXXMethodDecl>( + Importer.Import(LE->getCallOperator())); + if (!ToCallOp) + return nullptr; + + ToClass->completeDefinition(); + + unsigned NumCaptures = LE->capture_size(); + SmallVector<LambdaCapture, 8> Captures; + Captures.reserve(NumCaptures); + for (const auto &FromCapture : LE->captures()) { + if (auto ToCapture = ImportLambdaCapture(FromCapture)) + Captures.push_back(*ToCapture); + else + return nullptr; + } + + SmallVector<Expr *, 8> InitCaptures(NumCaptures); + if (ImportContainerChecked(LE->capture_inits(), InitCaptures)) + return nullptr; + + return LambdaExpr::Create(Importer.getToContext(), ToClass, + Importer.Import(LE->getIntroducerRange()), + LE->getCaptureDefault(), + Importer.Import(LE->getCaptureDefaultLoc()), + Captures, + LE->hasExplicitParameters(), + LE->hasExplicitResultType(), + InitCaptures, + Importer.Import(LE->getLocEnd()), + LE->containsUnexpandedParameterPack()); +} + Expr *ASTNodeImporter::VisitInitListExpr(InitListExpr *ILE) { QualType T = Importer.Import(ILE->getType()); if (T.isNull()) return nullptr; - llvm::SmallVector<Expr *, 4> Exprs(ILE->getNumInits()); + SmallVector<Expr *, 4> Exprs(ILE->getNumInits()); if (ImportContainerChecked(ILE->inits(), Exprs)) return nullptr; @@ -5940,15 +6740,14 @@ Expr *ASTNodeImporter::VisitInitListExpr(InitListExpr *ILE) { } if (FieldDecl *FromFD = ILE->getInitializedFieldInUnion()) { - FieldDecl *ToFD = cast_or_null<FieldDecl>(Importer.Import(FromFD)); + auto *ToFD = cast_or_null<FieldDecl>(Importer.Import(FromFD)); if (!ToFD) return nullptr; To->setInitializedFieldInUnion(ToFD); } if (InitListExpr *SyntForm = ILE->getSyntacticForm()) { - InitListExpr *ToSyntForm = cast_or_null<InitListExpr>( - Importer.Import(SyntForm)); + auto *ToSyntForm = cast_or_null<InitListExpr>(Importer.Import(SyntForm)); if (!ToSyntForm) return nullptr; To->setSyntacticForm(ToSyntForm); @@ -5961,6 +6760,35 @@ Expr *ASTNodeImporter::VisitInitListExpr(InitListExpr *ILE) { return To; } +Expr *ASTNodeImporter::VisitCXXStdInitializerListExpr( + CXXStdInitializerListExpr *E) { + QualType T = Importer.Import(E->getType()); + if (T.isNull()) + return nullptr; + + Expr *SE = Importer.Import(E->getSubExpr()); + if (!SE) + return nullptr; + + return new (Importer.getToContext()) CXXStdInitializerListExpr(T, SE); +} + +Expr *ASTNodeImporter::VisitCXXInheritedCtorInitExpr( + CXXInheritedCtorInitExpr *E) { + QualType T = Importer.Import(E->getType()); + if (T.isNull()) + return nullptr; + + auto *Ctor = cast_or_null<CXXConstructorDecl>(Importer.Import( + E->getConstructor())); + if (!Ctor) + return nullptr; + + return new (Importer.getToContext()) CXXInheritedCtorInitExpr( + Importer.Import(E->getLocation()), T, Ctor, + E->constructsVBase(), E->inheritedFromVBase()); +} + Expr *ASTNodeImporter::VisitArrayInitLoopExpr(ArrayInitLoopExpr *E) { QualType ToType = Importer.Import(E->getType()); if (ToType.isNull()) @@ -5986,8 +6814,7 @@ Expr *ASTNodeImporter::VisitArrayInitIndexExpr(ArrayInitIndexExpr *E) { } Expr *ASTNodeImporter::VisitCXXDefaultInitExpr(CXXDefaultInitExpr *DIE) { - FieldDecl *ToField = llvm::dyn_cast_or_null<FieldDecl>( - Importer.Import(DIE->getField())); + auto *ToField = dyn_cast_or_null<FieldDecl>(Importer.Import(DIE->getField())); if (!ToField && DIE->getField()) return nullptr; @@ -6029,14 +6856,13 @@ Expr *ASTNodeImporter::VisitCXXNamedCastExpr(CXXNamedCastExpr *E) { } } - Expr *ASTNodeImporter::VisitSubstNonTypeTemplateParmExpr( SubstNonTypeTemplateParmExpr *E) { QualType T = Importer.Import(E->getType()); if (T.isNull()) return nullptr; - NonTypeTemplateParmDecl *Param = cast_or_null<NonTypeTemplateParmDecl>( + auto *Param = cast_or_null<NonTypeTemplateParmDecl>( Importer.Import(E->getParameter())); if (!Param) return nullptr; @@ -6070,6 +6896,28 @@ Expr *ASTNodeImporter::VisitTypeTraitExpr(TypeTraitExpr *E) { E->getTrait(), ToArgs, Importer.Import(E->getLocEnd()), ToValue); } +Expr *ASTNodeImporter::VisitCXXTypeidExpr(CXXTypeidExpr *E) { + QualType ToType = Importer.Import(E->getType()); + if (ToType.isNull()) + return nullptr; + + if (E->isTypeOperand()) { + TypeSourceInfo *TSI = Importer.Import(E->getTypeOperandSourceInfo()); + if (!TSI) + return nullptr; + + return new (Importer.getToContext()) + CXXTypeidExpr(ToType, TSI, Importer.Import(E->getSourceRange())); + } + + Expr *Op = Importer.Import(E->getExprOperand()); + if (!Op) + return nullptr; + + return new (Importer.getToContext()) + CXXTypeidExpr(ToType, Op, Importer.Import(E->getSourceRange())); +} + void ASTNodeImporter::ImportOverrides(CXXMethodDecl *ToMethod, CXXMethodDecl *FromMethod) { for (auto *FromOverriddenMethod : FromMethod->overridden_methods()) @@ -6081,19 +6929,18 @@ void ASTNodeImporter::ImportOverrides(CXXMethodDecl *ToMethod, ASTImporter::ASTImporter(ASTContext &ToContext, FileManager &ToFileManager, ASTContext &FromContext, FileManager &FromFileManager, bool MinimalImport) - : ToContext(ToContext), FromContext(FromContext), - ToFileManager(ToFileManager), FromFileManager(FromFileManager), - Minimal(MinimalImport), LastDiagFromFrom(false) -{ + : ToContext(ToContext), FromContext(FromContext), + ToFileManager(ToFileManager), FromFileManager(FromFileManager), + Minimal(MinimalImport) { ImportedDecls[FromContext.getTranslationUnitDecl()] = ToContext.getTranslationUnitDecl(); } -ASTImporter::~ASTImporter() { } +ASTImporter::~ASTImporter() = default; QualType ASTImporter::Import(QualType FromT) { if (FromT.isNull()) - return QualType(); + return {}; const Type *fromTy = FromT.getTypePtr(); @@ -6129,10 +6976,17 @@ TypeSourceInfo *ASTImporter::Import(TypeSourceInfo *FromTSI) { Import(FromTSI->getTypeLoc().getLocStart())); } +Attr *ASTImporter::Import(const Attr *FromAttr) { + Attr *ToAttr = FromAttr->clone(ToContext); + ToAttr->setRange(Import(FromAttr->getRange())); + return ToAttr; +} + Decl *ASTImporter::GetAlreadyImportedOrNull(Decl *FromD) { llvm::DenseMap<Decl *, Decl *>::iterator Pos = ImportedDecls.find(FromD); if (Pos != ImportedDecls.end()) { Decl *ToD = Pos->second; + // FIXME: move this call to ImportDeclParts(). ASTNodeImporter(*this).ImportDefinitionIfNeeded(FromD, ToD); return ToD; } else { @@ -6146,44 +7000,22 @@ Decl *ASTImporter::Import(Decl *FromD) { ASTNodeImporter Importer(*this); - // Check whether we've already imported this declaration. - llvm::DenseMap<Decl *, Decl *>::iterator Pos = ImportedDecls.find(FromD); - if (Pos != ImportedDecls.end()) { - Decl *ToD = Pos->second; - Importer.ImportDefinitionIfNeeded(FromD, ToD); + // Check whether we've already imported this declaration. + Decl *ToD = GetAlreadyImportedOrNull(FromD); + if (ToD) { + // If FromD has some updated flags after last import, apply it + updateFlags(FromD, ToD); return ToD; } - - // Import the type - Decl *ToD = Importer.Visit(FromD); + + // Import the type. + ToD = Importer.Visit(FromD); if (!ToD) return nullptr; - // Record the imported declaration. - ImportedDecls[FromD] = ToD; - - if (TagDecl *FromTag = dyn_cast<TagDecl>(FromD)) { - // Keep track of anonymous tags that have an associated typedef. - if (FromTag->getTypedefNameForAnonDecl()) - AnonTagsWithPendingTypedefs.push_back(FromTag); - } else if (TypedefNameDecl *FromTypedef = dyn_cast<TypedefNameDecl>(FromD)) { - // When we've finished transforming a typedef, see whether it was the - // typedef for an anonymous tag. - for (SmallVectorImpl<TagDecl *>::iterator - FromTag = AnonTagsWithPendingTypedefs.begin(), - FromTagEnd = AnonTagsWithPendingTypedefs.end(); - FromTag != FromTagEnd; ++FromTag) { - if ((*FromTag)->getTypedefNameForAnonDecl() == FromTypedef) { - if (TagDecl *ToTag = cast_or_null<TagDecl>(Import(*FromTag))) { - // We found the typedef for an anonymous tag; link them. - ToTag->setTypedefNameForAnonDecl(cast<TypedefNameDecl>(ToD)); - AnonTagsWithPendingTypedefs.erase(FromTag); - break; - } - } - } - } - + // Notify subclasses. + Imported(FromD, ToD); + return ToD; } @@ -6191,14 +7023,14 @@ DeclContext *ASTImporter::ImportContext(DeclContext *FromDC) { if (!FromDC) return FromDC; - DeclContext *ToDC = cast_or_null<DeclContext>(Import(cast<Decl>(FromDC))); + auto *ToDC = cast_or_null<DeclContext>(Import(cast<Decl>(FromDC))); if (!ToDC) return nullptr; // When we're using a record/enum/Objective-C class/protocol as a context, we // need it to have a definition. - if (RecordDecl *ToRecord = dyn_cast<RecordDecl>(ToDC)) { - RecordDecl *FromRecord = cast<RecordDecl>(FromDC); + if (auto *ToRecord = dyn_cast<RecordDecl>(ToDC)) { + auto *FromRecord = cast<RecordDecl>(FromDC); if (ToRecord->isCompleteDefinition()) { // Do nothing. } else if (FromRecord->isCompleteDefinition()) { @@ -6207,8 +7039,8 @@ DeclContext *ASTImporter::ImportContext(DeclContext *FromDC) { } else { CompleteDecl(ToRecord); } - } else if (EnumDecl *ToEnum = dyn_cast<EnumDecl>(ToDC)) { - EnumDecl *FromEnum = cast<EnumDecl>(FromDC); + } else if (auto *ToEnum = dyn_cast<EnumDecl>(ToDC)) { + auto *FromEnum = cast<EnumDecl>(FromDC); if (ToEnum->isCompleteDefinition()) { // Do nothing. } else if (FromEnum->isCompleteDefinition()) { @@ -6217,8 +7049,8 @@ DeclContext *ASTImporter::ImportContext(DeclContext *FromDC) { } else { CompleteDecl(ToEnum); } - } else if (ObjCInterfaceDecl *ToClass = dyn_cast<ObjCInterfaceDecl>(ToDC)) { - ObjCInterfaceDecl *FromClass = cast<ObjCInterfaceDecl>(FromDC); + } else if (auto *ToClass = dyn_cast<ObjCInterfaceDecl>(ToDC)) { + auto *FromClass = cast<ObjCInterfaceDecl>(FromDC); if (ToClass->getDefinition()) { // Do nothing. } else if (ObjCInterfaceDecl *FromDef = FromClass->getDefinition()) { @@ -6227,8 +7059,8 @@ DeclContext *ASTImporter::ImportContext(DeclContext *FromDC) { } else { CompleteDecl(ToClass); } - } else if (ObjCProtocolDecl *ToProto = dyn_cast<ObjCProtocolDecl>(ToDC)) { - ObjCProtocolDecl *FromProto = cast<ObjCProtocolDecl>(FromDC); + } else if (auto *ToProto = dyn_cast<ObjCProtocolDecl>(ToDC)) { + auto *FromProto = cast<ObjCProtocolDecl>(FromDC); if (ToProto->getDefinition()) { // Do nothing. } else if (ObjCProtocolDecl *FromDef = FromProto->getDefinition()) { @@ -6283,14 +7115,14 @@ NestedNameSpecifier *ASTImporter::Import(NestedNameSpecifier *FromNNS) { return nullptr; case NestedNameSpecifier::Namespace: - if (NamespaceDecl *NS = - cast_or_null<NamespaceDecl>(Import(FromNNS->getAsNamespace()))) { + if (auto *NS = + cast_or_null<NamespaceDecl>(Import(FromNNS->getAsNamespace()))) { return NestedNameSpecifier::Create(ToContext, prefix, NS); } return nullptr; case NestedNameSpecifier::NamespaceAlias: - if (NamespaceAliasDecl *NSAD = + if (auto *NSAD = cast_or_null<NamespaceAliasDecl>(Import(FromNNS->getAsNamespaceAlias()))) { return NestedNameSpecifier::Create(ToContext, prefix, NSAD); } @@ -6300,7 +7132,7 @@ NestedNameSpecifier *ASTImporter::Import(NestedNameSpecifier *FromNNS) { return NestedNameSpecifier::GlobalSpecifier(ToContext); case NestedNameSpecifier::Super: - if (CXXRecordDecl *RD = + if (auto *RD = cast_or_null<CXXRecordDecl>(Import(FromNNS->getAsRecordDecl()))) { return NestedNameSpecifier::SuperSpecifier(ToContext, RD); } @@ -6396,22 +7228,20 @@ NestedNameSpecifierLoc ASTImporter::Import(NestedNameSpecifierLoc FromNNS) { TemplateName ASTImporter::Import(TemplateName From) { switch (From.getKind()) { case TemplateName::Template: - if (TemplateDecl *ToTemplate - = cast_or_null<TemplateDecl>(Import(From.getAsTemplateDecl()))) + if (auto *ToTemplate = + cast_or_null<TemplateDecl>(Import(From.getAsTemplateDecl()))) return TemplateName(ToTemplate); - return TemplateName(); + return {}; case TemplateName::OverloadedTemplate: { OverloadedTemplateStorage *FromStorage = From.getAsOverloadedTemplate(); UnresolvedSet<2> ToTemplates; - for (OverloadedTemplateStorage::iterator I = FromStorage->begin(), - E = FromStorage->end(); - I != E; ++I) { - if (NamedDecl *To = cast_or_null<NamedDecl>(Import(*I))) + for (auto *I : *FromStorage) { + if (auto *To = cast_or_null<NamedDecl>(Import(I))) ToTemplates.addDecl(To); else - return TemplateName(); + return {}; } return ToContext.getOverloadedTemplateName(ToTemplates.begin(), ToTemplates.end()); @@ -6421,22 +7251,22 @@ TemplateName ASTImporter::Import(TemplateName From) { QualifiedTemplateName *QTN = From.getAsQualifiedTemplateName(); NestedNameSpecifier *Qualifier = Import(QTN->getQualifier()); if (!Qualifier) - return TemplateName(); + return {}; - if (TemplateDecl *ToTemplate - = cast_or_null<TemplateDecl>(Import(From.getAsTemplateDecl()))) + if (auto *ToTemplate = + cast_or_null<TemplateDecl>(Import(From.getAsTemplateDecl()))) return ToContext.getQualifiedTemplateName(Qualifier, QTN->hasTemplateKeyword(), ToTemplate); - - return TemplateName(); + + return {}; } case TemplateName::DependentTemplate: { DependentTemplateName *DTN = From.getAsDependentTemplateName(); NestedNameSpecifier *Qualifier = Import(DTN->getQualifier()); if (!Qualifier) - return TemplateName(); + return {}; if (DTN->isIdentifier()) { return ToContext.getDependentTemplateName(Qualifier, @@ -6449,13 +7279,14 @@ TemplateName ASTImporter::Import(TemplateName From) { case TemplateName::SubstTemplateTemplateParm: { SubstTemplateTemplateParmStorage *subst = From.getAsSubstTemplateTemplateParm(); - TemplateTemplateParmDecl *param - = cast_or_null<TemplateTemplateParmDecl>(Import(subst->getParameter())); + auto *param = + cast_or_null<TemplateTemplateParmDecl>(Import(subst->getParameter())); if (!param) - return TemplateName(); + return {}; TemplateName replacement = Import(subst->getReplacement()); - if (replacement.isNull()) return TemplateName(); + if (replacement.isNull()) + return {}; return ToContext.getSubstTemplateTemplateParm(param, replacement); } @@ -6463,17 +7294,17 @@ TemplateName ASTImporter::Import(TemplateName From) { case TemplateName::SubstTemplateTemplateParmPack: { SubstTemplateTemplateParmPackStorage *SubstPack = From.getAsSubstTemplateTemplateParmPack(); - TemplateTemplateParmDecl *Param - = cast_or_null<TemplateTemplateParmDecl>( - Import(SubstPack->getParameterPack())); + auto *Param = + cast_or_null<TemplateTemplateParmDecl>( + Import(SubstPack->getParameterPack())); if (!Param) - return TemplateName(); + return {}; ASTNodeImporter Importer(*this); TemplateArgument ArgPack = Importer.ImportTemplateArgument(SubstPack->getArgumentPack()); if (ArgPack.isNull()) - return TemplateName(); + return {}; return ToContext.getSubstTemplateTemplateParmPack(Param, ArgPack); } @@ -6484,22 +7315,16 @@ TemplateName ASTImporter::Import(TemplateName From) { SourceLocation ASTImporter::Import(SourceLocation FromLoc) { if (FromLoc.isInvalid()) - return SourceLocation(); + return {}; SourceManager &FromSM = FromContext.getSourceManager(); - - // For now, map everything down to its file location, so that we - // don't have to import macro expansions. - // FIXME: Import macro expansions! - FromLoc = FromSM.getFileLoc(FromLoc); + std::pair<FileID, unsigned> Decomposed = FromSM.getDecomposedLoc(FromLoc); - SourceManager &ToSM = ToContext.getSourceManager(); FileID ToFileID = Import(Decomposed.first); if (ToFileID.isInvalid()) - return SourceLocation(); - SourceLocation ret = ToSM.getLocForStartOfFile(ToFileID) - .getLocWithOffset(Decomposed.second); - return ret; + return {}; + SourceManager &ToSM = ToContext.getSourceManager(); + return ToSM.getComposedLoc(ToFileID, Decomposed.second); } SourceRange ASTImporter::Import(SourceRange FromRange) { @@ -6507,44 +7332,58 @@ SourceRange ASTImporter::Import(SourceRange FromRange) { } FileID ASTImporter::Import(FileID FromID) { - llvm::DenseMap<FileID, FileID>::iterator Pos - = ImportedFileIDs.find(FromID); + 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); - assert(FromSLoc.isFile() && "Cannot handle macro expansions yet"); - - // Include location of this file. - SourceLocation ToIncludeLoc = Import(FromSLoc.getFile().getIncludeLoc()); - - // Map the FileID for to the "to" source manager. + + // Map the FromID to the "to" source manager. FileID ToID; - const SrcMgr::ContentCache *Cache = FromSLoc.getFile().getContentCache(); - 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. - const FileEntry *Entry = ToFileManager.getFile(Cache->OrigEntry->getName()); - if (!Entry) - return FileID(); - ToID = ToSM.createFileID(Entry, ToIncludeLoc, - FromSLoc.getFile().getFileCharacteristic()); + if (FromSLoc.isExpansion()) { + const SrcMgr::ExpansionInfo &FromEx = FromSLoc.getExpansion(); + SourceLocation ToSpLoc = Import(FromEx.getSpellingLoc()); + SourceLocation ToExLocS = Import(FromEx.getExpansionLocStart()); + unsigned TokenLen = FromSM.getFileIDSize(FromID); + SourceLocation MLoc; + if (FromEx.isMacroArgExpansion()) { + MLoc = ToSM.createMacroArgExpansionLoc(ToSpLoc, ToExLocS, TokenLen); + } else { + SourceLocation ToExLocE = Import(FromEx.getExpansionLocEnd()); + MLoc = ToSM.createExpansionLoc(ToSpLoc, ToExLocS, ToExLocE, TokenLen, + FromEx.isExpansionTokenRange()); + } + ToID = ToSM.getFileID(MLoc); } else { - // FIXME: We want to re-use the existing MemoryBuffer! - const llvm::MemoryBuffer * - FromBuf = Cache->getBuffer(FromContext.getDiagnostics(), FromSM); - std::unique_ptr<llvm::MemoryBuffer> ToBuf - = llvm::MemoryBuffer::getMemBufferCopy(FromBuf->getBuffer(), - FromBuf->getBufferIdentifier()); - ToID = ToSM.createFileID(std::move(ToBuf), - FromSLoc.getFile().getFileCharacteristic()); + // Include location of this file. + SourceLocation ToIncludeLoc = Import(FromSLoc.getFile().getIncludeLoc()); + + const SrcMgr::ContentCache *Cache = FromSLoc.getFile().getContentCache(); + 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. + const FileEntry *Entry = + ToFileManager.getFile(Cache->OrigEntry->getName()); + if (!Entry) + return {}; + ToID = ToSM.createFileID(Entry, ToIncludeLoc, + FromSLoc.getFile().getFileCharacteristic()); + } else { + // FIXME: We want to re-use the existing MemoryBuffer! + const llvm::MemoryBuffer *FromBuf = + Cache->getBuffer(FromContext.getDiagnostics(), FromSM); + std::unique_ptr<llvm::MemoryBuffer> ToBuf = + llvm::MemoryBuffer::getMemBufferCopy(FromBuf->getBuffer(), + FromBuf->getBufferIdentifier()); + ToID = ToSM.createFileID(std::move(ToBuf), + FromSLoc.getFile().getFileCharacteristic()); + } } - - + ImportedFileIDs[FromID] = ToID; return ToID; } @@ -6565,8 +7404,7 @@ CXXCtorInitializer *ASTImporter::Import(CXXCtorInitializer *From) { From->isPackExpansion() ? Import(From->getEllipsisLoc()) : SourceLocation()); } else if (From->isMemberInitializer()) { - FieldDecl *ToField = - llvm::cast_or_null<FieldDecl>(Import(From->getMember())); + auto *ToField = cast_or_null<FieldDecl>(Import(From->getMember())); if (!ToField && From->getMember()) return nullptr; @@ -6574,7 +7412,7 @@ CXXCtorInitializer *ASTImporter::Import(CXXCtorInitializer *From) { ToContext, ToField, Import(From->getMemberLocation()), Import(From->getLParenLoc()), ToExpr, Import(From->getRParenLoc())); } else if (From->isIndirectMemberInitializer()) { - IndirectFieldDecl *ToIField = llvm::cast_or_null<IndirectFieldDecl>( + auto *ToIField = cast_or_null<IndirectFieldDecl>( Import(From->getIndirectMember())); if (!ToIField && From->getIndirectMember()) return nullptr; @@ -6595,7 +7433,6 @@ CXXCtorInitializer *ASTImporter::Import(CXXCtorInitializer *From) { } } - CXXBaseSpecifier *ASTImporter::Import(const CXXBaseSpecifier *BaseSpec) { auto Pos = ImportedCXXBaseSpecifiers.find(BaseSpec); if (Pos != ImportedCXXBaseSpecifiers.end()) @@ -6616,10 +7453,10 @@ void ASTImporter::ImportDefinition(Decl *From) { if (!To) return; - if (DeclContext *FromDC = cast<DeclContext>(From)) { + if (auto *FromDC = cast<DeclContext>(From)) { ASTNodeImporter Importer(*this); - if (RecordDecl *ToRecord = dyn_cast<RecordDecl>(To)) { + if (auto *ToRecord = dyn_cast<RecordDecl>(To)) { if (!ToRecord->getDefinition()) { Importer.ImportDefinition(cast<RecordDecl>(FromDC), ToRecord, ASTNodeImporter::IDK_Everything); @@ -6627,7 +7464,7 @@ void ASTImporter::ImportDefinition(Decl *From) { } } - if (EnumDecl *ToEnum = dyn_cast<EnumDecl>(To)) { + if (auto *ToEnum = dyn_cast<EnumDecl>(To)) { if (!ToEnum->getDefinition()) { Importer.ImportDefinition(cast<EnumDecl>(FromDC), ToEnum, ASTNodeImporter::IDK_Everything); @@ -6635,7 +7472,7 @@ void ASTImporter::ImportDefinition(Decl *From) { } } - if (ObjCInterfaceDecl *ToIFace = dyn_cast<ObjCInterfaceDecl>(To)) { + if (auto *ToIFace = dyn_cast<ObjCInterfaceDecl>(To)) { if (!ToIFace->getDefinition()) { Importer.ImportDefinition(cast<ObjCInterfaceDecl>(FromDC), ToIFace, ASTNodeImporter::IDK_Everything); @@ -6643,7 +7480,7 @@ void ASTImporter::ImportDefinition(Decl *From) { } } - if (ObjCProtocolDecl *ToProto = dyn_cast<ObjCProtocolDecl>(To)) { + if (auto *ToProto = dyn_cast<ObjCProtocolDecl>(To)) { if (!ToProto->getDefinition()) { Importer.ImportDefinition(cast<ObjCProtocolDecl>(FromDC), ToProto, ASTNodeImporter::IDK_Everything); @@ -6657,7 +7494,7 @@ void ASTImporter::ImportDefinition(Decl *From) { DeclarationName ASTImporter::Import(DeclarationName FromName) { if (!FromName) - return DeclarationName(); + return {}; switch (FromName.getNameKind()) { case DeclarationName::Identifier: @@ -6671,7 +7508,7 @@ DeclarationName ASTImporter::Import(DeclarationName FromName) { case DeclarationName::CXXConstructorName: { QualType T = Import(FromName.getCXXNameType()); if (T.isNull()) - return DeclarationName(); + return {}; return ToContext.DeclarationNames.getCXXConstructorName( ToContext.getCanonicalType(T)); @@ -6680,24 +7517,24 @@ DeclarationName ASTImporter::Import(DeclarationName FromName) { case DeclarationName::CXXDestructorName: { QualType T = Import(FromName.getCXXNameType()); if (T.isNull()) - return DeclarationName(); + return {}; return ToContext.DeclarationNames.getCXXDestructorName( ToContext.getCanonicalType(T)); } case DeclarationName::CXXDeductionGuideName: { - TemplateDecl *Template = cast_or_null<TemplateDecl>( + auto *Template = cast_or_null<TemplateDecl>( Import(FromName.getCXXDeductionGuideTemplate())); if (!Template) - return DeclarationName(); + return {}; return ToContext.DeclarationNames.getCXXDeductionGuideName(Template); } case DeclarationName::CXXConversionFunctionName: { QualType T = Import(FromName.getCXXNameType()); if (T.isNull()) - return DeclarationName(); + return {}; return ToContext.DeclarationNames.getCXXConversionFunctionName( ToContext.getCanonicalType(T)); @@ -6733,7 +7570,7 @@ IdentifierInfo *ASTImporter::Import(const IdentifierInfo *FromId) { Selector ASTImporter::Import(Selector FromSel) { if (FromSel.isNull()) - return Selector(); + return {}; SmallVector<IdentifierInfo *, 4> Idents; Idents.push_back(Import(FromSel.getIdentifierInfoForSlot(0))); @@ -6767,36 +7604,31 @@ DiagnosticBuilder ASTImporter::FromDiag(SourceLocation Loc, unsigned DiagID) { } void ASTImporter::CompleteDecl (Decl *D) { - if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) { + if (auto *ID = dyn_cast<ObjCInterfaceDecl>(D)) { if (!ID->getDefinition()) ID->startDefinition(); } - else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) { + else if (auto *PD = dyn_cast<ObjCProtocolDecl>(D)) { if (!PD->getDefinition()) PD->startDefinition(); } - else if (TagDecl *TD = dyn_cast<TagDecl>(D)) { + 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"); + assert(0 && "CompleteDecl called on a Decl that can't be completed"); } } -Decl *ASTImporter::Imported(Decl *From, Decl *To) { - if (From->hasAttrs()) { - for (Attr *FromAttr : From->getAttrs()) - To->addAttr(FromAttr->clone(To->getASTContext())); - } - if (From->isUsed()) { - To->setIsUsed(); - } - if (From->isImplicit()) { - To->setImplicit(); - } +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; return To; } @@ -6809,6 +7641,7 @@ bool ASTImporter::IsStructurallyEquivalent(QualType From, QualType To, return true; StructuralEquivalenceContext Ctx(FromContext, ToContext, NonEquivalentDecls, - false, Complain); - return Ctx.IsStructurallyEquivalent(From, To); + getStructuralEquivalenceKind(*this), false, + Complain); + return Ctx.IsEquivalent(From, To); } |