shuaiwang created this revision. shuaiwang added a reviewer: aaron.ballman. Herald added a subscriber: cfe-commits.
Repository: rC Clang https://reviews.llvm.org/D50617 Files: docs/LibASTMatchersReference.html include/clang/ASTMatchers/ASTMatchers.h unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp Index: unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp =================================================================== --- unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp +++ unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp @@ -1517,6 +1517,26 @@ "struct X { int m; }; void f(X* x) { x->m; }", memberExpr(hasObjectExpression( hasType(pointsTo(recordDecl(hasName("X")))))))); + EXPECT_TRUE(matches("template <class T> struct X { void f() { T t; t.m; } };", + cxxDependentScopeMemberExpr(hasObjectExpression( + declRefExpr(to(namedDecl(hasName("t")))))))); + EXPECT_TRUE( + matches("template <class T> struct X { void f() { T t; t->m; } };", + cxxDependentScopeMemberExpr(hasObjectExpression( + declRefExpr(to(namedDecl(hasName("t")))))))); +} + +TEST(HasObjectExpression, MatchesBaseOfMemberFunc) { + EXPECT_TRUE(matches( + "struct X { void f(); }; void g(X x) { x.f(); }", + memberExpr(hasObjectExpression(hasType(recordDecl(hasName("X"))))))); + EXPECT_TRUE(matches("struct X { template <class T> void f(); };" + "template <class T> void g(X x) { x.f<T>(); }", + unresolvedMemberExpr(hasObjectExpression( + hasType(recordDecl(hasName("X"))))))); + EXPECT_TRUE(matches("template <class T> void f(T t) { t.g(); }", + cxxDependentScopeMemberExpr(hasObjectExpression( + declRefExpr(to(namedDecl(hasName("t")))))))); } TEST(HasObjectExpression, Index: include/clang/ASTMatchers/ASTMatchers.h =================================================================== --- include/clang/ASTMatchers/ASTMatchers.h +++ include/clang/ASTMatchers/ASTMatchers.h @@ -4806,8 +4806,11 @@ /// matches "x.m" and "m" /// with hasObjectExpression(...) /// matching "x" and the implicit object expression of "m" which has type X*. -AST_MATCHER_P(MemberExpr, hasObjectExpression, - internal::Matcher<Expr>, InnerMatcher) { +AST_POLYMORPHIC_MATCHER_P( + hasObjectExpression, + AST_POLYMORPHIC_SUPPORTED_TYPES(MemberExpr, UnresolvedMemberExpr, + CXXDependentScopeMemberExpr), + internal::Matcher<Expr>, InnerMatcher) { return InnerMatcher.matches(*Node.getBase(), Finder, Builder); } Index: docs/LibASTMatchersReference.html =================================================================== --- docs/LibASTMatchersReference.html +++ docs/LibASTMatchersReference.html @@ -4668,6 +4668,20 @@ </pre></td></tr> +<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXDependentScopeMemberExpr.html">CXXDependentScopeMemberExpr</a>></td><td class="name" onclick="toggle('hasObjectExpression2')"><a name="hasObjectExpression2Anchor">hasObjectExpression</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr> +<tr><td colspan="4" class="doc" id="hasObjectExpression2"><pre>Matches a member expression where the object expression is +matched by a given matcher. + +Given + struct X { int m; }; + void f(X x) { x.m; m; } +memberExpr(hasObjectExpression(hasType(cxxRecordDecl(hasName("X"))))))) + matches "x.m" and "m" +with hasObjectExpression(...) + matching "x" and the implicit object expression of "m" which has type X*. +</pre></td></tr> + + <tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXForRangeStmt.html">CXXForRangeStmt</a>></td><td class="name" onclick="toggle('hasBody3')"><a name="hasBody3Anchor">hasBody</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>> InnerMatcher</td></tr> <tr><td colspan="4" class="doc" id="hasBody3"><pre>Matches a 'for', 'while', 'do while' statement or a function definition that has a given body. @@ -6673,6 +6687,20 @@ </pre></td></tr> +<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1UnresolvedMemberExpr.html">UnresolvedMemberExpr</a>></td><td class="name" onclick="toggle('hasObjectExpression1')"><a name="hasObjectExpression1Anchor">hasObjectExpression</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr> +<tr><td colspan="4" class="doc" id="hasObjectExpression1"><pre>Matches a member expression where the object expression is +matched by a given matcher. + +Given + struct X { int m; }; + void f(X x) { x.m; m; } +memberExpr(hasObjectExpression(hasType(cxxRecordDecl(hasName("X"))))))) + matches "x.m" and "m" +with hasObjectExpression(...) + matching "x" and the implicit object expression of "m" which has type X*. +</pre></td></tr> + + <tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>></td><td class="name" onclick="toggle('hasDeclaration0')"><a name="hasDeclaration0Anchor">hasDeclaration</a></td><td>const Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>> InnerMatcher</td></tr> <tr><td colspan="4" class="doc" id="hasDeclaration0"><pre>Matches a node if the declaration associated with that node matches the given matcher.
Index: unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp =================================================================== --- unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp +++ unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp @@ -1517,6 +1517,26 @@ "struct X { int m; }; void f(X* x) { x->m; }", memberExpr(hasObjectExpression( hasType(pointsTo(recordDecl(hasName("X")))))))); + EXPECT_TRUE(matches("template <class T> struct X { void f() { T t; t.m; } };", + cxxDependentScopeMemberExpr(hasObjectExpression( + declRefExpr(to(namedDecl(hasName("t")))))))); + EXPECT_TRUE( + matches("template <class T> struct X { void f() { T t; t->m; } };", + cxxDependentScopeMemberExpr(hasObjectExpression( + declRefExpr(to(namedDecl(hasName("t")))))))); +} + +TEST(HasObjectExpression, MatchesBaseOfMemberFunc) { + EXPECT_TRUE(matches( + "struct X { void f(); }; void g(X x) { x.f(); }", + memberExpr(hasObjectExpression(hasType(recordDecl(hasName("X"))))))); + EXPECT_TRUE(matches("struct X { template <class T> void f(); };" + "template <class T> void g(X x) { x.f<T>(); }", + unresolvedMemberExpr(hasObjectExpression( + hasType(recordDecl(hasName("X"))))))); + EXPECT_TRUE(matches("template <class T> void f(T t) { t.g(); }", + cxxDependentScopeMemberExpr(hasObjectExpression( + declRefExpr(to(namedDecl(hasName("t")))))))); } TEST(HasObjectExpression, Index: include/clang/ASTMatchers/ASTMatchers.h =================================================================== --- include/clang/ASTMatchers/ASTMatchers.h +++ include/clang/ASTMatchers/ASTMatchers.h @@ -4806,8 +4806,11 @@ /// matches "x.m" and "m" /// with hasObjectExpression(...) /// matching "x" and the implicit object expression of "m" which has type X*. -AST_MATCHER_P(MemberExpr, hasObjectExpression, - internal::Matcher<Expr>, InnerMatcher) { +AST_POLYMORPHIC_MATCHER_P( + hasObjectExpression, + AST_POLYMORPHIC_SUPPORTED_TYPES(MemberExpr, UnresolvedMemberExpr, + CXXDependentScopeMemberExpr), + internal::Matcher<Expr>, InnerMatcher) { return InnerMatcher.matches(*Node.getBase(), Finder, Builder); } Index: docs/LibASTMatchersReference.html =================================================================== --- docs/LibASTMatchersReference.html +++ docs/LibASTMatchersReference.html @@ -4668,6 +4668,20 @@ </pre></td></tr> +<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXDependentScopeMemberExpr.html">CXXDependentScopeMemberExpr</a>></td><td class="name" onclick="toggle('hasObjectExpression2')"><a name="hasObjectExpression2Anchor">hasObjectExpression</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr> +<tr><td colspan="4" class="doc" id="hasObjectExpression2"><pre>Matches a member expression where the object expression is +matched by a given matcher. + +Given + struct X { int m; }; + void f(X x) { x.m; m; } +memberExpr(hasObjectExpression(hasType(cxxRecordDecl(hasName("X"))))))) + matches "x.m" and "m" +with hasObjectExpression(...) + matching "x" and the implicit object expression of "m" which has type X*. +</pre></td></tr> + + <tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXForRangeStmt.html">CXXForRangeStmt</a>></td><td class="name" onclick="toggle('hasBody3')"><a name="hasBody3Anchor">hasBody</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>> InnerMatcher</td></tr> <tr><td colspan="4" class="doc" id="hasBody3"><pre>Matches a 'for', 'while', 'do while' statement or a function definition that has a given body. @@ -6673,6 +6687,20 @@ </pre></td></tr> +<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1UnresolvedMemberExpr.html">UnresolvedMemberExpr</a>></td><td class="name" onclick="toggle('hasObjectExpression1')"><a name="hasObjectExpression1Anchor">hasObjectExpression</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr> +<tr><td colspan="4" class="doc" id="hasObjectExpression1"><pre>Matches a member expression where the object expression is +matched by a given matcher. + +Given + struct X { int m; }; + void f(X x) { x.m; m; } +memberExpr(hasObjectExpression(hasType(cxxRecordDecl(hasName("X"))))))) + matches "x.m" and "m" +with hasObjectExpression(...) + matching "x" and the implicit object expression of "m" which has type X*. +</pre></td></tr> + + <tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>></td><td class="name" onclick="toggle('hasDeclaration0')"><a name="hasDeclaration0Anchor">hasDeclaration</a></td><td>const Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>> InnerMatcher</td></tr> <tr><td colspan="4" class="doc" id="hasDeclaration0"><pre>Matches a node if the declaration associated with that node matches the given matcher.
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits