Given the following code: #define SHIFTLEFT(a,b) __builtin_choose_expr(__builtin_constant_p(b), \ ((a) << (b)), \ ((a) << (MIN(31,MAX(-31,(b)))))) int foo(int a, int b) { return SHIFTLEFT (a, b); } the compiler will error: gcc -O4 gcctest.c gcctest.c: In function `foo': gcctest.c:5: error: first argument to __builtin_choose_expr not a constant According to the documentation to __builtin_constant_p, it should resolve to 0 if the compiler cannot prove that the argument is a constant.
Created attachment 7961 [details] Test case as a file. Test case as a file.
The problem is the __builtin_constant_p is delayed for evalutation until optimizations are run but __builtin_choose_expr needs an answer right away. What we could do is for when processing the first argument of __builtin_choose_expr, say we are not in a function.
*** Bug 46711 has been marked as a duplicate of this bug. ***
*** Bug 56759 has been marked as a duplicate of this bug. ***
Created attachment 29742 [details] gcc49-pr19449.patch Untested patch. There is another case where we'd better fold __builtin_constant_p right away, for static/extern function-local array dimensions: int y; static char a[__builtin_constant_p (y) ? -1 : 1]; extern char b[__builtin_constant_p (y) ? -1 : 1]; char d[__builtin_constant_p (y) ? -1 : 1]; void foo (int x) { static char e[__builtin_constant_p (x) ? -1 : 1]; extern char f[__builtin_constant_p (x) ? -1 : 1]; auto char g[__builtin_constant_p (x) ? -1 : 1]; char h[__builtin_constant_p (x) ? -1 : 1]; } Right now this compiles fine for -O0, but for -O1 and above it errors on e and f (twice on the latter actually). When cfun == NULL, we always fold __builtin_constant_p right away, but when cfun is NULL, we don't consider static/extern. Not sure how to fix this issue though, because I think the declspecs aren't passed down to declarator parsing.
Author: jakub Date: Wed Apr 3 09:17:44 2013 New Revision: 197393 URL: http://gcc.gnu.org/viewcvs?rev=197393&root=gcc&view=rev Log: PR c/19449 * tree.h (force_folding_builtin_constant_p): New decl. * builtins.c (force_folding_builtin_constant_p): New variable. (fold_builtin_constant_p): Fold immediately also if force_folding_builtin_constant_p. * c-parser.c (c_parser_get_builtin_args): Add choose_expr_p argument. If set, or it temporarily for parsing of the first argument into force_folding_builtin_constant_p. (c_parser_postfix_expression): Adjust callers. * gcc.c-torture/execute/pr19449.c: New test. Added: trunk/gcc/testsuite/gcc.c-torture/execute/pr19449.c Modified: trunk/gcc/ChangeLog trunk/gcc/builtins.c trunk/gcc/c/ChangeLog trunk/gcc/c/c-parser.c trunk/gcc/testsuite/ChangeLog trunk/gcc/tree.h
Another case, and this one fails at all optimisation levels: int a(void) { return 0; } /* This always returns a constant expression. If we can't statically * determine its value, then this is the constant expression '0'. */ #define CONSTIFY(x) (__builtin_constant_p(x)&&(x)) /* works fine */ int b = CONSTIFY(a()); int c = CONSTIFY(a()) ? 2 : 3; /* fails */ int d = __builtin_choose_expr(CONSTIFY(a()), 2, 3);
No change in GCC 11: $ gcc -O -S -Wall pr19449.c pr19449.c: In function ‘foo’: pr19449.c:9:15: error: storage size of ‘e’ isn’t constant 9 | static char e[__builtin_constant_p (x) ? -1 : 1]; | ^ pr19449.c:10:15: error: object with variably modified type must have no linkage 10 | extern char f[__builtin_constant_p (x) ? -1 : 1]; | ^ pr19449.c:10:15: error: storage size of ‘f’ isn’t constant pr19449.c:12:8: warning: unused variable ‘h’ [-Wunused-variable] 12 | char h[__builtin_constant_p (x) ? -1 : 1]; | ^ pr19449.c:11:13: warning: unused variable ‘g’ [-Wunused-variable] 11 | auto char g[__builtin_constant_p (x) ? -1 : 1]; | ^ pr19449.c:10:15: warning: unused variable ‘f’ [-Wunused-variable] 10 | extern char f[__builtin_constant_p (x) ? -1 : 1]; | ^ pr19449.c:9:15: warning: unused variable ‘e’ [-Wunused-variable] 9 | static char e[__builtin_constant_p (x) ? -1 : 1]; | ^ At top level: pr19449.c:2:13: warning: ‘a’ defined but not used [-Wunused-variable] 2 | static char a[__builtin_constant_p (y) ? -1 : 1]; | ^