LambdaExpr.cpp 3.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. //===- unittest/Tooling/RecursiveASTVisitorTests/LambdaExpr.cpp -----------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #include "TestVisitor.h"
  9. #include <stack>
  10. using namespace clang;
  11. namespace {
  12. class LambdaExprVisitor : public ExpectedLocationVisitor<LambdaExprVisitor> {
  13. public:
  14. bool VisitLambdaExpr(LambdaExpr *Lambda) {
  15. PendingBodies.push(Lambda->getBody());
  16. PendingClasses.push(Lambda->getLambdaClass());
  17. Match("", Lambda->getIntroducerRange().getBegin());
  18. return true;
  19. }
  20. /// For each call to VisitLambdaExpr, we expect a subsequent call to visit
  21. /// the body (and maybe the lambda class, which is implicit).
  22. bool VisitStmt(Stmt *S) {
  23. if (!PendingBodies.empty() && S == PendingBodies.top())
  24. PendingBodies.pop();
  25. return true;
  26. }
  27. bool VisitDecl(Decl *D) {
  28. if (!PendingClasses.empty() && D == PendingClasses.top())
  29. PendingClasses.pop();
  30. return true;
  31. }
  32. /// Determine whether parts of lambdas (VisitLambdaExpr) were later traversed.
  33. bool allBodiesHaveBeenTraversed() const { return PendingBodies.empty(); }
  34. bool allClassesHaveBeenTraversed() const { return PendingClasses.empty(); }
  35. bool VisitImplicitCode = false;
  36. bool shouldVisitImplicitCode() const { return VisitImplicitCode; }
  37. private:
  38. std::stack<Stmt *> PendingBodies;
  39. std::stack<Decl *> PendingClasses;
  40. };
  41. TEST(RecursiveASTVisitor, VisitsLambdaExpr) {
  42. LambdaExprVisitor Visitor;
  43. Visitor.ExpectMatch("", 1, 12);
  44. EXPECT_TRUE(Visitor.runOver("void f() { []{ return; }(); }",
  45. LambdaExprVisitor::Lang_CXX11));
  46. EXPECT_TRUE(Visitor.allBodiesHaveBeenTraversed());
  47. EXPECT_FALSE(Visitor.allClassesHaveBeenTraversed());
  48. }
  49. TEST(RecursiveASTVisitor, LambdaInLambda) {
  50. LambdaExprVisitor Visitor;
  51. Visitor.ExpectMatch("", 1, 12);
  52. Visitor.ExpectMatch("", 1, 16);
  53. EXPECT_TRUE(Visitor.runOver("void f() { []{ []{ return; }; }(); }",
  54. LambdaExprVisitor::Lang_CXX11));
  55. EXPECT_TRUE(Visitor.allBodiesHaveBeenTraversed());
  56. EXPECT_FALSE(Visitor.allClassesHaveBeenTraversed());
  57. }
  58. TEST(RecursiveASTVisitor, TopLevelLambda) {
  59. LambdaExprVisitor Visitor;
  60. Visitor.VisitImplicitCode = true;
  61. Visitor.ExpectMatch("", 1, 10);
  62. Visitor.ExpectMatch("", 1, 14);
  63. EXPECT_TRUE(Visitor.runOver("auto x = []{ [] {}; };",
  64. LambdaExprVisitor::Lang_CXX11));
  65. EXPECT_TRUE(Visitor.allBodiesHaveBeenTraversed());
  66. EXPECT_TRUE(Visitor.allClassesHaveBeenTraversed());
  67. }
  68. TEST(RecursiveASTVisitor, VisitsLambdaExprAndImplicitClass) {
  69. LambdaExprVisitor Visitor;
  70. Visitor.VisitImplicitCode = true;
  71. Visitor.ExpectMatch("", 1, 12);
  72. EXPECT_TRUE(Visitor.runOver("void f() { []{ return; }(); }",
  73. LambdaExprVisitor::Lang_CXX11));
  74. EXPECT_TRUE(Visitor.allBodiesHaveBeenTraversed());
  75. EXPECT_TRUE(Visitor.allClassesHaveBeenTraversed());
  76. }
  77. TEST(RecursiveASTVisitor, VisitsAttributedLambdaExpr) {
  78. if (llvm::Triple(llvm::sys::getDefaultTargetTriple()).isPS4())
  79. return; // PS4 does not support fastcall.
  80. LambdaExprVisitor Visitor;
  81. Visitor.ExpectMatch("", 1, 12);
  82. EXPECT_TRUE(Visitor.runOver(
  83. "void f() { [] () __attribute__ (( fastcall )) { return; }(); }",
  84. LambdaExprVisitor::Lang_CXX14));
  85. }
  86. } // end anonymous namespace