summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCong Liu <congliu@google.com>2016-06-24 09:38:03 +0000
committerCong Liu <congliu@google.com>2016-06-24 09:38:03 +0000
commit85b4750b8d7cfecda65218124138d8254ffa3c46 (patch)
tree0e1d5d42174b639f97ffa10ea13357698bf0fd2e
parent17a752beb9a8c15a8667569bae759590264bcc91 (diff)
IgnoringImplicit matcher.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@273659 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--docs/LibASTMatchersReference.html25
-rwxr-xr-x[-rw-r--r--]docs/tools/dump_ast_matchers.py0
-rw-r--r--include/clang/ASTMatchers/ASTMatchers.h26
-rw-r--r--lib/ASTMatchers/Dynamic/Registry.cpp1
-rw-r--r--unittests/ASTMatchers/ASTMatchersTraversalTest.cpp10
5 files changed, 59 insertions, 3 deletions
diff --git a/docs/LibASTMatchersReference.html b/docs/LibASTMatchersReference.html
index 3606367d2f..30af7e326a 100644
--- a/docs/LibASTMatchersReference.html
+++ b/docs/LibASTMatchersReference.html
@@ -2347,7 +2347,7 @@ Given
private: int c;
};
fieldDecl(isPrivate())
- matches 'int c;'
+ matches 'int c;'
</pre></td></tr>
@@ -2361,7 +2361,7 @@ Given
private: int c;
};
fieldDecl(isProtected())
- matches 'int b;'
+ matches 'int b;'
</pre></td></tr>
@@ -2375,7 +2375,7 @@ Given
private: int c;
};
fieldDecl(isPublic())
- matches 'int a;'
+ matches 'int a;'
</pre></td></tr>
@@ -4455,6 +4455,25 @@ only match the declarations for b, c, and d.
</pre></td></tr>
+<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt;</td><td class="name" onclick="toggle('ignoringImplicit0')"><a name="ignoringImplicit0Anchor">ignoringImplicit</a></td><td>ast_matchers::Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
+<tr><td colspan="4" class="doc" id="ignoringImplicit0"><pre>Matches expressions that match InnerMatcher after any implicit AST
+nodes are stripped off.
+
+Parentheses and explicit casts are not discarded.
+Given
+ class C {};
+ C a = C();
+ C b;
+ C c = b;
+The matchers
+ varDecl(hasInitializer(ignoringImplicit(cxxConstructExpr())))
+would match the declarations for a, b, and c.
+While
+ varDecl(hasInitializer(cxxConstructExpr()))
+only match the declarations for b and c.
+</pre></td></tr>
+
+
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt;</td><td class="name" onclick="toggle('ignoringParenCasts0')"><a name="ignoringParenCasts0Anchor">ignoringParenCasts</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="ignoringParenCasts0"><pre>Matches expressions that match InnerMatcher after parentheses and
casts are stripped off.
diff --git a/docs/tools/dump_ast_matchers.py b/docs/tools/dump_ast_matchers.py
index 45540405de..45540405de 100644..100755
--- a/docs/tools/dump_ast_matchers.py
+++ b/docs/tools/dump_ast_matchers.py
diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h
index 712eef0d3c..41080e98e8 100644
--- a/include/clang/ASTMatchers/ASTMatchers.h
+++ b/include/clang/ASTMatchers/ASTMatchers.h
@@ -548,6 +548,32 @@ AST_POLYMORPHIC_MATCHER_P(
Builder);
}
+/// \brief Matches expressions that match InnerMatcher after any implicit AST
+/// nodes are stripped off.
+///
+/// Parentheses and explicit casts are not discarded.
+/// Given
+/// \code
+/// class C {};
+/// C a = C();
+/// C b;
+/// C c = b;
+/// \endcode
+/// The matchers
+/// \code
+/// varDecl(hasInitializer(ignoringImplicit(cxxConstructExpr())))
+/// \endcode
+/// would match the declarations for a, b, and c.
+/// While
+/// \code
+/// varDecl(hasInitializer(cxxConstructExpr()))
+/// \endcode
+/// only match the declarations for b and c.
+AST_MATCHER_P(Expr, ignoringImplicit, ast_matchers::internal::Matcher<Expr>,
+ InnerMatcher) {
+ return InnerMatcher.matches(*Node.IgnoreImplicit(), Finder, Builder);
+}
+
/// \brief Matches expressions that match InnerMatcher after any implicit casts
/// are stripped off.
///
diff --git a/lib/ASTMatchers/Dynamic/Registry.cpp b/lib/ASTMatchers/Dynamic/Registry.cpp
index 4961da8925..1fe08581db 100644
--- a/lib/ASTMatchers/Dynamic/Registry.cpp
+++ b/lib/ASTMatchers/Dynamic/Registry.cpp
@@ -265,6 +265,7 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(hasUnarySelector);
REGISTER_MATCHER(hasValueType);
REGISTER_MATCHER(ifStmt);
+ REGISTER_MATCHER(ignoringImplicit);
REGISTER_MATCHER(ignoringImpCasts);
REGISTER_MATCHER(ignoringParenCasts);
REGISTER_MATCHER(ignoringParenImpCasts);
diff --git a/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp b/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
index cc5cf715a7..a3f616967d 100644
--- a/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
+++ b/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
@@ -1088,6 +1088,16 @@ TEST(HasImplicitDestinationType, DoesNotMatchIncorrectly) {
unless(anything())))));
}
+TEST(IgnoringImplicit, MatchesImplicit) {
+ EXPECT_TRUE(matches("class C {}; C a = C();",
+ varDecl(has(ignoringImplicit(cxxConstructExpr())))));
+}
+
+TEST(IgnoringImplicit, DoesNotMatchIncorrectly) {
+ EXPECT_TRUE(
+ notMatches("class C {}; C a = C();", varDecl(has(cxxConstructExpr()))));
+}
+
TEST(IgnoringImpCasts, MatchesImpCasts) {
// This test checks that ignoringImpCasts matches when implicit casts are
// present and its inner matcher alone does not match.