1 //===- unittest/Tooling/RecursiveASTVisitorTests/LambdaExpr.cpp -----------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "TestVisitor.h"
10 #include "llvm/TargetParser/Host.h"
13 using namespace clang
;
17 class LambdaExprVisitor
: public ExpectedLocationVisitor
{
19 LambdaExprVisitor() { ShouldVisitImplicitCode
= false; }
21 bool VisitLambdaExpr(LambdaExpr
*Lambda
) override
{
22 PendingBodies
.push(Lambda
->getBody());
23 PendingClasses
.push(Lambda
->getLambdaClass());
24 Match("", Lambda
->getIntroducerRange().getBegin());
27 /// For each call to VisitLambdaExpr, we expect a subsequent call to visit
28 /// the body (and maybe the lambda class, which is implicit).
29 bool VisitStmt(Stmt
*S
) override
{
30 if (!PendingBodies
.empty() && S
== PendingBodies
.top())
34 bool VisitDecl(Decl
*D
) override
{
35 if (!PendingClasses
.empty() && D
== PendingClasses
.top())
39 /// Determine whether parts of lambdas (VisitLambdaExpr) were later traversed.
40 bool allBodiesHaveBeenTraversed() const { return PendingBodies
.empty(); }
41 bool allClassesHaveBeenTraversed() const { return PendingClasses
.empty(); }
44 std::stack
<Stmt
*> PendingBodies
;
45 std::stack
<Decl
*> PendingClasses
;
48 TEST(RecursiveASTVisitor
, VisitsLambdaExpr
) {
49 LambdaExprVisitor Visitor
;
50 Visitor
.ExpectMatch("", 1, 12);
51 EXPECT_TRUE(Visitor
.runOver("void f() { []{ return; }(); }",
52 LambdaExprVisitor::Lang_CXX11
));
53 EXPECT_TRUE(Visitor
.allBodiesHaveBeenTraversed());
54 EXPECT_FALSE(Visitor
.allClassesHaveBeenTraversed());
57 TEST(RecursiveASTVisitor
, LambdaInLambda
) {
58 LambdaExprVisitor Visitor
;
59 Visitor
.ExpectMatch("", 1, 12);
60 Visitor
.ExpectMatch("", 1, 16);
61 EXPECT_TRUE(Visitor
.runOver("void f() { []{ []{ return; }; }(); }",
62 LambdaExprVisitor::Lang_CXX11
));
63 EXPECT_TRUE(Visitor
.allBodiesHaveBeenTraversed());
64 EXPECT_FALSE(Visitor
.allClassesHaveBeenTraversed());
67 TEST(RecursiveASTVisitor
, TopLevelLambda
) {
68 LambdaExprVisitor Visitor
;
69 Visitor
.ShouldVisitImplicitCode
= true;
70 Visitor
.ExpectMatch("", 1, 10);
71 Visitor
.ExpectMatch("", 1, 14);
72 EXPECT_TRUE(Visitor
.runOver("auto x = []{ [] {}; };",
73 LambdaExprVisitor::Lang_CXX11
));
74 EXPECT_TRUE(Visitor
.allBodiesHaveBeenTraversed());
75 EXPECT_TRUE(Visitor
.allClassesHaveBeenTraversed());
78 TEST(RecursiveASTVisitor
, VisitsLambdaExprAndImplicitClass
) {
79 LambdaExprVisitor Visitor
;
80 Visitor
.ShouldVisitImplicitCode
= true;
81 Visitor
.ExpectMatch("", 1, 12);
82 EXPECT_TRUE(Visitor
.runOver("void f() { []{ return; }(); }",
83 LambdaExprVisitor::Lang_CXX11
));
84 EXPECT_TRUE(Visitor
.allBodiesHaveBeenTraversed());
85 EXPECT_TRUE(Visitor
.allClassesHaveBeenTraversed());
88 TEST(RecursiveASTVisitor
, VisitsAttributedLambdaExpr
) {
89 if (llvm::Triple(llvm::sys::getDefaultTargetTriple()).isPS())
90 GTEST_SKIP(); // PS4/PS5 do not support fastcall.
91 LambdaExprVisitor Visitor
;
92 Visitor
.ExpectMatch("", 1, 12);
93 EXPECT_TRUE(Visitor
.runOver(
94 "void f() { [] () __attribute__ (( fastcall )) { return; }(); }",
95 LambdaExprVisitor::Lang_CXX14
));
98 } // end anonymous namespace