[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