blob: a965632153fae6ac87e1cbfbab771738c8a256f5 [file] [log] [blame]
David Zarzyckid488daa2018-04-19 18:19:02 +00001//===- unittest/Tooling/RecursiveASTVisitorTests/LambdaExpr.cpp -----------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "TestVisitor.h"
11#include <stack>
12
13using namespace clang;
14
15namespace {
16
17class LambdaExprVisitor : public ExpectedLocationVisitor<LambdaExprVisitor> {
18public:
19 bool VisitLambdaExpr(LambdaExpr *Lambda) {
Sam McCalle60151c2019-01-14 10:31:42 +000020 PendingBodies.push(Lambda->getBody());
21 PendingClasses.push(Lambda->getLambdaClass());
David Zarzyckid488daa2018-04-19 18:19:02 +000022 Match("", Lambda->getIntroducerRange().getBegin());
23 return true;
24 }
Sam McCalle60151c2019-01-14 10:31:42 +000025 /// 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;
David Zarzyckid488daa2018-04-19 18:19:02 +000031 }
Sam McCalle60151c2019-01-14 10:31:42 +000032 bool VisitDecl(Decl *D) {
33 if (!PendingClasses.empty() && D == PendingClasses.top())
34 PendingClasses.pop();
35 return true;
David Zarzyckid488daa2018-04-19 18:19:02 +000036 }
Sam McCalle60151c2019-01-14 10:31:42 +000037 /// 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
David Zarzyckid488daa2018-04-19 18:19:02 +000044private:
Sam McCalle60151c2019-01-14 10:31:42 +000045 std::stack<Stmt *> PendingBodies;
46 std::stack<Decl *> PendingClasses;
David Zarzyckid488daa2018-04-19 18:19:02 +000047};
48
49TEST(RecursiveASTVisitor, VisitsLambdaExpr) {
50 LambdaExprVisitor Visitor;
51 Visitor.ExpectMatch("", 1, 12);
52 EXPECT_TRUE(Visitor.runOver("void f() { []{ return; }(); }",
53 LambdaExprVisitor::Lang_CXX11));
Sam McCalle60151c2019-01-14 10:31:42 +000054 EXPECT_TRUE(Visitor.allBodiesHaveBeenTraversed());
55 EXPECT_FALSE(Visitor.allClassesHaveBeenTraversed());
David Zarzyckid488daa2018-04-19 18:19:02 +000056}
57
Sam McCalle60151c2019-01-14 10:31:42 +000058TEST(RecursiveASTVisitor, LambdaInLambda) {
David Zarzyckid488daa2018-04-19 18:19:02 +000059 LambdaExprVisitor Visitor;
Sam McCalle60151c2019-01-14 10:31:42 +000060 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());
66}
67
68TEST(RecursiveASTVisitor, VisitsLambdaExprAndImplicitClass) {
69 LambdaExprVisitor Visitor;
70 Visitor.VisitImplicitCode = true;
71 Visitor.ExpectMatch("", 1, 12);
David Zarzyckid488daa2018-04-19 18:19:02 +000072 EXPECT_TRUE(Visitor.runOver("void f() { []{ return; }(); }",
73 LambdaExprVisitor::Lang_CXX11));
74 EXPECT_TRUE(Visitor.allBodiesHaveBeenTraversed());
Sam McCalle60151c2019-01-14 10:31:42 +000075 EXPECT_TRUE(Visitor.allClassesHaveBeenTraversed());
David Zarzyckid488daa2018-04-19 18:19:02 +000076}
77
78TEST(RecursiveASTVisitor, VisitsAttributedLambdaExpr) {
79 LambdaExprVisitor Visitor;
80 Visitor.ExpectMatch("", 1, 12);
81 EXPECT_TRUE(Visitor.runOver(
82 "void f() { [] () __attribute__ (( fastcall )) { return; }(); }",
83 LambdaExprVisitor::Lang_CXX14));
84}
85
86} // end anonymous namespace