This revision was automatically updated to reflect the committed changes.
mboehme marked an inline comment as done.
Closed by commit rL278933: Visit lambda capture inits from
RecursiveASTVisitor::TraverseLambdaCapture(). (authored by mboehme).
Changed prior to commit:
https://reviews.llvm.org/D23204?vs=68352&id=68357#toc
Repository:
rL LLVM
https://reviews.llvm.org/D23204
Files:
cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
cfe/trunk/lib/Index/IndexBody.cpp
cfe/trunk/unittests/Tooling/RecursiveASTVisitorTestExprVisitor.cpp
cfe/trunk/unittests/Tooling/TestVisitor.h
Index: cfe/trunk/lib/Index/IndexBody.cpp
===================================================================
--- cfe/trunk/lib/Index/IndexBody.cpp
+++ cfe/trunk/lib/Index/IndexBody.cpp
@@ -276,7 +276,8 @@
return true;
}
- bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C) {
+ bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C,
+ Expr *Init) {
if (C->capturesThis() || C->capturesVLAType())
return true;
Index: cfe/trunk/unittests/Tooling/RecursiveASTVisitorTestExprVisitor.cpp
===================================================================
--- cfe/trunk/unittests/Tooling/RecursiveASTVisitorTestExprVisitor.cpp
+++ cfe/trunk/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;
Index: cfe/trunk/unittests/Tooling/TestVisitor.h
===================================================================
--- cfe/trunk/unittests/Tooling/TestVisitor.h
+++ cfe/trunk/unittests/Tooling/TestVisitor.h
@@ -43,6 +43,7 @@
Lang_C,
Lang_CXX98,
Lang_CXX11,
+ Lang_CXX14,
Lang_OBJC,
Lang_OBJCXX11,
Lang_CXX = Lang_CXX98
@@ -55,6 +56,7 @@
case Lang_C: Args.push_back("-std=c99"); break;
case Lang_CXX98: Args.push_back("-std=c++98"); break;
case Lang_CXX11: Args.push_back("-std=c++11"); break;
+ case Lang_CXX14: Args.push_back("-std=c++14"); break;
case Lang_OBJC: Args.push_back("-ObjC"); break;
case Lang_OBJCXX11:
Args.push_back("-ObjC++");
@@ -127,9 +129,12 @@
/// \brief Expect 'Match' to occur at the given 'Line' and 'Column'.
///
/// Any number of expected matches can be set by calling this repeatedly.
- /// Each is expected to be matched exactly once.
- void ExpectMatch(Twine Match, unsigned Line, unsigned Column) {
- ExpectedMatches.push_back(ExpectedMatch(Match, Line, Column));
+ /// Each is expected to be matched 'Times' number of times. (This is useful in
+ /// cases in which different AST nodes can match at the same source code
+ /// location.)
+ void ExpectMatch(Twine Match, unsigned Line, unsigned Column,
+ unsigned Times = 1) {
+ ExpectedMatches.push_back(ExpectedMatch(Match, Line, Column, Times));
}
/// \brief Checks that all expected matches have been found.
@@ -200,30 +205,34 @@
};
struct ExpectedMatch {
- ExpectedMatch(Twine Name, unsigned LineNumber, unsigned ColumnNumber)
- : Candidate(Name, LineNumber, ColumnNumber), Found(false) {}
+ ExpectedMatch(Twine Name, unsigned LineNumber, unsigned ColumnNumber,
+ unsigned Times)
+ : Candidate(Name, LineNumber, ColumnNumber), TimesExpected(Times),
+ TimesSeen(0) {}
void UpdateFor(StringRef Name, FullSourceLoc Location, SourceManager &SM) {
if (Candidate.Matches(Name, Location)) {
- EXPECT_TRUE(!Found);
- Found = true;
- } else if (!Found && Candidate.PartiallyMatches(Name, Location)) {
+ EXPECT_LT(TimesSeen, TimesExpected);
+ ++TimesSeen;
+ } else if (TimesSeen < TimesExpected &&
+ Candidate.PartiallyMatches(Name, Location)) {
llvm::raw_string_ostream Stream(PartialMatches);
Stream << ", partial match: \"" << Name << "\" at ";
Location.print(Stream, SM);
}
}
void ExpectFound() const {
- EXPECT_TRUE(Found)
+ EXPECT_EQ(TimesExpected, TimesSeen)
<< "Expected \"" << Candidate.ExpectedName
<< "\" at " << Candidate.LineNumber
<< ":" << Candidate.ColumnNumber << PartialMatches;
}
MatchCandidate Candidate;
std::string PartialMatches;
- bool Found;
+ unsigned TimesExpected;
+ unsigned TimesSeen;
};
std::vector<MatchCandidate> DisallowedMatches;
Index: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
===================================================================
--- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
+++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
@@ -264,10 +264,12 @@
/// \returns false if the visitation was terminated early, true otherwise.
bool TraverseConstructorInitializer(CXXCtorInitializer *Init);
- /// \brief Recursively visit a lambda capture.
+ /// \brief Recursively visit a lambda capture. \c Init is the expression that
+ /// will be used to initialize the capture.
///
/// \returns false if the visitation was terminated early, true otherwise.
- bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C);
+ bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C,
+ Expr *Init);
/// \brief Recursively visit the body of a lambda expression.
///
@@ -885,9 +887,12 @@
template <typename Derived>
bool
RecursiveASTVisitor<Derived>::TraverseLambdaCapture(LambdaExpr *LE,
- const LambdaCapture *C) {
+ const LambdaCapture *C,
+ Expr *Init) {
if (LE->isInitCapture(C))
TRY_TO(TraverseDecl(C->getCapturedVar()));
+ else
+ TRY_TO(TraverseStmt(Init));
return true;
}
@@ -2261,13 +2266,11 @@
// Walk only the visible parts of lambda expressions.
DEF_TRAVERSE_STMT(LambdaExpr, {
- for (LambdaExpr::capture_iterator C = S->explicit_capture_begin(),
- CEnd = S->explicit_capture_end();
- C != CEnd; ++C) {
- TRY_TO(TraverseLambdaCapture(S, C));
- }
- for (Expr *Init : S->capture_inits()) {
- TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(Init);
+ for (unsigned I = 0, N = S->capture_size(); I != N; ++I) {
+ const LambdaCapture *C = S->capture_begin() + I;
+ if (C->isExplicit() || getDerived().shouldVisitImplicitCode()) {
+ TRY_TO(TraverseLambdaCapture(S, C, S->capture_init_begin()[I]));
+ }
}
TypeLoc TL = S->getCallOperator()->getTypeSourceInfo()->getTypeLoc();
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits