This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] __builtin_constant_p inside an initializer


Consider the following code:

int main (int argc, char *argv[])
{
  static int a[] = { __builtin_constant_p (argc) ? 1 : 0 };
  return a[0];
}

With 4.x series compilers this compiles successfully at -O0 but not
at -O2, for example, failing with an error of the form

foo.c: In function 'main':
foo.c:3: error: initializer element is not constant
foo.c:3: error: (near initialization for 'a[0]')

The underlying reason for this is that the folding function
fold_builtin_constant_p defers the decision to evaluate the
builtin (to a constant zero or one expression) until optimization.
A special case catches this at -O0 and changes that decision to
"evaluate this to a zero".  However at other optimization levels, the
__builtin_constant_p expression is not known to be a constant early
enough for the above error to be suppressed.

To fix this, the attached patch notes when folding inside an initializer,
and makes fold_builtin_constant_p give a definite answer rather than
deferring until a later stage.  This does not fix all of the situations
where similar problems could manifest themselves, of course: use of
__builtin_constant_p inside an array size bound would be one such.

OK for mainline?

Mark

--

gcc/ChangeLog:

2006-06-01 Mark Shinwell <shinwell@codesourcery.com>

	* tree.h: Declare folding_initializer.
	* builtins.c (fold_builtin_constant_p): Give definite answer
	if folding inside an initializer.
	* fold-const.c: Define folding_initializer.
	(START_FOLD_INIT): Save and then set folding_initializer.
	(END_FOLD_INIT): Restore folding_initializer.

gcc/testsuite/ChangeLog:

2006-06-01 Mark Shinwell <shinwell@codesourcery.com>

* gcc.c-torture/compile/builtin_constant_p.c: New test.
/* { dg-options "-O2" } */

int main (int argc, char *argv[])
{
  static int a[] = { __builtin_constant_p (argc) ? 1 : 0 };
  return a[0];
}

Index: gcc/tree.h
===================================================================
--- gcc/tree.h	(revision 114116)
+++ gcc/tree.h	(working copy)
@@ -3794,6 +3794,10 @@ extern void using_eh_for_cleanups (void)
 
 /* In fold-const.c */
 
+/* Non-zero if we are folding constants inside an initializer; zero
+   otherwise.  */
+extern int folding_initializer;
+
 /* Fold constants as much as possible in an expression.
    Returns the simplified expression.
    Acts only on the top level of the expression;
Index: gcc/builtins.c
===================================================================
--- gcc/builtins.c	(revision 114116)
+++ gcc/builtins.c	(working copy)
@@ -6562,7 +6562,8 @@ fold_builtin_constant_p (tree arglist)
   if (TREE_SIDE_EFFECTS (arglist)
       || AGGREGATE_TYPE_P (TREE_TYPE (arglist))
       || POINTER_TYPE_P (TREE_TYPE (arglist))
-      || cfun == 0)
+      || cfun == 0
+      || folding_initializer)
     return integer_zero_node;
 
   return 0;
Index: gcc/fold-const.c
===================================================================
--- gcc/fold-const.c	(revision 114116)
+++ gcc/fold-const.c	(working copy)
@@ -59,6 +59,10 @@ Software Foundation, 51 Franklin Street,
 #include "langhooks.h"
 #include "md5.h"
 
+/* Non-zero if we are folding constants inside an initializer; zero
+   otherwise.  */
+int folding_initializer = 0;
+
 /* The following constants represent a bit based encoding of GCC's
    comparison operators.  This encoding simplifies transformations
    on relational comparison operators, such as AND and OR.  */
@@ -10616,16 +10620,19 @@ fold_build3_stat (enum tree_code code, t
   int saved_trapping_math = flag_trapping_math;\
   int saved_rounding_math = flag_rounding_math;\
   int saved_trapv = flag_trapv;\
+  int saved_folding_initializer = folding_initializer;\
   flag_signaling_nans = 0;\
   flag_trapping_math = 0;\
   flag_rounding_math = 0;\
-  flag_trapv = 0
+  flag_trapv = 0;\
+  folding_initializer = 1;
 
 #define END_FOLD_INIT \
   flag_signaling_nans = saved_signaling_nans;\
   flag_trapping_math = saved_trapping_math;\
   flag_rounding_math = saved_rounding_math;\
-  flag_trapv = saved_trapv
+  flag_trapv = saved_trapv;\
+  folding_initializer = saved_folding_initializer;
 
 tree
 fold_build1_initializer (enum tree_code code, tree type, tree op)

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]