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
9#include "TestVisitor.h"
10#include "llvm/TargetParser/Host.h"
11#include <stack>
12
13using namespace clang;
14
15namespace {
16
17class LambdaExprVisitor : public ExpectedLocationVisitor<LambdaExprVisitor> {
18public:
19 bool VisitLambdaExpr(LambdaExpr *Lambda) {
20 PendingBodies.push(x: Lambda->getBody());
21 PendingClasses.push(Lambda->getLambdaClass());
22 Match(Name: "", Location: Lambda->getIntroducerRange().getBegin());
23 return true;
24 }
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())
29 PendingBodies.pop();
30 return true;
31 }
32 bool VisitDecl(Decl *D) {
33 if (!PendingClasses.empty() && D == PendingClasses.top())
34 PendingClasses.pop();
35 return true;
36 }
37 /// Determine whether parts of lambdas (VisitLambdaExpr) were later traversed.
38 bool allBodiesHaveBeenTraversed() const { return PendingBodies.empty(); }
39 bool allClassesHaveBeenTraversed() const { return PendingClasses.empty(); }
40
41 bool VisitImplicitCode = false;
42 bool shouldVisitImplicitCode() const { return VisitImplicitCode; }
43
44private:
45 std::stack<Stmt *> PendingBodies;
46 std::stack<Decl *> PendingClasses;
47};
48
49TEST(RecursiveASTVisitor, VisitsLambdaExpr) {
50 LambdaExprVisitor Visitor;
51 Visitor.ExpectMatch(Match: "", Line: 1, Column: 12);
52 EXPECT_TRUE(Visitor.runOver("void f() { []{ return; }(); }",
53 LambdaExprVisitor::Lang_CXX11));
54 EXPECT_TRUE(Visitor.allBodiesHaveBeenTraversed());
55 EXPECT_FALSE(Visitor.allClassesHaveBeenTraversed());
56}
57
58TEST(RecursiveASTVisitor, LambdaInLambda) {
59 LambdaExprVisitor Visitor;
60 Visitor.ExpectMatch(Match: "", Line: 1, Column: 12);
61 Visitor.ExpectMatch(Match: "", Line: 1, Column: 16);
62 EXPECT_TRUE(Visitor.runOver("void f() { []{ []{ return; }; }(); }",
63 LambdaExprVisitor::Lang_CXX11));
64 EXPECT_TRUE(Visitor.allBodiesHaveBeenTraversed());
65 EXPECT_FALSE(Visitor.allClassesHaveBeenTraversed());
66}
67
68TEST(RecursiveASTVisitor, TopLevelLambda) {
69 LambdaExprVisitor Visitor;
70 Visitor.VisitImplicitCode = true;
71 Visitor.ExpectMatch(Match: "", Line: 1, Column: 10);
72 Visitor.ExpectMatch(Match: "", Line: 1, Column: 14);
73 EXPECT_TRUE(Visitor.runOver("auto x = []{ [] {}; };",
74 LambdaExprVisitor::Lang_CXX11));
75 EXPECT_TRUE(Visitor.allBodiesHaveBeenTraversed());
76 EXPECT_TRUE(Visitor.allClassesHaveBeenTraversed());
77}
78
79TEST(RecursiveASTVisitor, VisitsLambdaExprAndImplicitClass) {
80 LambdaExprVisitor Visitor;
81 Visitor.VisitImplicitCode = true;
82 Visitor.ExpectMatch(Match: "", Line: 1, Column: 12);
83 EXPECT_TRUE(Visitor.runOver("void f() { []{ return; }(); }",
84 LambdaExprVisitor::Lang_CXX11));
85 EXPECT_TRUE(Visitor.allBodiesHaveBeenTraversed());
86 EXPECT_TRUE(Visitor.allClassesHaveBeenTraversed());
87}
88
89TEST(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(Match: "", Line: 1, Column: 12);
94 EXPECT_TRUE(Visitor.runOver(
95 "void f() { [] () __attribute__ (( fastcall )) { return; }(); }",
96 LambdaExprVisitor::Lang_CXX14));
97}
98
99} // end anonymous namespace
100

source code of clang/unittests/Tooling/RecursiveASTVisitorTests/LambdaExpr.cpp