Patch for PR c/32295

Joseph S. Myers joseph@codesourcery.com
Tue Sep 25 15:44:00 GMT 2007


This patch fixes PR 32295, an ICE on uses of variables of incomplete
enum type (a GNU extension).

Since the aim of the extension is to act like incomplete struct and
union types, it seems you should be able to declare such variables
with "extern" - and then take their addresses, but not use their
values; and declaring such variables with "static" falls under PRs
24293 and 26581.  So this patch continues to allow such declarations
when presently allowed, while requiring complete types when the value
is used.

Bootstrapped with no regressions on i686-pc-linux-gnu.  Applied to
mainline.  Will apply to 4.2 branch after 4.2.2 is released subject to
testing there.

2007-09-25  Joseph Myers  <joseph@codesourcery.com>

	PR c/32295
	* c-typeck.c (default_conversion): Call require_complete_type
	before perform_integral_promotions.
	(build_unary_op): Call require_complete_type except for ADDR_EXPR.
	(build_c_cast): Call require_complete_type except for casts to
	void types.
	(convert_for_assignment): Call require_complete_type.

testsuite:
2007-09-25  Joseph Myers  <joseph@codesourcery.com>

	PR c/32295
	* gcc.dg/enum-incomplete-1.c: New test.

Index: gcc/c-typeck.c
===================================================================
--- gcc/c-typeck.c	(revision 128710)
+++ gcc/c-typeck.c	(working copy)
@@ -1770,14 +1770,19 @@
   if (TREE_NO_WARNING (orig_exp))
     TREE_NO_WARNING (exp) = 1;
 
-  if (INTEGRAL_TYPE_P (type))
-    return perform_integral_promotions (exp);
-
   if (code == VOID_TYPE)
     {
       error ("void value not ignored as it ought to be");
       return error_mark_node;
     }
+
+  exp = require_complete_type (exp);
+  if (exp == error_mark_node)
+    return error_mark_node;
+
+  if (INTEGRAL_TYPE_P (type))
+    return perform_integral_promotions (exp);
+
   return exp;
 }
 
@@ -2871,11 +2876,15 @@
   /* No default_conversion here.  It causes trouble for ADDR_EXPR.  */
   tree arg = xarg;
   tree argtype = 0;
-  enum tree_code typecode = TREE_CODE (TREE_TYPE (arg));
+  enum tree_code typecode;
   tree val;
   int noconvert = flag;
   const char *invalid_op_diag;
 
+  if (code != ADDR_EXPR)
+    arg = require_complete_type (arg);
+
+  typecode = TREE_CODE (TREE_TYPE (arg));
   if (typecode == ERROR_MARK)
     return error_mark_node;
   if (typecode == ENUMERAL_TYPE || typecode == BOOLEAN_TYPE)
@@ -3589,6 +3598,13 @@
       return error_mark_node;
     }
 
+  if (!VOID_TYPE_P (type))
+    {
+      value = require_complete_type (value);
+      if (value == error_mark_node)
+	return error_mark_node;
+    }
+
   if (type == TYPE_MAIN_VARIANT (TREE_TYPE (value)))
     {
       if (pedantic)
@@ -3998,6 +4014,9 @@
       error ("void value not ignored as it ought to be");
       return error_mark_node;
     }
+  rhs = require_complete_type (rhs);
+  if (rhs == error_mark_node)
+    return error_mark_node;
   /* A type converts to a reference to it.
      This code doesn't fully support references, it's just for the
      special case of va_start and va_copy.  */
Index: gcc/testsuite/gcc.dg/enum-incomplete-1.c
===================================================================
--- gcc/testsuite/gcc.dg/enum-incomplete-1.c	(revision 0)
+++ gcc/testsuite/gcc.dg/enum-incomplete-1.c	(revision 0)
@@ -0,0 +1,86 @@
+/* Test for uses of incomplete enum variables: should be allowed just
+   when incomplete structs are allowed.  PR 32295.  */
+/* Origin: Joseph Myers <joseph@codesourcery.com> */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+extern enum e ve;
+extern struct s vs;
+void *p;
+
+int
+f0 (int i)
+{
+  ve; /* { dg-error "incomplete" } */
+  vs; /* { dg-error "incomplete" } */
+  (void) ve;
+  (void) vs;
+  (void) (i ? ve : ve); /* { dg-error "incomplete" } */
+  (void) (i ? vs : vs); /* { dg-error "incomplete" } */
+  (void) (ve = ve); /* { dg-error "incomplete" } */
+  (void) (vs = vs); /* { dg-error "incomplete" } */
+  (void) ve, (void) ve;
+  (void) vs, (void) vs;
+  p = &ve;
+  p = &vs;
+  (void) sizeof (ve); /* { dg-error "incomplete" } */
+  (void) sizeof (vs); /* { dg-error "incomplete" } */
+  typeof (ve) *pe;
+  typeof (vs) *ps;
+  /* ??? alignof should probably not be accepted here.  */
+  (void) __alignof (ve);
+  (void) __alignof (vs);
+  (void) (ve + i); /* { dg-error "incomplete" } */
+  (void) (i * ve); /* { dg-error "incomplete" } */
+  (void) (i / ve); /* { dg-error "incomplete" } */
+  (void) (ve - i); /* { dg-error "incomplete" } */
+  (void) (ve << i); /* { dg-error "incomplete" } */
+  (void) (i >> ve); /* { dg-error "incomplete" } */
+  (void) (ve < i); /* { dg-error "incomplete" } */
+  (void) (ve <= i); /* { dg-error "incomplete" } */
+  (void) (i > ve); /* { dg-error "incomplete" } */
+  (void) (i >= ve); /* { dg-error "incomplete" } */
+  (void) (ve == i); /* { dg-error "incomplete" } */
+  (void) (i != ve); /* { dg-error "incomplete" } */
+  (void) (ve & i); /* { dg-error "incomplete" } */
+  (void) (ve ^ i); /* { dg-error "incomplete" } */
+  (void) (i | ve); /* { dg-error "incomplete" } */
+  (void) (i && ve); /* { dg-error "incomplete" } */
+  (void) (ve || i); /* { dg-error "incomplete" } */
+  (void) -ve; /* { dg-error "incomplete" } */
+  (void) +ve; /* { dg-error "incomplete" } */
+  (void) ~ve; /* { dg-error "incomplete" } */
+  (void) !ve; /* { dg-error "incomplete" } */
+  (void) --ve; /* { dg-error "incomplete" } */
+  (void) ++ve; /* { dg-error "incomplete" } */
+  (void) ve--; /* { dg-error "incomplete" } */
+  (void) ve++; /* { dg-error "incomplete" } */
+  i = ve; /* { dg-error "incomplete" } */
+  i *= ve; /* { dg-error "incomplete" } */
+  i /= ve; /* { dg-error "incomplete" } */
+  i %= ve; /* { dg-error "incomplete" } */
+  i += ve; /* { dg-error "incomplete" } */
+  i -= ve; /* { dg-error "incomplete" } */
+  i <<= ve; /* { dg-error "incomplete" } */
+  i >>= ve; /* { dg-error "incomplete" } */
+  i &= ve; /* { dg-error "incomplete" } */
+  i ^= ve; /* { dg-error "incomplete" } */
+  i |= ve; /* { dg-error "incomplete" } */
+  (void) (ve ? 1 : 1); /* { dg-error "incomplete" } */
+  (void) (int) ve; /* { dg-error "incomplete" } */
+  f0 (ve); /* { dg-error "incomplete" } */
+  if (ve) /* { dg-error "incomplete" } */
+    ;
+  do
+    ;
+  while (ve); /* { dg-error "incomplete" } */
+  while (ve) /* { dg-error "incomplete" } */
+    ;
+  _Bool b = ve; /* { dg-error "incomplete" } */
+  float f = ve; /* { dg-error "incomplete" } */
+  switch (ve) /* { dg-error "incomplete" } */
+    ;
+  for (; ve;) /* { dg-error "incomplete" } */
+    ;
+  return ve; /* { dg-error "incomplete" } */
+}

-- 
Joseph S. Myers
joseph@codesourcery.com



More information about the Gcc-patches mailing list