Bug 19449 - __builtin_constant_p cannot resolve to const when optimizing
Summary: __builtin_constant_p cannot resolve to const when optimizing
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: c (show other bugs)
Version: 3.4.2
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: rejects-valid
: 46711 56759 (view as bug list)
Depends on:
Blocks:
 
Reported: 2005-01-14 19:11 UTC by Erich Plondke
Modified: 2021-09-29 08:25 UTC (History)
11 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail: 11.0, 3.4.2
Last reconfirmed: 2021-02-10 00:00:00


Attachments
Test case as a file. (299 bytes, text/plain)
2005-01-14 19:22 UTC, Erich Plondke
Details
gcc49-pr19449.patch (1.11 KB, patch)
2013-03-28 08:53 UTC, Jakub Jelinek
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
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]
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.
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
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
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);
Comment 8 Martin Sebor 2021-02-10 23:39:35 UTC
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];
      |             ^