diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h --- a/clang/include/clang/ASTMatchers/ASTMatchers.h +++ b/clang/include/clang/ASTMatchers/ASTMatchers.h @@ -731,6 +731,27 @@ InnerMatcher.matches(*Initializer, Finder, Builder)); } +/// Determines whether a declaration is a parameter pack. +/// +/// Given +/// \code +/// template class C, +/// template class... Ds> +/// void foo(A param, Bs... params); +/// \endcode +/// templateTypeParmDecl(isParameterPack()) +/// matches 'typename... Bs', but not 'typename A'. +/// nonTypeTemplateParmDecl(isParameterPack()) +/// matches 'int... js', but not 'int i'. +/// templateTemplateParmDecl(isParameterPack()) +/// matches 'template class... Ds', but not +/// 'template class C' +/// varDecl(isParameterPack()) +/// matches 'Bs... params', but not 'A param'. +AST_MATCHER(Decl, isParameterPack) { return Node.isParameterPack(); } + /// Determines whether the function is "main", which is the entry point /// into an executable program. AST_MATCHER(FunctionDecl, isMain) { @@ -2699,6 +2720,21 @@ return Node.size() == N; } +/// Matches pack expansion expressions. +/// +/// Given +/// \code +/// void bar(int, int); +/// template +/// void foo(T arg, Args args...) { +/// bar(arg + 1, (args + 1)...); +/// } +/// \endcode +/// packExpansionExpr() +/// matches '(args + 1)...', but not 'arg + 1'. +extern const internal::VariadicDynCastAllOfMatcher + packExpansionExpr; + /// Matches \c QualTypes in the clang AST. extern const internal::VariadicAllOfMatcher qualType; diff --git a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp --- a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp +++ b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp @@ -981,6 +981,8 @@ predefinedExpr; const internal::VariadicDynCastAllOfMatcher designatedInitExpr; +const internal::VariadicDynCastAllOfMatcher + packExpansionExpr; const internal::VariadicOperatorMatcherFunc< 2, std::numeric_limits::max()> eachOf = {internal::DynTypedMatcher::VO_EachOf}; diff --git a/clang/lib/ASTMatchers/Dynamic/Registry.cpp b/clang/lib/ASTMatchers/Dynamic/Registry.cpp --- a/clang/lib/ASTMatchers/Dynamic/Registry.cpp +++ b/clang/lib/ASTMatchers/Dynamic/Registry.cpp @@ -446,6 +446,7 @@ REGISTER_MATCHER(isNoThrow); REGISTER_MATCHER(isNoneKind); REGISTER_MATCHER(isOverride); + REGISTER_MATCHER(isParameterPack); REGISTER_MATCHER(isPrivate); REGISTER_MATCHER(isProtected); REGISTER_MATCHER(isPublic); @@ -513,6 +514,7 @@ REGISTER_MATCHER(onImplicitObjectArgument); REGISTER_MATCHER(opaqueValueExpr); REGISTER_MATCHER(optionally); + REGISTER_MATCHER(packExpansionExpr); REGISTER_MATCHER(parameterCountIs); REGISTER_MATCHER(parenExpr); REGISTER_MATCHER(parenListExpr);