Issue 175051
Summary -Wunused-lambda-capture vs template-dependent constexprness with C++23 rules
Labels c++, c++23
Assignees
Reporter frobtech
    Consider this code:
```
template <class C> int UseAccessor(C &&thing) {
  const int x = thing.foo();
  auto use = [x]() -> int { return x + 1; };
  return use();
}

struct Accessor {
  int foo() const { return 0; }
};

struct ConstexprAccessor {
  constexpr int foo() const { return 0; }
};

int AlwaysWorks() { return UseAccessor(Accessor{}); }

int WorksBefore23() { return UseAccessor(ConstexprAccessor{}); }
```

`clang++ -c -Wall -Wextra -Werror=unused-lambda-capture -std=c++20` accepts this happily.
`clang++ -c -Wall -Wextra -Werror=unused-lambda-capture -std=c++23` fails thusly:
```
cxx23-const-capture.cc:3:15: error: lambda capture 'x' is not required to be
      captured for this use [-Werror,-Wunused-lambda-capture]
    3 |   auto use = [x]() -> int { return x + 1; };
      |               ^
cxx23-const-capture.cc:17:30: note: in instantiation of function template
      specialization 'UseAccessor<ConstexprAccessor>' requested here
   17 | int WorksBefore23() { return UseAccessor(ConstexprAccessor{}); }
      | ^
1 error generated.
```

Here's my understanding of the issue:

 * It's template-dependent whether `thing.foo()` is a constant _expression_:
 * In `C = Accessor`, it's not a constant _expression_.
    * In `C = ConstexprAccessor`, it is a constant _expression_.
  * In C++ 20, perhaps `const int x = <constant _expression_>;` doesn't make `x` a constant _expression_ and that changed in C++23 so it's equivalent to `constexpr int x = <constant _expression_>;` (not sure if that's actually new or not).
  * In C++ 23, a capture of a local `constexpr` variable is superfluous.
  * Hence, it's template-dependent whether `x` needs to be an explicit capture or is superfluous.
  * There's no easy or generic way for the template-dependent code to know whether `thing.foo()` will in fact be a constant _expression_ or not.
  * Hence, there's no easy or generic way for the template-dependent code to know whether it needs to capture `x` in its lambda or not.

IMHO, the warning should not be issued for this case.  I'm not sure how best to define the rule by which it's determined when to warn and when not to, without eliding some cases where the warning really is desirable.
_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to