https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96311
--- Comment #4 from Jakub Jelinek <jakub at gcc dot gnu.org> --- If I compare void foo () { constexpr int used = 0; [](auto unused) { return used; }; } void bar () { constexpr int used = 0; [](int unused) { return used; }; } then in bar mark_exp_read is called on used from check_return_expr -> convert_for_initialization -> convert_from_assignment -> perform_implicit_conversion_flags -> mark_rvalue_use -> mark_use -> mark_exp_read, but for the generic lambda check_return_expr takes the goto dependent; and doesn't mark anything. It is only marked during instantiation of the lambda, such as when (0) as added in between } and ; and in that case the warning is gone. More complete testcase: void foo () { constexpr int used = 0; [](auto unused) { return used; }; } void bar () { constexpr int used = 0; [](int unused) { return used; }; } void baz () { constexpr int used = 0; [](auto unused) { return used; } (0); } void qux () { constexpr int used = 0; [](auto unused) { return used + 1; }; } void corge () { constexpr int used = 0; [](auto unused) { return used + unused; }; } This shows that if the variable is used in some non-dependent expression as in qux (and not directly in return statement), it is marked already without instantiation, but when it is only used directly in return stmt or used in a dependent expression, it is marked only during instantiation of the lambda. Though, when the lambda isn't really instantiated, the variable is not really used, so not 100% sure the warning is unwanted.