Index: cfe/trunk/docs/LibASTMatchersReference.html =================================================================== --- cfe/trunk/docs/LibASTMatchersReference.html +++ cfe/trunk/docs/LibASTMatchersReference.html @@ -866,6 +866,17 @@ +Matcher<Stmt>cxxDependentScopeMemberExprMatcher<CXXDependentScopeMemberExpr>... +
Matches member expressions where the actual member referenced could not be
+resolved because the base expression or the member name was dependent.
+
+Given
+  template <class T> void f() { T t; t.g(); }
+cxxDependentScopeMemberExpr()
+  matches t.g
+
+ + Matcher<Stmt>cxxDynamicCastExprMatcher<CXXDynamicCastExpr>...
Matches a dynamic_cast expression.
 
@@ -1455,6 +1466,20 @@
   matches foo<T>() 
+Matcher<Stmt>unresolvedMemberExprMatcher<UnresolvedMemberExpr>... +
Matches unresolved member expressions.
+
+Given
+  struct X {
+    template <class T> void f();
+    void g();
+  };
+  template <class T> void h() { X x; x.f<T>(); x.g(); }
+unresolvedMemberExpr()
+  matches x.f<T>
+
+ + Matcher<Stmt>userDefinedLiteralMatcher<UserDefinedLiteral>...
Matches user defined literal operator call.
 
@@ -1598,7 +1623,7 @@
   short i = 1;
   int j = 42;
   decltype(i + j) result = i + j;
-decltypeType() 
+decltypeType()
   matches "decltype(i + j)"
 
Index: cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h =================================================================== --- cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h +++ cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h @@ -1141,6 +1141,34 @@ /// matches this->x, x, y.x, a, this->b extern const internal::VariadicDynCastAllOfMatcher memberExpr; +/// Matches unresolved member expressions. +/// +/// Given +/// \code +/// struct X { +/// template void f(); +/// void g(); +/// }; +/// template void h() { X x; x.f(); x.g(); } +/// \endcode +/// unresolvedMemberExpr() +/// matches x.f +extern const internal::VariadicDynCastAllOfMatcher + unresolvedMemberExpr; + +/// Matches member expressions where the actual member referenced could not be +/// resolved because the base expression or the member name was dependent. +/// +/// Given +/// \code +/// template void f() { T t; t.g(); } +/// \endcode +/// cxxDependentScopeMemberExpr() +/// matches t.g +extern const internal::VariadicDynCastAllOfMatcher + cxxDependentScopeMemberExpr; + /// Matches call expressions. /// /// Example matches x.y() and y() Index: cfe/trunk/lib/ASTMatchers/ASTMatchersInternal.cpp =================================================================== --- cfe/trunk/lib/ASTMatchers/ASTMatchersInternal.cpp +++ cfe/trunk/lib/ASTMatchers/ASTMatchersInternal.cpp @@ -610,6 +610,10 @@ const internal::VariadicAllOfMatcher stmt; const internal::VariadicDynCastAllOfMatcher declStmt; const internal::VariadicDynCastAllOfMatcher memberExpr; +const internal::VariadicDynCastAllOfMatcher + unresolvedMemberExpr; +const internal::VariadicDynCastAllOfMatcher + cxxDependentScopeMemberExpr; const internal::VariadicDynCastAllOfMatcher callExpr; const internal::VariadicDynCastAllOfMatcher lambdaExpr; const internal::VariadicDynCastAllOfMatcher Index: cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp =================================================================== --- cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp +++ cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp @@ -167,6 +167,7 @@ REGISTER_MATCHER(cxxCtorInitializer); REGISTER_MATCHER(cxxDefaultArgExpr); REGISTER_MATCHER(cxxDeleteExpr); + REGISTER_MATCHER(cxxDependentScopeMemberExpr); REGISTER_MATCHER(cxxDestructorDecl); REGISTER_MATCHER(cxxDynamicCastExpr); REGISTER_MATCHER(cxxForRangeStmt); @@ -475,6 +476,7 @@ REGISTER_MATCHER(unaryTransformType); REGISTER_MATCHER(unless); REGISTER_MATCHER(unresolvedLookupExpr); + REGISTER_MATCHER(unresolvedMemberExpr); REGISTER_MATCHER(unresolvedUsingTypenameDecl); REGISTER_MATCHER(unresolvedUsingValueDecl); REGISTER_MATCHER(userDefinedLiteral); Index: cfe/trunk/unittests/AST/ASTImporterTest.cpp =================================================================== --- cfe/trunk/unittests/AST/ASTImporterTest.cpp +++ cfe/trunk/unittests/AST/ASTImporterTest.cpp @@ -814,9 +814,6 @@ functionTemplateDecl()); } -const internal::VariadicDynCastAllOfMatcher - cxxDependentScopeMemberExpr; - TEST_P(ImportExpr, ImportCXXDependentScopeMemberExpr) { MatchVerifier Verifier; testImport( @@ -2364,9 +2361,6 @@ cxxRecordDecl(has(typedefDecl(has(dependentNameType()))))))); } -const internal::VariadicDynCastAllOfMatcher - unresolvedMemberExpr; - TEST_P(ImportExpr, UnresolvedMemberExpr) { MatchVerifier Verifier; testImport("struct S { template void mem(); };" Index: cfe/trunk/unittests/ASTMatchers/ASTMatchersNodeTest.cpp =================================================================== --- cfe/trunk/unittests/ASTMatchers/ASTMatchersNodeTest.cpp +++ cfe/trunk/unittests/ASTMatchers/ASTMatchersNodeTest.cpp @@ -422,10 +422,17 @@ TEST(MemberExpression, DoesNotMatchClasses) { EXPECT_TRUE(notMatches("class Y { void x() {} };", memberExpr())); + EXPECT_TRUE(notMatches("class Y { void x() {} };", unresolvedMemberExpr())); + EXPECT_TRUE( + notMatches("class Y { void x() {} };", cxxDependentScopeMemberExpr())); } TEST(MemberExpression, MatchesMemberFunctionCall) { EXPECT_TRUE(matches("class Y { void x() { x(); } };", memberExpr())); + EXPECT_TRUE(matches("class Y { template void x() { x(); } };", + unresolvedMemberExpr())); + EXPECT_TRUE(matches("template void x() { T t; t.f(); }", + cxxDependentScopeMemberExpr())); } TEST(MemberExpression, MatchesVariable) { @@ -435,6 +442,13 @@ matches("class Y { void x() { y; } int y; };", memberExpr())); EXPECT_TRUE( matches("class Y { void x() { Y y; y.y; } int y; };", memberExpr())); + EXPECT_TRUE(matches("template " + "class X : T { void f() { this->T::v; } };", + cxxDependentScopeMemberExpr())); + EXPECT_TRUE(matches("template class X : T { void f() { T::v; } };", + cxxDependentScopeMemberExpr())); + EXPECT_TRUE(matches("template void x() { T t; t.v; }", + cxxDependentScopeMemberExpr())); } TEST(MemberExpression, MatchesStaticVariable) {