Skip to content

Commit

Permalink
[ASTMatchers] Add support of hasCondition for SwitchStmt.
Browse files Browse the repository at this point in the history
Summary:
The switch statement could be added to the hasCondition matcher.

Example:
```
clang-query> match switchStmt(hasCondition(ignoringImpCasts(declRefExpr())))
```

Output:
```
Match #1:

Binding for "root":
SwitchStmt 0x2f9b528 </usr/local/google/home/etienneb/examples/enum.cc:35:3, line:38:3>
|-<<<NULL>>>
|-ImplicitCastExpr 0x2f9b510 <line:35:11> 'int' <IntegralCast>
| `-ImplicitCastExpr 0x2f9b4f8 <col:11> 'enum Color' <LValueToRValue>
|   `-DeclRefExpr 0x2f9b4d0 <col:11> 'enum Color' lvalue Var 0x2f9a118 'C' 'enum Color'
`-CompoundStmt 0x2f9b610 <col:14, line:38:3>
  |-CaseStmt 0x2f9b578 <line:36:3, col:22>
  | |-ImplicitCastExpr 0x2f9b638 <col:8> 'int' <IntegralCast>
  | | `-DeclRefExpr 0x2f9b550 <col:8> 'enum Size' EnumConstant 0x2f99e40 'Small' 'enum Size'
  | |-<<<NULL>>>
  | `-ReturnStmt 0x2f9b5d0 <col:15, col:22>
  |   `-IntegerLiteral 0x2f9b5b0 <col:22> 'int' 1
  `-DefaultStmt 0x2f9b5f0 <line:37:3, col:12>
    `-BreakStmt 0x2f9b5e8 <col:12>

1 match.
```

Reviewers: aaron.ballman, sbenza, klimek

Subscribers: klimek, cfe-commits

Differential Revision: http://reviews.llvm.org/D20767

llvm-svn: 271208
bergeret committed May 30, 2016
1 parent 1c51a2d commit 5500f95
Showing 3 changed files with 40 additions and 9 deletions.
23 changes: 16 additions & 7 deletions clang/docs/LibASTMatchersReference.html
Original file line number Diff line number Diff line change
@@ -3536,9 +3536,9 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
</pre></td></tr>


<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1AbstractConditionalOperator.html">AbstractConditionalOperator</a>&gt;</td><td class="name" onclick="toggle('hasCondition4')"><a name="hasCondition4Anchor">hasCondition</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="hasCondition4"><pre>Matches the condition expression of an if statement, for loop,
or conditional operator.
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1AbstractConditionalOperator.html">AbstractConditionalOperator</a>&gt;</td><td class="name" onclick="toggle('hasCondition5')"><a name="hasCondition5Anchor">hasCondition</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="hasCondition5"><pre>Matches the condition expression of an if statement, for loop,
switch statement or conditional operator.

Example matches true (matcher = hasCondition(cxxBoolLiteral(equals(true))))
if (true) {}
@@ -4293,7 +4293,7 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>

<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1DoStmt.html">DoStmt</a>&gt;</td><td class="name" onclick="toggle('hasCondition3')"><a name="hasCondition3Anchor">hasCondition</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="hasCondition3"><pre>Matches the condition expression of an if statement, for loop,
or conditional operator.
switch statement or conditional operator.

Example matches true (matcher = hasCondition(cxxBoolLiteral(equals(true))))
if (true) {}
@@ -4476,7 +4476,7 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>

<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ForStmt.html">ForStmt</a>&gt;</td><td class="name" onclick="toggle('hasCondition1')"><a name="hasCondition1Anchor">hasCondition</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="hasCondition1"><pre>Matches the condition expression of an if statement, for loop,
or conditional operator.
switch statement or conditional operator.

Example matches true (matcher = hasCondition(cxxBoolLiteral(equals(true))))
if (true) {}
@@ -4554,7 +4554,7 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>

<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1IfStmt.html">IfStmt</a>&gt;</td><td class="name" onclick="toggle('hasCondition0')"><a name="hasCondition0Anchor">hasCondition</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="hasCondition0"><pre>Matches the condition expression of an if statement, for loop,
or conditional operator.
switch statement or conditional operator.

Example matches true (matcher = hasCondition(cxxBoolLiteral(equals(true))))
if (true) {}
@@ -5052,6 +5052,15 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
</pre></td></tr>


<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1SwitchStmt.html">SwitchStmt</a>&gt;</td><td class="name" onclick="toggle('hasCondition4')"><a name="hasCondition4Anchor">hasCondition</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="hasCondition4"><pre>Matches the condition expression of an if statement, for loop,
switch statement or conditional operator.

Example matches true (matcher = hasCondition(cxxBoolLiteral(equals(true))))
if (true) {}
</pre></td></tr>


<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration4')"><a name="hasDeclaration4Anchor">hasDeclaration</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasDeclaration4"><pre>Matches a node if the declaration associated with that node
matches the given matcher.
@@ -5385,7 +5394,7 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>

<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1WhileStmt.html">WhileStmt</a>&gt;</td><td class="name" onclick="toggle('hasCondition2')"><a name="hasCondition2Anchor">hasCondition</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="hasCondition2"><pre>Matches the condition expression of an if statement, for loop,
or conditional operator.
switch statement or conditional operator.

Example matches true (matcher = hasCondition(cxxBoolLiteral(equals(true))))
if (true) {}
4 changes: 2 additions & 2 deletions clang/include/clang/ASTMatchers/ASTMatchers.h
Original file line number Diff line number Diff line change
@@ -3299,7 +3299,7 @@ AST_POLYMORPHIC_MATCHER(isConstexpr,
}

/// \brief Matches the condition expression of an if statement, for loop,
/// or conditional operator.
/// switch statement or conditional operator.
///
/// Example matches true (matcher = hasCondition(cxxBoolLiteral(equals(true))))
/// \code
@@ -3308,7 +3308,7 @@ AST_POLYMORPHIC_MATCHER(isConstexpr,
AST_POLYMORPHIC_MATCHER_P(
hasCondition,
AST_POLYMORPHIC_SUPPORTED_TYPES(IfStmt, ForStmt, WhileStmt, DoStmt,
AbstractConditionalOperator),
SwitchStmt, AbstractConditionalOperator),
internal::Matcher<Expr>, InnerMatcher) {
const Expr *const Condition = Node.getCond();
return (Condition != nullptr &&
22 changes: 22 additions & 0 deletions clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
Original file line number Diff line number Diff line change
@@ -958,6 +958,28 @@ TEST(Matcher, VisitsTemplateInstantiations) {
callee(cxxMethodDecl(hasName("x"))))))));
}

TEST(Matcher, HasCondition) {
StatementMatcher IfStmt =
ifStmt(hasCondition(cxxBoolLiteral(equals(true))));
EXPECT_TRUE(matches("void x() { if (true) {} }", IfStmt));
EXPECT_TRUE(notMatches("void x() { if (false) {} }", IfStmt));

StatementMatcher ForStmt =
forStmt(hasCondition(cxxBoolLiteral(equals(true))));
EXPECT_TRUE(matches("void x() { for (;true;) {} }", ForStmt));
EXPECT_TRUE(notMatches("void x() { for (;false;) {} }", ForStmt));

StatementMatcher WhileStmt =
whileStmt(hasCondition(cxxBoolLiteral(equals(true))));
EXPECT_TRUE(matches("void x() { while (true) {} }", WhileStmt));
EXPECT_TRUE(notMatches("void x() { while (false) {} }", WhileStmt));

StatementMatcher SwitchStmt =
switchStmt(hasCondition(integerLiteral(equals(42))));
EXPECT_TRUE(matches("void x() { switch (42) {case 42:;} }", SwitchStmt));
EXPECT_TRUE(notMatches("void x() { switch (43) {case 43:;} }", SwitchStmt));
}

TEST(For, ForLoopInternals) {
EXPECT_TRUE(matches("void f(){ int i; for (; i < 3 ; ); }",
forStmt(hasCondition(anything()))));

0 comments on commit 5500f95

Please sign in to comment.