Reputation: 63124
While producing a MCVE for this problem I stumbled upon, I've found the following discrepancy between compilers:
Consider the following code :
// constexpr int f(); // 1
constexpr int g() {
constexpr int f(); // 2
return f();
}
constexpr int f() {
return 42;
}
int main() {
constexpr int i = g();
return i;
}
This code compiles on Clang 3.8.0, but fails on GCC 6.1.0 with:
error: 'constexpr int f()' used before its definition
Commenting out // 2
and uncommenting // 1
works on both compilers.
Interestingly, moving f
's definition in place of // 1
compiles, but triggers a warning at // 2
:
warning: inline function 'constexpr int f()' used but never defined
Which compiler is right ?
Upvotes: 9
Views: 698
Reputation: 4553
Replacing the constexpr
functions with inline
functions retains the exact same problem (it is okay with the global declaration 1, but not with the function-scope declaration 2.) Since constexpr
implies inline
this seems like the cause.
In this case, with declaration 2, GCC complains:
warning: 'inline' specifier invalid for function 'f' declared out of global scope
and warning: inline function 'int f()' used but never defined
.
It fails to link ("undefined reference to 'f()'
").
So it looks like it gives up on inlining, puts in a call, but doesn't bother emitting code for f()
because all uses are inlined (?), so the link fails.
and Clang complains:
error: inline declaration of 'f' not allowed in block scope
Since constexpr
implies inline
, it seems that this rule that inline declarations are not allowed in block scope should also apply to constexpr
, and so GCC is correct. But the standard does not seem to come out and say this. In the draft I examined, the rule about inline
is in §7.1.2 [dcl.fct.spec], part 3: "The inline specifier shall not appear on a block scope function declaration", but nothing similar appears about constexpr
.
Upvotes: 2