<feed xmlns='http://www.w3.org/2005/Atom'>
<title>llvm-project.git/lldb/test/API/lang/cpp/structured-binding/main.cpp, branch main</title>
<subtitle>Unnamed repository; edit this file 'description' to name the repository.
</subtitle>
<link rel='alternate' type='text/html' href='https://git.belthelziquor.com/llvm-project.git/'/>
<entry>
<title>[clang][Expr] Teach IgnoreUnlessSpelledInSource about implicit calls to std::get free function (#122265)</title>
<updated>2025-09-20T17:30:18+00:00</updated>
<author>
<name>Michael Buch</name>
<email>michaelbuch12@gmail.com</email>
</author>
<published>2025-09-20T17:30:18+00:00</published>
<link rel='alternate' type='text/html' href='https://git.belthelziquor.com/llvm-project.git/commit/?id=012680faf4c63a9bd432aa92fa0da97981793ac3'/>
<id>012680faf4c63a9bd432aa92fa0da97981793ac3</id>
<content type='text'>
When we generate the debug-info for a `VarDecl` we try to determine
whether it was introduced as part of a structure binding (aka a "holding
var"). If it was then we don't mark it as `artificial`.

The heuristic to determine a holding var uses
`IgnoreUnlessSpelledInSource` to unwrap the `VarDecl` initializer until
we hit a `DeclRefExpr` that refers to a `Decomposition`. For "tuple-like
decompositions", Clang will generate a call to a `template&lt;size_t I&gt; Foo
get(Bar)` function that retrieves the `Ith` element from the tuple-like
structure. If that function is a member function, we get an AST that
looks as follows:
```
VarDecl implicit used z1 'std::tuple_element&lt;0, B&gt;::type &amp;&amp;' cinit
`-ExprWithCleanups &lt;col:10&gt; 'int' xvalue
  `-MaterializeTemporaryExpr &lt;col:10&gt; 'int' xvalue extended by Var 0x11d110cf8 'z1' 'std::tuple_element&lt;0, B&gt;::type &amp;&amp;'
    `-CXXMemberCallExpr &lt;col:10&gt; 'int'
      `-MemberExpr &lt;col:10&gt; '&lt;bound member function type&gt;' .get 0x11d104390
        `-ImplicitCastExpr &lt;col:10&gt; 'B' xvalue &lt;NoOp&gt;
          `-DeclRefExpr &lt;col:10&gt; 'B' lvalue Decomposition 0x11d1100a8 '' 'B'
```
`IgnoreUnlessSpelledInSource` happily unwraps this down to the
`DeclRefExpr`. However, when the `get` helper is a free function (which
it is for `std::pair` in libc++ for example), then the AST is:
```
VarDecl col:16 implicit used k 'std::tuple_element&lt;0, const std::tuple&lt;int, int&gt;&gt;::type &amp;' cinit
`-CallExpr &lt;col:16&gt; 'const typename tuple_element&lt;0UL, tuple&lt;int, int&gt;&gt;::type':'const int' lvalue adl
  |-ImplicitCastExpr &lt;col:16&gt; 'const typename tuple_element&lt;0UL, tuple&lt;int, int&gt;&gt;::type &amp;(*)(const tuple&lt;int, int&gt; &amp;) noexcept' &lt;FunctionToPointerDecay&gt;
  | `-DeclRefExpr &lt;col:16&gt; 'const typename tuple_element&lt;0UL, tuple&lt;int, int&gt;&gt;::type &amp;(const tuple&lt;int, int&gt; &amp;) noexcept' lvalue Function 0x1210262d8 'get' 'const typename tuple_element&lt;0UL, tuple&lt;int, int&gt;&gt;::type &amp;(const tuple&lt;int, int&gt; &amp;) noexcept' (FunctionTemplate 0x11d068088 'get')
  `-DeclRefExpr &lt;col:16&gt; 'const std::tuple&lt;int, int&gt;' lvalue Decomposition 0x121021518 '' 'const std::tuple&lt;int, int&gt; &amp;'
```
`IgnoreUnlessSpelledInSource` doesn't unwrap this `CallExpr`, so we
incorrectly mark the binding as `artificial` in debug-info.

This patch adjusts `IgnoreUnlessSpelledInSource` so it unwraps implicit
`CallExpr`s. It's almost identical to how we treat implicit constructor
calls (unfortunately the code can't quite be re-used because a
`CXXConstructExpr` is-not a `CallExpr`, and we check `isElidable`, which
doesn't exist for regular function calls. So I added a new
`IgnoreImplicitCallSingleStep`).

Fixes https://github.com/llvm/llvm-project/issues/122028</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
When we generate the debug-info for a `VarDecl` we try to determine
whether it was introduced as part of a structure binding (aka a "holding
var"). If it was then we don't mark it as `artificial`.

The heuristic to determine a holding var uses
`IgnoreUnlessSpelledInSource` to unwrap the `VarDecl` initializer until
we hit a `DeclRefExpr` that refers to a `Decomposition`. For "tuple-like
decompositions", Clang will generate a call to a `template&lt;size_t I&gt; Foo
get(Bar)` function that retrieves the `Ith` element from the tuple-like
structure. If that function is a member function, we get an AST that
looks as follows:
```
VarDecl implicit used z1 'std::tuple_element&lt;0, B&gt;::type &amp;&amp;' cinit
`-ExprWithCleanups &lt;col:10&gt; 'int' xvalue
  `-MaterializeTemporaryExpr &lt;col:10&gt; 'int' xvalue extended by Var 0x11d110cf8 'z1' 'std::tuple_element&lt;0, B&gt;::type &amp;&amp;'
    `-CXXMemberCallExpr &lt;col:10&gt; 'int'
      `-MemberExpr &lt;col:10&gt; '&lt;bound member function type&gt;' .get 0x11d104390
        `-ImplicitCastExpr &lt;col:10&gt; 'B' xvalue &lt;NoOp&gt;
          `-DeclRefExpr &lt;col:10&gt; 'B' lvalue Decomposition 0x11d1100a8 '' 'B'
```
`IgnoreUnlessSpelledInSource` happily unwraps this down to the
`DeclRefExpr`. However, when the `get` helper is a free function (which
it is for `std::pair` in libc++ for example), then the AST is:
```
VarDecl col:16 implicit used k 'std::tuple_element&lt;0, const std::tuple&lt;int, int&gt;&gt;::type &amp;' cinit
`-CallExpr &lt;col:16&gt; 'const typename tuple_element&lt;0UL, tuple&lt;int, int&gt;&gt;::type':'const int' lvalue adl
  |-ImplicitCastExpr &lt;col:16&gt; 'const typename tuple_element&lt;0UL, tuple&lt;int, int&gt;&gt;::type &amp;(*)(const tuple&lt;int, int&gt; &amp;) noexcept' &lt;FunctionToPointerDecay&gt;
  | `-DeclRefExpr &lt;col:16&gt; 'const typename tuple_element&lt;0UL, tuple&lt;int, int&gt;&gt;::type &amp;(const tuple&lt;int, int&gt; &amp;) noexcept' lvalue Function 0x1210262d8 'get' 'const typename tuple_element&lt;0UL, tuple&lt;int, int&gt;&gt;::type &amp;(const tuple&lt;int, int&gt; &amp;) noexcept' (FunctionTemplate 0x11d068088 'get')
  `-DeclRefExpr &lt;col:16&gt; 'const std::tuple&lt;int, int&gt;' lvalue Decomposition 0x121021518 '' 'const std::tuple&lt;int, int&gt; &amp;'
```
`IgnoreUnlessSpelledInSource` doesn't unwrap this `CallExpr`, so we
incorrectly mark the binding as `artificial` in debug-info.

This patch adjusts `IgnoreUnlessSpelledInSource` so it unwraps implicit
`CallExpr`s. It's almost identical to how we treat implicit constructor
calls (unfortunately the code can't quite be re-used because a
`CXXConstructExpr` is-not a `CallExpr`, and we check `isElidable`, which
doesn't exist for regular function calls. So I added a new
`IgnoreImplicitCallSingleStep`).

Fixes https://github.com/llvm/llvm-project/issues/122028</pre>
</div>
</content>
</entry>
<entry>
<title>[DEBUGINFO] [LLDB] Add support for generating debug-info for structured bindings of structs and arrays</title>
<updated>2022-02-17T19:14:14+00:00</updated>
<author>
<name>Shafik Yaghmour</name>
<email>syaghmour@apple.com</email>
</author>
<published>2022-02-17T19:13:46+00:00</published>
<link rel='alternate' type='text/html' href='https://git.belthelziquor.com/llvm-project.git/commit/?id=f56cb520d8554ca42a215e82ecfa58d0b6c178e4'/>
<id>f56cb520d8554ca42a215e82ecfa58d0b6c178e4</id>
<content type='text'>
Currently we are not emitting debug-info for all cases of structured bindings a
C++17 feature which allows us to bind names to subobjects in an initializer.

A structured binding is represented by a DecompositionDecl AST node and the
binding are represented by a BindingDecl. It looks the original implementation
only covered the tuple like case which be represented by a DeclRefExpr which
contains a VarDecl.

If the binding is to a subobject of the struct the binding will contain a
MemberExpr and in the case of arrays it will contain an ArraySubscriptExpr.
This PR adds support emitting debug-info for the MemberExpr and ArraySubscriptExpr
cases as well as llvm and lldb tests for these cases as well as the tuple case.

Differential Revision: https://reviews.llvm.org/D119178
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Currently we are not emitting debug-info for all cases of structured bindings a
C++17 feature which allows us to bind names to subobjects in an initializer.

A structured binding is represented by a DecompositionDecl AST node and the
binding are represented by a BindingDecl. It looks the original implementation
only covered the tuple like case which be represented by a DeclRefExpr which
contains a VarDecl.

If the binding is to a subobject of the struct the binding will contain a
MemberExpr and in the case of arrays it will contain an ArraySubscriptExpr.
This PR adds support emitting debug-info for the MemberExpr and ArraySubscriptExpr
cases as well as llvm and lldb tests for these cases as well as the tuple case.

Differential Revision: https://reviews.llvm.org/D119178
</pre>
</div>
</content>
</entry>
</feed>
