Visit lambda capture inits from RecursiveASTVisitor::TraverseLambdaCapture().
Summary:
rL277342 made RecursiveASTVisitor visit lambda capture initialization
expressions (these are the Exprs in LambdaExpr::capture_inits()).
jdennett identified two issues with rL277342 (see comments there for details):
- It visits initialization expressions for implicit lambda captures, even if
shouldVisitImplicitCode() returns false.
- It visits initialization expressions for init captures twice (because these
were already traveresed in TraverseLambdaCapture() before rL277342)
This patch fixes these issues and moves the code for traversing initialization
expressions into TraverseLambdaCapture().
This patch also makes two changes required for the tests:
- It adds Lang_CXX14 to the Language enum in TestVisitor.
- It adds a parameter to ExpectedLocationVisitor::ExpectMatch() that specifies
the number of times a match is expected to be seen.
Reviewers: klimek, jdennett, alexfh
Subscribers: cfe-commits
Differential Revision: https://reviews.llvm.org/D23204
llvm-svn: 278933
diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTestExprVisitor.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTestExprVisitor.cpp
index d39ca4b..5f1dd65 100644
--- a/clang/unittests/Tooling/RecursiveASTVisitorTestExprVisitor.cpp
+++ b/clang/unittests/Tooling/RecursiveASTVisitorTestExprVisitor.cpp
@@ -161,10 +161,21 @@
class DeclRefExprVisitor : public ExpectedLocationVisitor<DeclRefExprVisitor> {
public:
+ DeclRefExprVisitor() : ShouldVisitImplicitCode(false) {}
+
+ bool shouldVisitImplicitCode() const { return ShouldVisitImplicitCode; }
+
+ void setShouldVisitImplicitCode(bool NewValue) {
+ ShouldVisitImplicitCode = NewValue;
+ }
+
bool VisitDeclRefExpr(DeclRefExpr *Reference) {
Match(Reference->getNameInfo().getAsString(), Reference->getLocation());
return true;
}
+
+private:
+ bool ShouldVisitImplicitCode;
};
TEST(RecursiveASTVisitor, VisitsBaseClassTemplateArguments) {
@@ -191,14 +202,43 @@
"void x(); void y() { x(); }"));
}
-TEST(RecursiveASTVisitor, VisitsLambdaCaptureInit) {
+TEST(RecursiveASTVisitor, VisitsExplicitLambdaCaptureInit) {
DeclRefExprVisitor Visitor;
Visitor.ExpectMatch("i", 1, 20);
EXPECT_TRUE(Visitor.runOver(
- "void f() { int i; [i]{}; };",
+ "void f() { int i; [i]{}; }",
DeclRefExprVisitor::Lang_CXX11));
}
+TEST(RecursiveASTVisitor, VisitsUseOfImplicitLambdaCapture) {
+ DeclRefExprVisitor Visitor;
+ Visitor.ExpectMatch("i", 1, 24);
+ EXPECT_TRUE(Visitor.runOver(
+ "void f() { int i; [=]{ i; }; }",
+ DeclRefExprVisitor::Lang_CXX11));
+}
+
+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);
+ EXPECT_TRUE(Visitor.runOver(
+ "void f() { int i; [=]{ i; }; }",
+ DeclRefExprVisitor::Lang_CXX11));
+}
+
+TEST(RecursiveASTVisitor, VisitsLambdaInitCaptureInit) {
+ DeclRefExprVisitor Visitor;
+ Visitor.ExpectMatch("i", 1, 24);
+ EXPECT_TRUE(Visitor.runOver(
+ "void f() { int i; [a = i + 1]{}; }",
+ DeclRefExprVisitor::Lang_CXX14));
+}
+
/* FIXME: According to Richard Smith this is a bug in the AST.
TEST(RecursiveASTVisitor, VisitsBaseClassTemplateArgumentsInInstantiation) {
DeclRefExprVisitor Visitor;