Index: include/clang/ASTMatchers/ASTMatchers.h =================================================================== --- include/clang/ASTMatchers/ASTMatchers.h +++ include/clang/ASTMatchers/ASTMatchers.h @@ -5444,6 +5444,22 @@ CUDAKernelCallExpr> cudaKernelCallExpr; +/// \brief Matches member access expressions where the member could not +/// be resolved because the base member was dependent. +/// +/// Example matches d.t, and also (&d)->t +/// \code +/// template class C {T t; }; +/// template void foo() { +/// C d; +/// d.t = T(); +/// (&d)->t = T(); +/// } +/// \endcode +const internal::VariadicDynCastAllOfMatcher + cxxDependentScopeMemberExpr; + + /// \brief Matches expressions that resolve to a null pointer constant, such as /// GNU's __null, C++11's nullptr, or C's NULL macro. /// Index: lib/AST/ASTImporter.cpp =================================================================== --- lib/AST/ASTImporter.cpp +++ lib/AST/ASTImporter.cpp @@ -159,6 +159,7 @@ Decl *VisitFieldDecl(FieldDecl *D); Decl *VisitIndirectFieldDecl(IndirectFieldDecl *D); Decl *VisitFriendDecl(FriendDecl *D); + Decl *VisitFunctionTemplateDecl(FunctionTemplateDecl *D); Decl *VisitObjCIvarDecl(ObjCIvarDecl *D); Decl *VisitVarDecl(VarDecl *D); Decl *VisitImplicitParamDecl(ImplicitParamDecl *D); @@ -265,6 +266,7 @@ Expr *VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E); Expr *VisitCXXNewExpr(CXXNewExpr *CE); Expr *VisitCXXDeleteExpr(CXXDeleteExpr *E); + Expr *VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E); Expr *VisitCXXConstructExpr(CXXConstructExpr *E); Expr *VisitCXXMemberCallExpr(CXXMemberCallExpr *E); Expr *VisitExprWithCleanups(ExprWithCleanups *EWC); @@ -3482,6 +3484,32 @@ return FrD; } +Decl *ASTNodeImporter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { + DeclContext *DC, *LexicalDC; + DeclarationName Name; + SourceLocation Loc; + NamedDecl *ToD; + + if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) + return nullptr; + if (!DC) + return nullptr; + if (ToD) + return ToD; + + TemplateParameterList *Params = ImportTemplateParameterList( + D->getTemplateParameters()); + if (!Params) + return nullptr; + + NamedDecl *ToDecl = cast_or_null(D->getTemplatedDecl()); + if (!ToDecl) + return nullptr; + + return FunctionTemplateDecl::Create(Importer.getToContext(), DC, Loc, + Name, Params, ToDecl); +} + Decl *ASTNodeImporter::VisitObjCIvarDecl(ObjCIvarDecl *D) { // Import the major distinguishing characteristics of an ivar. DeclContext *DC, *LexicalDC; @@ -6363,6 +6391,40 @@ Importer.Import(E->getLocStart())); } +Expr *ASTNodeImporter::VisitCXXDependentScopeMemberExpr( + CXXDependentScopeMemberExpr *E) { + Expr *Base = E->getBase(); + if (!Base) + return nullptr; + + QualType BaseType = E->getBaseType(); + if (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; + } + + return CXXDependentScopeMemberExpr::Create(Importer.getToContext(), + Base, BaseType, + E->isArrow(), + E->getOperatorLoc(), + E->getQualifierLoc(), + E->getTemplateKeywordLoc(), + E->getFirstQualifierFoundInScope(), + E->getMemberNameInfo(), + ResInfo); +} + Expr *ASTNodeImporter::VisitCXXConstructExpr(CXXConstructExpr *E) { QualType T = Importer.Import(E->getType()); if (T.isNull()) Index: lib/ASTMatchers/Dynamic/Registry.cpp =================================================================== --- lib/ASTMatchers/Dynamic/Registry.cpp +++ lib/ASTMatchers/Dynamic/Registry.cpp @@ -141,6 +141,7 @@ REGISTER_MATCHER(cxxCtorInitializer); REGISTER_MATCHER(cxxDefaultArgExpr); REGISTER_MATCHER(cxxDeleteExpr); + REGISTER_MATCHER(cxxDependentScopeMemberExpr); REGISTER_MATCHER(cxxDestructorDecl); REGISTER_MATCHER(cxxDynamicCastExpr); REGISTER_MATCHER(cxxForRangeStmt); Index: unittests/AST/ASTImporterTest.cpp =================================================================== --- unittests/AST/ASTImporterTest.cpp +++ unittests/AST/ASTImporterTest.cpp @@ -474,5 +474,54 @@ } +TEST(ImportDecl, ImportFunctionTemplateDecl) { + MatchVerifier Verifier; + EXPECT_TRUE( + testImport( + "template void declToImport() { };", + Lang_CXX, "", Lang_CXX, Verifier, + functionTemplateDecl())); +} + + +TEST(ImportExpr, ImportCXXDependentScopeMemberExpr) { + MatchVerifier Verifier; + EXPECT_TRUE( + testImport( + "template class C { T t; };" + "template void declToImport() {" + "C d;" + "d.t = T();" + "}", + Lang_CXX, "", Lang_CXX, Verifier, + functionTemplateDecl( + has( + functionDecl( + has( + compoundStmt( + has( + binaryOperator( + has( + cxxDependentScopeMemberExpr())))))))))); + EXPECT_TRUE( + testImport( + "template class C { T t; };" + "template void declToImport() {" + "C d;" + "(&d)->t = T();" + "}", + Lang_CXX, "", Lang_CXX, Verifier, + functionTemplateDecl( + has( + functionDecl( + has( + compoundStmt( + has( + binaryOperator( + has( + cxxDependentScopeMemberExpr())))))))))); +} + + } // end namespace ast_matchers } // end namespace clang