Issue 182691
Summary Wrong BindingDecl for PackIndexingExpr
Labels clang, c++26
Assignees
Reporter steakhal
    https://godbolt.org/z/M5qYzKrKW
```c++
template <class = void>
int templated_fn() {
    struct S { int a; };
    auto [... members] = S{12};
    return members...[0];
}

void repro() {
 templated_fn();
}
```

In the AST, there is the primary template for the function. That is followed by the `T=void` instantiation. Finally the function named `repro`.

Notice that the `DeclRefExpr` of the `PackIndexingExpr` of the template instantiation has the same `BindingDecl` pointer as is present in the primary template decl.
This seems to be a bug, as otherwise what would be the purpose of the `BindingDecl` inside the template instantiation?

Here is the AST part from the template instantiation:
```
|     |-DeclStmt 0x1d142688 <line:4:5, col:31>
|     | `-DecompositionDecl 0x1d1421d8 <col:5, col:30> col:10 used 'S' cinit
|     | |-CXXFunctionalCastExpr 0x1d142450 <col:26, col:30> 'S' functional cast to S <NoOp>
|     |   | `-InitListExpr 0x1d1422d0 <col:27, col:30> 'S'
|     | |   `-IntegerLiteral 0x1d11cd30 <col:28> 'int' 12
|     |   `-BindingDecl 0x1d142188 <col:15> col:15 referenced members '<dependent type>...'
|     | `-FunctionParmPackExpr 0x1d142610 <col:15> '<dependent type>...' lvalue
| `-ReturnStmt 0x1d142740 <line:5:5, col:24>
|       `-ImplicitCastExpr 0x1d142728 <col:12, col:24> 'int' <LValueToRValue>
| `-PackIndexingExpr 0x1d1426f8 <col:12, col:24> 'int' lvalue
| |-DeclRefExpr 0x1d11ce08 <col:12> '<dependent type>' lvalue Binding 0x1d11cc18 'members' '<dependent type>...' <--- this should be 0x1d142188
| `-ConstantExpr 0x1d1426d8 <col:23> '__size_t':'unsigned long'
```

Here is the full AST dump from compiler explorer:
```
|-FunctionTemplateDecl 0x1d11c7e0 <<source>:1:1, line:6:1> line:2:5 templated_fn
| |-TemplateTypeParmDecl 0x1d11c5e0 <line:1:11, col:19> col:17 class depth 0 index 0
| | `-TemplateArgument type 'void'
| | `-BuiltinType 0x1d0c3fe0 'void'
| |-FunctionDecl 0x1d11c730 <line:2:1, line:6:1> line:2:5 templated_fn 'int ()'
| | `-CompoundStmt 0x1d11ceb8 <col:20, line:6:1>
| |   |-DeclStmt 0x1d11cb78 <line:3:5, col:24>
| |   | `-CXXRecordDecl 0x1d11c910 <col:5, col:23> col:12 referenced struct S definition
| |   |   |-DefinitionData aggregate standard_layout trivially_copyable pod trivial literal has_constexpr_non_copy_move_ctor
| | |   | |-DefaultConstructor exists trivial constexpr needs_implicit defaulted_is_constexpr
| |   |   | |-CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param
| |   |   | |-MoveConstructor exists simple trivial needs_implicit
| |   |   | |-CopyAssignment simple trivial has_const_param needs_implicit implicit_has_const_param
| |   |   | |-MoveAssignment exists simple trivial needs_implicit
| |   |   | `-Destructor simple irrelevant trivial constexpr needs_implicit
| |   |   |-CXXRecordDecl 0x1d11ca28 <col:5, col:12> col:12 implicit struct S
| |   |   `-FieldDecl 0x1d11caf0 <col:16, col:20> col:20 a 'int'
| |   |-DeclStmt 0x1d11cdf0 <line:4:5, col:31>
| |   | `-DecompositionDecl 0x1d11cc68 <col:5, col:30> col:10 'auto' cinit
| |   | |-CXXUnresolvedConstructExpr 0x1d11cd98 <col:26, col:30> 'S' 'S' list
| | |   | `-InitListExpr 0x1d11cd50 <col:27, col:30> 'void'
| |   |   | `-IntegerLiteral 0x1d11cd30 <col:28> 'int' 12
| |   |   `-BindingDecl 0x1d11cc18 <col:15> col:15 referenced members '<dependent type>...'
| | `-ReturnStmt 0x1d11cea8 <line:5:5, col:24>
| |     `-PackIndexingExpr 0x1d11ce80 <col:12, col:24> '<dependent type>' lvalue
| | |-DeclRefExpr 0x1d11ce08 <col:12> '<dependent type>' lvalue Binding 0x1d11cc18 'members' '<dependent type>...'
| |       `-ConstantExpr 0x1d11ce60 <col:23> '__size_t':'unsigned long'
| |         |-value: Int 0
| |         `-ImplicitCastExpr 0x1d11ce48 <col:23> '__size_t':'unsigned long' <IntegralCast>
| |           `-IntegerLiteral 0x1d11ce28 <col:23> 'int' 0
| `-FunctionDecl 0x1d11d0a8 <line:2:1, line:6:1> line:2:5 used templated_fn 'int ()' implicit_instantiation instantiated_from 0x1d11c730
| |-TemplateArgument type 'void'
|   | `-BuiltinType 0x1d0c3fe0 'void'
| `-CompoundStmt 0x1d142750 <col:20, line:6:1>
|     |-DeclStmt 0x1d142168 <line:3:5, col:24>
|     | `-CXXRecordDecl 0x1d11d290 <col:5, col:23> col:12 struct S definition instantiated_from 0x1d11c910
|     |   |-DefinitionData pass_in_registers aggregate standard_layout trivially_copyable pod trivial literal has_constexpr_non_copy_move_ctor
|     |   | |-DefaultConstructor exists trivial constexpr needs_implicit defaulted_is_constexpr
|     |   | |-CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param
|     |   | |-MoveConstructor exists simple trivial needs_implicit
|     |   | |-CopyAssignment simple trivial has_const_param needs_implicit implicit_has_const_param
|     |   | |-MoveAssignment exists simple trivial needs_implicit
|     |   | `-Destructor simple irrelevant trivial constexpr
|     |   |-CXXRecordDecl 0x1d142028 <col:5, col:12> col:12 implicit struct S
|     |   |-FieldDecl 0x1d1420d8 <col:16, col:20> col:20 referenced a 'int'
|     |   `-CXXDestructorDecl 0x1d142320 <col:12> col:12 implicit referenced constexpr ~S 'void () noexcept' inline default trivial
|     |-DeclStmt 0x1d142688 <line:4:5, col:31>
|     | `-DecompositionDecl 0x1d1421d8 <col:5, col:30> col:10 used 'S' cinit
|     | |-CXXFunctionalCastExpr 0x1d142450 <col:26, col:30> 'S' functional cast to S <NoOp>
|     |   | `-InitListExpr 0x1d1422d0 <col:27, col:30> 'S'
|     | |   `-IntegerLiteral 0x1d11cd30 <col:28> 'int' 12
|     |   `-BindingDecl 0x1d142188 <col:15> col:15 referenced members '<dependent type>...'
|     | `-FunctionParmPackExpr 0x1d142610 <col:15> '<dependent type>...' lvalue
| `-ReturnStmt 0x1d142740 <line:5:5, col:24>
|       `-ImplicitCastExpr 0x1d142728 <col:12, col:24> 'int' <LValueToRValue>
| `-PackIndexingExpr 0x1d1426f8 <col:12, col:24> 'int' lvalue
| |-DeclRefExpr 0x1d11ce08 <col:12> '<dependent type>' lvalue Binding 0x1d11cc18 'members' '<dependent type>...'
|           `-ConstantExpr 0x1d1426d8 <col:23> '__size_t':'unsigned long'
|             |-value: Int 0
|             `-ImplicitCastExpr 0x1d1426c0 <col:23> '__size_t':'unsigned long' <IntegralCast>
|               `-IntegerLiteral 0x1d11ce28 <col:23> 'int' 0
`-FunctionDecl 0x1d11cf58 <line:8:1, line:10:1> line:8:6 repro 'void ()'
  `-CompoundStmt 0x1d11d270 <col:14, line:10:1>
    `-CallExpr 0x1d11d248 <line:9:5, col:18> 'int'
      `-ImplicitCastExpr 0x1d11d230 <col:5> 'int (*)()' <FunctionToPointerDecay>
        `-DeclRefExpr 0x1d11d1d0 <col:5> 'int ()' lvalue Function 0x1d11d0a8 'templated_fn' 'int ()' (FunctionTemplate 0x1d11c7e0 'templated_fn')
```

PS: I've noticed this while implementing structured binding pack indexing for the Clang Static Analyzer.
_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to