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 {
18public:
19 LambdaExprVisitor() { ShouldVisitImplicitCode = false; }
20
21 bool VisitLambdaExpr(LambdaExpr *Lambda) override {
22 PendingBodies.push(x: Lambda->getBody());
23 PendingClasses.push(Lambda->getLambdaClass());
24 Match("", Lambda->getIntroducerRange().getBegin());
25 return true;
26 }
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())
31 PendingBodies.pop();
32 return true;
33 }
34 bool VisitDecl(Decl *D) override {
35 if (!PendingClasses.empty() && D == PendingClasses.top())
36 PendingClasses.pop();
37 return true;
38 }
39 /// Determine whether parts of lambdas (VisitLambdaExpr) were later traversed.
40 bool allBodiesHaveBeenTraversed() const { return PendingBodies.empty(); }
41 bool allClassesHaveBeenTraversed() const { return PendingClasses.empty(); }
42
43private:
44 std::stack<Stmt *> PendingBodies;
45 std::stack<Decl *> PendingClasses;
46};
47
48TEST(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());
55}
56
57TEST(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());
65}
66
67TEST(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());
76}
77
78TEST(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());
86}
87
88TEST(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));
96}
97
98} // end anonymous namespace
99

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

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