Patchwork Fold __builtin_constant_p immediately when in the first argument of __builtin_choose_expr (PR c/19449)

login
register
mail settings
Submitter Jakub Jelinek
Date April 2, 2013, 11:25 a.m.
Message ID <20130402112519.GJ20616@tucnak.redhat.com>
Download mbox | patch
Permalink /patch/232962/
State New
Headers show

Comments

Jakub Jelinek - April 2, 2013, 11:25 a.m.
Hi!

As discussed in the PR, when __builtin_constant_p is used in the first
argument of __builtin_choose_expr, as we require a constant value
immediately, we'd better force folding of __builtin_constant_p immediately,
as if we don't, and it isn't 1 known immediately, we won't end up with a
constant expression.  For -O0 we accept code using __builtin_constant_p
in __builtin_choose_expr (as we fold it there immediately always), but not
for -O1 and above.

The following patch folds it there immediately too.  Bootstrapped/regtested
on x86_64-linux and i686-linux, ok for trunk?

BTW, in the PR I've also mentioned what has been reported to the Red Hat
bugzilla about __builtin_constant_p in array bounds of static (or extern)
arrays in block contexts.  Those can't be VLAs, so we want to know the
constant bound, but if __builtin_constant_p is used there, we error on it
(while at file scope it compiles fine, because if cfun is NULL, we fold
__builtin_constant_p immediately).  Any suggestions how to fix that?

2013-04-02  Jakub Jelinek  <jakub@redhat.com>

	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.


	Jakub
Joseph S. Myers - April 2, 2013, 10:43 p.m.
On Tue, 2 Apr 2013, Jakub Jelinek wrote:

> The following patch folds it there immediately too.  Bootstrapped/regtested
> on x86_64-linux and i686-linux, ok for trunk?

OK.

> BTW, in the PR I've also mentioned what has been reported to the Red Hat
> bugzilla about __builtin_constant_p in array bounds of static (or extern)
> arrays in block contexts.  Those can't be VLAs, so we want to know the
> constant bound, but if __builtin_constant_p is used there, we error on it
> (while at file scope it compiles fine, because if cfun is NULL, we fold
> __builtin_constant_p immediately).  Any suggestions how to fix that?

It's not going to be as simple as using information about the declaration 
specifiers when parsing array declarators, because a static pointer to VLA 
is valid, so it would also be necessary to distinguish whether the 
declaration in question is actually going to be of a static array itself.

Patch

--- gcc/tree.h.jj	2013-03-21 18:34:09.000000000 +0100
+++ gcc/tree.h	2013-03-21 18:34:09.000000000 +0100
@@ -5851,6 +5851,10 @@  fold_build_pointer_plus_hwi_loc (locatio
 	fold_build_pointer_plus_hwi_loc (UNKNOWN_LOCATION, p, o)
 
 /* In builtins.c */
+
+/* Non-zero if __builtin_constant_p should be folded right away.  */
+extern bool force_folding_builtin_constant_p;
+
 extern bool avoid_folding_inline_builtin (tree);
 extern tree fold_call_expr (location_t, tree, bool);
 extern tree fold_builtin_fputs (location_t, tree, tree, bool, bool, tree);
--- gcc/builtins.c.jj	2013-01-11 09:02:35.000000000 +0100
+++ gcc/builtins.c	2013-03-28 09:26:51.700817655 +0100
@@ -75,6 +75,9 @@  const char * built_in_names[(int) END_BU
    initialized to NULL_TREE.  */
 builtin_info_type builtin_info;
 
+/* Non-zero if __builtin_constant_p should be folded right away.  */
+bool force_folding_builtin_constant_p;
+
 static const char *c_getstr (tree);
 static rtx c_readstr (const char *, enum machine_mode);
 static int target_char_cast (tree, char *);
@@ -6974,7 +6977,8 @@  fold_builtin_constant_p (tree arg)
       || AGGREGATE_TYPE_P (TREE_TYPE (arg))
       || POINTER_TYPE_P (TREE_TYPE (arg))
       || cfun == 0
-      || folding_initializer)
+      || folding_initializer
+      || force_folding_builtin_constant_p)
     return integer_zero_node;
 
   return NULL_TREE;
--- gcc/c/c-parser.c.jj	2013-03-19 18:42:48.000000000 +0100
+++ gcc/c/c-parser.c	2013-03-28 09:30:17.609546890 +0100
@@ -6114,11 +6114,13 @@  c_parser_alignof_expression (c_parser *p
    stores the arguments in CEXPR_LIST.  */
 static bool
 c_parser_get_builtin_args (c_parser *parser, const char *bname,
-			   vec<c_expr_t, va_gc> **ret_cexpr_list)
+			   vec<c_expr_t, va_gc> **ret_cexpr_list,
+			   bool choose_expr_p)
 {
   location_t loc = c_parser_peek_token (parser)->location;
   vec<c_expr_t, va_gc> *cexpr_list;
   c_expr_t expr;
+  bool saved_force_folding_builtin_constant_p;
 
   *ret_cexpr_list = NULL;
   if (c_parser_next_token_is_not (parser, CPP_OPEN_PAREN))
@@ -6135,7 +6137,12 @@  c_parser_get_builtin_args (c_parser *par
       return true;
     }
 
+  saved_force_folding_builtin_constant_p
+    = force_folding_builtin_constant_p;
+  force_folding_builtin_constant_p |= choose_expr_p;
   expr = c_parser_expr_no_commas (parser, NULL);
+  force_folding_builtin_constant_p
+    = saved_force_folding_builtin_constant_p;
   vec_alloc (cexpr_list, 1);
   C_EXPR_APPEND (cexpr_list, expr);
   while (c_parser_next_token_is (parser, CPP_COMMA))
@@ -6509,7 +6516,7 @@  c_parser_postfix_expression (c_parser *p
 	    c_parser_consume_token (parser);
 	    if (!c_parser_get_builtin_args (parser,
 					    "__builtin_choose_expr",
-					    &cexpr_list))
+					    &cexpr_list, true))
 	      {
 		expr.value = error_mark_node;
 		break;
@@ -6591,7 +6598,7 @@  c_parser_postfix_expression (c_parser *p
 	    c_parser_consume_token (parser);
 	    if (!c_parser_get_builtin_args (parser,
 					    "__builtin_complex",
-					    &cexpr_list))
+					    &cexpr_list, false))
 	      {
 		expr.value = error_mark_node;
 		break;
@@ -6653,7 +6660,7 @@  c_parser_postfix_expression (c_parser *p
 	    c_parser_consume_token (parser);
 	    if (!c_parser_get_builtin_args (parser,
 					    "__builtin_shuffle",
-					    &cexpr_list))
+					    &cexpr_list, false))
 	      {
 		expr.value = error_mark_node;
 		break;
--- gcc/testsuite/gcc.c-torture/execute/pr19449.c.jj	2013-04-02 10:01:56.042354508 +0200
+++ gcc/testsuite/gcc.c-torture/execute/pr19449.c	2013-04-02 10:01:38.000000000 +0200
@@ -0,0 +1,20 @@ 
+/* PR c/19449 */
+
+extern void abort (void);
+
+int y;
+int z = __builtin_choose_expr (!__builtin_constant_p (y), 3, 4);
+
+int
+foo (int x)
+{
+  return __builtin_choose_expr (!__builtin_constant_p (x), 3, y++);
+}
+
+int
+main ()
+{
+  if (y || z != 3 || foo (4) != 3)
+    abort ();
+  return 0;
+}