<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/142267>142267</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
clang-tidy always emits clang-analyzer-core.CallAndMessage warning for reference captured structured bindings in lambdas
</td>
</tr>
<tr>
<th>Labels</th>
<td>
clang-tidy
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
justusranvier
</td>
</tr>
</table>
<pre>
This is allowed by P1091R3 and implemented since #54300 however in every case I've found using these constructs clang-tidy emits uninitialized variable warnings.
code example:
```
#include <functional>
#include <list>
#include <map>
#include <string>
void maybe_consume(std::string const&, std::list<std::string>&);
void example()
{
auto var = std::map<std::string, std::list<std::string>>{};
for (auto i = var.begin(); i != var.end();) {
auto& [key, value] = *i;
auto p1091r3 = [&] { maybe_consume(key, value); };
std::invoke(p1091r3);
if (value.empty()) {
i = var.erase(i);
} else {
++i;
}
}
}
```
compiler output: https://godbolt.org/z/ns7Yc7GT8
clang-tidy command line: `clang-tidy --checks="clang-analyzer-*" --extra-arg="-std=c++20"`
clang-tidy output:
```
1 warning generated.
/home/user/src/examples/clang-analyzer-p1091r3.cpp:14:30: warning: 1st function call argument is an uninitialized value [clang-analyzer-core.CallAndMessage]
14 | auto p1091r3 = [&] { maybe_consume(key, value); };
| ^
/home/user/src/examples/clang-analyzer-p1091r3.cpp:12:5: note: Loop condition is true. Entering loop body
12 | for (auto i = var.begin(); i != var.end();) {
| ^
/home/user/src/examples/clang-analyzer-p1091r3.cpp:15:9: note: Calling 'invoke<(lambda at /home/user/src/examples/clang-analyzer-p1091r3.cpp:14:24) &, >'
15 | std::invoke(p1091r3);
| ^~~~~~~~~~~~~~~~~~~~
/usr/lib/gcc/powerpc64le-unknown-linux-gnu/15/include/g++-v15/functional:122:14: note: Calling '__invoke<(lambda at /home/user/src/examples/clang-analyzer-p1091r3.cpp:14:24) &, >'
122 | return std::__invoke(std::forward<_Callable>(__fn),
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
123 | std::forward<_Args>(__args)...);
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/lib/gcc/powerpc64le-unknown-linux-gnu/15/include/g++-v15/bits/invoke.h:98:14: note: Calling '__invoke_impl<void, (lambda at /home/user/src/examples/clang-analyzer-p1091r3.cpp:14:24) &, >'
98 | return std::__invoke_impl<__type>(__tag{}, std::forward<_Callable>(__fn),
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
99 | std::forward<_Args>(__args)...);
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/lib/gcc/powerpc64le-unknown-linux-gnu/15/include/g++-v15/bits/invoke.h:63:14: note: Calling 'operator()'
63 | { return std::forward<_Fn>(__f)(std::forward<_Args>(__args)...); }
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/user/src/examples/clang-analyzer-p1091r3.cpp:14:30: note: 1st function call argument is an uninitialized value
14 | auto p1091r3 = [&] { maybe_consume(key, value); };
| ^ ~~~
```
Switching from default capture to named capture does not help:
```
1 warning generated.
/home/user/src/examples/clang-analyzer-p1091r3.cpp:14:41: warning: 1st function call argument is an uninitialized value [clang-analyzer-core.CallAndMessage]
14 | auto p1091r3 = [&key, &value] { maybe_consume(key, value); };
| ^
/home/user/src/examples/clang-analyzer-p1091r3.cpp:12:5: note: Loop condition is true. Entering loop body
12 | for (auto i = var.begin(); i != var.end();) {
| ^
/home/user/src/examples/clang-analyzer-p1091r3.cpp:15:9: note: Calling 'invoke<(lambda at /home/user/src/examples/clang-analyzer-p1091r3.cpp:14:24) &, >'
15 | std::invoke(p1091r3);
| ^~~~~~~~~~~~~~~~~~~~
/usr/lib/gcc/powerpc64le-unknown-linux-gnu/15/include/g++-v15/functional:122:14: note: Calling '__invoke<(lambda at /home/user/src/examples/clang-analyzer-p1091r3.cpp:14:24) &, >'
122 | return std::__invoke(std::forward<_Callable>(__fn),
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
123 | std::forward<_Args>(__args)...);
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/lib/gcc/powerpc64le-unknown-linux-gnu/15/include/g++-v15/bits/invoke.h:98:14: note: Calling '__invoke_impl<void, (lambda at /home/user/src/examples/clang-analyzer-p1091r3.cpp:14:24) &, >'
98 | return std::__invoke_impl<__type>(__tag{}, std::forward<_Callable>(__fn),
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
99 | std::forward<_Args>(__args)...);
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/lib/gcc/powerpc64le-unknown-linux-gnu/15/include/g++-v15/bits/invoke.h:63:14: note: Calling 'operator()'
63 | { return std::forward<_Fn>(__f)(std::forward<_Args>(__args)...); }
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/user/src/examples/clang-analyzer-p1091r3.cpp:14:41: note: 1st function call argument is an uninitialized value
14 | auto p1091r3 = [&key, &value] { maybe_consume(key, value); };
| ^ ~~~
```
</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJzsWU2P4rgW_TVmcwVK7ISEBYsAxdOT3pNGM72ZFTLJJbjLsSPbgaYX89tHzgdQBVPV06JbvShUKqhc5_qecz98inBrRakQ5yRekHg14o3bazP_3FjXWMPVQaAZbXVxmn_aCwvCApdSH7GA7Ql-C4NZ-DsDrgoQVS2xQuWwACtUjkAoiyMWBLDXRzygAaHAv58g5xbhv4QmB4SdblQBjRWqBLdHi5BrZZ1pcmchl1yVYyeKE2AlnIVGCSWc4FJ8xQIO3Ai-lQhHbpRQpZ2QICNBlusCAb9wHxJhWXeRTIP-J8gIZULlsikQCFvuGpU7oRWXhD3dWKWw7t71itf3LltnhCp7S5AdtCig4qctbjyupkJCU-sKHxbLusUdYkKnhC7hbOv2Xb5a6x37hTPCFlc7DGBp6k1BRhJvBQDgjdOeKCBsdXHeBn_j-9u2Z0_ee7I6R-C32WkDhKbtbqLd68DNZIulUH1QbOENNBxsqIqzhdAZXEIewiZ0CiRePOPJR3bgskESr1rnhGai278DWPtKNKyzxQtPkV-ZLG64f-GtC-uM5YJeqIN-9st7x9eEDyGKnUfcOppgVbtTD-cGS7v4zAkabr1ncfY5rCHJClBavHM7oQtCF-Jmvf-re-t_Xxe5b4SqFhIN6MbVjSMsg71ztfUg6ZrQdamLrZZuok1J6PoroWtlkz_z5D-f0t7DpQNzXVW-06VQvquATIMr63ic7zF_toStCKWdgSsuT1_RjAnNCKUwHuMXZ_iYm7JbNm4JX-UdPBoQSi-xX3yfo7_t5HDofShRoeEOi3YI0PVe-3yvG4uG0LU1OaHrvk0soetXEfZ5nuR1TVgWRoRlLPAoe_f-Y2gdDLMCci4lcFM2fua1c1HdTCfZoK_GV1vl2uBkyaXMVPF_tJaXvqy7vIYRkGQJ113wqNruS2YJJH56AEOUsCz2rCjt2nL4n9a1n2SFaPkRFpxpcALwpBy2Y076Ff4s6bHSM9bHTo_HgfQAZ9cgfdo8FEKTfkSwJaGp5NW24MAdPKLwaNQi6s6DduAnPWPxi-p4f1q94OOv21dHUWN9oFJs_UDIfbi1PqKp82kkcdyoZ6WPaiyFar6MS9UQug5jQtf9oedv6vp3fGivXx-nWUjpAOseiZvNz6cxpF3hGXSNURcWz7FcHdA7bY7cFIQtNz5qLzZaT-lms1PtsF9-A83_9OrDYe2t9_bMTGmH_bj_TGeTyeROet_f6PF53gpnW7MnbbL3rZJ-S643XioStvTCpU3NT-ufWfpm4ofANht3qs95drzs9Q69n6S3CuPf18QblQKz2XdXyq9TJFP2VpHo2h_i2gxaqs_clJ0nnz_4Xmfwioi1OuehdXC3l99ia5BV39nTr_l8kAwZqPoeDfJCWvwoSXGtVqFH_1KM_nEULt_7PO-MrqDAHW-kg5zXrjEIToPiFRbnC4VG63HDHmX9s8VfFP6q4q_PCKHTy39EH1rwQwt-aMEPLfgLHfMfWvBDC35owZd8PkiV_Ggt-GiF8Y40HBVzVszYjI9wHiZROk1nScpG-3lCk5ixKZ-lKadJiFEeMs7S6S6dxozzaCTmNKBxELMwDINZxCZhlCRJHARBlG_pLI9JFGDFhZxIeagm2pQjYW2D8zCidJqMJN-itO2jj-ErSyeKE6GUxKuRmfu7xtumtCQKpLDOXvw44STOr76j5PLIT7Z_TPG-6DsrVy93DO7QoMpx0L4FdE9A2o9boQqhSgtCQTcc7agxcv7qm1zh9s12kuvKt6w8DG_j2ujPmDvfeB67L7Qe_mFO_w4AAP__OwgFIw">