Consider the following code:
#include <stdio.h>
constexpr int f()
{
return printf("a side effect!\n");
}
int main()
{
char a[f()];
printf("%zd\n", sizeof a);
}
I would have expected the compiler to complain about the call to printf
inside f
, because f
is supposed to be constexpr
, but printf
is not. Why does the program compile and print 15?
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.