https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95699
Bug ID: 95699 Summary: __builtin_constant_p inconsistencies Product: gcc Version: 10.1.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: vincent-gcc at vinc17 dot net Target Milestone: --- Consider the following code on x86_64 (written for a 64-bit long), compiled with -O2. With gcc-9 (Debian 9.3.0-13) 9.3.0, I get: 0 1 1 With gcc-10 (Debian 10.1.0-3) 10.1.0, I get: 0 1 0 I'm not sure about the exact __builtin_constant_p specification, i.e. whether it may be duplicated into two branches so that the argument can become a constant for GCC (I think it should as this may allow the selection of code optimized for constants), and how this can be influenced by "volatile". But the first two cases are very similar, so that I would expect the same value, but I get 0 / 1 with both GCC 9 and GCC 10. Concerning the third case, the constantness has been lost in GCC 10, which is unexpected if a result 1 is allowed. Moreover, if I remove the second condition ("&& ...") in the printf, I always get 0 (i.e. false), which is counter-intuitive: adding a "&& ..." condition should never change a false condition to true (the results 1 I obtain above). int printf (const char *__restrict __format, ...); #undef C #define C 0x7fffffffffffffffUL static void tst1a (void) { volatile unsigned long r0 = 0; unsigned long r; r = r0; if (r < C) r = C; printf ("%d\n", __builtin_constant_p (r) && r == C); } #undef C #define C 0x8000000000000000UL static void tst1b (void) { volatile unsigned long r0 = 0; unsigned long r; r = r0; if (r < C) r = C; printf ("%d\n", __builtin_constant_p (r) && r == C); } static void tst2 (void) { volatile unsigned long r0 = 0; unsigned long r; r = r0; if (r < 0x8000000000000000) r = 0x8000000000000000; r *= r; printf ("%d\n", __builtin_constant_p (r) && r < 1); } int main (void) { tst1a (); tst1b (); tst2 (); return 0; }