关于 ODR 使用的另一个 clang/gcc 差异?
Yet another clang/gcc discrepancy regarding ODR usage?
为什么这段代码可以用 GCC(4.9 和 5+)编译,但不能用 clang (3.5-3.9) 编译?
void test(const int&) { }
int main() {
const int x = 42;
auto f = []{ test(x); };
}
我有一些模糊的想法,认为差异与 ODR(单一定义规则)的使用有关,但我不太了解,无法弄清楚这里发生了什么。
x
被 odr 使用,因为它绑定到一个引用(test
的参数)。因此必须捕获它 ([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.
违反此规则,与标准中未提及 "no diagnostic required" 或 "undefined behavior"、require a diagnostic.
的所有其他规则一样
不幸的是,GCC 过早地执行常量折叠,在它可以判断它是否是 odr-use 之前。这可能会导致问题 such as [&]()->const int & { return x; }
returning a dangling reference.
T.C。有正确的诊断,这是更清晰的法律代码,其中 clang 做正确的事而 gcc 没有:
#include <iostream>
void test(const int&a) { std::cout << "in test() -- " << &a << "\n"; }
int main() {
const int x = 42;
std::cout << "in main() -- " << &x << "\n";
auto f = [&]{ test(x); };
f();
}
gcc 为引用捕获变量打印的地址与原始地址不同!
为什么这段代码可以用 GCC(4.9 和 5+)编译,但不能用 clang (3.5-3.9) 编译?
void test(const int&) { }
int main() {
const int x = 42;
auto f = []{ test(x); };
}
我有一些模糊的想法,认为差异与 ODR(单一定义规则)的使用有关,但我不太了解,无法弄清楚这里发生了什么。
x
被 odr 使用,因为它绑定到一个引用(test
的参数)。因此必须捕获它 ([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.
违反此规则,与标准中未提及 "no diagnostic required" 或 "undefined behavior"、require a diagnostic.
的所有其他规则一样不幸的是,GCC 过早地执行常量折叠,在它可以判断它是否是 odr-use 之前。这可能会导致问题 such as [&]()->const int & { return x; }
returning a dangling reference.
T.C。有正确的诊断,这是更清晰的法律代码,其中 clang 做正确的事而 gcc 没有:
#include <iostream>
void test(const int&a) { std::cout << "in test() -- " << &a << "\n"; }
int main() {
const int x = 42;
std::cout << "in main() -- " << &x << "\n";
auto f = [&]{ test(x); };
f();
}
gcc 为引用捕获变量打印的地址与原始地址不同!