Index: lib/AST/ASTImporter.cpp =================================================================== --- lib/AST/ASTImporter.cpp +++ lib/AST/ASTImporter.cpp @@ -139,6 +139,8 @@ bool Complain = true); bool IsStructuralMatch(EnumDecl *FromEnum, EnumDecl *ToRecord); bool IsStructuralMatch(EnumConstantDecl *FromEC, EnumConstantDecl *ToEC); + bool IsStructuralMatch(FunctionTemplateDecl *From, + FunctionTemplateDecl *To); bool IsStructuralMatch(ClassTemplateDecl *From, ClassTemplateDecl *To); bool IsStructuralMatch(VarTemplateDecl *From, VarTemplateDecl *To); Decl *VisitDecl(Decl *D); @@ -185,6 +187,7 @@ ClassTemplateSpecializationDecl *D); Decl *VisitVarTemplateDecl(VarTemplateDecl *D); Decl *VisitVarTemplateSpecializationDecl(VarTemplateSpecializationDecl *D); + Decl *VisitFunctionTemplateDecl(FunctionTemplateDecl *D); // Importing statements DeclGroupRef ImportDeclGroup(DeclGroupRef DG); @@ -269,6 +272,7 @@ Expr *VisitCXXDeleteExpr(CXXDeleteExpr *E); Expr *VisitCXXConstructExpr(CXXConstructExpr *E); Expr *VisitCXXMemberCallExpr(CXXMemberCallExpr *E); + Expr *VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E); Expr *VisitExprWithCleanups(ExprWithCleanups *EWC); Expr *VisitCXXThisExpr(CXXThisExpr *E); Expr *VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E); @@ -1243,6 +1247,14 @@ return Ctx.IsStructurallyEquivalent(FromEnum, ToEnum); } +bool ASTNodeImporter::IsStructuralMatch(FunctionTemplateDecl *From, + FunctionTemplateDecl *To) { + StructuralEquivalenceContext Ctx( + Importer.getFromContext(), Importer.getToContext(), + Importer.getNonEquivalentDecls(), false, false); + return Ctx.IsStructurallyEquivalent(From, To); +} + bool ASTNodeImporter::IsStructuralMatch(EnumConstantDecl *FromEC, EnumConstantDecl *ToEC) { @@ -3835,6 +3847,70 @@ return D2; } +Decl *ASTNodeImporter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { + DeclContext *DC, *LexicalDC; + DeclarationName Name; + SourceLocation Loc; + NamedDecl *ToD; + + if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) + return nullptr; + assert(DC && "Null DeclContext after importing decl parts"); + if (ToD) + return ToD; + + // 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()) { + unsigned IDNS = Decl::IDNS_Ordinary; + SmallVector FoundDecls; + DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls); + for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { + if (!FoundDecls[I]->isInIdentifierNamespace(IDNS)) + continue; + + if (FunctionTemplateDecl *FoundFunction = + dyn_cast(FoundDecls[I])) { + if (FoundFunction->hasExternalFormalLinkage() && + D->hasExternalFormalLinkage()) { + if (IsStructuralMatch(D, FoundFunction)) { + Importer.Imported(D, FoundFunction); + // FIXME: Actually try to merge the body and other attributes. + return FoundFunction; + } + } + } + } + } + + TemplateParameterList *Params = + ImportTemplateParameterList(D->getTemplateParameters()); + if (!Params) + return nullptr; + + FunctionDecl *TemplatedFD = + cast_or_null(Importer.Import(D->getTemplatedDecl())); + if (!TemplatedFD) + return nullptr; + + FunctionTemplateDecl *ToFunc = FunctionTemplateDecl::Create( + Importer.getToContext(), DC, Loc, Name, Params, TemplatedFD); + + TemplatedFD->setDescribedFunctionTemplate(ToFunc); + // Import attributes. + for (Attr *A : D->attrs()) { + Attr *ToAttr = A->clone(Importer.getToContext()); + ToAttr->setRange(Importer.Import(A->getRange())); + ToFunc->addAttr(ToAttr); + } + ToFunc->setAccess(D->getAccess()); + ToFunc->setLexicalDeclContext(LexicalDC); + Importer.Imported(D, ToFunc); + + LexicalDC->addDeclInternal(ToFunc); + return ToFunc; +} + //---------------------------------------------------------------------------- // Import Statements //---------------------------------------------------------------------------- @@ -5347,6 +5423,47 @@ E->getObjectKind()); } +Expr *ASTNodeImporter::VisitCXXDependentScopeMemberExpr( + CXXDependentScopeMemberExpr *E) { + + Expr *Base = Importer.Import(E->getBase()); + if (E->getBase() && !Base) + return nullptr; + + QualType BaseType = Importer.Import(E->getBaseType()); + if (!E->getBaseType().isNull() && BaseType.isNull()) + return nullptr; + + TemplateArgumentListInfo ToTAInfo; + TemplateArgumentListInfo *ResInfo = nullptr; + if (E->hasExplicitTemplateArgs()) { + for (const auto &FromLoc : E->template_arguments()) { + bool Error = false; + TemplateArgumentLoc ToTALoc = ImportTemplateArgumentLoc(FromLoc, Error); + if (Error) + return nullptr; + ToTAInfo.addArgument(ToTALoc); + } + ResInfo = &ToTAInfo; + } + + DeclarationName Name = Importer.Import(E->getMember()); + if (E->getMember().isEmpty() && Name.isEmpty()) + return nullptr; + DeclarationNameInfo MemberNameInfo(Name, Importer.Import(E->getMemberLoc())); + // Import additional name location/type info. + ImportDeclarationNameLoc(E->getMemberNameInfo(), MemberNameInfo); + + return CXXDependentScopeMemberExpr::Create( + Importer.getToContext(), Base, BaseType, E->isArrow(), + Importer.Import(E->getOperatorLoc()), + Importer.Import(E->getQualifierLoc()), + Importer.Import(E->getTemplateKeywordLoc()), + cast_or_null( + Importer.Import(E->getFirstQualifierFoundInScope())), + MemberNameInfo, ResInfo); +} + Expr *ASTNodeImporter::VisitCallExpr(CallExpr *E) { QualType T = Importer.Import(E->getType()); if (T.isNull()) Index: unittests/AST/ASTImporterTest.cpp =================================================================== --- unittests/AST/ASTImporterTest.cpp +++ unittests/AST/ASTImporterTest.cpp @@ -472,6 +472,35 @@ has(atomicType())))))))))); } +TEST(ImportDecl, ImportFunctionTemplateDecl) { + MatchVerifier Verifier; + EXPECT_TRUE(testImport("template void declToImport() { };", + Lang_CXX, "", Lang_CXX, Verifier, + functionTemplateDecl())); +} + +const internal::VariadicDynCastAllOfMatcher + cxxDependentScopeMemberExpr; + +TEST(ImportExpr, ImportCXXDependentScopeMemberExpr) { + MatchVerifier Verifier; + EXPECT_TRUE(testImport("template class C { T t; };" + "template void declToImport() {" + "C d;" + "d.t" + "}", + Lang_CXX, "", Lang_CXX, Verifier, + functionTemplateDecl(has(functionDecl(has(compoundStmt( + has(cxxDependentScopeMemberExpr())))))))); + EXPECT_TRUE(testImport("template class C { T t; };" + "template void declToImport() {" + "C d;" + "(&d)->t" + "}", + Lang_CXX, "", Lang_CXX, Verifier, + functionTemplateDecl(has(functionDecl(has(compoundStmt( + has(cxxDependentScopeMemberExpr())))))))); +} } // end namespace ast_matchers } // end namespace clang