@@ -2062,6 +2062,18 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXDefaultArgExpr>
20622062extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXOperatorCallExpr>
20632063 cxxOperatorCallExpr;
20642064
2065+ // / Matches C++17 fold expressions.
2066+ // /
2067+ // / Example matches `(0 + ... + args)`:
2068+ // / \code
2069+ // / template <typename... Args>
2070+ // / auto sum(Args... args) {
2071+ // / return (0 + ... + args);
2072+ // / }
2073+ // / \endcode
2074+ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXFoldExpr>
2075+ cxxFoldExpr;
2076+
20652077// / Matches rewritten binary operators
20662078// /
20672079// / Example matches use of "<":
@@ -3881,7 +3893,7 @@ AST_MATCHER_P(ObjCMessageExpr, numSelectorArgs, unsigned, N) {
38813893 return Node.getSelector ().getNumArgs () == N;
38823894}
38833895
3884- // / Matches if the call expression's callee expression matches.
3896+ // / Matches if the call or fold expression's callee expression matches.
38853897// /
38863898// / Given
38873899// / \code
@@ -3893,13 +3905,32 @@ AST_MATCHER_P(ObjCMessageExpr, numSelectorArgs, unsigned, N) {
38933905// / with callee(...)
38943906// / matching this->x, x, y.x, f respectively
38953907// /
3908+ // / Given
3909+ // / \code
3910+ // / template <typename... Args>
3911+ // / auto sum(Args... args) {
3912+ // / return (0 + ... + args);
3913+ // / }
3914+ // /
3915+ // / template <typename... Args>
3916+ // / auto multiply(Args... args) {
3917+ // / return (args * ... * 1);
3918+ // / }
3919+ // / \endcode
3920+ // / cxxFoldExpr(callee(expr()))
3921+ // / matches (args * ... * 1)
3922+ // / with callee(...)
3923+ // / matching *
3924+ // /
38963925// / Note: Callee cannot take the more general internal::Matcher<Expr>
38973926// / because this introduces ambiguous overloads with calls to Callee taking a
38983927// / internal::Matcher<Decl>, as the matcher hierarchy is purely
38993928// / implemented in terms of implicit casts.
3900- AST_MATCHER_P (CallExpr, callee, internal::Matcher<Stmt>,
3901- InnerMatcher) {
3902- const Expr *ExprNode = Node.getCallee ();
3929+ AST_POLYMORPHIC_MATCHER_P_OVERLOAD (callee,
3930+ AST_POLYMORPHIC_SUPPORTED_TYPES (CallExpr,
3931+ CXXFoldExpr),
3932+ internal::Matcher<Stmt>, InnerMatcher, 0) {
3933+ const auto *ExprNode = Node.getCallee ();
39033934 return (ExprNode != nullptr &&
39043935 InnerMatcher.matches (*ExprNode, Finder, Builder));
39053936}
@@ -4532,6 +4563,121 @@ AST_POLYMORPHIC_MATCHER_P2(hasArgument,
45324563 return InnerMatcher.matches (*Arg->IgnoreParenImpCasts (), Finder, Builder);
45334564}
45344565
4566+ // / Matches the operand that does not contain the parameter pack.
4567+ // /
4568+ // / Example matches `(0 + ... + args)` and `(args * ... * 1)`
4569+ // / (matcher = cxxFoldExpr(hasFoldInit(expr())))
4570+ // / with hasFoldInit(...)
4571+ // / matching `0` and `1` respectively
4572+ // / \code
4573+ // / template <typename... Args>
4574+ // / auto sum(Args... args) {
4575+ // / return (0 + ... + args);
4576+ // / }
4577+ // /
4578+ // / template <typename... Args>
4579+ // / auto multiply(Args... args) {
4580+ // / return (args * ... * 1);
4581+ // / }
4582+ // / \endcode
4583+ AST_MATCHER_P (CXXFoldExpr, hasFoldInit, ast_matchers::internal::Matcher<Expr>,
4584+ InnerMacher) {
4585+ const auto *const Init = Node.getInit ();
4586+ return Init && InnerMacher.matches (*Init, Finder, Builder);
4587+ }
4588+
4589+ // / Matches the operand that contains the parameter pack.
4590+ // /
4591+ // / Example matches `(0 + ... + args)`
4592+ // / (matcher = cxxFoldExpr(hasPattern(expr())))
4593+ // / with hasPattern(...)
4594+ // / matching `args`
4595+ // / \code
4596+ // / template <typename... Args>
4597+ // / auto sum(Args... args) {
4598+ // / return (0 + ... + args);
4599+ // / }
4600+ // /
4601+ // / template <typename... Args>
4602+ // / auto multiply(Args... args) {
4603+ // / return (args * ... * 1);
4604+ // / }
4605+ // / \endcode
4606+ AST_MATCHER_P (CXXFoldExpr, hasPattern, ast_matchers::internal::Matcher<Expr>,
4607+ InnerMacher) {
4608+ const Expr *const Pattern = Node.getPattern ();
4609+ return Pattern && InnerMacher.matches (*Pattern, Finder, Builder);
4610+ }
4611+
4612+ // / Matches right-folding fold expressions.
4613+ // /
4614+ // / Example matches `(args * ... * 1)`
4615+ // / (matcher = cxxFoldExpr(isRightFold()))
4616+ // / \code
4617+ // / template <typename... Args>
4618+ // / auto sum(Args... args) {
4619+ // / return (0 + ... + args);
4620+ // / }
4621+ // /
4622+ // / template <typename... Args>
4623+ // / auto multiply(Args... args) {
4624+ // / return (args * ... * 1);
4625+ // / }
4626+ // / \endcode
4627+ AST_MATCHER (CXXFoldExpr, isRightFold) { return Node.isRightFold (); }
4628+
4629+ // / Matches left-folding fold expressions.
4630+ // /
4631+ // / Example matches `(0 + ... + args)`
4632+ // / (matcher = cxxFoldExpr(isLeftFold()))
4633+ // / \code
4634+ // / template <typename... Args>
4635+ // / auto sum(Args... args) {
4636+ // / return (0 + ... + args);
4637+ // / }
4638+ // /
4639+ // / template <typename... Args>
4640+ // / auto multiply(Args... args) {
4641+ // / return (args * ... * 1);
4642+ // / }
4643+ // / \endcode
4644+ AST_MATCHER (CXXFoldExpr, isLeftFold) { return Node.isLeftFold (); }
4645+
4646+ // / Matches unary fold expressions, i.e. fold expressions without an
4647+ // / initializer.
4648+ // /
4649+ // / Example matches `(args * ...)`
4650+ // / (matcher = cxxFoldExpr(isUnaryFold()))
4651+ // / \code
4652+ // / template <typename... Args>
4653+ // / auto sum(Args... args) {
4654+ // / return (0 + ... + args);
4655+ // / }
4656+ // /
4657+ // / template <typename... Args>
4658+ // / auto multiply(Args... args) {
4659+ // / return (args * ...);
4660+ // / }
4661+ // / \endcode
4662+ AST_MATCHER (CXXFoldExpr, isUnaryFold) { return Node.getInit () == nullptr ; }
4663+
4664+ // / Matches binary fold expressions, i.e. fold expressions with an initializer.
4665+ // /
4666+ // / Example matches `(0 + ... + args)`
4667+ // / (matcher = cxxFoldExpr(isBinaryFold()))
4668+ // / \code
4669+ // / template <typename... Args>
4670+ // / auto sum(Args... args) {
4671+ // / return (0 + ... + args);
4672+ // / }
4673+ // /
4674+ // / template <typename... Args>
4675+ // / auto multiply(Args... args) {
4676+ // / return (args * ...);
4677+ // / }
4678+ // / \endcode
4679+ AST_MATCHER (CXXFoldExpr, isBinaryFold) { return Node.getInit () != nullptr ; }
4680+
45354681// / Matches the n'th item of an initializer list expression.
45364682// /
45374683// / Example matches y.
@@ -5709,17 +5855,27 @@ AST_POLYMORPHIC_MATCHER_P_OVERLOAD(equals,
57095855 .matchesNode (Node);
57105856}
57115857
5712- // / Matches the operator Name of operator expressions (binary or
5713- // / unary).
5858+ // / Matches the operator Name of operator expressions and fold expressions
5859+ // / (binary or unary).
57145860// /
57155861// / Example matches a || b (matcher = binaryOperator(hasOperatorName("||")))
57165862// / \code
57175863// / !(a || b)
57185864// / \endcode
5865+ // /
5866+ // / Example matches `(0 + ... + args)`
5867+ // / (matcher = cxxFoldExpr(hasOperatorName("+")))
5868+ // / \code
5869+ // / template <typename... Args>
5870+ // / auto sum(Args... args) {
5871+ // / return (0 + ... + args);
5872+ // / }
5873+ // / \endcode
57195874AST_POLYMORPHIC_MATCHER_P (
57205875 hasOperatorName,
57215876 AST_POLYMORPHIC_SUPPORTED_TYPES (BinaryOperator, CXXOperatorCallExpr,
5722- CXXRewrittenBinaryOperator, UnaryOperator),
5877+ CXXRewrittenBinaryOperator, CXXFoldExpr,
5878+ UnaryOperator),
57235879 std::string, Name) {
57245880 if (std::optional<StringRef> OpName = internal::getOpName (Node))
57255881 return *OpName == Name;
@@ -5789,11 +5945,12 @@ AST_POLYMORPHIC_MATCHER(
57895945// / \code
57905946// / a || b
57915947// / \endcode
5792- AST_POLYMORPHIC_MATCHER_P (hasLHS,
5793- AST_POLYMORPHIC_SUPPORTED_TYPES (
5794- BinaryOperator, CXXOperatorCallExpr,
5795- CXXRewrittenBinaryOperator, ArraySubscriptExpr),
5796- internal::Matcher<Expr>, InnerMatcher) {
5948+ AST_POLYMORPHIC_MATCHER_P (
5949+ hasLHS,
5950+ AST_POLYMORPHIC_SUPPORTED_TYPES (BinaryOperator, CXXOperatorCallExpr,
5951+ CXXRewrittenBinaryOperator,
5952+ ArraySubscriptExpr, CXXFoldExpr),
5953+ internal::Matcher<Expr>, InnerMatcher) {
57975954 const Expr *LeftHandSide = internal::getLHS (Node);
57985955 return (LeftHandSide != nullptr &&
57995956 InnerMatcher.matches (*LeftHandSide, Finder, Builder));
@@ -5805,29 +5962,31 @@ AST_POLYMORPHIC_MATCHER_P(hasLHS,
58055962// / \code
58065963// / a || b
58075964// / \endcode
5808- AST_POLYMORPHIC_MATCHER_P (hasRHS,
5809- AST_POLYMORPHIC_SUPPORTED_TYPES (
5810- BinaryOperator, CXXOperatorCallExpr,
5811- CXXRewrittenBinaryOperator, ArraySubscriptExpr),
5812- internal::Matcher<Expr>, InnerMatcher) {
5965+ AST_POLYMORPHIC_MATCHER_P (
5966+ hasRHS,
5967+ AST_POLYMORPHIC_SUPPORTED_TYPES (BinaryOperator, CXXOperatorCallExpr,
5968+ CXXRewrittenBinaryOperator,
5969+ ArraySubscriptExpr, CXXFoldExpr),
5970+ internal::Matcher<Expr>, InnerMatcher) {
58135971 const Expr *RightHandSide = internal::getRHS (Node);
58145972 return (RightHandSide != nullptr &&
58155973 InnerMatcher.matches (*RightHandSide, Finder, Builder));
58165974}
58175975
58185976// / Matches if either the left hand side or the right hand side of a
5819- // / binary operator matches.
5977+ // / binary operator or fold expression matches.
58205978AST_POLYMORPHIC_MATCHER_P (
58215979 hasEitherOperand,
58225980 AST_POLYMORPHIC_SUPPORTED_TYPES (BinaryOperator, CXXOperatorCallExpr,
5823- CXXRewrittenBinaryOperator),
5981+ CXXFoldExpr, CXXRewrittenBinaryOperator),
58245982 internal::Matcher<Expr>, InnerMatcher) {
58255983 return internal::VariadicDynCastAllOfMatcher<Stmt, NodeType>()(
58265984 anyOf (hasLHS (InnerMatcher), hasRHS (InnerMatcher)))
58275985 .matches (Node, Finder, Builder);
58285986}
58295987
5830- // / Matches if both matchers match with opposite sides of the binary operator.
5988+ // / Matches if both matchers match with opposite sides of the binary operator
5989+ // / or fold expression.
58315990// /
58325991// / Example matcher = binaryOperator(hasOperands(integerLiteral(equals(1),
58335992// / integerLiteral(equals(2)))
@@ -5840,7 +5999,7 @@ AST_POLYMORPHIC_MATCHER_P(
58405999AST_POLYMORPHIC_MATCHER_P2 (
58416000 hasOperands,
58426001 AST_POLYMORPHIC_SUPPORTED_TYPES (BinaryOperator, CXXOperatorCallExpr,
5843- CXXRewrittenBinaryOperator),
6002+ CXXFoldExpr, CXXRewrittenBinaryOperator),
58446003 internal::Matcher<Expr>, Matcher1, internal::Matcher<Expr>, Matcher2) {
58456004 return internal::VariadicDynCastAllOfMatcher<Stmt, NodeType>()(
58466005 anyOf (allOf (hasLHS (Matcher1), hasRHS (Matcher2)),
0 commit comments