GCC incorrectly captures global variables by reference in lambda functions?

c++, c++11, gcc, lambda

Solution

§5.1.2/11:

If a *lambda-expression( has an associated capture-default and its compound-statement odr-uses (3.2) `this` or a variable with automatic storage duration and the odr-used entity is not explicitly captured, then the odr-used entity is said to be implicitly captured; ...

Global variables have static storage duration (§3.7.1), so the global `a` will not be implicitly captured by value. Still, you can access a global variable anywhere, so

[=]() { a = 9; } ();

will set the global `a` to 9 as expected.

Explicitly capturing a global should be an error or UB, because §5.1.2/10 says

The identifiers in a capture-list are looked up using the usual rules for unqualified name lookup (3.4.1); each such lookup shall find a variable with automatic storage duration declared in the reaching scope of the local lambda expression.

Problem

GCC seems to incorrectly capture global variables by reference in lambda functions, even when they are specified as 'capture by value'. This code will compile and print "a = 9": ``` #include <iostream> int a = 10; int main() { [=]() { a = 9; } (); std::cout << "a = " << a << std::endl; return 0; } ``` While this code will not compile: ``` #include <iostream> int main() { int a = 10; [=]() { a = 9; } (); // error: assignment of member 'main()::<lambda()>::a' in read-only object std::cout << "a = " << a << std::endl; return 0; } ``` But explicitly capturing a global by value and then assigning to it gives the error: ``` #include <iostream> int a = 10; int main() { [a]() { a = 9; } (); // assigment of read-only object std::cout << "a = " << a << std::endl; return 0; } ``` I'm pretty sure that the error is the correct behaviour -- why does the implicit capture circumvent this error? I am just exploring the new C++11 features and accidentally wrote the first piece of code (not realizing it should be an error) and was then surprised when the modifications to what I assumed was a local variable affected the global. Since it should be an error to assign to a captured-by-value variable in a lambda, GCC presumably uses a reference to the variable for optimization purposes, at least in this case, and doesn't detect the erroneous assignment.

Original source