[PATCH] D72505: [ASTMatchers] extract public matchers from const-analysis into own patch

2020-01-11 Thread Jonas Toth via Phabricator via cfe-commits
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(),
+

[PATCH] D72505: [ASTMatchers] extract public matchers from const-analysis into own patch

2020-01-11 Thread Jonas Toth via Phabricator via cfe-commits
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) {
+  

[PATCH] D72505: [ASTMatchers] extract public matchers from const-analysis into own patch

2020-01-11 Thread Jonas Toth via Phabricator via cfe-commits
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) {
+  

[PATCH] D72505: [ASTMatchers] extract public matchers from const-analysis into own patch

2020-01-11 Thread Jonas Toth via Phabricator via cfe-commits
JonasToth updated this revision to Diff 237510.
JonasToth marked 3 inline comments as done.
JonasToth added a comment.

- add test for K 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, 

[PATCH] D72505: [ASTMatchers] extract public matchers from const-analysis into own patch

2020-01-10 Thread Aaron Ballman via Phabricator via cfe-commits
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, )) {

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 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

2020-01-10 Thread Jonas Toth via Phabricator via cfe-commits
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, )) {

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

2020-01-10 Thread Jonas Toth via Phabricator via cfe-commits
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; 

[PATCH] D72505: [ASTMatchers] extract public matchers from const-analysis into own patch

2020-01-10 Thread Aaron Ballman via Phabricator via cfe-commits
aaron.ballman added inline comments.



Comment at: clang/include/clang/ASTMatchers/ASTMatchers.h:4207-4208
+  if (const auto *Call = dyn_cast()) {
+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 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, )) {

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

2020-01-10 Thread Jonas Toth via Phabricator via cfe-commits
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));
+