The program is ill-formed and requires no diagnostic according to the C++11 draft standard section 7.1.5
The constexpr specifier paragraph 5 which says:
For a constexpr function, if no function argument values exist such
that the function invocation substitution would produce a constant
expression (5.19), the program is ill-formed; no diagnostic required.
and provides the following example:
constexpr int f(bool b)
{ return b ? throw 0 : 0; } // OK
constexpr int f() { return f(true); } // ill-formed, no diagnostic required
and section 5.19
paragraph 2 says:
A conditional-expression is a core constant expression unless it
involves one of the following as a potentially evaluated subexpression
[...]
and includes:
— an invocation of a function other than a constexpr constructor for a
literal class or a constexpr function [ Note: Overload resolution
(13.3) is applied as usual —end note ];
We would probably prefer a diagnostic in this case, it could just be an oversight, I have a bug report for a similar situation where gcc
does not produce an error but we would probably like it to: Is the compiler allowed leeway in what it considers undefined behavior in a constant expression?.
Update
Using the -fno-builtin
flag will cause gcc
to generate the following error:
error: call to non-constexpr function 'int printf(const char*, ...)'
return printf("a side effect!\n");
^
So gcc
does consider this ill-formed it is just ignores it when it is using the builtin version of printf
.
Although somewhat inconsistently using the -pedantic
produces the following warning:
warning: ISO C++ forbids variable length array 'a' [-Wvla]
char a[f()];
^
Note that using f()
to initialized a constexpr variable:
constexpr int x = f() ;
does generate an error:
error: 'printf(((const char*)"a side effect!\012"))' is not a constant expression
Note that additionally in the more general case a compiler is not allowed mark standard library functions as constexpr unless explicitly allowed by the standard.
3.5
gives me an error:note: non-constexpr function 'printf' cannot be used in a constant expression
– Clubhaulerror: ISO C++ forbids variable length array 'a' [-Wvla]
– Dovap-pedantic
this gives an error. Apparently, gcc treats this as a VLA and never tries to check if this is reallyconstexpr
. Tring to usef()
as a non-type template argument will fail. – Jenjenaconstexpr
. Then it complains about VLAs, because that is something it supports by default. – Dovapconstexpr
be rejected: (a) always, like clang does, (b) when its compile-time evaluation is required? – Jenjenaclang
seems to be over-eager to reject this and this should probably be a warning instead of an error. It should be an error whenf()
is used as aconstexpr
. Unfortunately, I cannot easily back this up with a quote. – Jenjenaf()
was legal in a non-constexpr context. I have to check this though. – Dovapprintf
with one toint foo() {return 42;}
it fails to compile. It should do the same withprintf
because neither isconstexpr
. – Dovapstrlen
in GCC on a character literal isconstexpr
and GCC substitutesprintf
withputs
(orputs
+strlen
if you consume the return value) if the format string contains no format specifiers. So apart from the obvious side effect, one could believe that this is a mighty fineconstexpr
function. – Fixityconstexpr int x = f();
ingcc
it produces an error. – Clubhaulconstexpr int x = strlen("foo");
compiles just fine, and if you disassemble the binary, you never find a single call tostrlen
anywhere, only the literal (assuming you use it, so it isn't optimized out). Ironically, this is not true for built-in macros such as__func__
, which, to you and me, are quite obviouslyconstexpr
, but the compiler will claim that they're not. – Fixity-fno-builtin
these all become errors ingcc
. So that makes more sense, I still think the compiler is not allowed to do this though. – Clubhaulgcc
is allowed to do this or not. – Clubhaulstd::array<int, f()> a;
to test constant expressions rather than VLA's. Example – Shep