Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Yet another clang/gcc discrepancy regarding ODR usage?

Why does this code compile with GCC (4.9 and 5+), but not with clang (3.5-3.9)?

void test(const int&) { }
int main() {
  const int x = 42;
  auto f = []{ test(x); };
}

I have some vague idea that the discrepancy has to do with ODR (One Definition Rule) usage, but I don't understand that well enough to figure out what's going on here.

like image 366
Daisy Sophia Hollman Avatar asked Mar 17 '16 21:03

Daisy Sophia Hollman


1 Answers

x is odr-used because it's bound to a reference (test's parameter). It therefore must be captured ([expr.prim.lambda]/13):

If a lambda-expression or an instantiation of the function call operator template of a generic lambda odr-uses ([basic.def.odr]) this or a variable with automatic storage duration from its reaching scope, that entity shall be captured by the lambda-expression.

Violations of this rule, like all other rules in the standard that doesn't say "no diagnostic required" or "undefined behavior", require a diagnostic.

GCC, unfortunately, performs constant folding too early, before it could tell whether it's an odr-use or not. This can lead to problems such as [&]()->const int & { return x; } returning a dangling reference.

like image 60
T.C. Avatar answered Oct 19 '22 17:10

T.C.