Bug 19449

Summary: __builtin_constant_p cannot resolve to const when optimizing
Product: gcc Reporter: Erich Plondke <eplondke>
Component: cAssignee: Not yet assigned to anyone <unassigned>
Status: NEW ---    
Severity: normal CC: desrt, eplondke, gcc-bugs, ian, jakub, jbeulich, jsm28, prlw1, przemoc
Priority: P2 Keywords: rejects-valid
Version: 3.4.2   
Target Milestone: ---   
Host: Target:
Build: Known to work:
Known to fail: Last reconfirmed: 2005-12-18 01:38:34
Attachments: Test case as a file.

Description Erich Plondke 2005-01-14 19:11:20 UTC
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.
Comment 1 Erich Plondke 2005-01-14 19:22:23 UTC
Created attachment 7961 [details]
Test case as a file.

Test case as a file.
Comment 2 Andrew Pinski 2005-01-14 19:26:09 UTC
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.
Comment 3 Andrew Pinski 2010-11-29 19:37:32 UTC
*** Bug 46711 has been marked as a duplicate of this bug. ***
Comment 4 Marek Polacek 2013-03-28 06:57:56 UTC
*** Bug 56759 has been marked as a duplicate of this bug. ***
Comment 5 Jakub Jelinek 2013-03-28 08:53:54 UTC
Created attachment 29742 [details]

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];

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.
Comment 6 Jakub Jelinek 2013-04-03 10:00:19 UTC
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
	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

	* 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.

Comment 7 Ryan Lortie 2013-11-27 20:57:01 UTC
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);