aboutsummaryrefslogtreecommitdiff
path: root/unittests/Tooling/RecursiveASTVisitorTests
diff options
context:
space:
mode:
Diffstat (limited to 'unittests/Tooling/RecursiveASTVisitorTests')
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTests/Attr.cpp2
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTests/CXXMemberCall.cpp2
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTests/DeclRefExpr.cpp10
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTests/InitListExprPostOrder.cpp2
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTests/InitListExprPostOrderNoQueue.cpp2
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrder.cpp2
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrderNoQueue.cpp2
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTests/LambdaExpr.cpp62
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTests/TraversalScope.cpp51
9 files changed, 110 insertions, 25 deletions
diff --git a/unittests/Tooling/RecursiveASTVisitorTests/Attr.cpp b/unittests/Tooling/RecursiveASTVisitorTests/Attr.cpp
index a6ba92ea03b5..33163c30e5d0 100644
--- a/unittests/Tooling/RecursiveASTVisitorTests/Attr.cpp
+++ b/unittests/Tooling/RecursiveASTVisitorTests/Attr.cpp
@@ -18,7 +18,7 @@ namespace {
class AttrVisitor : public ExpectedLocationVisitor<AttrVisitor> {
public:
bool VisitMemberExpr(MemberExpr *ME) {
- Match(ME->getMemberDecl()->getNameAsString(), ME->getLocStart());
+ Match(ME->getMemberDecl()->getNameAsString(), ME->getBeginLoc());
return true;
}
bool VisitAttr(Attr *A) {
diff --git a/unittests/Tooling/RecursiveASTVisitorTests/CXXMemberCall.cpp b/unittests/Tooling/RecursiveASTVisitorTests/CXXMemberCall.cpp
index 8a979204b847..a83e55137ad7 100644
--- a/unittests/Tooling/RecursiveASTVisitorTests/CXXMemberCall.cpp
+++ b/unittests/Tooling/RecursiveASTVisitorTests/CXXMemberCall.cpp
@@ -18,7 +18,7 @@ class CXXMemberCallVisitor
public:
bool VisitCXXMemberCallExpr(CXXMemberCallExpr *Call) {
Match(Call->getMethodDecl()->getQualifiedNameAsString(),
- Call->getLocStart());
+ Call->getBeginLoc());
return true;
}
};
diff --git a/unittests/Tooling/RecursiveASTVisitorTests/DeclRefExpr.cpp b/unittests/Tooling/RecursiveASTVisitorTests/DeclRefExpr.cpp
index 67640486efb6..cd0e4260a8bc 100644
--- a/unittests/Tooling/RecursiveASTVisitorTests/DeclRefExpr.cpp
+++ b/unittests/Tooling/RecursiveASTVisitorTests/DeclRefExpr.cpp
@@ -75,11 +75,11 @@ TEST(RecursiveASTVisitor, VisitsUseOfImplicitLambdaCapture) {
TEST(RecursiveASTVisitor, VisitsImplicitLambdaCaptureInit) {
DeclRefExprVisitor Visitor;
Visitor.setShouldVisitImplicitCode(true);
- // We're expecting the "i" in the lambda to be visited twice:
- // - Once for the DeclRefExpr in the lambda capture initialization (whose
- // source code location is set to the first use of the variable).
- // - Once for the DeclRefExpr for the use of "i" inside the lambda.
- Visitor.ExpectMatch("i", 1, 24, /*Times=*/2);
+ // We're expecting "i" to be visited twice: once for the initialization expr
+ // for the captured variable "i" outside of the lambda body, and again for
+ // the use of "i" inside the lambda.
+ Visitor.ExpectMatch("i", 1, 20, /*Times=*/1);
+ Visitor.ExpectMatch("i", 1, 24, /*Times=*/1);
EXPECT_TRUE(Visitor.runOver(
"void f() { int i; [=]{ i; }; }",
DeclRefExprVisitor::Lang_CXX11));
diff --git a/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPostOrder.cpp b/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPostOrder.cpp
index 420b49aa1b14..396f25de5c5d 100644
--- a/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPostOrder.cpp
+++ b/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPostOrder.cpp
@@ -19,7 +19,7 @@ public:
bool shouldTraversePostOrder() const { return true; }
bool VisitInitListExpr(InitListExpr *ILE) {
- Match(ILE->isSemanticForm() ? "semantic" : "syntactic", ILE->getLocStart());
+ Match(ILE->isSemanticForm() ? "semantic" : "syntactic", ILE->getBeginLoc());
return true;
}
};
diff --git a/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPostOrderNoQueue.cpp b/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPostOrderNoQueue.cpp
index f9d5ef69e098..587f84bb430a 100644
--- a/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPostOrderNoQueue.cpp
+++ b/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPostOrderNoQueue.cpp
@@ -23,7 +23,7 @@ public:
}
bool VisitInitListExpr(InitListExpr *ILE) {
- Match(ILE->isSemanticForm() ? "semantic" : "syntactic", ILE->getLocStart());
+ Match(ILE->isSemanticForm() ? "semantic" : "syntactic", ILE->getBeginLoc());
return true;
}
};
diff --git a/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrder.cpp b/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrder.cpp
index f2036e232c01..01f6e1902916 100644
--- a/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrder.cpp
+++ b/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrder.cpp
@@ -19,7 +19,7 @@ class InitListExprPreOrderVisitor
: public ExpectedLocationVisitor<InitListExprPreOrderVisitor> {
public:
bool VisitInitListExpr(InitListExpr *ILE) {
- Match(ILE->isSemanticForm() ? "semantic" : "syntactic", ILE->getLocStart());
+ Match(ILE->isSemanticForm() ? "semantic" : "syntactic", ILE->getBeginLoc());
return true;
}
};
diff --git a/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrderNoQueue.cpp b/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrderNoQueue.cpp
index 064cd74390b4..d48b5a89c824 100644
--- a/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrderNoQueue.cpp
+++ b/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrderNoQueue.cpp
@@ -21,7 +21,7 @@ public:
}
bool VisitInitListExpr(InitListExpr *ILE) {
- Match(ILE->isSemanticForm() ? "semantic" : "syntactic", ILE->getLocStart());
+ Match(ILE->isSemanticForm() ? "semantic" : "syntactic", ILE->getBeginLoc());
return true;
}
};
diff --git a/unittests/Tooling/RecursiveASTVisitorTests/LambdaExpr.cpp b/unittests/Tooling/RecursiveASTVisitorTests/LambdaExpr.cpp
index 80aeb43528c4..d3a3eba15d16 100644
--- a/unittests/Tooling/RecursiveASTVisitorTests/LambdaExpr.cpp
+++ b/unittests/Tooling/RecursiveASTVisitorTests/LambdaExpr.cpp
@@ -17,25 +17,33 @@ namespace {
class LambdaExprVisitor : public ExpectedLocationVisitor<LambdaExprVisitor> {
public:
bool VisitLambdaExpr(LambdaExpr *Lambda) {
- PendingBodies.push(Lambda);
+ PendingBodies.push(Lambda->getBody());
+ PendingClasses.push(Lambda->getLambdaClass());
Match("", Lambda->getIntroducerRange().getBegin());
return true;
}
- /// For each call to VisitLambdaExpr, we expect a subsequent call (with
- /// proper nesting) to TraverseLambdaBody.
- bool TraverseLambdaBody(LambdaExpr *Lambda) {
- EXPECT_FALSE(PendingBodies.empty());
- EXPECT_EQ(PendingBodies.top(), Lambda);
- PendingBodies.pop();
- return TraverseStmt(Lambda->getBody());
+ /// For each call to VisitLambdaExpr, we expect a subsequent call to visit
+ /// the body (and maybe the lambda class, which is implicit).
+ bool VisitStmt(Stmt *S) {
+ if (!PendingBodies.empty() && S == PendingBodies.top())
+ PendingBodies.pop();
+ return true;
}
- /// Determine whether TraverseLambdaBody has been called for every call to
- /// VisitLambdaExpr.
- bool allBodiesHaveBeenTraversed() const {
- return PendingBodies.empty();
+ bool VisitDecl(Decl *D) {
+ if (!PendingClasses.empty() && D == PendingClasses.top())
+ PendingClasses.pop();
+ return true;
}
+ /// Determine whether parts of lambdas (VisitLambdaExpr) were later traversed.
+ bool allBodiesHaveBeenTraversed() const { return PendingBodies.empty(); }
+ bool allClassesHaveBeenTraversed() const { return PendingClasses.empty(); }
+
+ bool VisitImplicitCode = false;
+ bool shouldVisitImplicitCode() const { return VisitImplicitCode; }
+
private:
- std::stack<LambdaExpr *> PendingBodies;
+ std::stack<Stmt *> PendingBodies;
+ std::stack<Decl *> PendingClasses;
};
TEST(RecursiveASTVisitor, VisitsLambdaExpr) {
@@ -43,13 +51,39 @@ TEST(RecursiveASTVisitor, VisitsLambdaExpr) {
Visitor.ExpectMatch("", 1, 12);
EXPECT_TRUE(Visitor.runOver("void f() { []{ return; }(); }",
LambdaExprVisitor::Lang_CXX11));
+ EXPECT_TRUE(Visitor.allBodiesHaveBeenTraversed());
+ EXPECT_FALSE(Visitor.allClassesHaveBeenTraversed());
}
-TEST(RecursiveASTVisitor, TraverseLambdaBodyCanBeOverridden) {
+TEST(RecursiveASTVisitor, LambdaInLambda) {
LambdaExprVisitor Visitor;
+ Visitor.ExpectMatch("", 1, 12);
+ Visitor.ExpectMatch("", 1, 16);
+ EXPECT_TRUE(Visitor.runOver("void f() { []{ []{ return; }; }(); }",
+ LambdaExprVisitor::Lang_CXX11));
+ EXPECT_TRUE(Visitor.allBodiesHaveBeenTraversed());
+ EXPECT_FALSE(Visitor.allClassesHaveBeenTraversed());
+}
+
+TEST(RecursiveASTVisitor, TopLevelLambda) {
+ LambdaExprVisitor Visitor;
+ Visitor.VisitImplicitCode = true;
+ Visitor.ExpectMatch("", 1, 10);
+ Visitor.ExpectMatch("", 1, 14);
+ EXPECT_TRUE(Visitor.runOver("auto x = []{ [] {}; };",
+ LambdaExprVisitor::Lang_CXX11));
+ EXPECT_TRUE(Visitor.allBodiesHaveBeenTraversed());
+ EXPECT_TRUE(Visitor.allClassesHaveBeenTraversed());
+}
+
+TEST(RecursiveASTVisitor, VisitsLambdaExprAndImplicitClass) {
+ LambdaExprVisitor Visitor;
+ Visitor.VisitImplicitCode = true;
+ Visitor.ExpectMatch("", 1, 12);
EXPECT_TRUE(Visitor.runOver("void f() { []{ return; }(); }",
LambdaExprVisitor::Lang_CXX11));
EXPECT_TRUE(Visitor.allBodiesHaveBeenTraversed());
+ EXPECT_TRUE(Visitor.allClassesHaveBeenTraversed());
}
TEST(RecursiveASTVisitor, VisitsAttributedLambdaExpr) {
diff --git a/unittests/Tooling/RecursiveASTVisitorTests/TraversalScope.cpp b/unittests/Tooling/RecursiveASTVisitorTests/TraversalScope.cpp
new file mode 100644
index 000000000000..72f6c644b388
--- /dev/null
+++ b/unittests/Tooling/RecursiveASTVisitorTests/TraversalScope.cpp
@@ -0,0 +1,51 @@
+//===- unittest/Tooling/RecursiveASTVisitorTests/TraversalScope.cpp -------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "TestVisitor.h"
+
+using namespace clang;
+
+namespace {
+
+class Visitor : public ExpectedLocationVisitor<Visitor, clang::TestVisitor> {
+public:
+ Visitor(ASTContext *Context) { this->Context = Context; }
+
+ bool VisitNamedDecl(NamedDecl *D) {
+ if (!D->isImplicit())
+ Match(D->getName(), D->getLocation());
+ return true;
+ }
+};
+
+TEST(RecursiveASTVisitor, RespectsTraversalScope) {
+ auto AST = tooling::buildASTFromCode(
+ R"cpp(
+struct foo {
+ struct bar {
+ struct baz {};
+ };
+};
+ )cpp",
+ "foo.cpp", std::make_shared<PCHContainerOperations>());
+ auto &Ctx = AST->getASTContext();
+ auto &TU = *Ctx.getTranslationUnitDecl();
+ auto &Foo = *TU.lookup(&Ctx.Idents.get("foo")).front();
+ auto &Bar = *cast<DeclContext>(Foo).lookup(&Ctx.Idents.get("bar")).front();
+
+ Ctx.setTraversalScope({&Bar});
+
+ Visitor V(&Ctx);
+ V.DisallowMatch("foo", 2, 8);
+ V.ExpectMatch("bar", 3, 10);
+ V.ExpectMatch("baz", 4, 12);
+ V.TraverseAST(Ctx);
+}
+
+} // end anonymous namespace