[PATCH] D72505: [ASTMatchers] extract public matchers from const-analysis into own patch
This revision was automatically updated to reflect the committed changes. Closed by commit rG4c48ea68e491: [ASTMatchers] extract public matchers from const-analysis into own patch (authored by JonasToth). Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D72505/new/ https://reviews.llvm.org/D72505 Files: clang/docs/LibASTMatchersReference.html clang/include/clang/ASTMatchers/ASTMatchers.h clang/lib/ASTMatchers/Dynamic/Registry.cpp clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp Index: clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp === --- clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp +++ clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp @@ -735,6 +735,172 @@ std::make_unique>("v", 4))); } +TEST(ForEachArgumentWithParamType, ReportsNoFalsePositives) { + StatementMatcher ArgumentY = +declRefExpr(to(varDecl(hasName("y".bind("arg"); + TypeMatcher IntType = qualType(isInteger()).bind("type"); + StatementMatcher CallExpr = +callExpr(forEachArgumentWithParamType(ArgumentY, IntType)); + + // IntParam does not match. + EXPECT_TRUE(notMatches("void f(int* i) { int* y; f(y); }", CallExpr)); + // ArgumentY does not match. + EXPECT_TRUE(notMatches("void f(int i) { int x; f(x); }", CallExpr)); +} + +TEST(ForEachArgumentWithParamType, MatchesCXXMemberCallExpr) { + StatementMatcher ArgumentY = +declRefExpr(to(varDecl(hasName("y".bind("arg"); + TypeMatcher IntType = qualType(isInteger()).bind("type"); + StatementMatcher CallExpr = +callExpr(forEachArgumentWithParamType(ArgumentY, IntType)); + EXPECT_TRUE(matchAndVerifyResultTrue( +"struct S {" + " const S& operator[](int i) { return *this; }" + "};" + "void f(S S1) {" + " int y = 1;" + " S1[y];" + "}", +CallExpr, std::make_unique>("type", 1))); + + StatementMatcher CallExpr2 = +callExpr(forEachArgumentWithParamType(ArgumentY, IntType)); + EXPECT_TRUE(matchAndVerifyResultTrue( +"struct S {" + " static void g(int i);" + "};" + "void f() {" + " int y = 1;" + " S::g(y);" + "}", +CallExpr2, std::make_unique>("type", 1))); +} + +TEST(ForEachArgumentWithParamType, MatchesCallExpr) { + StatementMatcher ArgumentY = +declRefExpr(to(varDecl(hasName("y".bind("arg"); + TypeMatcher IntType = qualType(isInteger()).bind("type"); + StatementMatcher CallExpr = +callExpr(forEachArgumentWithParamType(ArgumentY, IntType)); + + EXPECT_TRUE( +matchAndVerifyResultTrue("void f(int i) { int y; f(y); }", CallExpr, + std::make_unique>( + "type"))); + EXPECT_TRUE( +matchAndVerifyResultTrue("void f(int i) { int y; f(y); }", CallExpr, + std::make_unique>( + "arg"))); + + EXPECT_TRUE(matchAndVerifyResultTrue( +"void f(int i, int j) { int y; f(y, y); }", CallExpr, +std::make_unique>("type", 2))); + EXPECT_TRUE(matchAndVerifyResultTrue( +"void f(int i, int j) { int y; f(y, y); }", CallExpr, +std::make_unique>("arg", 2))); +} + +TEST(ForEachArgumentWithParamType, MatchesConstructExpr) { + StatementMatcher ArgumentY = +declRefExpr(to(varDecl(hasName("y".bind("arg"); + TypeMatcher IntType = qualType(isInteger()).bind("type"); + StatementMatcher ConstructExpr = +cxxConstructExpr(forEachArgumentWithParamType(ArgumentY, IntType)); + + EXPECT_TRUE(matchAndVerifyResultTrue( +"struct C {" + " C(int i) {}" + "};" + "int y = 0;" + "C Obj(y);", +ConstructExpr, +std::make_unique>("type"))); + EXPECT_TRUE(matchAndVerifyResultTrue( +"struct C {" + " C(int i) {}" + "};" + "int y = 0;" + "C Obj(y);", +ConstructExpr, +std::make_unique>("arg"))); +} + +TEST(ForEachArgumentWithParamType, HandlesKandRFunctions) { + StatementMatcher ArgumentY = + declRefExpr(to(varDecl(hasName("y".bind("arg"); + TypeMatcher IntType = qualType(isInteger()).bind("type"); + StatementMatcher CallExpr = + callExpr(forEachArgumentWithParamType(ArgumentY, IntType)); + + EXPECT_TRUE(matchesC("void f();\n" + "void call_it(void) { int x, y; f(x, y); }\n" + "void f(a, b) int a, b; {}\n" + "void call_it2(void) { int x, y; f(x, y); }", + CallExpr)); +} + +TEST(ForEachArgumentWithParamType, HandlesBoundNodesForNonMatches) { + EXPECT_TRUE(matchAndVerifyResultTrue( +"void g(int i, int j) {" + " int a;" + " int b;" + " int c;" + " g(a, 0);" + " g(a, b);" + " g(0, b);" + "}", +functionDecl( + forEachDescendant(varDecl().bind("v")), + forEachDescendant(callExpr(forEachArgumentWithParamType( +declRefExpr(to(decl(equalsBoundNode("v", qualType(), +std::make_unique>
[PATCH] D72505: [ASTMatchers] extract public matchers from const-analysis into own patch
JonasToth updated this revision to Diff 237514. JonasToth added a comment. - remove merge conflict markers in docs Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D72505/new/ https://reviews.llvm.org/D72505 Files: clang/docs/LibASTMatchersReference.html clang/include/clang/ASTMatchers/ASTMatchers.h clang/lib/ASTMatchers/Dynamic/Registry.cpp clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp Index: clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp === --- clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp +++ clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp @@ -735,6 +735,172 @@ std::make_unique>("v", 4))); } +TEST(ForEachArgumentWithParamType, ReportsNoFalsePositives) { + StatementMatcher ArgumentY = +declRefExpr(to(varDecl(hasName("y".bind("arg"); + TypeMatcher IntType = qualType(isInteger()).bind("type"); + StatementMatcher CallExpr = +callExpr(forEachArgumentWithParamType(ArgumentY, IntType)); + + // IntParam does not match. + EXPECT_TRUE(notMatches("void f(int* i) { int* y; f(y); }", CallExpr)); + // ArgumentY does not match. + EXPECT_TRUE(notMatches("void f(int i) { int x; f(x); }", CallExpr)); +} + +TEST(ForEachArgumentWithParamType, MatchesCXXMemberCallExpr) { + StatementMatcher ArgumentY = +declRefExpr(to(varDecl(hasName("y".bind("arg"); + TypeMatcher IntType = qualType(isInteger()).bind("type"); + StatementMatcher CallExpr = +callExpr(forEachArgumentWithParamType(ArgumentY, IntType)); + EXPECT_TRUE(matchAndVerifyResultTrue( +"struct S {" + " const S& operator[](int i) { return *this; }" + "};" + "void f(S S1) {" + " int y = 1;" + " S1[y];" + "}", +CallExpr, std::make_unique>("type", 1))); + + StatementMatcher CallExpr2 = +callExpr(forEachArgumentWithParamType(ArgumentY, IntType)); + EXPECT_TRUE(matchAndVerifyResultTrue( +"struct S {" + " static void g(int i);" + "};" + "void f() {" + " int y = 1;" + " S::g(y);" + "}", +CallExpr2, std::make_unique>("type", 1))); +} + +TEST(ForEachArgumentWithParamType, MatchesCallExpr) { + StatementMatcher ArgumentY = +declRefExpr(to(varDecl(hasName("y".bind("arg"); + TypeMatcher IntType = qualType(isInteger()).bind("type"); + StatementMatcher CallExpr = +callExpr(forEachArgumentWithParamType(ArgumentY, IntType)); + + EXPECT_TRUE( +matchAndVerifyResultTrue("void f(int i) { int y; f(y); }", CallExpr, + std::make_unique>( + "type"))); + EXPECT_TRUE( +matchAndVerifyResultTrue("void f(int i) { int y; f(y); }", CallExpr, + std::make_unique>( + "arg"))); + + EXPECT_TRUE(matchAndVerifyResultTrue( +"void f(int i, int j) { int y; f(y, y); }", CallExpr, +std::make_unique>("type", 2))); + EXPECT_TRUE(matchAndVerifyResultTrue( +"void f(int i, int j) { int y; f(y, y); }", CallExpr, +std::make_unique>("arg", 2))); +} + +TEST(ForEachArgumentWithParamType, MatchesConstructExpr) { + StatementMatcher ArgumentY = +declRefExpr(to(varDecl(hasName("y".bind("arg"); + TypeMatcher IntType = qualType(isInteger()).bind("type"); + StatementMatcher ConstructExpr = +cxxConstructExpr(forEachArgumentWithParamType(ArgumentY, IntType)); + + EXPECT_TRUE(matchAndVerifyResultTrue( +"struct C {" + " C(int i) {}" + "};" + "int y = 0;" + "C Obj(y);", +ConstructExpr, +std::make_unique>("type"))); + EXPECT_TRUE(matchAndVerifyResultTrue( +"struct C {" + " C(int i) {}" + "};" + "int y = 0;" + "C Obj(y);", +ConstructExpr, +std::make_unique>("arg"))); +} + +TEST(ForEachArgumentWithParamType, HandlesKandRFunctions) { + StatementMatcher ArgumentY = + declRefExpr(to(varDecl(hasName("y".bind("arg"); + TypeMatcher IntType = qualType(isInteger()).bind("type"); + StatementMatcher CallExpr = + callExpr(forEachArgumentWithParamType(ArgumentY, IntType)); + + EXPECT_TRUE(matchesC("void f();\n" + "void call_it(void) { int x, y; f(x, y); }\n" + "void f(a, b) int a, b; {}\n" + "void call_it2(void) { int x, y; f(x, y); }", + CallExpr)); +} + +TEST(ForEachArgumentWithParamType, HandlesBoundNodesForNonMatches) { + EXPECT_TRUE(matchAndVerifyResultTrue( +"void g(int i, int j) {" + " int a;" + " int b;" + " int c;" + " g(a, 0);" + " g(a, b);" + " g(0, b);" + "}", +functionDecl( + forEachDescendant(varDecl().bind("v")), + forEachDescendant(callExpr(forEachArgumentWithParamType( +declRefExpr(to(decl(equalsBoundNode("v", qualType(), +std::make_unique>("v", 4))); +} + +TEST(ForEachArgumentWithParamType, MatchesFunctionPtrCalls) { + Statem
[PATCH] D72505: [ASTMatchers] extract public matchers from const-analysis into own patch
JonasToth updated this revision to Diff 237511. JonasToth added a comment. - fix compilation error, missing getType Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D72505/new/ https://reviews.llvm.org/D72505 Files: clang/docs/LibASTMatchersReference.html clang/include/clang/ASTMatchers/ASTMatchers.h clang/lib/ASTMatchers/Dynamic/Registry.cpp clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp Index: clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp === --- clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp +++ clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp @@ -735,6 +735,172 @@ std::make_unique>("v", 4))); } +TEST(ForEachArgumentWithParamType, ReportsNoFalsePositives) { + StatementMatcher ArgumentY = +declRefExpr(to(varDecl(hasName("y".bind("arg"); + TypeMatcher IntType = qualType(isInteger()).bind("type"); + StatementMatcher CallExpr = +callExpr(forEachArgumentWithParamType(ArgumentY, IntType)); + + // IntParam does not match. + EXPECT_TRUE(notMatches("void f(int* i) { int* y; f(y); }", CallExpr)); + // ArgumentY does not match. + EXPECT_TRUE(notMatches("void f(int i) { int x; f(x); }", CallExpr)); +} + +TEST(ForEachArgumentWithParamType, MatchesCXXMemberCallExpr) { + StatementMatcher ArgumentY = +declRefExpr(to(varDecl(hasName("y".bind("arg"); + TypeMatcher IntType = qualType(isInteger()).bind("type"); + StatementMatcher CallExpr = +callExpr(forEachArgumentWithParamType(ArgumentY, IntType)); + EXPECT_TRUE(matchAndVerifyResultTrue( +"struct S {" + " const S& operator[](int i) { return *this; }" + "};" + "void f(S S1) {" + " int y = 1;" + " S1[y];" + "}", +CallExpr, std::make_unique>("type", 1))); + + StatementMatcher CallExpr2 = +callExpr(forEachArgumentWithParamType(ArgumentY, IntType)); + EXPECT_TRUE(matchAndVerifyResultTrue( +"struct S {" + " static void g(int i);" + "};" + "void f() {" + " int y = 1;" + " S::g(y);" + "}", +CallExpr2, std::make_unique>("type", 1))); +} + +TEST(ForEachArgumentWithParamType, MatchesCallExpr) { + StatementMatcher ArgumentY = +declRefExpr(to(varDecl(hasName("y".bind("arg"); + TypeMatcher IntType = qualType(isInteger()).bind("type"); + StatementMatcher CallExpr = +callExpr(forEachArgumentWithParamType(ArgumentY, IntType)); + + EXPECT_TRUE( +matchAndVerifyResultTrue("void f(int i) { int y; f(y); }", CallExpr, + std::make_unique>( + "type"))); + EXPECT_TRUE( +matchAndVerifyResultTrue("void f(int i) { int y; f(y); }", CallExpr, + std::make_unique>( + "arg"))); + + EXPECT_TRUE(matchAndVerifyResultTrue( +"void f(int i, int j) { int y; f(y, y); }", CallExpr, +std::make_unique>("type", 2))); + EXPECT_TRUE(matchAndVerifyResultTrue( +"void f(int i, int j) { int y; f(y, y); }", CallExpr, +std::make_unique>("arg", 2))); +} + +TEST(ForEachArgumentWithParamType, MatchesConstructExpr) { + StatementMatcher ArgumentY = +declRefExpr(to(varDecl(hasName("y".bind("arg"); + TypeMatcher IntType = qualType(isInteger()).bind("type"); + StatementMatcher ConstructExpr = +cxxConstructExpr(forEachArgumentWithParamType(ArgumentY, IntType)); + + EXPECT_TRUE(matchAndVerifyResultTrue( +"struct C {" + " C(int i) {}" + "};" + "int y = 0;" + "C Obj(y);", +ConstructExpr, +std::make_unique>("type"))); + EXPECT_TRUE(matchAndVerifyResultTrue( +"struct C {" + " C(int i) {}" + "};" + "int y = 0;" + "C Obj(y);", +ConstructExpr, +std::make_unique>("arg"))); +} + +TEST(ForEachArgumentWithParamType, HandlesKandRFunctions) { + StatementMatcher ArgumentY = + declRefExpr(to(varDecl(hasName("y".bind("arg"); + TypeMatcher IntType = qualType(isInteger()).bind("type"); + StatementMatcher CallExpr = + callExpr(forEachArgumentWithParamType(ArgumentY, IntType)); + + EXPECT_TRUE(matchesC("void f();\n" + "void call_it(void) { int x, y; f(x, y); }\n" + "void f(a, b) int a, b; {}\n" + "void call_it2(void) { int x, y; f(x, y); }", + CallExpr)); +} + +TEST(ForEachArgumentWithParamType, HandlesBoundNodesForNonMatches) { + EXPECT_TRUE(matchAndVerifyResultTrue( +"void g(int i, int j) {" + " int a;" + " int b;" + " int c;" + " g(a, 0);" + " g(a, b);" + " g(0, b);" + "}", +functionDecl( + forEachDescendant(varDecl().bind("v")), + forEachDescendant(callExpr(forEachArgumentWithParamType( +declRefExpr(to(decl(equalsBoundNode("v", qualType(), +std::make_unique>("v", 4))); +} + +TEST(ForEachArgumentWithParamType, MatchesFunctionPtrCalls) { + State
[PATCH] D72505: [ASTMatchers] extract public matchers from const-analysis into own patch
JonasToth updated this revision to Diff 237510. JonasToth marked 3 inline comments as done. JonasToth added a comment. - add test for K&R functions Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D72505/new/ https://reviews.llvm.org/D72505 Files: clang/docs/LibASTMatchersReference.html clang/include/clang/ASTMatchers/ASTMatchers.h clang/lib/ASTMatchers/Dynamic/Registry.cpp clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp Index: clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp === --- clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp +++ clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp @@ -735,6 +735,172 @@ std::make_unique>("v", 4))); } +TEST(ForEachArgumentWithParamType, ReportsNoFalsePositives) { + StatementMatcher ArgumentY = +declRefExpr(to(varDecl(hasName("y".bind("arg"); + TypeMatcher IntType = qualType(isInteger()).bind("type"); + StatementMatcher CallExpr = +callExpr(forEachArgumentWithParamType(ArgumentY, IntType)); + + // IntParam does not match. + EXPECT_TRUE(notMatches("void f(int* i) { int* y; f(y); }", CallExpr)); + // ArgumentY does not match. + EXPECT_TRUE(notMatches("void f(int i) { int x; f(x); }", CallExpr)); +} + +TEST(ForEachArgumentWithParamType, MatchesCXXMemberCallExpr) { + StatementMatcher ArgumentY = +declRefExpr(to(varDecl(hasName("y".bind("arg"); + TypeMatcher IntType = qualType(isInteger()).bind("type"); + StatementMatcher CallExpr = +callExpr(forEachArgumentWithParamType(ArgumentY, IntType)); + EXPECT_TRUE(matchAndVerifyResultTrue( +"struct S {" + " const S& operator[](int i) { return *this; }" + "};" + "void f(S S1) {" + " int y = 1;" + " S1[y];" + "}", +CallExpr, std::make_unique>("type", 1))); + + StatementMatcher CallExpr2 = +callExpr(forEachArgumentWithParamType(ArgumentY, IntType)); + EXPECT_TRUE(matchAndVerifyResultTrue( +"struct S {" + " static void g(int i);" + "};" + "void f() {" + " int y = 1;" + " S::g(y);" + "}", +CallExpr2, std::make_unique>("type", 1))); +} + +TEST(ForEachArgumentWithParamType, MatchesCallExpr) { + StatementMatcher ArgumentY = +declRefExpr(to(varDecl(hasName("y".bind("arg"); + TypeMatcher IntType = qualType(isInteger()).bind("type"); + StatementMatcher CallExpr = +callExpr(forEachArgumentWithParamType(ArgumentY, IntType)); + + EXPECT_TRUE( +matchAndVerifyResultTrue("void f(int i) { int y; f(y); }", CallExpr, + std::make_unique>( + "type"))); + EXPECT_TRUE( +matchAndVerifyResultTrue("void f(int i) { int y; f(y); }", CallExpr, + std::make_unique>( + "arg"))); + + EXPECT_TRUE(matchAndVerifyResultTrue( +"void f(int i, int j) { int y; f(y, y); }", CallExpr, +std::make_unique>("type", 2))); + EXPECT_TRUE(matchAndVerifyResultTrue( +"void f(int i, int j) { int y; f(y, y); }", CallExpr, +std::make_unique>("arg", 2))); +} + +TEST(ForEachArgumentWithParamType, MatchesConstructExpr) { + StatementMatcher ArgumentY = +declRefExpr(to(varDecl(hasName("y".bind("arg"); + TypeMatcher IntType = qualType(isInteger()).bind("type"); + StatementMatcher ConstructExpr = +cxxConstructExpr(forEachArgumentWithParamType(ArgumentY, IntType)); + + EXPECT_TRUE(matchAndVerifyResultTrue( +"struct C {" + " C(int i) {}" + "};" + "int y = 0;" + "C Obj(y);", +ConstructExpr, +std::make_unique>("type"))); + EXPECT_TRUE(matchAndVerifyResultTrue( +"struct C {" + " C(int i) {}" + "};" + "int y = 0;" + "C Obj(y);", +ConstructExpr, +std::make_unique>("arg"))); +} + +TEST(ForEachArgumentWithParamType, HandlesKandRFunctions) { + StatementMatcher ArgumentY = + declRefExpr(to(varDecl(hasName("y".bind("arg"); + TypeMatcher IntType = qualType(isInteger()).bind("type"); + StatementMatcher CallExpr = + callExpr(forEachArgumentWithParamType(ArgumentY, IntType)); + + EXPECT_TRUE(matchesC("void f();\n" + "void call_it(void) { int x, y; f(x, y); }\n" + "void f(a, b) int a, b; {}\n" + "void call_it2(void) { int x, y; f(x, y); }", + CallExpr)); +} + +TEST(ForEachArgumentWithParamType, HandlesBoundNodesForNonMatches) { + EXPECT_TRUE(matchAndVerifyResultTrue( +"void g(int i, int j) {" + " int a;" + " int b;" + " int c;" + " g(a, 0);" + " g(a, b);" + " g(0, b);" + "}", +functionDecl( + forEachDescendant(varDecl().bind("v")), + forEachDescendant(callExpr(forEachArgumentWithParamType( +declRefExpr(to(decl(equalsBoundNode("v", qualType(), +std::make_unique>("v", 4))); +} + +TEST(ForEachArgumentWithParamType, Mat
[PATCH] D72505: [ASTMatchers] extract public matchers from const-analysis into own patch
aaron.ballman accepted this revision. aaron.ballman added a comment. This revision is now accepted and ready to land. LGTM aside from a testing request. Comment at: clang/include/clang/ASTMatchers/ASTMatchers.h:4243 + if (FProto) { +QualType ParamType = FProto->getParamType(ParamIndex); +if (ParamMatcher.matches(ParamType, Finder, &ParamMatches)) { JonasToth wrote: > aaron.ballman wrote: > > Should we be canonicalizing this type as well? > I think here we shouldn't. In that case you could not match if e.g. the > parameter has a typedef. I think that would reduce possibilities for the > matcher usage. Okay, that's a good point! Comment at: clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp:868 +std::make_unique>("arg"))); +} + I would like to see one K&R C test case just to be sure we're not doing anything horrible: ``` void f(); void call_it_1(void) { f(1.0f, 2.0f); } // Especially curious about type promotions void f(a, b) float a, b; { } void call_it_2(void) { f(1.0f, 2.0f); } // And if they differ here (IIRC, we may have a bug here in the compiler) ``` Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D72505/new/ https://reviews.llvm.org/D72505 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D72505: [ASTMatchers] extract public matchers from const-analysis into own patch
JonasToth marked 3 inline comments as done. JonasToth added inline comments. Comment at: clang/include/clang/ASTMatchers/ASTMatchers.h:4243 + if (FProto) { +QualType ParamType = FProto->getParamType(ParamIndex); +if (ParamMatcher.matches(ParamType, Finder, &ParamMatches)) { aaron.ballman wrote: > Should we be canonicalizing this type as well? I think here we shouldn't. In that case you could not match if e.g. the parameter has a typedef. I think that would reduce possibilities for the matcher usage. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D72505/new/ https://reviews.llvm.org/D72505 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D72505: [ASTMatchers] extract public matchers from const-analysis into own patch
JonasToth updated this revision to Diff 237338. JonasToth added a comment. - address review comments Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D72505/new/ https://reviews.llvm.org/D72505 Files: clang/docs/LibASTMatchersReference.html clang/include/clang/ASTMatchers/ASTMatchers.h clang/lib/ASTMatchers/Dynamic/Registry.cpp clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp Index: clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp === --- clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp +++ clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp @@ -715,6 +715,158 @@ std::make_unique>("v", 4))); } +TEST(ForEachArgumentWithParamType, ReportsNoFalsePositives) { + StatementMatcher ArgumentY = +declRefExpr(to(varDecl(hasName("y".bind("arg"); + TypeMatcher IntType = qualType(isInteger()).bind("type"); + StatementMatcher CallExpr = +callExpr(forEachArgumentWithParamType(ArgumentY, IntType)); + + // IntParam does not match. + EXPECT_TRUE(notMatches("void f(int* i) { int* y; f(y); }", CallExpr)); + // ArgumentY does not match. + EXPECT_TRUE(notMatches("void f(int i) { int x; f(x); }", CallExpr)); +} + +TEST(ForEachArgumentWithParamType, MatchesCXXMemberCallExpr) { + StatementMatcher ArgumentY = +declRefExpr(to(varDecl(hasName("y".bind("arg"); + TypeMatcher IntType = qualType(isInteger()).bind("type"); + StatementMatcher CallExpr = +callExpr(forEachArgumentWithParamType(ArgumentY, IntType)); + EXPECT_TRUE(matchAndVerifyResultTrue( +"struct S {" + " const S& operator[](int i) { return *this; }" + "};" + "void f(S S1) {" + " int y = 1;" + " S1[y];" + "}", +CallExpr, std::make_unique>("type", 1))); + + StatementMatcher CallExpr2 = +callExpr(forEachArgumentWithParamType(ArgumentY, IntType)); + EXPECT_TRUE(matchAndVerifyResultTrue( +"struct S {" + " static void g(int i);" + "};" + "void f() {" + " int y = 1;" + " S::g(y);" + "}", +CallExpr2, std::make_unique>("type", 1))); +} + +TEST(ForEachArgumentWithParamType, MatchesCallExpr) { + StatementMatcher ArgumentY = +declRefExpr(to(varDecl(hasName("y".bind("arg"); + TypeMatcher IntType = qualType(isInteger()).bind("type"); + StatementMatcher CallExpr = +callExpr(forEachArgumentWithParamType(ArgumentY, IntType)); + + EXPECT_TRUE( +matchAndVerifyResultTrue("void f(int i) { int y; f(y); }", CallExpr, + std::make_unique>( + "type"))); + EXPECT_TRUE( +matchAndVerifyResultTrue("void f(int i) { int y; f(y); }", CallExpr, + std::make_unique>( + "arg"))); + + EXPECT_TRUE(matchAndVerifyResultTrue( +"void f(int i, int j) { int y; f(y, y); }", CallExpr, +std::make_unique>("type", 2))); + EXPECT_TRUE(matchAndVerifyResultTrue( +"void f(int i, int j) { int y; f(y, y); }", CallExpr, +std::make_unique>("arg", 2))); +} + +TEST(ForEachArgumentWithParamType, MatchesConstructExpr) { + StatementMatcher ArgumentY = +declRefExpr(to(varDecl(hasName("y".bind("arg"); + TypeMatcher IntType = qualType(isInteger()).bind("type"); + StatementMatcher ConstructExpr = +cxxConstructExpr(forEachArgumentWithParamType(ArgumentY, IntType)); + + EXPECT_TRUE(matchAndVerifyResultTrue( +"struct C {" + " C(int i) {}" + "};" + "int y = 0;" + "C Obj(y);", +ConstructExpr, +std::make_unique>("type"))); + EXPECT_TRUE(matchAndVerifyResultTrue( +"struct C {" + " C(int i) {}" + "};" + "int y = 0;" + "C Obj(y);", +ConstructExpr, +std::make_unique>("arg"))); +} + +TEST(ForEachArgumentWithParamType, HandlesBoundNodesForNonMatches) { + EXPECT_TRUE(matchAndVerifyResultTrue( +"void g(int i, int j) {" + " int a;" + " int b;" + " int c;" + " g(a, 0);" + " g(a, b);" + " g(0, b);" + "}", +functionDecl( + forEachDescendant(varDecl().bind("v")), + forEachDescendant(callExpr(forEachArgumentWithParamType( +declRefExpr(to(decl(equalsBoundNode("v", qualType(), +std::make_unique>("v", 4))); +} + +TEST(ForEachArgumentWithParamType, MatchesFunctionPtrCalls) { + StatementMatcher ArgumentY = +declRefExpr(to(varDecl(hasName("y".bind("arg"); + TypeMatcher IntType = qualType(builtinType()).bind("type"); + StatementMatcher CallExpr = +callExpr(forEachArgumentWithParamType(ArgumentY, IntType)); + + EXPECT_TRUE( +matchAndVerifyResultTrue("void f(int i) {" + "void (*f_ptr)(int) = f; int y; f_ptr(y); }", + CallExpr, + std::make_unique>("type"))); + EXPECT_TRUE( +matchAndVerifyResultTrue("void f(int i) {" + "void (*f_ptr)(int) = f; i
[PATCH] D72505: [ASTMatchers] extract public matchers from const-analysis into own patch
aaron.ballman added inline comments. Comment at: clang/include/clang/ASTMatchers/ASTMatchers.h:4207-4208 + if (const auto *Call = dyn_cast(&Node)) { +if (const Decl *Callee = Call->getCalleeDecl()) { + if (const auto *Value = dyn_cast(Callee)) { +QualType QT = Value->getType(); `if (const auto *Value = dyn_cast_or_null(Call->getCalleeDecl())) { ... }` Comment at: clang/include/clang/ASTMatchers/ASTMatchers.h:4209 + if (const auto *Value = dyn_cast(Callee)) { +QualType QT = Value->getType(); + Should you be getting the canonical type here? That would skip over things like paren types and typedefs. Comment at: clang/include/clang/ASTMatchers/ASTMatchers.h:4214-4215 + FProto = FPT->getAs(); + assert(FProto && + "The call must have happened through a function pointer"); +} This seems like an invalid assertion -- K&R C functions would have a function pointer type but not a prototype, for instance. Comment at: clang/include/clang/ASTMatchers/ASTMatchers.h:4243 + if (FProto) { +QualType ParamType = FProto->getParamType(ParamIndex); +if (ParamMatcher.matches(ParamType, Finder, &ParamMatches)) { Should we be canonicalizing this type as well? Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D72505/new/ https://reviews.llvm.org/D72505 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D72505: [ASTMatchers] extract public matchers from const-analysis into own patch
JonasToth created this revision. JonasToth added a reviewer: aaron.ballman. Herald added a project: clang. Herald added a subscriber: cfe-commits. JonasToth added a child revision: D54943: [clang-tidy] implement const-transformation for cppcoreguidelines-const-correctness. The analysis for const-ness of local variables required a view generally useful matchers that are extracted into its own patch. They are `decompositionDecl` and `forEachArgumentWithParamType`, that works for calls through function pointers as well. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D72505 Files: clang/docs/LibASTMatchersReference.html clang/include/clang/ASTMatchers/ASTMatchers.h clang/lib/ASTMatchers/Dynamic/Registry.cpp clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp Index: clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp === --- clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp +++ clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp @@ -715,6 +715,158 @@ std::make_unique>("v", 4))); } +TEST(ForEachArgumentWithParamType, ReportsNoFalsePositives) { + StatementMatcher ArgumentY = +declRefExpr(to(varDecl(hasName("y".bind("arg"); + TypeMatcher IntType = qualType(isInteger()).bind("type"); + StatementMatcher CallExpr = +callExpr(forEachArgumentWithParamType(ArgumentY, IntType)); + + // IntParam does not match. + EXPECT_TRUE(notMatches("void f(int* i) { int* y; f(y); }", CallExpr)); + // ArgumentY does not match. + EXPECT_TRUE(notMatches("void f(int i) { int x; f(x); }", CallExpr)); +} + +TEST(ForEachArgumentWithParamType, MatchesCXXMemberCallExpr) { + StatementMatcher ArgumentY = +declRefExpr(to(varDecl(hasName("y".bind("arg"); + TypeMatcher IntType = qualType(isInteger()).bind("type"); + StatementMatcher CallExpr = +callExpr(forEachArgumentWithParamType(ArgumentY, IntType)); + EXPECT_TRUE(matchAndVerifyResultTrue( +"struct S {" + " const S& operator[](int i) { return *this; }" + "};" + "void f(S S1) {" + " int y = 1;" + " S1[y];" + "}", +CallExpr, std::make_unique>("type", 1))); + + StatementMatcher CallExpr2 = +callExpr(forEachArgumentWithParamType(ArgumentY, IntType)); + EXPECT_TRUE(matchAndVerifyResultTrue( +"struct S {" + " static void g(int i);" + "};" + "void f() {" + " int y = 1;" + " S::g(y);" + "}", +CallExpr2, std::make_unique>("type", 1))); +} + +TEST(ForEachArgumentWithParamType, MatchesCallExpr) { + StatementMatcher ArgumentY = +declRefExpr(to(varDecl(hasName("y".bind("arg"); + TypeMatcher IntType = qualType(isInteger()).bind("type"); + StatementMatcher CallExpr = +callExpr(forEachArgumentWithParamType(ArgumentY, IntType)); + + EXPECT_TRUE( +matchAndVerifyResultTrue("void f(int i) { int y; f(y); }", CallExpr, + std::make_unique>( + "type"))); + EXPECT_TRUE( +matchAndVerifyResultTrue("void f(int i) { int y; f(y); }", CallExpr, + std::make_unique>( + "arg"))); + + EXPECT_TRUE(matchAndVerifyResultTrue( +"void f(int i, int j) { int y; f(y, y); }", CallExpr, +std::make_unique>("type", 2))); + EXPECT_TRUE(matchAndVerifyResultTrue( +"void f(int i, int j) { int y; f(y, y); }", CallExpr, +std::make_unique>("arg", 2))); +} + +TEST(ForEachArgumentWithParamType, MatchesConstructExpr) { + StatementMatcher ArgumentY = +declRefExpr(to(varDecl(hasName("y".bind("arg"); + TypeMatcher IntType = qualType(isInteger()).bind("type"); + StatementMatcher ConstructExpr = +cxxConstructExpr(forEachArgumentWithParamType(ArgumentY, IntType)); + + EXPECT_TRUE(matchAndVerifyResultTrue( +"struct C {" + " C(int i) {}" + "};" + "int y = 0;" + "C Obj(y);", +ConstructExpr, +std::make_unique>("type"))); + EXPECT_TRUE(matchAndVerifyResultTrue( +"struct C {" + " C(int i) {}" + "};" + "int y = 0;" + "C Obj(y);", +ConstructExpr, +std::make_unique>("arg"))); +} + +TEST(ForEachArgumentWithParamType, HandlesBoundNodesForNonMatches) { + EXPECT_TRUE(matchAndVerifyResultTrue( +"void g(int i, int j) {" + " int a;" + " int b;" + " int c;" + " g(a, 0);" + " g(a, b);" + " g(0, b);" + "}", +functionDecl( + forEachDescendant(varDecl().bind("v")), + forEachDescendant(callExpr(forEachArgumentWithParamType( +declRefExpr(to(decl(equalsBoundNode("v", qualType(), +std::make_unique>("v", 4))); +} + +TEST(ForEachArgumentWithParamType, MatchesFunctionPtrCalls) { + StatementMatcher ArgumentY = +declRefExpr(to(varDecl(hasName("y".bind("arg"); + TypeMatcher IntType = qualType(builtinType()).bind("type"); + StatementMatcher CallExpr = +callExpr(forEachArgumentWithParamType(ArgumentY, IntType)); + +