GCC 4.5: "nonconstant array index in initializer" error

Joseph S. Myers joseph@codesourcery.com
Sat Apr 25 23:37:00 GMT 2009


On Sat, 25 Apr 2009, Denis Onischenko wrote:

> Thanks for the patch.
> 
> There are another error while building linux kernel with GCC 4.5.0
> revision 146771.
> 
> The minimal code for reproducing the error looks like:
> 
> extern unsigned int __invalid_size_argument;
> #define TYPECHECK(t)    ( sizeof(t) == sizeof(t[1]) ?  sizeof(t) :
> __invalid_size_argument )
> 
> enum {
>      ENUM_VALUE_NAME = TYPECHECK(int),
> };

I have applied this further patch to make this case also a
pedwarn-if-pedantic.  Bootstrapped with no regressions on
x86_64-unknown-linux-gnu.

2009-04-25  Joseph Myers  <joseph@codesourcery.com>

	* c-decl.c (build_enumerator): Allow values folding to integer
	constants but not integer constant expressions with a pedwarn if
	pedantic.

testsuite:
2009-04-25  Joseph Myers  <joseph@codesourcery.com>

	* gcc.dg/enum-const-1.c, gcc.dg/enum-const-2.c,
	gcc.dg/enum-const-3.c: New tests.
	* gcc.dg/gnu89-const-expr-1.c, gcc.dg/gnu99-const-expr-1.c: Use
	-pedantic-errors.  Update expected diagnostics.

Index: gcc/testsuite/gcc.dg/enum-const-3.c
===================================================================
--- gcc/testsuite/gcc.dg/enum-const-3.c	(revision 0)
+++ gcc/testsuite/gcc.dg/enum-const-3.c	(revision 0)
@@ -0,0 +1,8 @@
+/* Test for enumeration constants not integer constant expressions but
+   folding to integer constants (used in Linux kernel,
+   <http://gcc.gnu.org/ml/gcc/2009-04/msg00677.html>).  */
+/* { dg-do compile } */
+/* { dg-options "-pedantic-errors" } */
+
+extern int i;
+enum e { E = (1 ? 1 : i) }; /* { dg-error "not an integer constant expression" } */
Index: gcc/testsuite/gcc.dg/enum-const-1.c
===================================================================
--- gcc/testsuite/gcc.dg/enum-const-1.c	(revision 0)
+++ gcc/testsuite/gcc.dg/enum-const-1.c	(revision 0)
@@ -0,0 +1,8 @@
+/* Test for enumeration constants not integer constant expressions but
+   folding to integer constants (used in Linux kernel,
+   <http://gcc.gnu.org/ml/gcc/2009-04/msg00677.html>).  */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+extern int i;
+enum e { E = (1 ? 1 : i) };
Index: gcc/testsuite/gcc.dg/gnu89-const-expr-1.c
===================================================================
--- gcc/testsuite/gcc.dg/gnu89-const-expr-1.c	(revision 146747)
+++ gcc/testsuite/gcc.dg/gnu89-const-expr-1.c	(working copy)
@@ -1,7 +1,7 @@
 /* Test for constant expressions: GNU extensions.  */
 /* Origin: Joseph Myers <joseph@codesourcery.com> */
 /* { dg-do compile } */
-/* { dg-options "-std=gnu89" } */
+/* { dg-options "-std=gnu89 -pedantic-errors" } */
 
 int n;
 
@@ -9,39 +9,48 @@ void
 f (void)
 {
   int i = 0;
-  int a[n];
+  int a[n]; /* { dg-error "ISO C90 forbids variable length array" } */
   enum e1 {
     /* Integer constant expressions may not contain statement
        expressions (not a permitted operand).  */
-    E1 = (1 ? 0 : ({ 0; })), /* { dg-error "constant" } */
+    E1 = (1 ? 0 : ({ 0; })), /* { dg-error "constant expression" } */
+    /* { dg-error "ISO C forbids braced-groups" "ISO" { target *-*-* } 16 } */
     /* Real and imaginary parts act like other arithmetic
        operators.  */
-    E2 = __real__ (1 ? 0 : i++), /* { dg-error "constant" } */
+    E2 = __real__ (1 ? 0 : i++), /* { dg-error "constant expression" } */
     E3 = __real__ 0,
     E4 = __imag__ (1 ? 0 : i++), /* { dg-error "constant" } */
     E5 = __imag__ 0,
     /* __alignof__ always constant.  */
-    E6 = __alignof__ (int[n]),
+    E6 = __alignof__ (int[n]), /* { dg-error "ISO C90 forbids variable length array" } */
     E7 = __alignof__ (a),
     /* __extension__ ignored for constant expression purposes.  */
-    E8 = __extension__ (1 ? 0 : i++), /* { dg-error "constant" } */
+    E8 = __extension__ (1 ? 0 : i++), /* { dg-error "constant expression" } */
     E9 = __extension__ 0,
     /* Conditional expressions with omitted arguments act like the
        standard type.  */ 
-    E10 = (1 ? : i++), /* { dg-error "constant" } */
-    E11 = (1 ? : 0)
+    E10 = (1 ? : i++), /* { dg-error "constant expression" } */
+    /* { dg-error "ISO C forbids omitting" "ISO" { target *-*-* } 32 } */
+    E11 = (1 ? : 0) /* { dg-error "ISO C forbids omitting" } */
   };
   enum e2 {
     /* Complex integer constants may be cast directly to integer
        types, but not after further arithmetic on them.  */
-    F1 = (int) (_Complex int) 2i, /* { dg-error "constant" } */
-    F2 = (int) +2i, /* { dg-error "constant" } */
-    F3 = (int) (1 + 2i), /* { dg-error "constant" } */
-    F4 = (int) 2i
+    F1 = (int) (_Complex int) 2i, /* { dg-error "constant expression" } */
+    /* { dg-error "complex" "complex" { target *-*-* } 39 } */
+    /* { dg-error "imaginary" "imaginary" { target *-*-* } 39 } */
+    F2 = (int) +2i, /* { dg-error "constant expression" } */
+    /* { dg-error "imaginary" "ISO" { target *-*-* } 42 } */
+    F3 = (int) (1 + 2i), /* { dg-error "constant expression" } */
+    /* { dg-error "imaginary" "ISO" { target *-*-* } 44 } */
+    F4 = (int) 2i /* { dg-error "imaginary" } */
   };
   static double dr = __real__ (1.0 + 2.0i);
+  /* { dg-error "imaginary" "ISO" { target *-*-* } 48 } */
   static double di = __imag__ (1.0 + 2.0i);
+  /* { dg-error "imaginary" "ISO" { target *-*-* } 50 } */
   /* Statement expressions allowed in unevaluated subexpressions in
      initializers in gnu99 but not gnu89.  */
-  static int j = (1 ? 0 : ({ 0; })); /* { dg-warning "constant expression" } */
+  static int j = (1 ? 0 : ({ 0; })); /* { dg-error "constant expression" } */
+  /* { dg-error "braced" "ISO" { target *-*-* } 54 } */
 }
Index: gcc/testsuite/gcc.dg/gnu99-const-expr-1.c
===================================================================
--- gcc/testsuite/gcc.dg/gnu99-const-expr-1.c	(revision 146747)
+++ gcc/testsuite/gcc.dg/gnu99-const-expr-1.c	(working copy)
@@ -1,7 +1,7 @@
 /* Test for constant expressions: GNU extensions.  */
 /* Origin: Joseph Myers <joseph@codesourcery.com> */
 /* { dg-do compile } */
-/* { dg-options "-std=gnu99" } */
+/* { dg-options "-std=gnu99 -pedantic-errors" } */
 
 int n;
 
@@ -13,10 +13,11 @@ f (void)
   enum e1 {
     /* Integer constant expressions may not contain statement
        expressions (not a permitted operand).  */
-    E1 = (1 ? 0 : ({ 0; })), /* { dg-error "constant" } */
+    E1 = (1 ? 0 : ({ 0; })), /* { dg-error "constant expression" } */
+    /* { dg-error "ISO C forbids braced-groups" "ISO" { target *-*-* } 16 } */
     /* Real and imaginary parts act like other arithmetic
        operators.  */
-    E2 = __real__ (1 ? 0 : i++), /* { dg-error "constant" } */
+    E2 = __real__ (1 ? 0 : i++), /* { dg-error "constant expression" } */
     E3 = __real__ 0,
     E4 = __imag__ (1 ? 0 : i++), /* { dg-error "constant" } */
     E5 = __imag__ 0,
@@ -24,24 +25,32 @@ f (void)
     E6 = __alignof__ (int[n]),
     E7 = __alignof__ (a),
     /* __extension__ ignored for constant expression purposes.  */
-    E8 = __extension__ (1 ? 0 : i++), /* { dg-error "constant" } */
+    E8 = __extension__ (1 ? 0 : i++), /* { dg-error "constant expression" } */
     E9 = __extension__ 0,
     /* Conditional expressions with omitted arguments act like the
        standard type.  */ 
-    E10 = (1 ? : i++), /* { dg-error "constant" } */
-    E11 = (1 ? : 0)
+    E10 = (1 ? : i++), /* { dg-error "constant expression" } */
+    /* { dg-error "ISO C forbids omitting" "ISO" { target *-*-* } 32 } */
+    E11 = (1 ? : 0) /* { dg-error "ISO C forbids omitting" } */
   };
   enum e2 {
     /* Complex integer constants may be cast directly to integer
        types, but not after further arithmetic on them.  */
-    F1 = (int) (_Complex int) 2i, /* { dg-error "constant" } */
-    F2 = (int) +2i, /* { dg-error "constant" } */
-    F3 = (int) (1 + 2i), /* { dg-error "constant" } */
-    F4 = (int) 2i
+    F1 = (int) (_Complex int) 2i, /* { dg-error "constant expression" } */
+    /* { dg-error "complex" "complex" { target *-*-* } 39 } */
+    /* { dg-error "imaginary" "imaginary" { target *-*-* } 39 } */
+    F2 = (int) +2i, /* { dg-error "constant expression" } */
+    /* { dg-error "imaginary" "ISO" { target *-*-* } 42 } */
+    F3 = (int) (1 + 2i), /* { dg-error "constant expression" } */
+    /* { dg-error "imaginary" "ISO" { target *-*-* } 44 } */
+    F4 = (int) 2i /* { dg-error "imaginary" } */
   };
   static double dr = __real__ (1.0 + 2.0i);
+  /* { dg-error "imaginary" "ISO" { target *-*-* } 48 } */
   static double di = __imag__ (1.0 + 2.0i);
+  /* { dg-error "imaginary" "ISO" { target *-*-* } 50 } */
   /* Statement expressions allowed in unevaluated subexpressions in
      initializers in gnu99 but not gnu89.  */
   static int j = (1 ? 0 : ({ 0; }));
+  /* { dg-error "braced" "ISO" { target *-*-* } 54 } */
 }
Index: gcc/testsuite/gcc.dg/enum-const-2.c
===================================================================
--- gcc/testsuite/gcc.dg/enum-const-2.c	(revision 0)
+++ gcc/testsuite/gcc.dg/enum-const-2.c	(revision 0)
@@ -0,0 +1,8 @@
+/* Test for enumeration constants not integer constant expressions but
+   folding to integer constants (used in Linux kernel,
+   <http://gcc.gnu.org/ml/gcc/2009-04/msg00677.html>).  */
+/* { dg-do compile } */
+/* { dg-options "-pedantic" } */
+
+extern int i;
+enum e { E = (1 ? 1 : i) }; /* { dg-warning "not an integer constant expression" } */
Index: gcc/c-decl.c
===================================================================
--- gcc/c-decl.c	(revision 146778)
+++ gcc/c-decl.c	(working copy)
@@ -6077,16 +6077,32 @@ build_enumerator (struct c_enum_contents
 	 undeclared identifier) - just ignore the value expression.  */
       if (value == error_mark_node)
 	value = 0;
-      else if (!INTEGRAL_TYPE_P (TREE_TYPE (value))
-	       || TREE_CODE (value) != INTEGER_CST)
+      else if (!INTEGRAL_TYPE_P (TREE_TYPE (value)))
 	{
 	  error ("enumerator value for %qE is not an integer constant", name);
 	  value = 0;
 	}
       else
 	{
-	  value = default_conversion (value);
-	  constant_expression_warning (value);
+	  if (TREE_CODE (value) != INTEGER_CST)
+	    {
+	      value = c_fully_fold (value, false, NULL);
+	      if (TREE_CODE (value) == INTEGER_CST)
+		pedwarn (value_loc, OPT_pedantic,
+			 "enumerator value for %qE is not an integer "
+			 "constant expression", name);
+	    }
+	  if (TREE_CODE (value) != INTEGER_CST)
+	    {
+	      error ("enumerator value for %qE is not an integer constant",
+		     name);
+	      value = 0;
+	    }
+	  else
+	    {
+	      value = default_conversion (value);
+	      constant_expression_warning (value);
+	    }
 	}
     }
 

-- 
Joseph S. Myers
joseph@codesourcery.com



More information about the Gcc-patches mailing list