99 lines · cpp
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-exception6//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(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 visit28 /// 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 namespace99