[llvm-branch-commits] [clang] c3a21e5 - [ASTMatchers] Ensure that we can match inside lambdas
Alexander Kornienko via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Thu Jan 28 04:44:25 PST 2021
Thanks for the prompt response!
On Thu, Jan 28, 2021 at 12:52 AM Stephen Kelly <steveire at gmail.com> wrote:
>
> Thanks for reporting. Please try https://reviews.llvm.org/D95573
>
> Thanks,
>
> Stephen.
> On 27/01/2021 22:58, Alexander Kornienko wrote:
>
> This patch causes practically infinite traversal times on code that
> contains deeply nested lambdas. Please fix or revert the commit.
>
> There's a very simple test case (add more nesting, if it's still fast ;):
>
> void f() {
> [] {
> [] {
> [] {
> [] {
> [] {
> [] {
> [] {
> [] {
> [] {
> [] {
> [] {
> [] {
> [] {
> [] {
> [] {
> [] {
> [] {
> [] {
> [] {
> [] {
> [] {
> [] {
> [] {
> [] {
> [] {
> [] {
> [] {
> [] {
> [] {
> }();
> }();
> }();
> }();
> }();
> }();
> }();
> }();
> }();
> }();
> }();
> }();
> }();
> }();
> }();
> }();
> }();
> }();
> }();
> }();
> }();
> }();
> }();
> }();
> }();
> }();
> }();
> }();
> }();
> }
>
> Three nested lambdas are enough to demonstrate the issue by looking at the
> AST dump. The body of the innermost lambda (0x45593fda99a0) is printed 8
> times, and it will be traversed 8 times as well by AST matchers:
> `-FunctionDecl 0x45593fda9198 </tmp/nested-lambdas.cc:1:1, line:8:1>
> line:1:6 f 'void ()'
> `-CompoundStmt 0x45593fdce970 <col:10, line:8:1>
> `-ExprWithCleanups 0x45593fdce958 <line:2:3, line:7:5> 'void':'void'
> `-CXXOperatorCallExpr 0x45593fdce928 <line:2:3, line:7:5>
> 'void':'void' '()'
> |-ImplicitCastExpr 0x45593fdce8b0 <col:4, col:5> 'auto (*)() const
> -> void' <FunctionToPointerDecay>
> | `-DeclRefExpr 0x45593fdce890 <col:4, col:5> 'auto () const ->
> void' lvalue CXXMethod 0x45593fda9490 'operator()' 'auto () const -> void'
> `-ImplicitCastExpr 0x45593fdce910 <line:2:3, line:7:3> 'const
> (lambda at /tmp/nested-lambdas.cc:2:3)' lvalue <NoOp>
> `-MaterializeTemporaryExpr 0x45593fdce8f8 <line:2:3, line:7:3>
> '(lambda at /tmp/nested-lambdas.cc:2:3)' lvalue
> `-LambdaExpr 0x45593fdce788 <line:2:3, line:7:3> '(lambda at
> /tmp/nested-lambdas.cc:2:3)'
> |-CXXRecordDecl 0x45593fda9350 <line:2:3> col:3 implicit
> class definition
> | |-DefinitionData lambda pass_in_registers empty
> standard_layout trivially_copyable literal can_const_default_init
> | | |-DefaultConstructor defaulted_is_constexpr
> | | |-CopyConstructor simple trivial has_const_param
> needs_implicit implicit_has_const_param
> | | |-MoveConstructor exists simple trivial needs_implicit
> | | |-CopyAssignment trivial has_const_param needs_implicit
> implicit_has_const_param
> | | |-MoveAssignment
> | | `-Destructor simple irrelevant trivial
> | |-CXXMethodDecl 0x45593fda9490 <col:4, line:7:3> line:2:3
> used constexpr operator() 'auto () const -> void' inline
> | | `-CompoundStmt 0x45593fdce4e0 <col:6, line:7:3>
> | | `-ExprWithCleanups 0x45593fdce4c8 <line:3:3, line:6:5>
> 'void':'void'
> | | `-CXXOperatorCallExpr 0x45593fdce498 <line:3:3,
> line:6:5> 'void':'void' '()'
> | | |-ImplicitCastExpr 0x45593fdce420 <col:4, col:5>
> 'auto (*)() const -> void' <FunctionToPointerDecay>
> | | | `-DeclRefExpr 0x45593fdce400 <col:4, col:5>
> 'auto () const -> void' lvalue CXXMethod 0x45593fda96c0 'operator()' 'auto
> () const -> void'
> | | `-ImplicitCastExpr 0x45593fdce480 <line:3:3,
> line:6:3> 'const (lambda at /tmp/nested-lambdas.cc:3:3)' lvalue <NoOp>
> | | `-MaterializeTemporaryExpr 0x45593fdce468
> <line:3:3, line:6:3> '(lambda at /tmp/nested-lambdas.cc:3:3)' lvalue
> | | `-LambdaExpr 0x45593fdce2f0 <line:3:3,
> line:6:3> '(lambda at /tmp/nested-lambdas.cc:3:3)'
> | | |-CXXRecordDecl 0x45593fda9588 <line:3:3>
> col:3 implicit class definition
> | | | |-DefinitionData lambda pass_in_registers
> empty standard_layout trivially_copyable literal can_const_default_init
> | | | | |-DefaultConstructor
> defaulted_is_constexpr
> | | | | |-CopyConstructor simple trivial
> has_const_param needs_implicit implicit_has_const_param
> | | | | |-MoveConstructor exists simple trivial
> needs_implicit
> | | | | |-CopyAssignment trivial has_const_param
> needs_implicit implicit_has_const_param
> | | | | |-MoveAssignment
> | | | | `-Destructor simple irrelevant trivial
> | | | |-CXXMethodDecl 0x45593fda96c0 <col:4,
> line:6:3> line:3:3 used constexpr operator() 'auto () const -> void' inline
> | | | | `-CompoundStmt 0x45593fdce048 <col:6,
> line:6:3>
> | | | | `-ExprWithCleanups 0x45593fdce030
> <line:4:3, line:5:5> 'void':'void'
> | | | | `-CXXOperatorCallExpr 0x45593fdce000
> <line:4:3, line:5:5> 'void':'void' '()'
> | | | | |-ImplicitCastExpr 0x45593fda9f88
> <col:4, col:5> 'auto (*)() const -> void' <FunctionToPointerDecay>
> | | | | | `-DeclRefExpr 0x45593fda9f08
> <col:4, col:5> 'auto () const -> void' lvalue CXXMethod 0x45593fda98f0
> 'operator()' 'auto () const -> void'
> | | | | `-ImplicitCastExpr 0x45593fda9fe0
> <line:4:3, line:5:3> 'const (lambda at /tmp/nested-lambdas.cc:4:3)' lvalue
> <NoOp>
> | | | | `-MaterializeTemporaryExpr
> 0x45593fda9fc8 <line:4:3, line:5:3> '(lambda at
> /tmp/nested-lambdas.cc:4:3)' lvalue
> | | | | `-LambdaExpr 0x45593fda9dd0
> <line:4:3, line:5:3> '(lambda at /tmp/nested-lambdas.cc:4:3)'
> | | | | |-CXXRecordDecl
> 0x45593fda97b8 <line:4:3> col:3 implicit class definition
> | | | | | |-DefinitionData lambda
> pass_in_registers empty standard_layout trivially_copyable literal
> can_const_default_init
> | | | | | | |-DefaultConstructor
> defaulted_is_constexpr
> | | | | | | |-CopyConstructor simple
> trivial has_const_param needs_implicit implicit_has_const_param
> | | | | | | |-MoveConstructor exists
> simple trivial needs_implicit
> | | | | | | |-CopyAssignment trivial
> has_const_param needs_implicit implicit_has_const_param
> | | | | | | |-MoveAssignment
> | | | | | | `-Destructor simple
> irrelevant trivial
> | | | | | |-CXXMethodDecl
> 0x45593fda98f0 <col:4, line:5:3> line:4:3 used constexpr operator() 'auto
> () const -> void' inline
> | | | | | | `-CompoundStmt
> 0x45593fda99a0 <col:6, line:5:3>
> | | | | | |-CXXConversionDecl
> 0x45593fda9c68 <line:4:3, line:5:3> line:4:3 implicit constexpr operator
> void (*)() 'auto (*() const noexcept)() -> void' inline
> | | | | | |-CXXMethodDecl
> 0x45593fda9d18 <col:3, line:5:3> line:4:3 implicit __invoke 'auto () ->
> void' static inline
> | | | | | `-CXXDestructorDecl
> 0x45593fda9df8 <col:3> col:3 implicit referenced ~ 'void () noexcept'
> inline default trivial
> | | | | `-CompoundStmt
> 0x45593fda99a0 <col:6, line:5:3>
> | | | |-CXXConversionDecl 0x45593fdce188
> <line:3:3, line:6:3> line:3:3 implicit constexpr operator void (*)() 'auto
> (*() const noexcept)() -> void' inline
> | | | |-CXXMethodDecl 0x45593fdce238 <col:3,
> line:6:3> line:3:3 implicit __invoke 'auto () -> void' static inline
> | | | `-CXXDestructorDecl 0x45593fdce318 <col:3>
> col:3 implicit referenced ~ 'void () noexcept' inline default trivial
> | | `-CompoundStmt 0x45593fdce048 <col:6,
> line:6:3>
> | | `-ExprWithCleanups 0x45593fdce030
> <line:4:3, line:5:5> 'void':'void'
> | | `-CXXOperatorCallExpr 0x45593fdce000
> <line:4:3, line:5:5> 'void':'void' '()'
> | | |-ImplicitCastExpr 0x45593fda9f88
> <col:4, col:5> 'auto (*)() const -> void' <FunctionToPointerDecay>
> | | | `-DeclRefExpr 0x45593fda9f08 <col:4,
> col:5> 'auto () const -> void' lvalue CXXMethod 0x45593fda98f0 'operator()'
> 'auto () const -> void'
> | | `-ImplicitCastExpr 0x45593fda9fe0
> <line:4:3, line:5:3> 'const (lambda at /tmp/nested-lambdas.cc:4:3)' lvalue
> <NoOp>
> | | `-MaterializeTemporaryExpr
> 0x45593fda9fc8 <line:4:3, line:5:3> '(lambda at
> /tmp/nested-lambdas.cc:4:3)' lvalue
> | | `-LambdaExpr 0x45593fda9dd0
> <line:4:3, line:5:3> '(lambda at /tmp/nested-lambdas.cc:4:3)'
> | | |-CXXRecordDecl 0x45593fda97b8
> <line:4:3> col:3 implicit class definition
> | | | |-DefinitionData lambda
> pass_in_registers empty standard_layout trivially_copyable literal
> can_const_default_init
> | | | | |-DefaultConstructor
> defaulted_is_constexpr
> | | | | |-CopyConstructor simple
> trivial has_const_param needs_implicit implicit_has_const_param
> | | | | |-MoveConstructor exists
> simple trivial needs_implicit
> | | | | |-CopyAssignment trivial
> has_const_param needs_implicit implicit_has_const_param
> | | | | |-MoveAssignment
> | | | | `-Destructor simple
> irrelevant trivial
> | | | |-CXXMethodDecl 0x45593fda98f0
> <col:4, line:5:3> line:4:3 used constexpr operator() 'auto () const ->
> void' inline
> | | | | `-CompoundStmt
> 0x45593fda99a0 <col:6, line:5:3>
> | | | |-CXXConversionDecl
> 0x45593fda9c68 <line:4:3, line:5:3> line:4:3 implicit constexpr operator
> void (*)() 'auto (*() const noexcept)() -> void' inline
> | | | |-CXXMethodDecl 0x45593fda9d18
> <col:3, line:5:3> line:4:3 implicit __invoke 'auto () -> void' static inline
> | | | `-CXXDestructorDecl
> 0x45593fda9df8 <col:3> col:3 implicit referenced ~ 'void () noexcept'
> inline default trivial
> | | `-CompoundStmt 0x45593fda99a0
> <col:6, line:5:3>
> | |-CXXConversionDecl 0x45593fdce620 <line:2:3, line:7:3>
> line:2:3 implicit constexpr operator void (*)() 'auto (*() const
> noexcept)() -> void' inline
> | |-CXXMethodDecl 0x45593fdce6d0 <col:3, line:7:3> line:2:3
> implicit __invoke 'auto () -> void' static inline
> | `-CXXDestructorDecl 0x45593fdce7b0 <col:3> col:3 implicit
> referenced ~ 'void () noexcept' inline default trivial
> `-CompoundStmt 0x45593fdce4e0 <col:6, line:7:3>
> `-ExprWithCleanups 0x45593fdce4c8 <line:3:3, line:6:5>
> 'void':'void'
> `-CXXOperatorCallExpr 0x45593fdce498 <line:3:3,
> line:6:5> 'void':'void' '()'
> |-ImplicitCastExpr 0x45593fdce420 <col:4, col:5> 'auto
> (*)() const -> void' <FunctionToPointerDecay>
> | `-DeclRefExpr 0x45593fdce400 <col:4, col:5> 'auto ()
> const -> void' lvalue CXXMethod 0x45593fda96c0 'operator()' 'auto () const
> -> void'
> `-ImplicitCastExpr 0x45593fdce480 <line:3:3, line:6:3>
> 'const (lambda at /tmp/nested-lambdas.cc:3:3)' lvalue <NoOp>
> `-MaterializeTemporaryExpr 0x45593fdce468 <line:3:3,
> line:6:3> '(lambda at /tmp/nested-lambdas.cc:3:3)' lvalue
> `-LambdaExpr 0x45593fdce2f0 <line:3:3, line:6:3>
> '(lambda at /tmp/nested-lambdas.cc:3:3)'
> |-CXXRecordDecl 0x45593fda9588 <line:3:3> col:3
> implicit class definition
> | |-DefinitionData lambda pass_in_registers
> empty standard_layout trivially_copyable literal can_const_default_init
> | | |-DefaultConstructor defaulted_is_constexpr
> | | |-CopyConstructor simple trivial
> has_const_param needs_implicit implicit_has_const_param
> | | |-MoveConstructor exists simple trivial
> needs_implicit
> | | |-CopyAssignment trivial has_const_param
> needs_implicit implicit_has_const_param
> | | |-MoveAssignment
> | | `-Destructor simple irrelevant trivial
> | |-CXXMethodDecl 0x45593fda96c0 <col:4,
> line:6:3> line:3:3 used constexpr operator() 'auto () const -> void' inline
> | | `-CompoundStmt 0x45593fdce048 <col:6,
> line:6:3>
> | | `-ExprWithCleanups 0x45593fdce030
> <line:4:3, line:5:5> 'void':'void'
> | | `-CXXOperatorCallExpr 0x45593fdce000
> <line:4:3, line:5:5> 'void':'void' '()'
> | | |-ImplicitCastExpr 0x45593fda9f88
> <col:4, col:5> 'auto (*)() const -> void' <FunctionToPointerDecay>
> | | | `-DeclRefExpr 0x45593fda9f08 <col:4,
> col:5> 'auto () const -> void' lvalue CXXMethod 0x45593fda98f0 'operator()'
> 'auto () const -> void'
> | | `-ImplicitCastExpr 0x45593fda9fe0
> <line:4:3, line:5:3> 'const (lambda at /tmp/nested-lambdas.cc:4:3)' lvalue
> <NoOp>
> | | `-MaterializeTemporaryExpr
> 0x45593fda9fc8 <line:4:3, line:5:3> '(lambda at
> /tmp/nested-lambdas.cc:4:3)' lvalue
> | | `-LambdaExpr 0x45593fda9dd0
> <line:4:3, line:5:3> '(lambda at /tmp/nested-lambdas.cc:4:3)'
> | | |-CXXRecordDecl 0x45593fda97b8
> <line:4:3> col:3 implicit class definition
> | | | |-DefinitionData lambda
> pass_in_registers empty standard_layout trivially_copyable literal
> can_const_default_init
> | | | | |-DefaultConstructor
> defaulted_is_constexpr
> | | | | |-CopyConstructor simple
> trivial has_const_param needs_implicit implicit_has_const_param
> | | | | |-MoveConstructor exists
> simple trivial needs_implicit
> | | | | |-CopyAssignment trivial
> has_const_param needs_implicit implicit_has_const_param
> | | | | |-MoveAssignment
> | | | | `-Destructor simple
> irrelevant trivial
> | | | |-CXXMethodDecl 0x45593fda98f0
> <col:4, line:5:3> line:4:3 used constexpr operator() 'auto () const ->
> void' inline
> | | | | `-CompoundStmt
> 0x45593fda99a0 <col:6, line:5:3>
> | | | |-CXXConversionDecl
> 0x45593fda9c68 <line:4:3, line:5:3> line:4:3 implicit constexpr operator
> void (*)() 'auto (*() const noexcept)() -> void' inline
> | | | |-CXXMethodDecl 0x45593fda9d18
> <col:3, line:5:3> line:4:3 implicit __invoke 'auto () -> void' static inline
> | | | `-CXXDestructorDecl
> 0x45593fda9df8 <col:3> col:3 implicit referenced ~ 'void () noexcept'
> inline default trivial
> | | `-CompoundStmt 0x45593fda99a0
> <col:6, line:5:3>
> | |-CXXConversionDecl 0x45593fdce188 <line:3:3,
> line:6:3> line:3:3 implicit constexpr operator void (*)() 'auto (*() const
> noexcept)() -> void' inline
> | |-CXXMethodDecl 0x45593fdce238 <col:3,
> line:6:3> line:3:3 implicit __invoke 'auto () -> void' static inline
> | `-CXXDestructorDecl 0x45593fdce318 <col:3>
> col:3 implicit referenced ~ 'void () noexcept' inline default trivial
> `-CompoundStmt 0x45593fdce048 <col:6, line:6:3>
> `-ExprWithCleanups 0x45593fdce030 <line:4:3,
> line:5:5> 'void':'void'
> `-CXXOperatorCallExpr 0x45593fdce000
> <line:4:3, line:5:5> 'void':'void' '()'
> |-ImplicitCastExpr 0x45593fda9f88 <col:4,
> col:5> 'auto (*)() const -> void' <FunctionToPointerDecay>
> | `-DeclRefExpr 0x45593fda9f08 <col:4,
> col:5> 'auto () const -> void' lvalue CXXMethod 0x45593fda98f0 'operator()'
> 'auto () const -> void'
> `-ImplicitCastExpr 0x45593fda9fe0
> <line:4:3, line:5:3> 'const (lambda at /tmp/nested-lambdas.cc:4:3)' lvalue
> <NoOp>
> `-MaterializeTemporaryExpr
> 0x45593fda9fc8 <line:4:3, line:5:3> '(lambda at
> /tmp/nested-lambdas.cc:4:3)' lvalue
> `-LambdaExpr 0x45593fda9dd0 <line:4:3,
> line:5:3> '(lambda at /tmp/nested-lambdas.cc:4:3)'
> |-CXXRecordDecl 0x45593fda97b8
> <line:4:3> col:3 implicit class definition
> | |-DefinitionData lambda
> pass_in_registers empty standard_layout trivially_copyable literal
> can_const_default_init
> | | |-DefaultConstructor
> defaulted_is_constexpr
> | | |-CopyConstructor simple trivial
> has_const_param needs_implicit implicit_has_const_param
> | | |-MoveConstructor exists simple
> trivial needs_implicit
> | | |-CopyAssignment trivial
> has_const_param needs_implicit implicit_has_const_param
> | | |-MoveAssignment
> | | `-Destructor simple irrelevant
> trivial
> | |-CXXMethodDecl 0x45593fda98f0
> <col:4, line:5:3> line:4:3 used constexpr operator() 'auto () const ->
> void' inline
> | | `-CompoundStmt 0x45593fda99a0
> <col:6, line:5:3>
> | |-CXXConversionDecl 0x45593fda9c68
> <line:4:3, line:5:3> line:4:3 implicit constexpr operator void (*)() 'auto
> (*() const noexcept)() -> void' inline
> | |-CXXMethodDecl 0x45593fda9d18
> <col:3, line:5:3> line:4:3 implicit __invoke 'auto () -> void' static inline
> | `-CXXDestructorDecl 0x45593fda9df8
> <col:3> col:3 implicit referenced ~ 'void () noexcept' inline default
> trivial
> `-CompoundStmt 0x45593fda99a0
> <col:6, line:5:3>
>
>
> On Tue, Jan 5, 2021 at 3:45 PM Stephen Kelly via llvm-branch-commits <
> llvm-branch-commits at lists.llvm.org> wrote:
>
>>
>> Author: Stephen Kelly
>> Date: 2021-01-05T14:39:46Z
>> New Revision: c3a21e5de3dc3f55e4d219afd55dec518159d356
>>
>> URL:
>> https://github.com/llvm/llvm-project/commit/c3a21e5de3dc3f55e4d219afd55dec518159d356
>> DIFF:
>> https://github.com/llvm/llvm-project/commit/c3a21e5de3dc3f55e4d219afd55dec518159d356.diff
>>
>> LOG: [ASTMatchers] Ensure that we can match inside lambdas
>>
>> Because we don't know in ASTMatchFinder whether we're matching in AsIs
>> or IgnoreUnlessSpelledInSource mode, we need to traverse the lambda
>> twice, but store whether we're matching in nodes spelled in source or
>> not.
>>
>> Differential Revision: https://reviews.llvm.org/D93688
>>
>> Added:
>>
>>
>> Modified:
>> clang/include/clang/ASTMatchers/ASTMatchersInternal.h
>> clang/lib/ASTMatchers/ASTMatchFinder.cpp
>> clang/lib/ASTMatchers/ASTMatchersInternal.cpp
>> clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
>>
>> Removed:
>>
>>
>>
>>
>> ################################################################################
>> diff --git a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
>> b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
>> index 46de4093272d..f49728d1f50e 100644
>> --- a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
>> +++ b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
>> @@ -723,6 +723,8 @@ class ASTMatchFinder {
>>
>> virtual bool IsMatchingInASTNodeNotSpelledInSource() const = 0;
>>
>> + virtual bool IsMatchingInASTNodeNotAsIs() const = 0;
>> +
>> bool isTraversalIgnoringImplicitNodes() const;
>>
>> protected:
>>
>> diff --git a/clang/lib/ASTMatchers/ASTMatchFinder.cpp
>> b/clang/lib/ASTMatchers/ASTMatchFinder.cpp
>> index 762885fa0052..af21e2283d8b 100644
>> --- a/clang/lib/ASTMatchers/ASTMatchFinder.cpp
>> +++ b/clang/lib/ASTMatchers/ASTMatchFinder.cpp
>> @@ -475,6 +475,55 @@ class MatchASTVisitor : public
>> RecursiveASTVisitor<MatchASTVisitor>,
>> }
>> }
>> return true;
>> + } else if (auto *LE = dyn_cast<LambdaExpr>(S)) {
>> + for (auto I : llvm::zip(LE->captures(), LE->capture_inits())) {
>> + auto C = std::get<0>(I);
>> + ASTNodeNotSpelledInSourceScope RAII(
>> + this, TraversingASTNodeNotSpelledInSource ||
>> !C.isExplicit());
>> + TraverseLambdaCapture(LE, &C, std::get<1>(I));
>> + }
>> +
>> + {
>> + ASTNodeNotSpelledInSourceScope RAII(this, true);
>> + TraverseDecl(LE->getLambdaClass());
>>
>
> The line above triggers an additional traversal of all nested lambdas,
> leading to exponential time growth.
>
> + }
>> + {
>> + ASTNodeNotAsIsSourceScope RAII(this, true);
>> +
>> + // We need to poke around to find the bits that might be
>> explicitly
>> + // written.
>> + TypeLoc TL =
>> LE->getCallOperator()->getTypeSourceInfo()->getTypeLoc();
>> + FunctionProtoTypeLoc Proto =
>> TL.getAsAdjusted<FunctionProtoTypeLoc>();
>> +
>> + if (auto *TPL = LE->getTemplateParameterList()) {
>> + for (NamedDecl *D : *TPL) {
>> + TraverseDecl(D);
>> + }
>> + if (Expr *RequiresClause = TPL->getRequiresClause()) {
>> + TraverseStmt(RequiresClause);
>> + }
>> + }
>> +
>> + if (LE->hasExplicitParameters()) {
>> + // Visit parameters.
>> + for (ParmVarDecl *Param : Proto.getParams())
>> + TraverseDecl(Param);
>> + }
>> +
>> + const auto *T = Proto.getTypePtr();
>> + for (const auto &E : T->exceptions())
>> + TraverseType(E);
>> +
>> + if (Expr *NE = T->getNoexceptExpr())
>> + TraverseStmt(NE, Queue);
>> +
>> + if (LE->hasExplicitResultType())
>> + TraverseTypeLoc(Proto.getReturnLoc());
>> + TraverseStmt(LE->getTrailingRequiresClause());
>> +
>> + TraverseStmt(LE->getBody());
>> + }
>> + return true;
>> }
>> return RecursiveASTVisitor<MatchASTVisitor>::dataTraverseNode(S,
>> Queue);
>> }
>> @@ -617,6 +666,9 @@ class MatchASTVisitor : public
>> RecursiveASTVisitor<MatchASTVisitor>,
>> bool IsMatchingInASTNodeNotSpelledInSource() const override {
>> return TraversingASTNodeNotSpelledInSource;
>> }
>> + bool IsMatchingInASTNodeNotAsIs() const override {
>> + return TraversingASTNodeNotAsIs;
>> + }
>>
>> bool TraverseTemplateInstantiations(ClassTemplateDecl *D) {
>> ASTNodeNotSpelledInSourceScope RAII(this, true);
>> @@ -638,6 +690,7 @@ class MatchASTVisitor : public
>> RecursiveASTVisitor<MatchASTVisitor>,
>>
>> private:
>> bool TraversingASTNodeNotSpelledInSource = false;
>> + bool TraversingASTNodeNotAsIs = false;
>> bool TraversingASTChildrenNotSpelledInSource = false;
>>
>> struct ASTNodeNotSpelledInSourceScope {
>> @@ -654,6 +707,18 @@ class MatchASTVisitor : public
>> RecursiveASTVisitor<MatchASTVisitor>,
>> bool MB;
>> };
>>
>> + struct ASTNodeNotAsIsSourceScope {
>> + ASTNodeNotAsIsSourceScope(MatchASTVisitor *V, bool B)
>> + : MV(V), MB(V->TraversingASTNodeNotAsIs) {
>> + V->TraversingASTNodeNotAsIs = B;
>> + }
>> + ~ASTNodeNotAsIsSourceScope() { MV->TraversingASTNodeNotAsIs = MB; }
>> +
>> + private:
>> + MatchASTVisitor *MV;
>> + bool MB;
>> + };
>> +
>> struct ASTChildrenNotSpelledInSource {
>> ASTChildrenNotSpelledInSource(MatchASTVisitor *V, bool B)
>> : MV(V), MB(V->TraversingASTChildrenNotSpelledInSource) {
>>
>> diff --git a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
>> b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
>> index 3c19bceb079e..eb0fffcc3c37 100644
>> --- a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
>> +++ b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
>> @@ -293,6 +293,10 @@ bool DynTypedMatcher::matches(const DynTypedNode
>> &DynNode,
>> Finder->IsMatchingInASTNodeNotSpelledInSource())
>> return false;
>>
>> + if (!Finder->isTraversalIgnoringImplicitNodes() &&
>> + Finder->IsMatchingInASTNodeNotAsIs())
>> + return false;
>> +
>> auto N =
>>
>> Finder->getASTContext().getParentMapContext().traverseIgnored(DynNode);
>>
>> @@ -317,6 +321,10 @@ bool DynTypedMatcher::matchesNoKindCheck(const
>> DynTypedNode &DynNode,
>> Finder->IsMatchingInASTNodeNotSpelledInSource())
>> return false;
>>
>> + if (!Finder->isTraversalIgnoringImplicitNodes() &&
>> + Finder->IsMatchingInASTNodeNotAsIs())
>> + return false;
>> +
>> auto N =
>>
>> Finder->getASTContext().getParentMapContext().traverseIgnored(DynNode);
>>
>>
>> diff --git a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
>> b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
>> index a3a3a911b85c..1dc5179ce857 100644
>> --- a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
>> +++ b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
>> @@ -3065,6 +3065,33 @@ void func14() {
>> traverse(TK_IgnoreUnlessSpelledInSource,
>> functionDecl(hasName("func14"),
>> hasDescendant(floatLiteral()))),
>> langCxx20OrLater()));
>> +
>> + Code = R"cpp(
>> +void foo() {
>> + int explicit_captured = 0;
>> + int implicit_captured = 0;
>> + auto l = [&, explicit_captured](int i) {
>> + if (i || explicit_captured || implicit_captured) return;
>> + };
>> +}
>> +)cpp";
>> +
>> + EXPECT_TRUE(matches(Code, traverse(TK_AsIs, ifStmt())));
>> + EXPECT_TRUE(
>> + matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, ifStmt())));
>> +
>> + auto lambdaExplicitCapture = declRefExpr(
>> + to(varDecl(hasName("explicit_captured"))),
>> unless(hasAncestor(ifStmt())));
>> + auto lambdaImplicitCapture = declRefExpr(
>> + to(varDecl(hasName("implicit_captured"))),
>> unless(hasAncestor(ifStmt())));
>> +
>> + EXPECT_TRUE(matches(Code, traverse(TK_AsIs, lambdaExplicitCapture)));
>> + EXPECT_TRUE(matches(
>> + Code, traverse(TK_IgnoreUnlessSpelledInSource,
>> lambdaExplicitCapture)));
>> +
>> + EXPECT_TRUE(matches(Code, traverse(TK_AsIs, lambdaImplicitCapture)));
>> + EXPECT_FALSE(matches(
>> + Code, traverse(TK_IgnoreUnlessSpelledInSource,
>> lambdaImplicitCapture)));
>> }
>>
>> TEST(IgnoringImpCasts, MatchesImpCasts) {
>>
>>
>>
>> _______________________________________________
>> llvm-branch-commits mailing list
>> llvm-branch-commits at lists.llvm.org
>> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-branch-commits/attachments/20210128/beb98357/attachment-0001.html>
More information about the llvm-branch-commits
mailing list