https://github.com/5chmidti updated https://github.com/llvm/llvm-project/pull/71245
>From ae352f244a031b587d136423e0e3ef51f522c771 Mon Sep 17 00:00:00 2001 From: Julian Schmidt <44101708+5chmi...@users.noreply.github.com> Date: Fri, 3 Nov 2023 21:51:57 +0100 Subject: [PATCH 1/5] [clang][ASTMatcher] Add matchers for CXXFoldExpr --- clang/docs/LibASTMatchersReference.html | 209 +++++++++++++++++- clang/docs/ReleaseNotes.rst | 3 + clang/include/clang/ASTMatchers/ASTMatchers.h | 194 ++++++++++++++-- clang/lib/ASTMatchers/ASTMatchersInternal.cpp | 1 + clang/lib/ASTMatchers/Dynamic/Registry.cpp | 1 + clang/unittests/AST/ASTImporterTest.cpp | 27 +-- .../ASTMatchers/ASTMatchersNarrowingTest.cpp | 99 ++++++++- .../ASTMatchers/ASTMatchersNodeTest.cpp | 13 ++ .../ASTMatchers/ASTMatchersTraversalTest.cpp | 89 ++++++++ 9 files changed, 594 insertions(+), 42 deletions(-) diff --git a/clang/docs/LibASTMatchersReference.html b/clang/docs/LibASTMatchersReference.html index fcd3114bb523105..39d1ffe3d2dee3b 100644 --- a/clang/docs/LibASTMatchersReference.html +++ b/clang/docs/LibASTMatchersReference.html @@ -1629,6 +1629,17 @@ <h2 id="decl-matchers">Node Matchers</h2> </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. @@ -3430,6 +3441,92 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2> </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('hasOperator0')"><a name="hasOperator0Anchor">hasOperator</a></td><td>BinaryOperatorKind Op</td></tr> +<tr><td colspan="4" class="doc" id="hasOperator0"><pre>Matches the operator kind of the fold expression. + +Example matches `(0 + ... + args)` + (matcher = cxxFoldExpr(hasOperator(BO_Add))) + 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('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. @@ -6885,6 +6982,93 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2> </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('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('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 @@ -7436,8 +7620,8 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2> </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 +7642,7 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2> <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 +7652,21 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2> 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 +9286,8 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2> </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. diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index afe7e2e79c2d087..9f753af4f7dfe6f 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -830,6 +830,9 @@ AST Matchers - Add ``convertVectorExpr``. - Add ``dependentSizedExtVectorType``. - Add ``macroQualifiedType``. +- Add ``CXXFoldExpr`` related matchers: ``cxxFoldExpr``, ``callee``, + ``hasInit``, ``hasPattern``, ``isRightFold``, ``isLeftFold``, + ``isUnaryFold``, ``isBinaryFold``, ``hasOperator``, ``hasLHS``, ``hasRHS``. clang-format ------------ diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h index 82a26356c58f556..2cd50dbf3a55d8c 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchers.h +++ b/clang/include/clang/ASTMatchers/ASTMatchers.h @@ -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,139 @@ 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) { + return InnerMacher.matches(*Node.getPattern(), 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 operator kind of the fold expression. +/// +/// Example matches `(0 + ... + args)` +/// (matcher = cxxFoldExpr(hasOperator(BO_Add))) +/// \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, hasOperator, BinaryOperatorKind, Op) { + return Node.getOperator() == Op; +} + /// Matches the n'th item of an initializer list expression. /// /// Example matches y. @@ -5789,11 +5953,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,11 +5970,12 @@ 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)); diff --git a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp index 435bbdeda22066e..616e6a959e0f59d 100644 --- a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp +++ b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp @@ -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; diff --git a/clang/lib/ASTMatchers/Dynamic/Registry.cpp b/clang/lib/ASTMatchers/Dynamic/Registry.cpp index 2e43dec331b75f8..8ce9e27aa36d692 100644 --- a/clang/lib/ASTMatchers/Dynamic/Registry.cpp +++ b/clang/lib/ASTMatchers/Dynamic/Registry.cpp @@ -319,6 +319,7 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(hasExplicitSpecifier); REGISTER_MATCHER(hasExternalFormalLinkage); REGISTER_MATCHER(hasFalseExpression); + REGISTER_MATCHER(hasFoldInit); REGISTER_MATCHER(hasGlobalStorage); REGISTER_MATCHER(hasImplicitDestinationType); REGISTER_MATCHER(hasInClassInitializer); diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp index 5f4d8d040772cb1..b150ba665fa4762 100644 --- a/clang/unittests/AST/ASTImporterTest.cpp +++ b/clang/unittests/AST/ASTImporterTest.cpp @@ -803,22 +803,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(hasOperator(BO_Add), isLeftFold(), + unless(hasFoldInit(expr()))); + auto Match2 = + cxxFoldExpr(hasOperator(BO_Sub), isLeftFold(), hasFoldInit(expr())); + auto Match3 = cxxFoldExpr(hasOperator(BO_Mul), isRightFold(), + unless(hasFoldInit(expr()))); + auto Match4 = + cxxFoldExpr(hasOperator(BO_Div), isRightFold(), hasFoldInit(expr())); MatchVerifier<Decl> Verifier; testImport("template <typename... Ts>" @@ -1704,7 +1697,7 @@ TEST_P(ASTImporterOptionSpecificTestBase, R"s( struct declToImport { int a = d; - union { + union { int b; int c; }; @@ -3999,7 +3992,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; diff --git a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp index d78676fd289d5e5..ff107995715c745 100644 --- a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp +++ b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp @@ -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_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_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(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(hasOperator(BO_Add)))); + EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { " + "return (... + args); };", + cxxFoldExpr(hasOperator(BO_Add)))); + + EXPECT_FALSE( + matches("template <typename... Args> auto multiply(Args... args) { " + "return (0 * ... * args); }", + cxxFoldExpr(hasOperator(BO_Add)))); + EXPECT_FALSE( + matches("template <typename... Args> auto multiply(Args... args) { " + "return (... * args); };", + cxxFoldExpr(hasOperator(BO_Add)))); } TEST_P(ASTMatchersTest, IsMain) { diff --git a/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp index 8f0dd5602307c53..ae30c03126d768c 100644 --- a/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp +++ b/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp @@ -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; diff --git a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp index d4a695b974bf0e5..0e7a4b4657ed439 100644 --- a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp +++ b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp @@ -2000,6 +2000,95 @@ 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, 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; }", >From 81c42219f3047b1c1e03ae23885fbb63f6079e95 Mon Sep 17 00:00:00 2001 From: Julian Schmidt <44101708+5chmi...@users.noreply.github.com> Date: Fri, 24 Nov 2023 23:22:45 +0100 Subject: [PATCH 2/5] add missing support for `hasEitherOperand` and `hasOperands` --- clang/docs/LibASTMatchersReference.html | 40 ++++++++--- clang/docs/ReleaseNotes.rst | 2 +- clang/include/clang/ASTMatchers/ASTMatchers.h | 9 +-- .../ASTMatchers/ASTMatchersTraversalTest.cpp | 69 ++++++++++++++++--- 4 files changed, 97 insertions(+), 23 deletions(-) diff --git a/clang/docs/LibASTMatchersReference.html b/clang/docs/LibASTMatchersReference.html index 39d1ffe3d2dee3b..7d72e4eb70943f2 100644 --- a/clang/docs/LibASTMatchersReference.html +++ b/clang/docs/LibASTMatchersReference.html @@ -6550,7 +6550,7 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2> <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> @@ -6563,7 +6563,8 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2> <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))) @@ -7015,6 +7016,12 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2> </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. @@ -7042,6 +7049,19 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2> </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. @@ -7363,7 +7383,7 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2> <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> @@ -7376,7 +7396,8 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2> <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))) @@ -7501,9 +7522,9 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2> </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> @@ -7515,8 +7536,9 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2> </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))) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 9f753af4f7dfe6f..fc40da2eaec0e0d 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -832,7 +832,7 @@ AST Matchers - Add ``macroQualifiedType``. - Add ``CXXFoldExpr`` related matchers: ``cxxFoldExpr``, ``callee``, ``hasInit``, ``hasPattern``, ``isRightFold``, ``isLeftFold``, - ``isUnaryFold``, ``isBinaryFold``, ``hasOperator``, ``hasLHS``, ``hasRHS``. + ``isUnaryFold``, ``isBinaryFold``, ``hasOperator``, ``hasLHS``, ``hasRHS``, ``hasEitherOperand``. clang-format ------------ diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h index 2cd50dbf3a55d8c..07d7254404d95b0 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchers.h +++ b/clang/include/clang/ASTMatchers/ASTMatchers.h @@ -5982,18 +5982,19 @@ AST_POLYMORPHIC_MATCHER_P( } /// 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))) @@ -6006,7 +6007,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)), diff --git a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp index 0e7a4b4657ed439..6911d7600a71889 100644 --- a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp +++ b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp @@ -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> @@ -2075,6 +2075,57 @@ TEST_P(ASTMatchersTest, HasLHSAndHasRHS) { 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; >From dfe053f7de82894087ad812eecb2716f8bed96ec Mon Sep 17 00:00:00 2001 From: Julian Schmidt <44101708+5chmi...@users.noreply.github.com> Date: Fri, 24 Nov 2023 23:25:49 +0100 Subject: [PATCH 3/5] check if the pattern is not null in `hasPattern` --- clang/include/clang/ASTMatchers/ASTMatchers.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h index 07d7254404d95b0..ccd72f734800171 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchers.h +++ b/clang/include/clang/ASTMatchers/ASTMatchers.h @@ -4605,7 +4605,8 @@ AST_MATCHER_P(CXXFoldExpr, hasFoldInit, ast_matchers::internal::Matcher<Expr>, /// \endcode AST_MATCHER_P(CXXFoldExpr, hasPattern, ast_matchers::internal::Matcher<Expr>, InnerMacher) { - return InnerMacher.matches(*Node.getPattern(), Finder, Builder); + const Expr *const Pattern = Node.getPattern(); + return Pattern && InnerMacher.matches(*Pattern, Finder, Builder); } /// Matches right-folding fold expressions. >From 0b3632c58dba2f9aff756ded8181ca9a15e3f34c Mon Sep 17 00:00:00 2001 From: Julian Schmidt <44101708+5chmi...@users.noreply.github.com> Date: Fri, 24 Nov 2023 23:30:14 +0100 Subject: [PATCH 4/5] register all added matchers in the registry --- clang/lib/ASTMatchers/Dynamic/Registry.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/clang/lib/ASTMatchers/Dynamic/Registry.cpp b/clang/lib/ASTMatchers/Dynamic/Registry.cpp index 8ce9e27aa36d692..a37f02056feb29f 100644 --- a/clang/lib/ASTMatchers/Dynamic/Registry.cpp +++ b/clang/lib/ASTMatchers/Dynamic/Registry.cpp @@ -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); @@ -341,10 +342,12 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(hasNullSelector); REGISTER_MATCHER(hasObjectExpression); REGISTER_MATCHER(hasOperands); + REGISTER_MATCHER(hasOperator); REGISTER_MATCHER(hasOperatorName); REGISTER_MATCHER(hasOverloadedOperatorName); REGISTER_MATCHER(hasParameter); REGISTER_MATCHER(hasParent); + REGISTER_MATCHER(hasPattern); REGISTER_MATCHER(hasPointeeLoc); REGISTER_MATCHER(hasQualifier); REGISTER_MATCHER(hasRHS); @@ -405,6 +408,7 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(isAssignmentOperator); REGISTER_MATCHER(isAtPosition); REGISTER_MATCHER(isBaseInitializer); + REGISTER_MATCHER(isBinaryFold); REGISTER_MATCHER(isBitField); REGISTER_MATCHER(isCatchAll); REGISTER_MATCHER(isClass); @@ -448,6 +452,7 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(isInteger); REGISTER_MATCHER(isIntegral); REGISTER_MATCHER(isLambda); + REGISTER_MATCHER(isLeftFold); REGISTER_MATCHER(isListInitialization); REGISTER_MATCHER(isMain); REGISTER_MATCHER(isMemberInitializer); @@ -461,6 +466,7 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(isProtected); REGISTER_MATCHER(isPublic); REGISTER_MATCHER(isPure); + REGISTER_MATCHER(isRightFold); REGISTER_MATCHER(isScoped); REGISTER_MATCHER(isSharedKind); REGISTER_MATCHER(isSignedInteger); @@ -470,6 +476,7 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(isStruct); REGISTER_MATCHER(isTemplateInstantiation); REGISTER_MATCHER(isTypeDependent); + REGISTER_MATCHER(isUnaryFold); REGISTER_MATCHER(isUnion); REGISTER_MATCHER(isUnsignedInteger); REGISTER_MATCHER(isUserProvided); >From 02f5f90caf11315adfc8d865ca911025d60b25e4 Mon Sep 17 00:00:00 2001 From: Julian Schmidt <44101708+5chmi...@users.noreply.github.com> Date: Fri, 24 Nov 2023 23:49:05 +0100 Subject: [PATCH 5/5] extend `hasOperatorName` instead of adding `hasOperator` --- clang/docs/LibASTMatchersReference.html | 61 +++++++++++++------ clang/include/clang/ASTMatchers/ASTMatchers.h | 35 ++++------- .../clang/ASTMatchers/ASTMatchersInternal.h | 3 + clang/lib/ASTMatchers/Dynamic/Registry.cpp | 1 - clang/unittests/AST/ASTImporterTest.cpp | 8 +-- .../ASTMatchers/ASTMatchersNarrowingTest.cpp | 8 +-- 6 files changed, 68 insertions(+), 48 deletions(-) diff --git a/clang/docs/LibASTMatchersReference.html b/clang/docs/LibASTMatchersReference.html index 7d72e4eb70943f2..c40d679e383bb2a 100644 --- a/clang/docs/LibASTMatchersReference.html +++ b/clang/docs/LibASTMatchersReference.html @@ -2976,11 +2976,18 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2> <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> @@ -3441,20 +3448,19 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2> </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('hasOperator0')"><a name="hasOperator0Anchor">hasOperator</a></td><td>BinaryOperatorKind Op</td></tr> -<tr><td colspan="4" class="doc" id="hasOperator0"><pre>Matches the operator kind of the fold expression. +<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(hasOperator(BO_Add))) + (matcher = cxxFoldExpr(hasOperatorName("+"))) template <typename... Args> auto sum(Args... args) { return (0 + ... + args); } - - template <typename... Args> - auto multiply(Args... args) { - return (args * ... * 1); - } </pre></td></tr> @@ -3696,11 +3702,18 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2> <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> @@ -3854,11 +3867,18 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2> <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> @@ -5808,12 +5828,19 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2> </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> diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h index ccd72f734800171..65196c52a3e293e 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchers.h +++ b/clang/include/clang/ASTMatchers/ASTMatchers.h @@ -4678,25 +4678,6 @@ AST_MATCHER(CXXFoldExpr, isUnaryFold) { return Node.getInit() == nullptr; } /// \endcode AST_MATCHER(CXXFoldExpr, isBinaryFold) { return Node.getInit() != nullptr; } -/// Matches the operator kind of the fold expression. -/// -/// Example matches `(0 + ... + args)` -/// (matcher = cxxFoldExpr(hasOperator(BO_Add))) -/// \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, hasOperator, BinaryOperatorKind, Op) { - return Node.getOperator() == Op; -} - /// Matches the n'th item of an initializer list expression. /// /// Example matches y. @@ -5874,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; diff --git a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h index 7136d0d2fe0845a..47d912c73dd7eb4 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h +++ b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h @@ -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. /// diff --git a/clang/lib/ASTMatchers/Dynamic/Registry.cpp b/clang/lib/ASTMatchers/Dynamic/Registry.cpp index a37f02056feb29f..15dad022df5fe09 100644 --- a/clang/lib/ASTMatchers/Dynamic/Registry.cpp +++ b/clang/lib/ASTMatchers/Dynamic/Registry.cpp @@ -342,7 +342,6 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(hasNullSelector); REGISTER_MATCHER(hasObjectExpression); REGISTER_MATCHER(hasOperands); - REGISTER_MATCHER(hasOperator); REGISTER_MATCHER(hasOperatorName); REGISTER_MATCHER(hasOverloadedOperatorName); REGISTER_MATCHER(hasParameter); diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp index b150ba665fa4762..0c01af4ec98aa1b 100644 --- a/clang/unittests/AST/ASTImporterTest.cpp +++ b/clang/unittests/AST/ASTImporterTest.cpp @@ -804,14 +804,14 @@ TEST_P(ImportExpr, ImportSizeOfPackExpr) { } TEST_P(ImportExpr, ImportCXXFoldExpr) { - auto Match1 = cxxFoldExpr(hasOperator(BO_Add), isLeftFold(), + auto Match1 = cxxFoldExpr(hasOperatorName("+"), isLeftFold(), unless(hasFoldInit(expr()))); auto Match2 = - cxxFoldExpr(hasOperator(BO_Sub), isLeftFold(), hasFoldInit(expr())); - auto Match3 = cxxFoldExpr(hasOperator(BO_Mul), isRightFold(), + cxxFoldExpr(hasOperatorName("-"), isLeftFold(), hasFoldInit(expr())); + auto Match3 = cxxFoldExpr(hasOperatorName("*"), isRightFold(), unless(hasFoldInit(expr()))); auto Match4 = - cxxFoldExpr(hasOperator(BO_Div), isRightFold(), hasFoldInit(expr())); + cxxFoldExpr(hasOperatorName("/"), isRightFold(), hasFoldInit(expr())); MatchVerifier<Decl> Verifier; testImport("template <typename... Ts>" diff --git a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp index ff107995715c745..edcdae4559d970b 100644 --- a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp +++ b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp @@ -4186,19 +4186,19 @@ TEST_P(ASTMatchersTest, hasOperator) { EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { " "return (0 + ... + args); }", - cxxFoldExpr(hasOperator(BO_Add)))); + cxxFoldExpr(hasOperatorName("+")))); EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { " "return (... + args); };", - cxxFoldExpr(hasOperator(BO_Add)))); + cxxFoldExpr(hasOperatorName("+")))); EXPECT_FALSE( matches("template <typename... Args> auto multiply(Args... args) { " "return (0 * ... * args); }", - cxxFoldExpr(hasOperator(BO_Add)))); + cxxFoldExpr(hasOperatorName("+")))); EXPECT_FALSE( matches("template <typename... Args> auto multiply(Args... args) { " "return (... * args); };", - cxxFoldExpr(hasOperator(BO_Add)))); + cxxFoldExpr(hasOperatorName("+")))); } TEST_P(ASTMatchersTest, IsMain) { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits