[clang] 2ae8a4a - [ASTMatchers] Add argumentCountAtLeast narrowing matcher
Piotr Zegar via cfe-commits
cfe-commits at lists.llvm.org
Sun Jun 25 11:43:26 PDT 2023
Author: Mike Crowe
Date: 2023-06-25T18:41:55Z
New Revision: 2ae8a4a17888f739c1082f52eed56887c2004908
URL: https://github.com/llvm/llvm-project/commit/2ae8a4a17888f739c1082f52eed56887c2004908
DIFF: https://github.com/llvm/llvm-project/commit/2ae8a4a17888f739c1082f52eed56887c2004908.diff
LOG: [ASTMatchers] Add argumentCountAtLeast narrowing matcher
This will be used by the modernize-use-std-print clang-tidy check and
related checks later.
Reviewed By: PiotrZSL
Differential Revision: https://reviews.llvm.org/D153716
Added:
Modified:
clang/docs/LibASTMatchersReference.html
clang/include/clang/ASTMatchers/ASTMatchers.h
clang/lib/ASTMatchers/Dynamic/Registry.cpp
clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
Removed:
################################################################################
diff --git a/clang/docs/LibASTMatchersReference.html b/clang/docs/LibASTMatchersReference.html
index 571dfc3f21b81..e6b8c771f1a39 100644
--- a/clang/docs/LibASTMatchersReference.html
+++ b/clang/docs/LibASTMatchersReference.html
@@ -3036,6 +3036,18 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
</pre></td></tr>
+<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>></td><td class="name" onclick="toggle('argumentCountAtLeast1')"><a name="argumentCountAtLeast1Anchor">argumentCountAtLeast</a></td><td>unsigned N</td></tr>
+<tr><td colspan="4" class="doc" id="argumentCountAtLeast1"><pre>Checks that a call expression or a constructor call expression has
+at least the specified number of arguments (including absent default arguments).
+
+Example matches f(0, 0) and g(0, 0, 0) (matcher = callExpr(argumentCountAtLeast(2)))
+ void f(int x, int y);
+ void g(int x, int y, int z);
+ f(0, 0);
+ g(0, 0, 0);
+</pre></td></tr>
+
+
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>></td><td class="name" onclick="toggle('argumentCountIs1')"><a name="argumentCountIs1Anchor">argumentCountIs</a></td><td>unsigned N</td></tr>
<tr><td colspan="4" class="doc" id="argumentCountIs1"><pre>Checks that a call expression or a constructor call expression has
a specific number of arguments (including absent default arguments).
@@ -3693,6 +3705,18 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
</pre></td></tr>
+<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXUnresolvedConstructExpr.html">CXXUnresolvedConstructExpr</a>></td><td class="name" onclick="toggle('argumentCountAtLeast2')"><a name="argumentCountAtLeast2Anchor">argumentCountAtLeast</a></td><td>unsigned N</td></tr>
+<tr><td colspan="4" class="doc" id="argumentCountAtLeast2"><pre>Checks that a call expression or a constructor call expression has
+at least the specified number of arguments (including absent default arguments).
+
+Example matches f(0, 0) and g(0, 0, 0) (matcher = callExpr(argumentCountAtLeast(2)))
+ void f(int x, int y);
+ void g(int x, int y, int z);
+ f(0, 0);
+ g(0, 0, 0);
+</pre></td></tr>
+
+
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXUnresolvedConstructExpr.html">CXXUnresolvedConstructExpr</a>></td><td class="name" onclick="toggle('argumentCountIs2')"><a name="argumentCountIs2Anchor">argumentCountIs</a></td><td>unsigned N</td></tr>
<tr><td colspan="4" class="doc" id="argumentCountIs2"><pre>Checks that a call expression or a constructor call expression has
a specific number of arguments (including absent default arguments).
@@ -3703,6 +3727,18 @@ <h2 id="narrowing-matchers">Narrowing 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('argumentCountAtLeast0')"><a name="argumentCountAtLeast0Anchor">argumentCountAtLeast</a></td><td>unsigned N</td></tr>
+<tr><td colspan="4" class="doc" id="argumentCountAtLeast0"><pre>Checks that a call expression or a constructor call expression has
+at least the specified number of arguments (including absent default arguments).
+
+Example matches f(0, 0) and g(0, 0, 0) (matcher = callExpr(argumentCountAtLeast(2)))
+ void f(int x, int y);
+ void g(int x, int y, int z);
+ f(0, 0);
+ g(0, 0, 0);
+</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('argumentCountIs0')"><a name="argumentCountIs0Anchor">argumentCountIs</a></td><td>unsigned N</td></tr>
<tr><td colspan="4" class="doc" id="argumentCountIs0"><pre>Checks that a call expression or a constructor call expression has
a specific number of arguments (including absent default arguments).
@@ -4860,6 +4896,18 @@ <h2 id="narrowing-matchers">Narrowing 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('argumentCountAtLeast3')"><a name="argumentCountAtLeast3Anchor">argumentCountAtLeast</a></td><td>unsigned N</td></tr>
+<tr><td colspan="4" class="doc" id="argumentCountAtLeast3"><pre>Checks that a call expression or a constructor call expression has
+at least the specified number of arguments (including absent default arguments).
+
+Example matches f(0, 0) and g(0, 0, 0) (matcher = callExpr(argumentCountAtLeast(2)))
+ void f(int x, int y);
+ void g(int x, int y, int z);
+ f(0, 0);
+ g(0, 0, 0);
+</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('argumentCountIs3')"><a name="argumentCountIs3Anchor">argumentCountIs</a></td><td>unsigned N</td></tr>
<tr><td colspan="4" class="doc" id="argumentCountIs3"><pre>Checks that a call expression or a constructor call expression has
a specific number of arguments (including absent default arguments).
diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h
index 628533f94a8ae..b698365f949bf 100644
--- a/clang/include/clang/ASTMatchers/ASTMatchers.h
+++ b/clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -4431,6 +4431,33 @@ AST_POLYMORPHIC_MATCHER_P(argumentCountIs,
return NumArgs == N;
}
+/// Checks that a call expression or a constructor call expression has at least
+/// the specified number of arguments (including absent default arguments).
+///
+/// Example matches f(0, 0) and g(0, 0, 0)
+/// (matcher = callExpr(argumentCountAtLeast(2)))
+/// \code
+/// void f(int x, int y);
+/// void g(int x, int y, int z);
+/// f(0, 0);
+/// g(0, 0, 0);
+/// \endcode
+AST_POLYMORPHIC_MATCHER_P(argumentCountAtLeast,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(
+ CallExpr, CXXConstructExpr,
+ CXXUnresolvedConstructExpr, ObjCMessageExpr),
+ unsigned, N) {
+ unsigned NumArgs = Node.getNumArgs();
+ if (!Finder->isTraversalIgnoringImplicitNodes())
+ return NumArgs >= N;
+ while (NumArgs) {
+ if (!isa<CXXDefaultArgExpr>(Node.getArg(NumArgs - 1)))
+ break;
+ --NumArgs;
+ }
+ return NumArgs >= N;
+}
+
/// Matches the n'th argument of a call expression or a constructor
/// call expression.
///
diff --git a/clang/lib/ASTMatchers/Dynamic/Registry.cpp b/clang/lib/ASTMatchers/Dynamic/Registry.cpp
index 37e1780e68a60..995c082d53365 100644
--- a/clang/lib/ASTMatchers/Dynamic/Registry.cpp
+++ b/clang/lib/ASTMatchers/Dynamic/Registry.cpp
@@ -135,6 +135,7 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(anyOf);
REGISTER_MATCHER(anything);
REGISTER_MATCHER(argumentCountIs);
+ REGISTER_MATCHER(argumentCountAtLeast);
REGISTER_MATCHER(arraySubscriptExpr);
REGISTER_MATCHER(arrayType);
REGISTER_MATCHER(asString);
diff --git a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
index aed3c9f7d77f0..d78676fd289d5 100644
--- a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
+++ b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
@@ -1640,6 +1640,95 @@ TEST_P(ASTMatchersTest, IsExplicit_CXXConversionDecl_CXX20) {
cxxConversionDecl(isExplicit())));
}
+TEST_P(ASTMatchersTest, ArgumentCountAtLeast_CallExpr) {
+ StatementMatcher Call2PlusArgs = callExpr(argumentCountAtLeast(2));
+
+ EXPECT_TRUE(notMatches("void x(void) { x(); }", Call2PlusArgs));
+ EXPECT_TRUE(notMatches("void x(int) { x(0); }", Call2PlusArgs));
+ EXPECT_TRUE(matches("void x(int, int) { x(0, 0); }", Call2PlusArgs));
+ EXPECT_TRUE(matches("void x(int, int, int) { x(0, 0, 0); }", Call2PlusArgs));
+
+ if (!GetParam().isCXX()) {
+ return;
+ }
+
+ EXPECT_TRUE(
+ notMatches("void x(int = 1) { x(); }", traverse(TK_AsIs, Call2PlusArgs)));
+ EXPECT_TRUE(matches("void x(int, int = 1) { x(0); }",
+ traverse(TK_AsIs, Call2PlusArgs)));
+ EXPECT_TRUE(matches("void x(int, int = 1, int = 1) { x(0); }",
+ traverse(TK_AsIs, Call2PlusArgs)));
+ EXPECT_TRUE(matches("void x(int, int, int = 1) { x(0, 0); }",
+ traverse(TK_AsIs, Call2PlusArgs)));
+ EXPECT_TRUE(matches("void x(int, int, int, int = 1) { x(0, 0, 0); }",
+ traverse(TK_AsIs, Call2PlusArgs)));
+
+ EXPECT_TRUE(
+ notMatches("void x(int = 1) { x(); }",
+ traverse(TK_IgnoreUnlessSpelledInSource, Call2PlusArgs)));
+ EXPECT_TRUE(
+ notMatches("void x(int, int = 1) { x(0); }",
+ traverse(TK_IgnoreUnlessSpelledInSource, Call2PlusArgs)));
+ EXPECT_TRUE(
+ notMatches("void x(int, int = 1, int = 1) { x(0); }",
+ traverse(TK_IgnoreUnlessSpelledInSource, Call2PlusArgs)));
+ EXPECT_TRUE(matches("void x(int, int, int = 1) { x(0, 0); }",
+ traverse(TK_IgnoreUnlessSpelledInSource, Call2PlusArgs)));
+ EXPECT_TRUE(matches("void x(int, int, int, int = 1) { x(0, 0, 0); }",
+ traverse(TK_IgnoreUnlessSpelledInSource, Call2PlusArgs)));
+}
+
+TEST_P(ASTMatchersTest, ArgumentCountAtLeast_CallExpr_CXX) {
+ if (!GetParam().isCXX()) {
+ return;
+ }
+
+ StatementMatcher Call2PlusArgs = callExpr(argumentCountAtLeast(2));
+ EXPECT_TRUE(notMatches("class X { void x() { x(); } };", Call2PlusArgs));
+ EXPECT_TRUE(notMatches("class X { void x(int) { x(0); } };", Call2PlusArgs));
+ EXPECT_TRUE(
+ matches("class X { void x(int, int) { x(0, 0); } };", Call2PlusArgs));
+ EXPECT_TRUE(matches("class X { void x(int, int, int) { x(0, 0, 0); } };",
+ Call2PlusArgs));
+
+ EXPECT_TRUE(notMatches("class X { void x(int = 1) { x(0); } };",
+ traverse(TK_AsIs, Call2PlusArgs)));
+ EXPECT_TRUE(matches("class X { void x(int, int = 1) { x(0); } };",
+ traverse(TK_AsIs, Call2PlusArgs)));
+ EXPECT_TRUE(matches("class X { void x(int, int = 1, int = 1) { x(0); } };",
+ traverse(TK_AsIs, Call2PlusArgs)));
+ EXPECT_TRUE(matches("class X { void x(int, int, int = 1) { x(0, 0); } };",
+ traverse(TK_AsIs, Call2PlusArgs)));
+ EXPECT_TRUE(
+ matches("class X { void x(int, int, int, int = 1) { x(0, 0, 0); } };",
+ traverse(TK_AsIs, Call2PlusArgs)));
+
+ EXPECT_TRUE(
+ notMatches("class X { void x(int = 1) { x(0); } };",
+ traverse(TK_IgnoreUnlessSpelledInSource, Call2PlusArgs)));
+ EXPECT_TRUE(
+ notMatches("class X { void x(int, int = 1) { x(0); } };",
+ traverse(TK_IgnoreUnlessSpelledInSource, Call2PlusArgs)));
+ EXPECT_TRUE(
+ notMatches("class X { void x(int, int = 1, int = 1) { x(0); } };",
+ traverse(TK_IgnoreUnlessSpelledInSource, Call2PlusArgs)));
+ EXPECT_TRUE(matches("class X { void x(int, int, int = 1) { x(0, 0); } };",
+ traverse(TK_IgnoreUnlessSpelledInSource, Call2PlusArgs)));
+ EXPECT_TRUE(
+ matches("class X { void x(int, int, int, int = 1) { x(0, 0, 0); } };",
+ traverse(TK_IgnoreUnlessSpelledInSource, Call2PlusArgs)));
+
+ EXPECT_TRUE(
+ notMatches("class X { static void x() { x(); } };", Call2PlusArgs));
+ EXPECT_TRUE(
+ notMatches("class X { static void x(int) { x(0); } };", Call2PlusArgs));
+ EXPECT_TRUE(matches("class X { static void x(int, int) { x(0, 0); } };",
+ Call2PlusArgs));
+ EXPECT_TRUE(
+ matches("class X { static void x(int, int, int) { x(0, 0, 0); } };",
+ Call2PlusArgs));
+}
+
TEST_P(ASTMatchersTest, ArgumentCountIs_CallExpr) {
StatementMatcher Call1Arg = callExpr(argumentCountIs(1));
More information about the cfe-commits
mailing list