Issue 142267
Summary clang-tidy always emits clang-analyzer-core.CallAndMessage warning for reference captured structured bindings in lambdas
Labels clang-tidy
Assignees
Reporter justusranvier
    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); };
      | ^             ~~~
```

_______________________________________________
llvm-bugs mailing list
llvm-bugs@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to