[PATCH] D95573: [ASTMatchers] Avoid pathological traversal over nested lambdas

2021-01-29 Thread Sam McCall via Phabricator via cfe-commits
sammccall added a comment.

Since the 12 branch has been cut, I've added a blocking bug to get this fixed 
in some form: https://bugs.llvm.org/show_bug.cgi?id=48935

@rsmith I've assigned it to you to make a call about whether to cherrypick this 
patch, this patch+followup, or revert the original change on the branch.
(@steveire is a revert really an option here, or is there already more stuff 
relying on this?)


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D95573/new/

https://reviews.llvm.org/D95573

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D95573: [ASTMatchers] Avoid pathological traversal over nested lambdas

2021-01-28 Thread Stephen Kelly via Phabricator via cfe-commits
steveire added inline comments.



Comment at: clang/include/clang/AST/RecursiveASTVisitor.h:2063-2065
+  if (const auto *MD = dyn_cast(D)) {
+if (const CXXRecordDecl *RD = MD->getParent()) {
+  if (RD->isLambda()) {

rsmith wrote:
> This is incorrectly skipping the bodies of all other lambda member functions 
> (default ctor, copy ctor, destructor, implicit conversion to function pointer 
> type), not only the "body" of the lambda itself (the definition of the 
> `operator()`).
Please see https://reviews.llvm.org/D95644.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D95573/new/

https://reviews.llvm.org/D95573

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D95573: [ASTMatchers] Avoid pathological traversal over nested lambdas

2021-01-28 Thread Richard Smith - zygoloid via Phabricator via cfe-commits
rsmith added inline comments.



Comment at: clang/include/clang/AST/RecursiveASTVisitor.h:2063-2065
+  if (const auto *MD = dyn_cast(D)) {
+if (const CXXRecordDecl *RD = MD->getParent()) {
+  if (RD->isLambda()) {

This is incorrectly skipping the bodies of all other lambda member functions 
(default ctor, copy ctor, destructor, implicit conversion to function pointer 
type), not only the "body" of the lambda itself (the definition of the 
`operator()`).


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D95573/new/

https://reviews.llvm.org/D95573

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D95573: [ASTMatchers] Avoid pathological traversal over nested lambdas

2021-01-28 Thread Stephen Kelly via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG6f0df3cddb3e: [ASTMatchers] Avoid pathological traversal 
over nested lambdas (authored by stephenkelly).

Changed prior to commit:
  https://reviews.llvm.org/D95573?vs=319702=319941#toc

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D95573/new/

https://reviews.llvm.org/D95573

Files:
  clang/include/clang/AST/RecursiveASTVisitor.h
  clang/lib/ASTMatchers/ASTMatchFinder.cpp
  clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp

Index: clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
===
--- clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
@@ -3853,6 +3853,78 @@
   }
 }
 
+TEST(IgnoringImpCasts, PathologicalLambda) {
+
+  // Test that deeply nested lambdas are not a performance penalty
+  StringRef Code = R"cpp(
+void f() {
+  [] {
+  [] {
+  [] {
+  [] {
+  [] {
+  [] {
+  [] {
+  [] {
+  [] {
+  [] {
+  [] {
+  [] {
+  [] {
+  [] {
+  [] {
+  [] {
+  [] {
+  [] {
+  [] {
+  [] {
+  [] {
+  [] {
+  [] {
+  [] {
+  [] {
+  [] {
+  [] {
+  [] {
+  [] {
+int i = 42;
+(void)i;
+  }();
+  }();
+  }();
+  }();
+  }();
+  }();
+  }();
+  }();
+  }();
+  }();
+  }();
+  }();
+  }();
+  }();
+  }();
+  }();
+  }();
+  }();
+  }();
+  }();
+  }();
+  }();
+  }();
+  }();
+  }();
+  }();
+  }();
+  }();
+  }();
+}
+  )cpp";
+
+  EXPECT_TRUE(matches(Code, integerLiteral(equals(42;
+  EXPECT_TRUE(matches(Code, functionDecl(hasDescendant(integerLiteral(equals(42));
+}
+
 TEST(IgnoringImpCasts, MatchesImpCasts) {
   // This test checks that ignoringImpCasts matches when implicit casts are
   // present and its inner matcher alone does not match.
Index: clang/lib/ASTMatchers/ASTMatchFinder.cpp
===
--- clang/lib/ASTMatchers/ASTMatchFinder.cpp
+++ clang/lib/ASTMatchers/ASTMatchFinder.cpp
@@ -556,9 +556,9 @@
 if (LE->hasExplicitResultType())
   TraverseTypeLoc(Proto.getReturnLoc());
 TraverseStmt(LE->getTrailingRequiresClause());
-
-TraverseStmt(LE->getBody());
   }
+
+  TraverseStmt(LE->getBody());
   return true;
 }
 return RecursiveASTVisitor::dataTraverseNode(S, Queue);
@@ -697,6 +697,10 @@
   bool shouldVisitTemplateInstantiations() const { return true; }
   bool shouldVisitImplicitCode() const { return true; }
 
+  // We visit the lambda body explicitly, so instruct the RAV
+  // to not visit it on our behalf too.
+  bool shouldVisitLambdaBody() const { return false; }
+
   bool IsMatchingInASTNodeNotSpelledInSource() const override {
 return TraversingASTNodeNotSpelledInSource;
   }
Index: clang/include/clang/AST/RecursiveASTVisitor.h
===
--- clang/include/clang/AST/RecursiveASTVisitor.h
+++ clang/include/clang/AST/RecursiveASTVisitor.h
@@ -186,6 +186,9 @@
   /// code, e.g., implicit constructors and destructors.
   bool shouldVisitImplicitCode() const { return false; }
 
+  /// Return whether this visitor should recurse into lambda body
+  bool shouldVisitLambdaBody() const { return true; }
+
   /// Return whether this visitor should traverse post-order.
   bool shouldTraversePostOrder() const { return false; }
 
@@ -2057,6 +2060,14 @@
   // by clang.
   (!D->isDefaulted() || getDerived().shouldVisitImplicitCode());
 
+  if (const auto *MD = dyn_cast(D)) {
+if (const CXXRecordDecl *RD = MD->getParent()) {
+  if (RD->isLambda()) {
+VisitBody = VisitBody && getDerived().shouldVisitLambdaBody();
+  }
+}
+  }
+
   if (VisitBody) {
 TRY_TO(TraverseStmt(D->getBody())); // Function body.
   }
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D95573: [ASTMatchers] Avoid pathological traversal over nested lambdas

2021-01-28 Thread Alexander Kornienko via Phabricator via cfe-commits
alexfh added a comment.

Thanks for the prompt fix, btw!




Comment at: clang/include/clang/AST/RecursiveASTVisitor.h:2064
+  if (const auto *MD = dyn_cast(D)) {
+if (const auto *RD = MD->getParent()) {
+  if (RD->isLambda()) {

Please specify the type explicitly here.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D95573/new/

https://reviews.llvm.org/D95573

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D95573: [ASTMatchers] Avoid pathological traversal over nested lambdas

2021-01-28 Thread Alexander Kornienko via Phabricator via cfe-commits
alexfh accepted this revision.
alexfh added a comment.
This revision is now accepted and ready to land.

This fixes the issue with exponential traversal times for deeply nested 
lambdas. Please add a test though. For example, this one:

  void f() {
[] {
[] {
[] {
[] {
[] {
[] {
[] {
[] {
[] {
[] {
[] {
[] {
[] {
[] {
[] {
[] {
[] {
[] {
[] {
[] {
[] {
[] {
[] {
[] {
[] {
[] {
[] {
[] {
[] {
}();
}();
}();
}();
}();
}();
}();
}();
}();
}();
}();
}();
}();
}();
}();
}();
}();
}();
}();
}();
}();
}();
}();
}();
}();
}();
}();
}();
}();
  }


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D95573/new/

https://reviews.llvm.org/D95573

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D95573: [ASTMatchers] Avoid pathological traversal over nested lambdas

2021-01-27 Thread Stephen Kelly via Phabricator via cfe-commits
steveire created this revision.
steveire added a reviewer: aaron.ballman.
steveire requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D95573

Files:
  clang/include/clang/AST/RecursiveASTVisitor.h
  clang/lib/ASTMatchers/ASTMatchFinder.cpp


Index: clang/lib/ASTMatchers/ASTMatchFinder.cpp
===
--- clang/lib/ASTMatchers/ASTMatchFinder.cpp
+++ clang/lib/ASTMatchers/ASTMatchFinder.cpp
@@ -561,9 +561,9 @@
 if (LE->hasExplicitResultType())
   TraverseTypeLoc(Proto.getReturnLoc());
 TraverseStmt(LE->getTrailingRequiresClause());
-
-TraverseStmt(LE->getBody());
   }
+
+  TraverseStmt(LE->getBody());
   return true;
 }
 return RecursiveASTVisitor::dataTraverseNode(S, Queue);
@@ -702,6 +702,10 @@
   bool shouldVisitTemplateInstantiations() const { return true; }
   bool shouldVisitImplicitCode() const { return true; }
 
+  // We visit the lambda body explicitly, so instruct the RAV
+  // to not visit it on our behalf too.
+  bool shouldVisitLambdaBody() const { return false; }
+
   bool IsMatchingInASTNodeNotSpelledInSource() const override {
 return TraversingASTNodeNotSpelledInSource;
   }
Index: clang/include/clang/AST/RecursiveASTVisitor.h
===
--- clang/include/clang/AST/RecursiveASTVisitor.h
+++ clang/include/clang/AST/RecursiveASTVisitor.h
@@ -186,6 +186,9 @@
   /// code, e.g., implicit constructors and destructors.
   bool shouldVisitImplicitCode() const { return false; }
 
+  /// Return whether this visitor should recurse into lambda body
+  bool shouldVisitLambdaBody() const { return true; }
+
   /// Return whether this visitor should traverse post-order.
   bool shouldTraversePostOrder() const { return false; }
 
@@ -2057,6 +2060,14 @@
   // by clang.
   (!D->isDefaulted() || getDerived().shouldVisitImplicitCode());
 
+  if (const auto *MD = dyn_cast(D)) {
+if (const auto *RD = MD->getParent()) {
+  if (RD->isLambda()) {
+VisitBody = VisitBody && getDerived().shouldVisitLambdaBody();
+  }
+}
+  }
+
   if (VisitBody) {
 TRY_TO(TraverseStmt(D->getBody())); // Function body.
   }


Index: clang/lib/ASTMatchers/ASTMatchFinder.cpp
===
--- clang/lib/ASTMatchers/ASTMatchFinder.cpp
+++ clang/lib/ASTMatchers/ASTMatchFinder.cpp
@@ -561,9 +561,9 @@
 if (LE->hasExplicitResultType())
   TraverseTypeLoc(Proto.getReturnLoc());
 TraverseStmt(LE->getTrailingRequiresClause());
-
-TraverseStmt(LE->getBody());
   }
+
+  TraverseStmt(LE->getBody());
   return true;
 }
 return RecursiveASTVisitor::dataTraverseNode(S, Queue);
@@ -702,6 +702,10 @@
   bool shouldVisitTemplateInstantiations() const { return true; }
   bool shouldVisitImplicitCode() const { return true; }
 
+  // We visit the lambda body explicitly, so instruct the RAV
+  // to not visit it on our behalf too.
+  bool shouldVisitLambdaBody() const { return false; }
+
   bool IsMatchingInASTNodeNotSpelledInSource() const override {
 return TraversingASTNodeNotSpelledInSource;
   }
Index: clang/include/clang/AST/RecursiveASTVisitor.h
===
--- clang/include/clang/AST/RecursiveASTVisitor.h
+++ clang/include/clang/AST/RecursiveASTVisitor.h
@@ -186,6 +186,9 @@
   /// code, e.g., implicit constructors and destructors.
   bool shouldVisitImplicitCode() const { return false; }
 
+  /// Return whether this visitor should recurse into lambda body
+  bool shouldVisitLambdaBody() const { return true; }
+
   /// Return whether this visitor should traverse post-order.
   bool shouldTraversePostOrder() const { return false; }
 
@@ -2057,6 +2060,14 @@
   // by clang.
   (!D->isDefaulted() || getDerived().shouldVisitImplicitCode());
 
+  if (const auto *MD = dyn_cast(D)) {
+if (const auto *RD = MD->getParent()) {
+  if (RD->isLambda()) {
+VisitBody = VisitBody && getDerived().shouldVisitLambdaBody();
+  }
+}
+  }
+
   if (VisitBody) {
 TRY_TO(TraverseStmt(D->getBody())); // Function body.
   }
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits