GCC misses a diagnostic when the fabs() or fma() function is used in an initializer. For instance, consider: ---------------------------------------- double fabs (double); double fma (double, double, double); double foo (double, double, double); double f (void) { static double x = fabs (3.0); static double y = fma (2.0, 3.0, 4.0); static double z = foo (2.0, 3.0, 4.0); return x + y + z; } ---------------------------------------- $ gcc-snapshot -std=c99 -c tst-cst.c tst-cst.c: In function 'f': tst-cst.c:9:21: error: initializer element is not constant static double z = foo (2.0, 3.0, 4.0); ^~~ where gcc-snapshot is: gcc version 8.0.0 20170512 (experimental) [trunk revision 247986] (Debian 20170512-1) I get the diagnostic as expected for foo(), but not for fabs() and fma(). Note that <math.h> is not included, so that fabs() and fma() must not be regarded as special. But even when these functions are regarded as ISO C's specified ones, the diagnostic should probably still be present (it seems that the C standard does not make an exception for such functions, unfortunately). Same problem with GCC 6.3.0. But GCC 5.4.1 gives: $ gcc-5 -std=c99 -c tst-cst.c tst-cst.c: In function ‘f’: tst-cst.c:7:21: warning: initializer element is not a constant expression static double x = fabs (3.0); ^ tst-cst.c:8:21: warning: initializer element is not a constant expression static double y = fma (2.0, 3.0, 4.0); ^ tst-cst.c:9:21: error: initializer element is not constant static double z = foo (2.0, 3.0, 4.0); ^ As far as the C standard is concerned, there are no differences between warnings and errors (all diagnostics), so that this is much better. But this should really be an error in all cases. As a comparison, Clang gives 3 "error" diagnostics (tested 3.6 to 4.0 RC1): $ clang-4.0 -c tst-cst.c tst-cst.c:7:21: error: initializer element is not a compile-time constant static double x = fabs (3.0); ^~~~~~~~~~ tst-cst.c:8:21: error: initializer element is not a compile-time constant static double y = fma (2.0, 3.0, 4.0); ^~~~~~~~~~~~~~~~~~~ tst-cst.c:9:21: error: initializer element is not a compile-time constant static double z = foo (2.0, 3.0, 4.0); ^~~~~~~~~~~~~~~~~~~ 3 errors generated.
The cause seems to be that the functions are builtins: $ gcc-snapshot -std=c99 -c tst-cst.c tst-cst.c: In function 'f': tst-cst.c:7:21: error: initializer element is not constant static double x = fabs (3.0); ^~~~ tst-cst.c:8:21: error: initializer element is not constant static double y = fma (2.0, 3.0, 4.0); ^~~ tst-cst.c:9:21: error: initializer element is not constant static double z = foo (2.0, 3.0, 4.0); ^~~ But I think that this is wrong. The use of -std=c99 shouldn't allow builtin functions when they would give a different result (and even without -std=c99, as this would be confusing). On this point, Clang has the same issue.
(In reply to Vincent Lefèvre from comment #1) > The cause seems to be that the functions are builtins: > > $ gcc-snapshot -std=c99 -c tst-cst.c [...] Oops, incomplete copy-paste. It should have been: $ gcc-snapshot -std=c99 -c tst-cst.c -fno-builtin tst-cst.c: In function 'f': tst-cst.c:7:21: error: initializer element is not constant static double x = fabs (3.0); ^~~~ tst-cst.c:8:21: error: initializer element is not constant static double y = fma (2.0, 3.0, 4.0); ^~~ tst-cst.c:9:21: error: initializer element is not constant static double z = foo (2.0, 3.0, 4.0); ^~~ Without the -fno-builtin, the diagnostic for fabs() and fma() are missing.
fabs and fma identifiers are reserved for the implementation and it is valid to treat them as constant expression in initializers based on c99 6.6p10 i think the gcc behaviour is reasonable.
(In reply to nsz from comment #3) > fabs and fma identifiers are reserved for the implementation and it is valid > to treat them as constant expression in initializers based on c99 6.6p10 Well, if <math.h> is included, perhaps, but this would need to be documented as an implementation-defined behavior. The GCC manual Section 4 "C Implementation-Defined Behavior" doesn't seem to document such constant expressions and when they are available. If <math.h> is not included, there should be at least a warning because fabs() or fma() is used without including the header first, thus potentially yielding unexpected results and obscure bugs.
On Mon, 15 May 2017, vincent-gcc at vinc17 dot net wrote: > GCC misses a diagnostic when the fabs() or fma() function is used in an > initializer. For instance, consider: There are pedwarns-if-pedantic for these cases. > Note that <math.h> is not included, so that fabs() and fma() must not be > regarded as special. But even when these functions are regarded as ISO C's > specified ones, the diagnostic should probably still be present (it seems that > the C standard does not make an exception for such functions, unfortunately). The reservations with external linkage in C99/C11 7.1.3#1 are not conditional on whether the corresponding header is included. (Only C90 Amendment 1 had such reservations conditional on inclusion of the corresponding header, for the new functions it added, and that condition would only be relevant with -std=iso9899:199409.)
On Mon, 15 May 2017, nsz at gcc dot gnu.org wrote: > fabs and fma identifiers are reserved for the implementation and it is valid to > treat them as constant expression in initializers based on c99 6.6p10 The calls violate the requirement for constant expressions not to contain function calls, hence the pedwarns-if-pedantic being necessary for this code.
As mentioned -std=c99 -pedantic-errors errors out like expected.