blob: 560cdf95c0ef592c95ef25c5e221d83a4f6d0889 [file] [log] [blame]
David Zarzyckid488daa2018-04-19 18:19:02 +00001//===- unittest/Tooling/RecursiveASTVisitorTests/LambdaExpr.cpp -----------===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// 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
David Zarzyckid488daa2018-04-19 18:19:02 +00006//
7//===----------------------------------------------------------------------===//
8
9#include "TestVisitor.h"
10#include <stack>
11
12using namespace clang;
13
14namespace {
15
16class LambdaExprVisitor : public ExpectedLocationVisitor<LambdaExprVisitor> {
17public:
18 bool VisitLambdaExpr(LambdaExpr *Lambda) {
Sam McCalle60151c2019-01-14 10:31:42 +000019 PendingBodies.push(Lambda->getBody());
20 PendingClasses.push(Lambda->getLambdaClass());
David Zarzyckid488daa2018-04-19 18:19:02 +000021 Match("", Lambda->getIntroducerRange().getBegin());
22 return true;
23 }
Sam McCalle60151c2019-01-14 10:31:42 +000024 /// For each call to VisitLambdaExpr, we expect a subsequent call to visit
25 /// the body (and maybe the lambda class, which is implicit).
26 bool VisitStmt(Stmt *S) {
27 if (!PendingBodies.empty() && S == PendingBodies.top())
28 PendingBodies.pop();
29 return true;
David Zarzyckid488daa2018-04-19 18:19:02 +000030 }
Sam McCalle60151c2019-01-14 10:31:42 +000031 bool VisitDecl(Decl *D) {
32 if (!PendingClasses.empty() && D == PendingClasses.top())
33 PendingClasses.pop();
34 return true;
David Zarzyckid488daa2018-04-19 18:19:02 +000035 }
Sam McCalle60151c2019-01-14 10:31:42 +000036 /// Determine whether parts of lambdas (VisitLambdaExpr) were later traversed.
37 bool allBodiesHaveBeenTraversed() const { return PendingBodies.empty(); }
38 bool allClassesHaveBeenTraversed() const { return PendingClasses.empty(); }
39
40 bool VisitImplicitCode = false;
41 bool shouldVisitImplicitCode() const { return VisitImplicitCode; }
42
David Zarzyckid488daa2018-04-19 18:19:02 +000043private:
Sam McCalle60151c2019-01-14 10:31:42 +000044 std::stack<Stmt *> PendingBodies;
45 std::stack<Decl *> PendingClasses;
David Zarzyckid488daa2018-04-19 18:19:02 +000046};
47
48TEST(RecursiveASTVisitor, VisitsLambdaExpr) {
49 LambdaExprVisitor Visitor;
50 Visitor.ExpectMatch("", 1, 12);
51 EXPECT_TRUE(Visitor.runOver("void f() { []{ return; }(); }",
52 LambdaExprVisitor::Lang_CXX11));
Sam McCalle60151c2019-01-14 10:31:42 +000053 EXPECT_TRUE(Visitor.allBodiesHaveBeenTraversed());
54 EXPECT_FALSE(Visitor.allClassesHaveBeenTraversed());
David Zarzyckid488daa2018-04-19 18:19:02 +000055}
56
Sam McCalle60151c2019-01-14 10:31:42 +000057TEST(RecursiveASTVisitor, LambdaInLambda) {
David Zarzyckid488daa2018-04-19 18:19:02 +000058 LambdaExprVisitor Visitor;
Sam McCalle60151c2019-01-14 10:31:42 +000059 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());
65}
66
Sam McCall32ef5202019-01-14 17:16:00 +000067TEST(RecursiveASTVisitor, TopLevelLambda) {
68 LambdaExprVisitor Visitor;
69 Visitor.VisitImplicitCode = 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());
76}
77
Sam McCalle60151c2019-01-14 10:31:42 +000078TEST(RecursiveASTVisitor, VisitsLambdaExprAndImplicitClass) {
79 LambdaExprVisitor Visitor;
80 Visitor.VisitImplicitCode = true;
81 Visitor.ExpectMatch("", 1, 12);
David Zarzyckid488daa2018-04-19 18:19:02 +000082 EXPECT_TRUE(Visitor.runOver("void f() { []{ return; }(); }",
83 LambdaExprVisitor::Lang_CXX11));
84 EXPECT_TRUE(Visitor.allBodiesHaveBeenTraversed());
Sam McCalle60151c2019-01-14 10:31:42 +000085 EXPECT_TRUE(Visitor.allClassesHaveBeenTraversed());
David Zarzyckid488daa2018-04-19 18:19:02 +000086}
87
88TEST(RecursiveASTVisitor, VisitsAttributedLambdaExpr) {
89 LambdaExprVisitor Visitor;
90 Visitor.ExpectMatch("", 1, 12);
91 EXPECT_TRUE(Visitor.runOver(
92 "void f() { [] () __attribute__ (( fastcall )) { return; }(); }",
93 LambdaExprVisitor::Lang_CXX14));
94}
95
96} // end anonymous namespace