Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unused lambda capture warning when capture is actually used

Tags:

c++

clang

This code:

void foo(int);
int main() {
    const int i = 0;
    auto l = [i](){foo(i);};
}

(godbolt)

Will issue a compiler error when compiled by clang with

-std=c++17 -Werror -Wunused-lambda-capture

The error message is error: lambda capture 'i' is not required to be captured for this use.

The error is correct: i could be implicitly captured here, explicitly capturing it is not necessary. However, a) the warning is poorly named, since i is used but the warning is for unused lambda captures, and b) I would just not like this to be an error. I want to error for actually unused lambda captures, but not error for used explicitly captured variables that could have been implicitly captured.

Is there a clang setting that does this? Or do I have to squelch the error using pragma diagnostic push/pop?

like image 609
Drew Avatar asked Sep 20 '18 01:09

Drew


1 Answers

I think you are unfortunately out of luck here. If we examine the review that implemented this feature [Sema] Add warning for unused lambda captures, we can see the discussion of how to silence the warning was extensively discussed. Including the canonical clang method of silencing unused warning, which is cast to void:

I think that expected-warning shouldn't be used here as you have (void)fname in the lambda (I don't get this warning if I test this locally).

Which does work see it live but feels silly for this case.

Using -Wno-unused-lambda-capture but that is not a favorable option for you:

I think that the patch would be neater if you add "-Wno-unused-lambda-capture" to the options for all of the tests that are modified by this patch in the CXX/ directory. This would avoid redundant (void) uses and ensure that the (void) uses won't interfere with the original intent where things might be only used in the capture list.

Leaving out the variable from the capture since it is not odr-used but as it is pointed out this exposes implementation divergence since MSVC does not do this optimization:

It will compile without any warnings if I remove kDelta from the list of captures:

#include <stdio.h>

int main(void) {
  const int kDelta = 10000001;
  auto g = [](int i)
           {
             printf("%d\n", i % kDelta);
           };
  g(2);
}

But then Microsoft C++ compiler will raise the error:

error C3493: 'kDelta' cannot be implicitly captured because no default capture mode has been specified

We can see this case live as well and indeed removing i from the capture does indeed fix it for clang and gcc but not for MSVC.

The other solution that will work for all implemntation is to explicitly capture [i=i] but it sounds like that is also not a desirable solution (see it live).

It would be nice if we could apply [[maybe_unused]] here but we can't.

like image 186
Shafik Yaghmour Avatar answered Oct 23 '22 13:10

Shafik Yaghmour