From: Sam McCall Date: Mon, 14 Jan 2019 17:16:00 +0000 (+0000) Subject: [AST] Fix double-traversal of code in top-level lambdas in RAV(implicit = yes). X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c60c7d3712d5da3a720ca1528cfca408672482fc;p=clang [AST] Fix double-traversal of code in top-level lambdas in RAV(implicit = yes). Summary: Prior to r351069, lambda classes were traversed or not depending on the {Function, Class, Namespace, TU} DeclContext containing them. If it was a function (common case) they were not traversed. If it was a namespace or TU (top-level lambda) they were traversed as part of that DeclContext traversal. r351069 "fixed" RAV to traverse these as part of the LambdaExpr, which is the right place. But top-level lambdas are now traversed twice. We fix that as blocks and block captures were apparently fixed in the past. Maybe it would be nicer to avoid adding the lambda classes to the DeclContext in the first place, but I can't work out the implications of that. Reviewers: bkramer, klimek Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D56665 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@351075 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h index 96f3d24c6d..44aba63557 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -1368,9 +1368,14 @@ DEF_TRAVERSE_TYPELOC(PipeType, { TRY_TO(TraverseTypeLoc(TL.getValueLoc())); }) template bool RecursiveASTVisitor::canIgnoreChildDeclWhileTraversingDeclContext( const Decl *Child) { - // BlockDecls and CapturedDecls are traversed through BlockExprs and - // CapturedStmts respectively. - return isa(Child) || isa(Child); + // BlockDecls are traversed through BlockExprs, + // CapturedDecls are traversed through CapturedStmts. + if (isa(Child) || isa(Child)) + return true; + // Lambda classes are traversed through LambdaExprs. + if (const CXXRecordDecl* Cls = dyn_cast(Child)) + return Cls->isLambda(); + return false; } template diff --git a/unittests/Tooling/RecursiveASTVisitorTests/LambdaExpr.cpp b/unittests/Tooling/RecursiveASTVisitorTests/LambdaExpr.cpp index a965632153..d3a3eba15d 100644 --- a/unittests/Tooling/RecursiveASTVisitorTests/LambdaExpr.cpp +++ b/unittests/Tooling/RecursiveASTVisitorTests/LambdaExpr.cpp @@ -65,6 +65,17 @@ TEST(RecursiveASTVisitor, LambdaInLambda) { 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;