Search code examples
c++gcclambdacompiler-warnings

"Variable shadowed" warning in lambda (when not captured)


Let's consider this code:

int main()
{
    int a = 1;

    auto f1 = [a]() {
        int a = 10;
        return a;
    };

    auto f2 = []() {
        int a = 100;
        return a;
    };

    return a + f1() + f2();
}

When using flag -Wshadow with gcc (tested on 10.2), we get these warnings:

<source>:26:13: warning: declaration of 'a' shadows a lambda capture [-Wshadow]
    6 |         int a = 10;

<source>:21:13: warning: declaration of 'a' shadows a previous local [-Wshadow]
   11 |         int a = 100;

I understand the first case, where we explicitly capture a, and thus are shadowing the original local. However, the second case is interesting, because if we remove declaration int a = 100; we get a compile error (= error: 'a' is not captured: return a;). Doesn't that "prove" that the declaration is not in the same scope as the original local, and thus we are not actually shadowing anything? Hence my question, whether the warning (for the second case) is indeed valid, or whether gcc is being a bit too strict here?


Solution

  • You are correct, lambda a doesn't shadow main::a because main::a isn't captured in the lambda, thus is not on scope there.

    However I think about what the purpose of the shadow warning is: to avoid programmer confusion. If a long body of code if the programmer sees the outer declaration, but doesn't see the inner declaration he or she may incorrectly assume that a use of the inner variable refers to the outer variable. And this possible confusion still applies here, even if the variable doesn't tehnically shadow the outer one.

    I don't know if this is the intention of the warning or if it is a bug. Or even if that is a compelling enough reason to have a warning even a differently worded one. Shadow warning are problematic anyways. You can find a lot of discussions and bug reports about shadow warning that even if tehnically correct are considered harmful.