mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-02-17 08:21:13 +00:00
[clang][ASTMatcher] Add matchers for CXXFoldExpr (#71245)
Adds support for the following matchers related to `CXXFoldExpr`: `cxxFoldExpr`, `callee`, `hasInit`, `hasPattern`, `isRightFold`, `isLeftFold`, `isUnaryFold`, `isBinaryFold`, `hasOperator`, `hasLHS`, `hasRHS`.
This commit is contained in:
parent
27acfdd2de
commit
cbaadb1f0f
@ -1629,6 +1629,17 @@ in
|
||||
</pre></td></tr>
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('cxxFoldExpr0')"><a name="cxxFoldExpr0Anchor">cxxFoldExpr</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXFoldExpr.html">CXXFoldExpr</a>>...</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="cxxFoldExpr0"><pre>Matches C++17 fold expressions.
|
||||
|
||||
Example matches `(0 + ... + args)`:
|
||||
template <typename... Args>
|
||||
auto sum(Args... args) {
|
||||
return (0 + ... + args);
|
||||
}
|
||||
</pre></td></tr>
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('cxxForRangeStmt0')"><a name="cxxForRangeStmt0Anchor">cxxForRangeStmt</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXForRangeStmt.html">CXXForRangeStmt</a>>...</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="cxxForRangeStmt0"><pre>Matches range-based for statements.
|
||||
|
||||
@ -2965,11 +2976,18 @@ specified names.
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1BinaryOperator.html">BinaryOperator</a>></td><td class="name" onclick="toggle('hasOperatorName0')"><a name="hasOperatorName0Anchor">hasOperatorName</a></td><td>std::string Name</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="hasOperatorName0"><pre>Matches the operator Name of operator expressions (binary or
|
||||
unary).
|
||||
<tr><td colspan="4" class="doc" id="hasOperatorName0"><pre>Matches the operator Name of operator expressions and fold expressions
|
||||
(binary or unary).
|
||||
|
||||
Example matches a || b (matcher = binaryOperator(hasOperatorName("||")))
|
||||
!(a || b)
|
||||
|
||||
Example matches `(0 + ... + args)`
|
||||
(matcher = cxxFoldExpr(hasOperatorName("+")))
|
||||
template <typename... Args>
|
||||
auto sum(Args... args) {
|
||||
return (0 + ... + args);
|
||||
}
|
||||
</pre></td></tr>
|
||||
|
||||
|
||||
@ -3430,6 +3448,91 @@ compares its name to the usage in @c s.mem() in the @c x function template
|
||||
</pre></td></tr>
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXFoldExpr.html">CXXFoldExpr</a>></td><td class="name" onclick="toggle('hasOperatorName3')"><a name="hasOperatorName3Anchor">hasOperatorName</a></td><td>std::string Name</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="hasOperatorName3"><pre>Matches the operator Name of operator expressions and fold expressions
|
||||
(binary or unary).
|
||||
|
||||
Example matches a || b (matcher = binaryOperator(hasOperatorName("||")))
|
||||
!(a || b)
|
||||
|
||||
Example matches `(0 + ... + args)`
|
||||
(matcher = cxxFoldExpr(hasOperatorName("+")))
|
||||
template <typename... Args>
|
||||
auto sum(Args... args) {
|
||||
return (0 + ... + args);
|
||||
}
|
||||
</pre></td></tr>
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXFoldExpr.html">CXXFoldExpr</a>></td><td class="name" onclick="toggle('isBinaryFold0')"><a name="isBinaryFold0Anchor">isBinaryFold</a></td><td></td></tr>
|
||||
<tr><td colspan="4" class="doc" id="isBinaryFold0"><pre>Matches binary fold expressions, i.e. fold expressions with an initializer.
|
||||
|
||||
Example matches `(0 + ... + args)`
|
||||
(matcher = cxxFoldExpr(isBinaryFold()))
|
||||
template <typename... Args>
|
||||
auto sum(Args... args) {
|
||||
return (0 + ... + args);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
auto multiply(Args... args) {
|
||||
return (args * ...);
|
||||
}
|
||||
</pre></td></tr>
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXFoldExpr.html">CXXFoldExpr</a>></td><td class="name" onclick="toggle('isLeftFold0')"><a name="isLeftFold0Anchor">isLeftFold</a></td><td></td></tr>
|
||||
<tr><td colspan="4" class="doc" id="isLeftFold0"><pre>Matches left-folding fold expressions.
|
||||
|
||||
Example matches `(0 + ... + args)`
|
||||
(matcher = cxxFoldExpr(isLeftFold()))
|
||||
template <typename... Args>
|
||||
auto sum(Args... args) {
|
||||
return (0 + ... + args);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
auto multiply(Args... args) {
|
||||
return (args * ... * 1);
|
||||
}
|
||||
</pre></td></tr>
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXFoldExpr.html">CXXFoldExpr</a>></td><td class="name" onclick="toggle('isRightFold0')"><a name="isRightFold0Anchor">isRightFold</a></td><td></td></tr>
|
||||
<tr><td colspan="4" class="doc" id="isRightFold0"><pre>Matches right-folding fold expressions.
|
||||
|
||||
Example matches `(args * ... * 1)`
|
||||
(matcher = cxxFoldExpr(isRightFold()))
|
||||
template <typename... Args>
|
||||
auto sum(Args... args) {
|
||||
return (0 + ... + args);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
auto multiply(Args... args) {
|
||||
return (args * ... * 1);
|
||||
}
|
||||
</pre></td></tr>
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXFoldExpr.html">CXXFoldExpr</a>></td><td class="name" onclick="toggle('isUnaryFold0')"><a name="isUnaryFold0Anchor">isUnaryFold</a></td><td></td></tr>
|
||||
<tr><td colspan="4" class="doc" id="isUnaryFold0"><pre>Matches unary fold expressions, i.e. fold expressions without an
|
||||
initializer.
|
||||
|
||||
Example matches `(args * ...)`
|
||||
(matcher = cxxFoldExpr(isUnaryFold()))
|
||||
template <typename... Args>
|
||||
auto sum(Args... args) {
|
||||
return (0 + ... + args);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
auto multiply(Args... args) {
|
||||
return (args * ...);
|
||||
}
|
||||
</pre></td></tr>
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXMethodDecl.html">CXXMethodDecl</a>></td><td class="name" onclick="toggle('isConst0')"><a name="isConst0Anchor">isConst</a></td><td></td></tr>
|
||||
<tr><td colspan="4" class="doc" id="isConst0"><pre>Matches if the given method declaration is const.
|
||||
|
||||
@ -3599,11 +3702,18 @@ Is equivalent to
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXOperatorCallExpr.html">CXXOperatorCallExpr</a>></td><td class="name" onclick="toggle('hasOperatorName1')"><a name="hasOperatorName1Anchor">hasOperatorName</a></td><td>std::string Name</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="hasOperatorName1"><pre>Matches the operator Name of operator expressions (binary or
|
||||
unary).
|
||||
<tr><td colspan="4" class="doc" id="hasOperatorName1"><pre>Matches the operator Name of operator expressions and fold expressions
|
||||
(binary or unary).
|
||||
|
||||
Example matches a || b (matcher = binaryOperator(hasOperatorName("||")))
|
||||
!(a || b)
|
||||
|
||||
Example matches `(0 + ... + args)`
|
||||
(matcher = cxxFoldExpr(hasOperatorName("+")))
|
||||
template <typename... Args>
|
||||
auto sum(Args... args) {
|
||||
return (0 + ... + args);
|
||||
}
|
||||
</pre></td></tr>
|
||||
|
||||
|
||||
@ -3757,11 +3867,18 @@ specified names.
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXRewrittenBinaryOperator.html">CXXRewrittenBinaryOperator</a>></td><td class="name" onclick="toggle('hasOperatorName2')"><a name="hasOperatorName2Anchor">hasOperatorName</a></td><td>std::string Name</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="hasOperatorName2"><pre>Matches the operator Name of operator expressions (binary or
|
||||
unary).
|
||||
<tr><td colspan="4" class="doc" id="hasOperatorName2"><pre>Matches the operator Name of operator expressions and fold expressions
|
||||
(binary or unary).
|
||||
|
||||
Example matches a || b (matcher = binaryOperator(hasOperatorName("||")))
|
||||
!(a || b)
|
||||
|
||||
Example matches `(0 + ... + args)`
|
||||
(matcher = cxxFoldExpr(hasOperatorName("+")))
|
||||
template <typename... Args>
|
||||
auto sum(Args... args) {
|
||||
return (0 + ... + args);
|
||||
}
|
||||
</pre></td></tr>
|
||||
|
||||
|
||||
@ -5711,12 +5828,19 @@ specified names.
|
||||
</pre></td></tr>
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1UnaryOperator.html">UnaryOperator</a>></td><td class="name" onclick="toggle('hasOperatorName3')"><a name="hasOperatorName3Anchor">hasOperatorName</a></td><td>std::string Name</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="hasOperatorName3"><pre>Matches the operator Name of operator expressions (binary or
|
||||
unary).
|
||||
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1UnaryOperator.html">UnaryOperator</a>></td><td class="name" onclick="toggle('hasOperatorName4')"><a name="hasOperatorName4Anchor">hasOperatorName</a></td><td>std::string Name</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="hasOperatorName4"><pre>Matches the operator Name of operator expressions and fold expressions
|
||||
(binary or unary).
|
||||
|
||||
Example matches a || b (matcher = binaryOperator(hasOperatorName("||")))
|
||||
!(a || b)
|
||||
|
||||
Example matches `(0 + ... + args)`
|
||||
(matcher = cxxFoldExpr(hasOperatorName("+")))
|
||||
template <typename... Args>
|
||||
auto sum(Args... args) {
|
||||
return (0 + ... + args);
|
||||
}
|
||||
</pre></td></tr>
|
||||
|
||||
|
||||
@ -6453,7 +6577,7 @@ usingDecl(hasAnyUsingShadowDecl(hasName("b"))))
|
||||
|
||||
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1BinaryOperator.html">BinaryOperator</a>></td><td class="name" onclick="toggle('hasEitherOperand0')"><a name="hasEitherOperand0Anchor">hasEitherOperand</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="hasEitherOperand0"><pre>Matches if either the left hand side or the right hand side of a
|
||||
binary operator matches.
|
||||
binary operator or fold expression matches.
|
||||
</pre></td></tr>
|
||||
|
||||
|
||||
@ -6466,7 +6590,8 @@ Example matches a (matcher = binaryOperator(hasLHS()))
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1BinaryOperator.html">BinaryOperator</a>></td><td class="name" onclick="toggle('hasOperands0')"><a name="hasOperands0Anchor">hasOperands</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> Matcher1, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> Matcher2</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="hasOperands0"><pre>Matches if both matchers match with opposite sides of the binary operator.
|
||||
<tr><td colspan="4" class="doc" id="hasOperands0"><pre>Matches if both matchers match with opposite sides of the binary operator
|
||||
or fold expression.
|
||||
|
||||
Example matcher = binaryOperator(hasOperands(integerLiteral(equals(1),
|
||||
integerLiteral(equals(2)))
|
||||
@ -6885,6 +7010,112 @@ memberExpr(hasObjectExpression(hasType(pointsTo(
|
||||
</pre></td></tr>
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXFoldExpr.html">CXXFoldExpr</a>></td><td class="name" onclick="toggle('callee1')"><a name="callee1Anchor">callee</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>> InnerMatcher</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="callee1"><pre>Matches if the call or fold expression's callee expression matches.
|
||||
|
||||
Given
|
||||
class Y { void x() { this->x(); x(); Y y; y.x(); } };
|
||||
void f() { f(); }
|
||||
callExpr(callee(expr()))
|
||||
matches this->x(), x(), y.x(), f()
|
||||
with callee(...)
|
||||
matching this->x, x, y.x, f respectively
|
||||
|
||||
Given
|
||||
template <typename... Args>
|
||||
auto sum(Args... args) {
|
||||
return (0 + ... + args);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
auto multiply(Args... args) {
|
||||
return (args * ... * 1);
|
||||
}
|
||||
cxxFoldExpr(callee(expr()))
|
||||
matches (args * ... * 1)
|
||||
with callee(...)
|
||||
matching *
|
||||
|
||||
Note: Callee cannot take the more general internal::Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>>
|
||||
because this introduces ambiguous overloads with calls to Callee taking a
|
||||
internal::Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>>, as the matcher hierarchy is purely
|
||||
implemented in terms of implicit casts.
|
||||
</pre></td></tr>
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXFoldExpr.html">CXXFoldExpr</a>></td><td class="name" onclick="toggle('hasEitherOperand2')"><a name="hasEitherOperand2Anchor">hasEitherOperand</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="hasEitherOperand2"><pre>Matches if either the left hand side or the right hand side of a
|
||||
binary operator or fold expression matches.
|
||||
</pre></td></tr>
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXFoldExpr.html">CXXFoldExpr</a>></td><td class="name" onclick="toggle('hasFoldInit0')"><a name="hasFoldInit0Anchor">hasFoldInit</a></td><td>ast_matchers::Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMacher</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="hasFoldInit0"><pre>Matches the operand that does not contain the parameter pack.
|
||||
|
||||
Example matches `(0 + ... + args)` and `(args * ... * 1)`
|
||||
(matcher = cxxFoldExpr(hasFoldInit(expr())))
|
||||
with hasFoldInit(...)
|
||||
matching `0` and `1` respectively
|
||||
template <typename... Args>
|
||||
auto sum(Args... args) {
|
||||
return (0 + ... + args);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
auto multiply(Args... args) {
|
||||
return (args * ... * 1);
|
||||
}
|
||||
</pre></td></tr>
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXFoldExpr.html">CXXFoldExpr</a>></td><td class="name" onclick="toggle('hasLHS4')"><a name="hasLHS4Anchor">hasLHS</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="hasLHS4"><pre>Matches the left hand side of binary operator expressions.
|
||||
|
||||
Example matches a (matcher = binaryOperator(hasLHS()))
|
||||
a || b
|
||||
</pre></td></tr>
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXFoldExpr.html">CXXFoldExpr</a>></td><td class="name" onclick="toggle('hasOperands2')"><a name="hasOperands2Anchor">hasOperands</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> Matcher1, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> Matcher2</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="hasOperands2"><pre>Matches if both matchers match with opposite sides of the binary operator
|
||||
or fold expression.
|
||||
|
||||
Example matcher = binaryOperator(hasOperands(integerLiteral(equals(1),
|
||||
integerLiteral(equals(2)))
|
||||
1 + 2 // Match
|
||||
2 + 1 // Match
|
||||
1 + 1 // No match
|
||||
2 + 2 // No match
|
||||
</pre></td></tr>
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXFoldExpr.html">CXXFoldExpr</a>></td><td class="name" onclick="toggle('hasPattern0')"><a name="hasPattern0Anchor">hasPattern</a></td><td>ast_matchers::Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMacher</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="hasPattern0"><pre>Matches the operand that contains the parameter pack.
|
||||
|
||||
Example matches `(0 + ... + args)`
|
||||
(matcher = cxxFoldExpr(hasPattern(expr())))
|
||||
with hasPattern(...)
|
||||
matching `args`
|
||||
template <typename... Args>
|
||||
auto sum(Args... args) {
|
||||
return (0 + ... + args);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
auto multiply(Args... args) {
|
||||
return (args * ... * 1);
|
||||
}
|
||||
</pre></td></tr>
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXFoldExpr.html">CXXFoldExpr</a>></td><td class="name" onclick="toggle('hasRHS4')"><a name="hasRHS4Anchor">hasRHS</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="hasRHS4"><pre>Matches the right hand side of binary operator expressions.
|
||||
|
||||
Example matches b (matcher = binaryOperator(hasRHS()))
|
||||
a || b
|
||||
</pre></td></tr>
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="https://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="https://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', 'while' statement or a function or coroutine
|
||||
definition that has a given body. Note that in case of functions or
|
||||
@ -7179,7 +7410,7 @@ Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Bloc
|
||||
|
||||
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXOperatorCallExpr.html">CXXOperatorCallExpr</a>></td><td class="name" onclick="toggle('hasEitherOperand1')"><a name="hasEitherOperand1Anchor">hasEitherOperand</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="hasEitherOperand1"><pre>Matches if either the left hand side or the right hand side of a
|
||||
binary operator matches.
|
||||
binary operator or fold expression matches.
|
||||
</pre></td></tr>
|
||||
|
||||
|
||||
@ -7192,7 +7423,8 @@ Example matches a (matcher = binaryOperator(hasLHS()))
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXOperatorCallExpr.html">CXXOperatorCallExpr</a>></td><td class="name" onclick="toggle('hasOperands1')"><a name="hasOperands1Anchor">hasOperands</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> Matcher1, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> Matcher2</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="hasOperands1"><pre>Matches if both matchers match with opposite sides of the binary operator.
|
||||
<tr><td colspan="4" class="doc" id="hasOperands1"><pre>Matches if both matchers match with opposite sides of the binary operator
|
||||
or fold expression.
|
||||
|
||||
Example matcher = binaryOperator(hasOperands(integerLiteral(equals(1),
|
||||
integerLiteral(equals(2)))
|
||||
@ -7317,9 +7549,9 @@ match Base.
|
||||
</pre></td></tr>
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXRewrittenBinaryOperator.html">CXXRewrittenBinaryOperator</a>></td><td class="name" onclick="toggle('hasEitherOperand2')"><a name="hasEitherOperand2Anchor">hasEitherOperand</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="hasEitherOperand2"><pre>Matches if either the left hand side or the right hand side of a
|
||||
binary operator matches.
|
||||
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXRewrittenBinaryOperator.html">CXXRewrittenBinaryOperator</a>></td><td class="name" onclick="toggle('hasEitherOperand3')"><a name="hasEitherOperand3Anchor">hasEitherOperand</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="hasEitherOperand3"><pre>Matches if either the left hand side or the right hand side of a
|
||||
binary operator or fold expression matches.
|
||||
</pre></td></tr>
|
||||
|
||||
|
||||
@ -7331,8 +7563,9 @@ Example matches a (matcher = binaryOperator(hasLHS()))
|
||||
</pre></td></tr>
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXRewrittenBinaryOperator.html">CXXRewrittenBinaryOperator</a>></td><td class="name" onclick="toggle('hasOperands2')"><a name="hasOperands2Anchor">hasOperands</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> Matcher1, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> Matcher2</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="hasOperands2"><pre>Matches if both matchers match with opposite sides of the binary operator.
|
||||
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXRewrittenBinaryOperator.html">CXXRewrittenBinaryOperator</a>></td><td class="name" onclick="toggle('hasOperands3')"><a name="hasOperands3Anchor">hasOperands</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> Matcher1, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> Matcher2</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="hasOperands3"><pre>Matches if both matchers match with opposite sides of the binary operator
|
||||
or fold expression.
|
||||
|
||||
Example matcher = binaryOperator(hasOperands(integerLiteral(equals(1),
|
||||
integerLiteral(equals(2)))
|
||||
@ -7436,8 +7669,8 @@ Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Bloc
|
||||
</pre></td></tr>
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>></td><td class="name" onclick="toggle('callee2')"><a name="callee2Anchor">callee</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>> InnerMatcher</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="callee2"><pre>Matches 1) if the call expression's callee's declaration matches the
|
||||
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>></td><td class="name" onclick="toggle('callee3')"><a name="callee3Anchor">callee</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>> InnerMatcher</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="callee3"><pre>Matches 1) if the call expression's callee's declaration matches the
|
||||
given matcher; or 2) if the Obj-C message expression's callee's method
|
||||
declaration matches the given matcher.
|
||||
|
||||
@ -7458,7 +7691,7 @@ objcMessageExpr(callee(objcMethodDecl(hasName("foo"))))
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>></td><td class="name" onclick="toggle('callee0')"><a name="callee0Anchor">callee</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>> InnerMatcher</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="callee0"><pre>Matches if the call expression's callee expression matches.
|
||||
<tr><td colspan="4" class="doc" id="callee0"><pre>Matches if the call or fold expression's callee expression matches.
|
||||
|
||||
Given
|
||||
class Y { void x() { this->x(); x(); Y y; y.x(); } };
|
||||
@ -7468,6 +7701,21 @@ callExpr(callee(expr()))
|
||||
with callee(...)
|
||||
matching this->x, x, y.x, f respectively
|
||||
|
||||
Given
|
||||
template <typename... Args>
|
||||
auto sum(Args... args) {
|
||||
return (0 + ... + args);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
auto multiply(Args... args) {
|
||||
return (args * ... * 1);
|
||||
}
|
||||
cxxFoldExpr(callee(expr()))
|
||||
matches (args * ... * 1)
|
||||
with callee(...)
|
||||
matching *
|
||||
|
||||
Note: Callee cannot take the more general internal::Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>>
|
||||
because this introduces ambiguous overloads with calls to Callee taking a
|
||||
internal::Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>>, as the matcher hierarchy is purely
|
||||
@ -9087,8 +9335,8 @@ match Base.
|
||||
</pre></td></tr>
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCMessageExpr.html">ObjCMessageExpr</a>></td><td class="name" onclick="toggle('callee1')"><a name="callee1Anchor">callee</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>> InnerMatcher</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="callee1"><pre>Matches 1) if the call expression's callee's declaration matches the
|
||||
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCMessageExpr.html">ObjCMessageExpr</a>></td><td class="name" onclick="toggle('callee2')"><a name="callee2Anchor">callee</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>> InnerMatcher</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="callee2"><pre>Matches 1) if the call expression's callee's declaration matches the
|
||||
given matcher; or 2) if the Obj-C message expression's callee's method
|
||||
declaration matches the given matcher.
|
||||
|
||||
|
@ -1123,6 +1123,9 @@ AST Matchers
|
||||
- Add ``convertVectorExpr``.
|
||||
- Add ``dependentSizedExtVectorType``.
|
||||
- Add ``macroQualifiedType``.
|
||||
- Add ``CXXFoldExpr`` related matchers: ``cxxFoldExpr``, ``callee``,
|
||||
``hasInit``, ``hasPattern``, ``isRightFold``, ``isLeftFold``,
|
||||
``isUnaryFold``, ``isBinaryFold``, ``hasOperator``, ``hasLHS``, ``hasRHS``, ``hasEitherOperand``.
|
||||
|
||||
clang-format
|
||||
------------
|
||||
|
@ -2062,6 +2062,18 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXDefaultArgExpr>
|
||||
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXOperatorCallExpr>
|
||||
cxxOperatorCallExpr;
|
||||
|
||||
/// Matches C++17 fold expressions.
|
||||
///
|
||||
/// Example matches `(0 + ... + args)`:
|
||||
/// \code
|
||||
/// template <typename... Args>
|
||||
/// auto sum(Args... args) {
|
||||
/// return (0 + ... + args);
|
||||
/// }
|
||||
/// \endcode
|
||||
extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXFoldExpr>
|
||||
cxxFoldExpr;
|
||||
|
||||
/// Matches rewritten binary operators
|
||||
///
|
||||
/// Example matches use of "<":
|
||||
@ -3881,7 +3893,7 @@ AST_MATCHER_P(ObjCMessageExpr, numSelectorArgs, unsigned, N) {
|
||||
return Node.getSelector().getNumArgs() == N;
|
||||
}
|
||||
|
||||
/// Matches if the call expression's callee expression matches.
|
||||
/// Matches if the call or fold expression's callee expression matches.
|
||||
///
|
||||
/// Given
|
||||
/// \code
|
||||
@ -3893,13 +3905,32 @@ AST_MATCHER_P(ObjCMessageExpr, numSelectorArgs, unsigned, N) {
|
||||
/// with callee(...)
|
||||
/// matching this->x, x, y.x, f respectively
|
||||
///
|
||||
/// Given
|
||||
/// \code
|
||||
/// template <typename... Args>
|
||||
/// auto sum(Args... args) {
|
||||
/// return (0 + ... + args);
|
||||
/// }
|
||||
///
|
||||
/// template <typename... Args>
|
||||
/// auto multiply(Args... args) {
|
||||
/// return (args * ... * 1);
|
||||
/// }
|
||||
/// \endcode
|
||||
/// cxxFoldExpr(callee(expr()))
|
||||
/// matches (args * ... * 1)
|
||||
/// with callee(...)
|
||||
/// matching *
|
||||
///
|
||||
/// Note: Callee cannot take the more general internal::Matcher<Expr>
|
||||
/// because this introduces ambiguous overloads with calls to Callee taking a
|
||||
/// internal::Matcher<Decl>, as the matcher hierarchy is purely
|
||||
/// implemented in terms of implicit casts.
|
||||
AST_MATCHER_P(CallExpr, callee, internal::Matcher<Stmt>,
|
||||
InnerMatcher) {
|
||||
const Expr *ExprNode = Node.getCallee();
|
||||
AST_POLYMORPHIC_MATCHER_P_OVERLOAD(callee,
|
||||
AST_POLYMORPHIC_SUPPORTED_TYPES(CallExpr,
|
||||
CXXFoldExpr),
|
||||
internal::Matcher<Stmt>, InnerMatcher, 0) {
|
||||
const auto *ExprNode = Node.getCallee();
|
||||
return (ExprNode != nullptr &&
|
||||
InnerMatcher.matches(*ExprNode, Finder, Builder));
|
||||
}
|
||||
@ -4532,6 +4563,121 @@ AST_POLYMORPHIC_MATCHER_P2(hasArgument,
|
||||
return InnerMatcher.matches(*Arg->IgnoreParenImpCasts(), Finder, Builder);
|
||||
}
|
||||
|
||||
/// Matches the operand that does not contain the parameter pack.
|
||||
///
|
||||
/// Example matches `(0 + ... + args)` and `(args * ... * 1)`
|
||||
/// (matcher = cxxFoldExpr(hasFoldInit(expr())))
|
||||
/// with hasFoldInit(...)
|
||||
/// matching `0` and `1` respectively
|
||||
/// \code
|
||||
/// template <typename... Args>
|
||||
/// auto sum(Args... args) {
|
||||
/// return (0 + ... + args);
|
||||
/// }
|
||||
///
|
||||
/// template <typename... Args>
|
||||
/// auto multiply(Args... args) {
|
||||
/// return (args * ... * 1);
|
||||
/// }
|
||||
/// \endcode
|
||||
AST_MATCHER_P(CXXFoldExpr, hasFoldInit, ast_matchers::internal::Matcher<Expr>,
|
||||
InnerMacher) {
|
||||
const auto *const Init = Node.getInit();
|
||||
return Init && InnerMacher.matches(*Init, Finder, Builder);
|
||||
}
|
||||
|
||||
/// Matches the operand that contains the parameter pack.
|
||||
///
|
||||
/// Example matches `(0 + ... + args)`
|
||||
/// (matcher = cxxFoldExpr(hasPattern(expr())))
|
||||
/// with hasPattern(...)
|
||||
/// matching `args`
|
||||
/// \code
|
||||
/// template <typename... Args>
|
||||
/// auto sum(Args... args) {
|
||||
/// return (0 + ... + args);
|
||||
/// }
|
||||
///
|
||||
/// template <typename... Args>
|
||||
/// auto multiply(Args... args) {
|
||||
/// return (args * ... * 1);
|
||||
/// }
|
||||
/// \endcode
|
||||
AST_MATCHER_P(CXXFoldExpr, hasPattern, ast_matchers::internal::Matcher<Expr>,
|
||||
InnerMacher) {
|
||||
const Expr *const Pattern = Node.getPattern();
|
||||
return Pattern && InnerMacher.matches(*Pattern, Finder, Builder);
|
||||
}
|
||||
|
||||
/// Matches right-folding fold expressions.
|
||||
///
|
||||
/// Example matches `(args * ... * 1)`
|
||||
/// (matcher = cxxFoldExpr(isRightFold()))
|
||||
/// \code
|
||||
/// template <typename... Args>
|
||||
/// auto sum(Args... args) {
|
||||
/// return (0 + ... + args);
|
||||
/// }
|
||||
///
|
||||
/// template <typename... Args>
|
||||
/// auto multiply(Args... args) {
|
||||
/// return (args * ... * 1);
|
||||
/// }
|
||||
/// \endcode
|
||||
AST_MATCHER(CXXFoldExpr, isRightFold) { return Node.isRightFold(); }
|
||||
|
||||
/// Matches left-folding fold expressions.
|
||||
///
|
||||
/// Example matches `(0 + ... + args)`
|
||||
/// (matcher = cxxFoldExpr(isLeftFold()))
|
||||
/// \code
|
||||
/// template <typename... Args>
|
||||
/// auto sum(Args... args) {
|
||||
/// return (0 + ... + args);
|
||||
/// }
|
||||
///
|
||||
/// template <typename... Args>
|
||||
/// auto multiply(Args... args) {
|
||||
/// return (args * ... * 1);
|
||||
/// }
|
||||
/// \endcode
|
||||
AST_MATCHER(CXXFoldExpr, isLeftFold) { return Node.isLeftFold(); }
|
||||
|
||||
/// Matches unary fold expressions, i.e. fold expressions without an
|
||||
/// initializer.
|
||||
///
|
||||
/// Example matches `(args * ...)`
|
||||
/// (matcher = cxxFoldExpr(isUnaryFold()))
|
||||
/// \code
|
||||
/// template <typename... Args>
|
||||
/// auto sum(Args... args) {
|
||||
/// return (0 + ... + args);
|
||||
/// }
|
||||
///
|
||||
/// template <typename... Args>
|
||||
/// auto multiply(Args... args) {
|
||||
/// return (args * ...);
|
||||
/// }
|
||||
/// \endcode
|
||||
AST_MATCHER(CXXFoldExpr, isUnaryFold) { return Node.getInit() == nullptr; }
|
||||
|
||||
/// Matches binary fold expressions, i.e. fold expressions with an initializer.
|
||||
///
|
||||
/// Example matches `(0 + ... + args)`
|
||||
/// (matcher = cxxFoldExpr(isBinaryFold()))
|
||||
/// \code
|
||||
/// template <typename... Args>
|
||||
/// auto sum(Args... args) {
|
||||
/// return (0 + ... + args);
|
||||
/// }
|
||||
///
|
||||
/// template <typename... Args>
|
||||
/// auto multiply(Args... args) {
|
||||
/// return (args * ...);
|
||||
/// }
|
||||
/// \endcode
|
||||
AST_MATCHER(CXXFoldExpr, isBinaryFold) { return Node.getInit() != nullptr; }
|
||||
|
||||
/// Matches the n'th item of an initializer list expression.
|
||||
///
|
||||
/// Example matches y.
|
||||
@ -5709,17 +5855,27 @@ AST_POLYMORPHIC_MATCHER_P_OVERLOAD(equals,
|
||||
.matchesNode(Node);
|
||||
}
|
||||
|
||||
/// Matches the operator Name of operator expressions (binary or
|
||||
/// unary).
|
||||
/// Matches the operator Name of operator expressions and fold expressions
|
||||
/// (binary or unary).
|
||||
///
|
||||
/// Example matches a || b (matcher = binaryOperator(hasOperatorName("||")))
|
||||
/// \code
|
||||
/// !(a || b)
|
||||
/// \endcode
|
||||
///
|
||||
/// Example matches `(0 + ... + args)`
|
||||
/// (matcher = cxxFoldExpr(hasOperatorName("+")))
|
||||
/// \code
|
||||
/// template <typename... Args>
|
||||
/// auto sum(Args... args) {
|
||||
/// return (0 + ... + args);
|
||||
/// }
|
||||
/// \endcode
|
||||
AST_POLYMORPHIC_MATCHER_P(
|
||||
hasOperatorName,
|
||||
AST_POLYMORPHIC_SUPPORTED_TYPES(BinaryOperator, CXXOperatorCallExpr,
|
||||
CXXRewrittenBinaryOperator, UnaryOperator),
|
||||
CXXRewrittenBinaryOperator, CXXFoldExpr,
|
||||
UnaryOperator),
|
||||
std::string, Name) {
|
||||
if (std::optional<StringRef> OpName = internal::getOpName(Node))
|
||||
return *OpName == Name;
|
||||
@ -5789,11 +5945,12 @@ AST_POLYMORPHIC_MATCHER(
|
||||
/// \code
|
||||
/// a || b
|
||||
/// \endcode
|
||||
AST_POLYMORPHIC_MATCHER_P(hasLHS,
|
||||
AST_POLYMORPHIC_SUPPORTED_TYPES(
|
||||
BinaryOperator, CXXOperatorCallExpr,
|
||||
CXXRewrittenBinaryOperator, ArraySubscriptExpr),
|
||||
internal::Matcher<Expr>, InnerMatcher) {
|
||||
AST_POLYMORPHIC_MATCHER_P(
|
||||
hasLHS,
|
||||
AST_POLYMORPHIC_SUPPORTED_TYPES(BinaryOperator, CXXOperatorCallExpr,
|
||||
CXXRewrittenBinaryOperator,
|
||||
ArraySubscriptExpr, CXXFoldExpr),
|
||||
internal::Matcher<Expr>, InnerMatcher) {
|
||||
const Expr *LeftHandSide = internal::getLHS(Node);
|
||||
return (LeftHandSide != nullptr &&
|
||||
InnerMatcher.matches(*LeftHandSide, Finder, Builder));
|
||||
@ -5805,29 +5962,31 @@ AST_POLYMORPHIC_MATCHER_P(hasLHS,
|
||||
/// \code
|
||||
/// a || b
|
||||
/// \endcode
|
||||
AST_POLYMORPHIC_MATCHER_P(hasRHS,
|
||||
AST_POLYMORPHIC_SUPPORTED_TYPES(
|
||||
BinaryOperator, CXXOperatorCallExpr,
|
||||
CXXRewrittenBinaryOperator, ArraySubscriptExpr),
|
||||
internal::Matcher<Expr>, InnerMatcher) {
|
||||
AST_POLYMORPHIC_MATCHER_P(
|
||||
hasRHS,
|
||||
AST_POLYMORPHIC_SUPPORTED_TYPES(BinaryOperator, CXXOperatorCallExpr,
|
||||
CXXRewrittenBinaryOperator,
|
||||
ArraySubscriptExpr, CXXFoldExpr),
|
||||
internal::Matcher<Expr>, InnerMatcher) {
|
||||
const Expr *RightHandSide = internal::getRHS(Node);
|
||||
return (RightHandSide != nullptr &&
|
||||
InnerMatcher.matches(*RightHandSide, Finder, Builder));
|
||||
}
|
||||
|
||||
/// Matches if either the left hand side or the right hand side of a
|
||||
/// binary operator matches.
|
||||
/// binary operator or fold expression matches.
|
||||
AST_POLYMORPHIC_MATCHER_P(
|
||||
hasEitherOperand,
|
||||
AST_POLYMORPHIC_SUPPORTED_TYPES(BinaryOperator, CXXOperatorCallExpr,
|
||||
CXXRewrittenBinaryOperator),
|
||||
CXXFoldExpr, CXXRewrittenBinaryOperator),
|
||||
internal::Matcher<Expr>, InnerMatcher) {
|
||||
return internal::VariadicDynCastAllOfMatcher<Stmt, NodeType>()(
|
||||
anyOf(hasLHS(InnerMatcher), hasRHS(InnerMatcher)))
|
||||
.matches(Node, Finder, Builder);
|
||||
}
|
||||
|
||||
/// Matches if both matchers match with opposite sides of the binary operator.
|
||||
/// Matches if both matchers match with opposite sides of the binary operator
|
||||
/// or fold expression.
|
||||
///
|
||||
/// Example matcher = binaryOperator(hasOperands(integerLiteral(equals(1),
|
||||
/// integerLiteral(equals(2)))
|
||||
@ -5840,7 +5999,7 @@ AST_POLYMORPHIC_MATCHER_P(
|
||||
AST_POLYMORPHIC_MATCHER_P2(
|
||||
hasOperands,
|
||||
AST_POLYMORPHIC_SUPPORTED_TYPES(BinaryOperator, CXXOperatorCallExpr,
|
||||
CXXRewrittenBinaryOperator),
|
||||
CXXFoldExpr, CXXRewrittenBinaryOperator),
|
||||
internal::Matcher<Expr>, Matcher1, internal::Matcher<Expr>, Matcher2) {
|
||||
return internal::VariadicDynCastAllOfMatcher<Stmt, NodeType>()(
|
||||
anyOf(allOf(hasLHS(Matcher1), hasRHS(Matcher2)),
|
||||
|
@ -2195,6 +2195,9 @@ inline std::optional<StringRef> getOpName(const CXXOperatorCallExpr &Node) {
|
||||
}
|
||||
return BinaryOperator::getOpcodeStr(*optBinaryOpcode);
|
||||
}
|
||||
inline StringRef getOpName(const CXXFoldExpr &Node) {
|
||||
return BinaryOperator::getOpcodeStr(Node.getOperator());
|
||||
}
|
||||
|
||||
/// Matches overloaded operators with a specific name.
|
||||
///
|
||||
|
@ -893,6 +893,7 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, CXXOperatorCallExpr>
|
||||
cxxOperatorCallExpr;
|
||||
const internal::VariadicDynCastAllOfMatcher<Stmt, CXXRewrittenBinaryOperator>
|
||||
cxxRewrittenBinaryOperator;
|
||||
const internal::VariadicDynCastAllOfMatcher<Stmt, CXXFoldExpr> cxxFoldExpr;
|
||||
const internal::VariadicDynCastAllOfMatcher<Stmt, Expr> expr;
|
||||
const internal::VariadicDynCastAllOfMatcher<Stmt, DeclRefExpr> declRefExpr;
|
||||
const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCIvarRefExpr> objcIvarRefExpr;
|
||||
|
@ -198,6 +198,7 @@ RegistryMaps::RegistryMaps() {
|
||||
REGISTER_MATCHER(cxxDependentScopeMemberExpr);
|
||||
REGISTER_MATCHER(cxxDestructorDecl);
|
||||
REGISTER_MATCHER(cxxDynamicCastExpr);
|
||||
REGISTER_MATCHER(cxxFoldExpr);
|
||||
REGISTER_MATCHER(cxxForRangeStmt);
|
||||
REGISTER_MATCHER(cxxFunctionalCastExpr);
|
||||
REGISTER_MATCHER(cxxMemberCallExpr);
|
||||
@ -319,6 +320,7 @@ RegistryMaps::RegistryMaps() {
|
||||
REGISTER_MATCHER(hasExplicitSpecifier);
|
||||
REGISTER_MATCHER(hasExternalFormalLinkage);
|
||||
REGISTER_MATCHER(hasFalseExpression);
|
||||
REGISTER_MATCHER(hasFoldInit);
|
||||
REGISTER_MATCHER(hasGlobalStorage);
|
||||
REGISTER_MATCHER(hasImplicitDestinationType);
|
||||
REGISTER_MATCHER(hasInClassInitializer);
|
||||
@ -344,6 +346,7 @@ RegistryMaps::RegistryMaps() {
|
||||
REGISTER_MATCHER(hasOverloadedOperatorName);
|
||||
REGISTER_MATCHER(hasParameter);
|
||||
REGISTER_MATCHER(hasParent);
|
||||
REGISTER_MATCHER(hasPattern);
|
||||
REGISTER_MATCHER(hasPointeeLoc);
|
||||
REGISTER_MATCHER(hasQualifier);
|
||||
REGISTER_MATCHER(hasRHS);
|
||||
@ -404,6 +407,7 @@ RegistryMaps::RegistryMaps() {
|
||||
REGISTER_MATCHER(isAssignmentOperator);
|
||||
REGISTER_MATCHER(isAtPosition);
|
||||
REGISTER_MATCHER(isBaseInitializer);
|
||||
REGISTER_MATCHER(isBinaryFold);
|
||||
REGISTER_MATCHER(isBitField);
|
||||
REGISTER_MATCHER(isCatchAll);
|
||||
REGISTER_MATCHER(isClass);
|
||||
@ -447,6 +451,7 @@ RegistryMaps::RegistryMaps() {
|
||||
REGISTER_MATCHER(isInteger);
|
||||
REGISTER_MATCHER(isIntegral);
|
||||
REGISTER_MATCHER(isLambda);
|
||||
REGISTER_MATCHER(isLeftFold);
|
||||
REGISTER_MATCHER(isListInitialization);
|
||||
REGISTER_MATCHER(isMain);
|
||||
REGISTER_MATCHER(isMemberInitializer);
|
||||
@ -460,6 +465,7 @@ RegistryMaps::RegistryMaps() {
|
||||
REGISTER_MATCHER(isProtected);
|
||||
REGISTER_MATCHER(isPublic);
|
||||
REGISTER_MATCHER(isPure);
|
||||
REGISTER_MATCHER(isRightFold);
|
||||
REGISTER_MATCHER(isScoped);
|
||||
REGISTER_MATCHER(isSharedKind);
|
||||
REGISTER_MATCHER(isSignedInteger);
|
||||
@ -469,6 +475,7 @@ RegistryMaps::RegistryMaps() {
|
||||
REGISTER_MATCHER(isStruct);
|
||||
REGISTER_MATCHER(isTemplateInstantiation);
|
||||
REGISTER_MATCHER(isTypeDependent);
|
||||
REGISTER_MATCHER(isUnaryFold);
|
||||
REGISTER_MATCHER(isUnion);
|
||||
REGISTER_MATCHER(isUnsignedInteger);
|
||||
REGISTER_MATCHER(isUserProvided);
|
||||
|
@ -816,22 +816,15 @@ TEST_P(ImportExpr, ImportSizeOfPackExpr) {
|
||||
hasUnqualifiedDesugaredType(constantArrayType(hasSize(7))))))))));
|
||||
}
|
||||
|
||||
const internal::VariadicDynCastAllOfMatcher<Stmt, CXXFoldExpr> cxxFoldExpr;
|
||||
|
||||
AST_MATCHER_P(CXXFoldExpr, hasOperator, BinaryOperatorKind, Op) {
|
||||
return Node.getOperator() == Op;
|
||||
}
|
||||
AST_MATCHER(CXXFoldExpr, hasInit) { return Node.getInit(); }
|
||||
AST_MATCHER(CXXFoldExpr, isRightFold) { return Node.isRightFold(); }
|
||||
AST_MATCHER(CXXFoldExpr, isLeftFold) { return Node.isLeftFold(); }
|
||||
|
||||
TEST_P(ImportExpr, ImportCXXFoldExpr) {
|
||||
auto Match1 =
|
||||
cxxFoldExpr(hasOperator(BO_Add), isLeftFold(), unless(hasInit()));
|
||||
auto Match2 = cxxFoldExpr(hasOperator(BO_Sub), isLeftFold(), hasInit());
|
||||
auto Match3 =
|
||||
cxxFoldExpr(hasOperator(BO_Mul), isRightFold(), unless(hasInit()));
|
||||
auto Match4 = cxxFoldExpr(hasOperator(BO_Div), isRightFold(), hasInit());
|
||||
auto Match1 = cxxFoldExpr(hasOperatorName("+"), isLeftFold(),
|
||||
unless(hasFoldInit(expr())));
|
||||
auto Match2 =
|
||||
cxxFoldExpr(hasOperatorName("-"), isLeftFold(), hasFoldInit(expr()));
|
||||
auto Match3 = cxxFoldExpr(hasOperatorName("*"), isRightFold(),
|
||||
unless(hasFoldInit(expr())));
|
||||
auto Match4 =
|
||||
cxxFoldExpr(hasOperatorName("/"), isRightFold(), hasFoldInit(expr()));
|
||||
|
||||
MatchVerifier<Decl> Verifier;
|
||||
testImport("template <typename... Ts>"
|
||||
@ -1717,7 +1710,7 @@ TEST_P(ASTImporterOptionSpecificTestBase,
|
||||
R"s(
|
||||
struct declToImport {
|
||||
int a = d;
|
||||
union {
|
||||
union {
|
||||
int b;
|
||||
int c;
|
||||
};
|
||||
@ -4012,7 +4005,7 @@ TEST_P(ImportVariables, ImportBindingDecl) {
|
||||
int a[2] = {1,2};
|
||||
auto [x1,y1] = a;
|
||||
auto& [x2,y2] = a;
|
||||
|
||||
|
||||
struct S {
|
||||
mutable int x1 : 2;
|
||||
volatile double y1;
|
||||
|
@ -4103,15 +4103,102 @@ TEST_P(ASTMatchersTest, IsComparisonOperator) {
|
||||
notMatches("void x() { int a; if(a = 0) return; }", BinCompOperator));
|
||||
}
|
||||
|
||||
TEST_P(ASTMatchersTest, HasInit) {
|
||||
if (!GetParam().isCXX11OrLater()) {
|
||||
// FIXME: Add a test for `hasInit()` that does not depend on C++.
|
||||
TEST_P(ASTMatchersTest, isRightFold) {
|
||||
if (!GetParam().isCXX17OrLater()) {
|
||||
return;
|
||||
}
|
||||
|
||||
EXPECT_TRUE(matches("int x{0};", initListExpr(hasInit(0, expr()))));
|
||||
EXPECT_FALSE(matches("int x{0};", initListExpr(hasInit(1, expr()))));
|
||||
EXPECT_FALSE(matches("int x;", initListExpr(hasInit(0, expr()))));
|
||||
EXPECT_FALSE(matches("template <typename... Args> auto sum(Args... args) { "
|
||||
"return (0 + ... + args); }",
|
||||
cxxFoldExpr(isRightFold())));
|
||||
EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
|
||||
"return (args + ... + 0); }",
|
||||
cxxFoldExpr(isRightFold())));
|
||||
EXPECT_FALSE(matches("template <typename... Args> auto sum(Args... args) { "
|
||||
"return (... + args); };",
|
||||
cxxFoldExpr(isRightFold())));
|
||||
EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
|
||||
"return (args + ...); };",
|
||||
cxxFoldExpr(isRightFold())));
|
||||
}
|
||||
|
||||
TEST_P(ASTMatchersTest, isLeftFold) {
|
||||
if (!GetParam().isCXX17OrLater()) {
|
||||
return;
|
||||
}
|
||||
|
||||
EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
|
||||
"return (0 + ... + args); }",
|
||||
cxxFoldExpr(isLeftFold())));
|
||||
EXPECT_FALSE(matches("template <typename... Args> auto sum(Args... args) { "
|
||||
"return (args + ... + 0); }",
|
||||
cxxFoldExpr(isLeftFold())));
|
||||
EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
|
||||
"return (... + args); };",
|
||||
cxxFoldExpr(isLeftFold())));
|
||||
EXPECT_FALSE(matches("template <typename... Args> auto sum(Args... args) { "
|
||||
"return (args + ...); };",
|
||||
cxxFoldExpr(isLeftFold())));
|
||||
}
|
||||
|
||||
TEST_P(ASTMatchersTest, isUnaryFold) {
|
||||
if (!GetParam().isCXX17OrLater()) {
|
||||
return;
|
||||
}
|
||||
|
||||
EXPECT_FALSE(matches("template <typename... Args> auto sum(Args... args) { "
|
||||
"return (0 + ... + args); }",
|
||||
cxxFoldExpr(isUnaryFold())));
|
||||
EXPECT_FALSE(matches("template <typename... Args> auto sum(Args... args) { "
|
||||
"return (args + ... + 0); }",
|
||||
cxxFoldExpr(isUnaryFold())));
|
||||
EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
|
||||
"return (... + args); };",
|
||||
cxxFoldExpr(isUnaryFold())));
|
||||
EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
|
||||
"return (args + ...); };",
|
||||
cxxFoldExpr(isUnaryFold())));
|
||||
}
|
||||
|
||||
TEST_P(ASTMatchersTest, isBinaryFold) {
|
||||
if (!GetParam().isCXX17OrLater()) {
|
||||
return;
|
||||
}
|
||||
|
||||
EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
|
||||
"return (0 + ... + args); }",
|
||||
cxxFoldExpr(isBinaryFold())));
|
||||
EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
|
||||
"return (args + ... + 0); }",
|
||||
cxxFoldExpr(isBinaryFold())));
|
||||
EXPECT_FALSE(matches("template <typename... Args> auto sum(Args... args) { "
|
||||
"return (... + args); };",
|
||||
cxxFoldExpr(isBinaryFold())));
|
||||
EXPECT_FALSE(matches("template <typename... Args> auto sum(Args... args) { "
|
||||
"return (args + ...); };",
|
||||
cxxFoldExpr(isBinaryFold())));
|
||||
}
|
||||
|
||||
TEST_P(ASTMatchersTest, hasOperator) {
|
||||
if (!GetParam().isCXX17OrLater()) {
|
||||
return;
|
||||
}
|
||||
|
||||
EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
|
||||
"return (0 + ... + args); }",
|
||||
cxxFoldExpr(hasOperatorName("+"))));
|
||||
EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
|
||||
"return (... + args); };",
|
||||
cxxFoldExpr(hasOperatorName("+"))));
|
||||
|
||||
EXPECT_FALSE(
|
||||
matches("template <typename... Args> auto multiply(Args... args) { "
|
||||
"return (0 * ... * args); }",
|
||||
cxxFoldExpr(hasOperatorName("+"))));
|
||||
EXPECT_FALSE(
|
||||
matches("template <typename... Args> auto multiply(Args... args) { "
|
||||
"return (... * args); };",
|
||||
cxxFoldExpr(hasOperatorName("+"))));
|
||||
}
|
||||
|
||||
TEST_P(ASTMatchersTest, IsMain) {
|
||||
|
@ -471,6 +471,19 @@ TEST_P(ASTMatchersTest, CXXOperatorCallExpr) {
|
||||
EXPECT_TRUE(notMatches("int t = 5 << 2;", OpCall));
|
||||
}
|
||||
|
||||
TEST_P(ASTMatchersTest, FoldExpr) {
|
||||
if (!GetParam().isCXX() || !GetParam().isCXX17OrLater()) {
|
||||
return;
|
||||
}
|
||||
|
||||
EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
|
||||
"return (0 + ... + args); }",
|
||||
cxxFoldExpr()));
|
||||
EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
|
||||
"return (args + ...); }",
|
||||
cxxFoldExpr()));
|
||||
}
|
||||
|
||||
TEST_P(ASTMatchersTest, ThisPointerType) {
|
||||
if (!GetParam().isCXX()) {
|
||||
return;
|
||||
|
@ -658,27 +658,27 @@ void check_match_co_return() {
|
||||
co_return 1;
|
||||
}
|
||||
)cpp";
|
||||
EXPECT_TRUE(matchesConditionally(CoReturnCode,
|
||||
coreturnStmt(isExpansionInMainFile()),
|
||||
true, {"-std=c++20", "-I/"}, M));
|
||||
EXPECT_TRUE(matchesConditionally(CoReturnCode,
|
||||
coreturnStmt(isExpansionInMainFile()), true,
|
||||
{"-std=c++20", "-I/"}, M));
|
||||
StringRef CoAwaitCode = R"cpp(
|
||||
#include <coro_header>
|
||||
void check_match_co_await() {
|
||||
co_await a;
|
||||
}
|
||||
)cpp";
|
||||
EXPECT_TRUE(matchesConditionally(CoAwaitCode,
|
||||
coawaitExpr(isExpansionInMainFile()),
|
||||
true, {"-std=c++20", "-I/"}, M));
|
||||
EXPECT_TRUE(matchesConditionally(CoAwaitCode,
|
||||
coawaitExpr(isExpansionInMainFile()), true,
|
||||
{"-std=c++20", "-I/"}, M));
|
||||
StringRef CoYieldCode = R"cpp(
|
||||
#include <coro_header>
|
||||
void check_match_co_yield() {
|
||||
co_yield 1.0;
|
||||
}
|
||||
)cpp";
|
||||
EXPECT_TRUE(matchesConditionally(CoYieldCode,
|
||||
coyieldExpr(isExpansionInMainFile()),
|
||||
true, {"-std=c++20", "-I/"}, M));
|
||||
EXPECT_TRUE(matchesConditionally(CoYieldCode,
|
||||
coyieldExpr(isExpansionInMainFile()), true,
|
||||
{"-std=c++20", "-I/"}, M));
|
||||
|
||||
StringRef NonCoroCode = R"cpp(
|
||||
#include <coro_header>
|
||||
@ -2000,6 +2000,146 @@ TEST(Matcher, UnaryOperatorTypes) {
|
||||
"void x() { A a; !a; }", unaryOperator(hasOperatorName("!"))));
|
||||
}
|
||||
|
||||
TEST_P(ASTMatchersTest, HasInit) {
|
||||
if (!GetParam().isCXX11OrLater()) {
|
||||
// FIXME: Add a test for `hasInit()` that does not depend on C++.
|
||||
return;
|
||||
}
|
||||
|
||||
EXPECT_TRUE(matches("int x{0};", initListExpr(hasInit(0, expr()))));
|
||||
EXPECT_FALSE(matches("int x{0};", initListExpr(hasInit(1, expr()))));
|
||||
EXPECT_FALSE(matches("int x;", initListExpr(hasInit(0, expr()))));
|
||||
}
|
||||
|
||||
TEST_P(ASTMatchersTest, HasFoldInit) {
|
||||
if (!GetParam().isCXX17OrLater()) {
|
||||
return;
|
||||
}
|
||||
|
||||
EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
|
||||
"return (0 + ... + args); }",
|
||||
cxxFoldExpr(hasFoldInit(expr()))));
|
||||
EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
|
||||
"return (args + ... + 0); }",
|
||||
cxxFoldExpr(hasFoldInit(expr()))));
|
||||
EXPECT_FALSE(matches("template <typename... Args> auto sum(Args... args) { "
|
||||
"return (... + args); };",
|
||||
cxxFoldExpr(hasFoldInit(expr()))));
|
||||
}
|
||||
|
||||
TEST_P(ASTMatchersTest, HasPattern) {
|
||||
if (!GetParam().isCXX17OrLater()) {
|
||||
return;
|
||||
}
|
||||
|
||||
EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
|
||||
"return (0 + ... + args); }",
|
||||
cxxFoldExpr(hasPattern(expr()))));
|
||||
EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
|
||||
"return (args + ... + 0); }",
|
||||
cxxFoldExpr(hasPattern(expr()))));
|
||||
EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
|
||||
"return (... + args); };",
|
||||
cxxFoldExpr(hasPattern(expr()))));
|
||||
}
|
||||
|
||||
TEST_P(ASTMatchersTest, HasLHSAndHasRHS) {
|
||||
if (!GetParam().isCXX17OrLater()) {
|
||||
return;
|
||||
}
|
||||
|
||||
EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
|
||||
"return (0 + ... + args); }",
|
||||
cxxFoldExpr(hasLHS(expr()))));
|
||||
EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
|
||||
"return (args + ... + 0); }",
|
||||
cxxFoldExpr(hasLHS(expr()))));
|
||||
EXPECT_FALSE(matches("template <typename... Args> auto sum(Args... args) { "
|
||||
"return (... + args); };",
|
||||
cxxFoldExpr(hasLHS(expr()))));
|
||||
EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
|
||||
"return (args + ...); };",
|
||||
cxxFoldExpr(hasLHS(expr()))));
|
||||
|
||||
EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
|
||||
"return (0 + ... + args); }",
|
||||
cxxFoldExpr(hasRHS(expr()))));
|
||||
EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
|
||||
"return (args + ... + 0); }",
|
||||
cxxFoldExpr(hasRHS(expr()))));
|
||||
EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
|
||||
"return (... + args); };",
|
||||
cxxFoldExpr(hasRHS(expr()))));
|
||||
EXPECT_FALSE(matches("template <typename... Args> auto sum(Args... args) { "
|
||||
"return (args + ...); };",
|
||||
cxxFoldExpr(hasRHS(expr()))));
|
||||
}
|
||||
|
||||
TEST_P(ASTMatchersTest, HasEitherOperandAndHasOperands) {
|
||||
if (!GetParam().isCXX17OrLater()) {
|
||||
return;
|
||||
}
|
||||
|
||||
EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
|
||||
"return (0 + ... + args); }",
|
||||
cxxFoldExpr(hasEitherOperand(integerLiteral()))));
|
||||
EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
|
||||
"return (args + ... + 0); }",
|
||||
cxxFoldExpr(hasEitherOperand(integerLiteral()))));
|
||||
|
||||
EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
|
||||
"return (0 + ... + args); }",
|
||||
cxxFoldExpr(hasEitherOperand(
|
||||
declRefExpr(to(namedDecl(hasName("args"))))))));
|
||||
EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
|
||||
"return (args + ... + 0); }",
|
||||
cxxFoldExpr(hasEitherOperand(
|
||||
declRefExpr(to(namedDecl(hasName("args"))))))));
|
||||
EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
|
||||
"return (... + args); };",
|
||||
cxxFoldExpr(hasEitherOperand(
|
||||
declRefExpr(to(namedDecl(hasName("args"))))))));
|
||||
EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
|
||||
"return (args + ...); };",
|
||||
cxxFoldExpr(hasEitherOperand(
|
||||
declRefExpr(to(namedDecl(hasName("args"))))))));
|
||||
|
||||
EXPECT_TRUE(matches(
|
||||
"template <typename... Args> auto sum(Args... args) { "
|
||||
"return (0 + ... + args); }",
|
||||
cxxFoldExpr(hasOperands(declRefExpr(to(namedDecl(hasName("args")))),
|
||||
integerLiteral()))));
|
||||
EXPECT_TRUE(matches(
|
||||
"template <typename... Args> auto sum(Args... args) { "
|
||||
"return (args + ... + 0); }",
|
||||
cxxFoldExpr(hasOperands(declRefExpr(to(namedDecl(hasName("args")))),
|
||||
integerLiteral()))));
|
||||
EXPECT_FALSE(matches(
|
||||
"template <typename... Args> auto sum(Args... args) { "
|
||||
"return (... + args); };",
|
||||
cxxFoldExpr(hasOperands(declRefExpr(to(namedDecl(hasName("args")))),
|
||||
integerLiteral()))));
|
||||
EXPECT_FALSE(matches(
|
||||
"template <typename... Args> auto sum(Args... args) { "
|
||||
"return (args + ...); };",
|
||||
cxxFoldExpr(hasOperands(declRefExpr(to(namedDecl(hasName("args")))),
|
||||
integerLiteral()))));
|
||||
}
|
||||
|
||||
TEST_P(ASTMatchersTest, Callee) {
|
||||
if (!GetParam().isCXX17OrLater()) {
|
||||
return;
|
||||
}
|
||||
|
||||
EXPECT_TRUE(matches(
|
||||
"struct Dummy {}; Dummy operator+(Dummy, Dummy); template "
|
||||
"<typename... Args> auto sum(Args... args) { return (0 + ... + args); }",
|
||||
cxxFoldExpr(callee(expr()))));
|
||||
EXPECT_FALSE(matches("template <typename... Args> auto sum(Args... args) { "
|
||||
"return (0 + ... + args); }",
|
||||
cxxFoldExpr(callee(expr()))));
|
||||
}
|
||||
|
||||
TEST(ArraySubscriptMatchers, ArrayIndex) {
|
||||
EXPECT_TRUE(matches(
|
||||
"int i[2]; void f() { i[1] = 1; }",
|
||||
|
Loading…
x
Reference in New Issue
Block a user