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
<LambdaExprVisitor
> {
19 bool VisitLambdaExpr(LambdaExpr
*Lambda
) {
20 PendingBodies
.push(Lambda
->getBody());
21 PendingClasses
.push(Lambda
->getLambdaClass());
22 Match("", Lambda
->getIntroducerRange().getBegin());
25 /// For each call to VisitLambdaExpr, we expect a subsequent call to visit
26 /// the body (and maybe the lambda class, which is implicit).
27 bool VisitStmt(Stmt
*S
) {
28 if (!PendingBodies
.empty() && S
== PendingBodies
.top())
32 bool VisitDecl(Decl
*D
) {
33 if (!PendingClasses
.empty() && D
== PendingClasses
.top())
37 /// Determine whether parts of lambdas (VisitLambdaExpr) were later traversed.
38 bool allBodiesHaveBeenTraversed() const { return PendingBodies
.empty(); }
39 bool allClassesHaveBeenTraversed() const { return PendingClasses
.empty(); }
41 bool VisitImplicitCode
= false;
42 bool shouldVisitImplicitCode() const { return VisitImplicitCode
; }
45 std::stack
<Stmt
*> PendingBodies
;
46 std::stack
<Decl
*> PendingClasses
;
49 TEST(RecursiveASTVisitor
, VisitsLambdaExpr
) {
50 LambdaExprVisitor Visitor
;
51 Visitor
.ExpectMatch("", 1, 12);
52 EXPECT_TRUE(Visitor
.runOver("void f() { []{ return; }(); }",
53 LambdaExprVisitor::Lang_CXX11
));
54 EXPECT_TRUE(Visitor
.allBodiesHaveBeenTraversed());
55 EXPECT_FALSE(Visitor
.allClassesHaveBeenTraversed());
58 TEST(RecursiveASTVisitor
, LambdaInLambda
) {
59 LambdaExprVisitor Visitor
;
60 Visitor
.ExpectMatch("", 1, 12);
61 Visitor
.ExpectMatch("", 1, 16);
62 EXPECT_TRUE(Visitor
.runOver("void f() { []{ []{ return; }; }(); }",
63 LambdaExprVisitor::Lang_CXX11
));
64 EXPECT_TRUE(Visitor
.allBodiesHaveBeenTraversed());
65 EXPECT_FALSE(Visitor
.allClassesHaveBeenTraversed());
68 TEST(RecursiveASTVisitor
, TopLevelLambda
) {
69 LambdaExprVisitor Visitor
;
70 Visitor
.VisitImplicitCode
= true;
71 Visitor
.ExpectMatch("", 1, 10);
72 Visitor
.ExpectMatch("", 1, 14);
73 EXPECT_TRUE(Visitor
.runOver("auto x = []{ [] {}; };",
74 LambdaExprVisitor::Lang_CXX11
));
75 EXPECT_TRUE(Visitor
.allBodiesHaveBeenTraversed());
76 EXPECT_TRUE(Visitor
.allClassesHaveBeenTraversed());
79 TEST(RecursiveASTVisitor
, VisitsLambdaExprAndImplicitClass
) {
80 LambdaExprVisitor Visitor
;
81 Visitor
.VisitImplicitCode
= true;
82 Visitor
.ExpectMatch("", 1, 12);
83 EXPECT_TRUE(Visitor
.runOver("void f() { []{ return; }(); }",
84 LambdaExprVisitor::Lang_CXX11
));
85 EXPECT_TRUE(Visitor
.allBodiesHaveBeenTraversed());
86 EXPECT_TRUE(Visitor
.allClassesHaveBeenTraversed());
89 TEST(RecursiveASTVisitor
, VisitsAttributedLambdaExpr
) {
90 if (llvm::Triple(llvm::sys::getDefaultTargetTriple()).isPS())
91 GTEST_SKIP(); // PS4/PS5 do not support fastcall.
92 LambdaExprVisitor Visitor
;
93 Visitor
.ExpectMatch("", 1, 12);
94 EXPECT_TRUE(Visitor
.runOver(
95 "void f() { [] () __attribute__ (( fastcall )) { return; }(); }",
96 LambdaExprVisitor::Lang_CXX14
));
99 } // end anonymous namespace