Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

G++ vs Clang : inconsistent behavior for constexpr and const

Consider the following code:

constexpr const int A = 42;

const int &B = A;
static_assert(&A == &B, "Bug");

constexpr const int &C = B;
static_assert(&A == &C, "Bug");

int main() { return 0; }

It is perfectly accepted by clang version 3.3, whereas g++ (SUSE Linux) 4.8.1 20130909 [gcc-4_8-branch revision 202388 refuses it with:

bug2.cpp:5:1: error: non-constant condition for static assertion
 static_assert(&A == &B, "Bug");
 ^
bug2.cpp:5:1: error: the value of ‘B’ is not usable in a constant expression
bug2.cpp:2:12: note: ‘B’ was not declared ‘constexpr’
 const int &B = A;
            ^

It seems to me that GCC is correct (whereas I certainly would prefer clang behavior). Trying to read the standard I realized that I'm not enough of a language lawyer to decide. Can anyone confirm that?

like image 788
hivert Avatar asked Oct 02 '22 10:10

hivert


2 Answers

the value of ‘B’ is not usable in a constant expression is incorrect. You are not performing an lvalue-to-rvalue conversion on B, which is the usual meaning of "value;" you are only taking its address. The only relevant constant-expression rule forbids:

an id-expression that refers to a variable or data member of reference type unless the reference has a preceding initialization, initialized with a constant expression;

However B does have a preceding initialization to a reference constant expression.

A reference constant expression is an lvalue core constant expression that designates an object with static storage duration or a function.

In this case, B's initializer is A, which is as constant as you can get. A and B statically refer to the same object.

So, this is a GCC bug.

like image 139
Potatoswatter Avatar answered Oct 05 '22 11:10

Potatoswatter


Without being a language lawyer, you cannot use a reference as a constant expression in general, only values (if there are exceptions please correct me). In this sense, the closest valid to your code would be:

constexpr int A = 42;
constexpr int B = A;

static_assert(A == B, "Bug");

However, in my case, both Clang 3.3 and GCC 4.8.1 give errors on your code as expected.

EDIT Apparently my knowledge is still a bit narrow, sorry. There are probably exceptions depending on linkage, for instance the code is accepted (live) if the statements are global, outside main().

like image 45
iavr Avatar answered Oct 05 '22 11:10

iavr