blob: c28704532a6edb141476ece4f9983fcdd81549d4 [file] [log] [blame]
David Blaikieea7d8472012-04-26 20:39:46 +00001//===- unittest/Tooling/RecursiveASTVisitorTest.cpp -----------------------===//
Manuel Klimek770691b2012-04-19 08:48:53 +00002//
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
Richard Smith87d8fb92012-06-24 23:56:26 +000010#include "TestVisitor.h"
James Dennett86e67a22013-07-10 18:29:15 +000011#include <stack>
12
Richard Smith1be902c2014-05-19 22:34:38 +000013using namespace clang;
14
15namespace {
Manuel Klimek770691b2012-04-19 08:48:53 +000016
James Dennett9ad99592013-06-30 03:13:35 +000017class LambdaExprVisitor : public ExpectedLocationVisitor<LambdaExprVisitor> {
18public:
19 bool VisitLambdaExpr(LambdaExpr *Lambda) {
James Dennett86e67a22013-07-10 18:29:15 +000020 PendingBodies.push(Lambda);
James Dennett9ad99592013-06-30 03:13:35 +000021 Match("", Lambda->getIntroducerRange().getBegin());
22 return true;
23 }
James Dennett86e67a22013-07-10 18:29:15 +000024 /// For each call to VisitLambdaExpr, we expect a subsequent call (with
25 /// proper nesting) to TraverseLambdaBody.
26 bool TraverseLambdaBody(LambdaExpr *Lambda) {
27 EXPECT_FALSE(PendingBodies.empty());
28 EXPECT_EQ(PendingBodies.top(), Lambda);
29 PendingBodies.pop();
30 return TraverseStmt(Lambda->getBody());
31 }
32 /// Determine whether TraverseLambdaBody has been called for every call to
33 /// VisitLambdaExpr.
34 bool allBodiesHaveBeenTraversed() const {
35 return PendingBodies.empty();
36 }
37private:
James Dennettddd36ff2013-08-09 23:08:25 +000038 std::stack<LambdaExpr *> PendingBodies;
39};
40
James Dennett9ad99592013-06-30 03:13:35 +000041TEST(RecursiveASTVisitor, VisitsLambdaExpr) {
42 LambdaExprVisitor Visitor;
43 Visitor.ExpectMatch("", 1, 12);
44 EXPECT_TRUE(Visitor.runOver("void f() { []{ return; }(); }",
45 LambdaExprVisitor::Lang_CXX11));
46}
47
James Dennett86e67a22013-07-10 18:29:15 +000048TEST(RecursiveASTVisitor, TraverseLambdaBodyCanBeOverridden) {
49 LambdaExprVisitor Visitor;
50 EXPECT_TRUE(Visitor.runOver("void f() { []{ return; }(); }",
51 LambdaExprVisitor::Lang_CXX11));
52 EXPECT_TRUE(Visitor.allBodiesHaveBeenTraversed());
53}
54
Manuel Klimek20c1c892014-10-09 15:02:06 +000055// Matches the (optional) capture-default of a lambda-introducer.
56class LambdaDefaultCaptureVisitor
57 : public ExpectedLocationVisitor<LambdaDefaultCaptureVisitor> {
58public:
59 bool VisitLambdaExpr(LambdaExpr *Lambda) {
60 if (Lambda->getCaptureDefault() != LCD_None) {
61 Match("", Lambda->getCaptureDefaultLoc());
62 }
63 return true;
64 }
65};
66
James Dennettddd36ff2013-08-09 23:08:25 +000067TEST(RecursiveASTVisitor, HasCaptureDefaultLoc) {
68 LambdaDefaultCaptureVisitor Visitor;
69 Visitor.ExpectMatch("", 1, 20);
70 EXPECT_TRUE(Visitor.runOver("void f() { int a; [=]{a;}; }",
71 LambdaDefaultCaptureVisitor::Lang_CXX11));
72}
73
James Dennett8f60cdd2013-09-05 17:46:21 +000074// Checks for lambda classes that are not marked as implicitly-generated.
75// (There should be none.)
76class ClassVisitor : public ExpectedLocationVisitor<ClassVisitor> {
77public:
78 ClassVisitor() : SawNonImplicitLambdaClass(false) {}
79 bool VisitCXXRecordDecl(CXXRecordDecl* record) {
80 if (record->isLambda() && !record->isImplicit())
81 SawNonImplicitLambdaClass = true;
82 return true;
83 }
84
85 bool sawOnlyImplicitLambdaClasses() const {
86 return !SawNonImplicitLambdaClass;
87 }
88
89private:
90 bool SawNonImplicitLambdaClass;
91};
92
93TEST(RecursiveASTVisitor, LambdaClosureTypesAreImplicit) {
94 ClassVisitor Visitor;
95 EXPECT_TRUE(Visitor.runOver("auto lambda = []{};",
96 ClassVisitor::Lang_CXX11));
97 EXPECT_TRUE(Visitor.sawOnlyImplicitLambdaClasses());
98}
99
DeLesley Hutchinsc4a82432013-12-30 17:24:36 +0000100
DeLesley Hutchinsc4a82432013-12-30 17:24:36 +0000101// Check to ensure that attributes and expressions within them are being
102// visited.
103class AttrVisitor : public ExpectedLocationVisitor<AttrVisitor> {
104public:
105 bool VisitMemberExpr(MemberExpr *ME) {
106 Match(ME->getMemberDecl()->getNameAsString(), ME->getLocStart());
107 return true;
108 }
109 bool VisitAttr(Attr *A) {
110 Match("Attr", A->getLocation());
111 return true;
112 }
113 bool VisitGuardedByAttr(GuardedByAttr *A) {
114 Match("guarded_by", A->getLocation());
115 return true;
116 }
117};
118
119
120TEST(RecursiveASTVisitor, AttributesAreVisited) {
121 AttrVisitor Visitor;
122 Visitor.ExpectMatch("Attr", 4, 24);
123 Visitor.ExpectMatch("guarded_by", 4, 24);
124 Visitor.ExpectMatch("mu1", 4, 35);
125 Visitor.ExpectMatch("Attr", 5, 29);
126 Visitor.ExpectMatch("mu1", 5, 54);
127 Visitor.ExpectMatch("mu2", 5, 59);
128 EXPECT_TRUE(Visitor.runOver(
129 "class Foo {\n"
130 " int mu1;\n"
131 " int mu2;\n"
132 " int a __attribute__((guarded_by(mu1)));\n"
133 " void bar() __attribute__((exclusive_locks_required(mu1, mu2)));\n"
134 "};\n"));
135}
136
Richard Smith1be902c2014-05-19 22:34:38 +0000137} // end anonymous namespace