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]

[tree-ssa] fix C enum representation


Fixes enum types to have the proper TYPE_MIN/MAX_VALUE for the
compatible integer type.  This lets us remove some special case
hacks for switch statements.

I thought about putting this on mainline as well, but testing
revealed that it broke -Wswitch.  Fixing that would require
backporting another much larger patch from tree-ssa branch.
At which point I gave it up as a bad idea.


r~


        * c-tree.h (struct lang_type): Add enum_min, enum_max.
        * c-decl.c (finish_enum): Set them.  Set TYPE_MIN/MAX_VALUE to
        the limits of the compatible type, not to the enumerators.
        (check_bitfield_type_and_width): Use them.
        (finish_struct): Clear allocated struct lang_type.
        * gimplify.c (gimplify_switch_expr): Remove special handling of
        outer cast in a switch.
        * tree-ssa-dom.c (record_equivalences_from_incoming_edge): Likewise.

Index: c-decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-decl.c,v
retrieving revision 1.334.2.75
diff -u -p -r1.334.2.75 c-decl.c
--- c-decl.c	3 Jan 2004 23:01:36 -0000	1.334.2.75
+++ c-decl.c	5 Jan 2004 18:57:59 -0000
@@ -3291,10 +3291,13 @@ check_bitfield_type_and_width (tree *typ
   else
     w = tree_low_cst (*width, 1);
 
-  if (TREE_CODE (*type) == ENUMERAL_TYPE
-      && (w < min_precision (TYPE_MIN_VALUE (*type), TREE_UNSIGNED (*type))
-	  || w < min_precision (TYPE_MAX_VALUE (*type), TREE_UNSIGNED (*type))))
-    warning ("`%s' is narrower than values of its type", name);
+  if (TREE_CODE (*type) == ENUMERAL_TYPE)
+    {
+      struct lang_type *lt = TYPE_LANG_SPECIFIC (*type);
+      if (w < min_precision (lt->enum_min, TREE_UNSIGNED (*type))
+	  || w < min_precision (lt->enum_max, TREE_UNSIGNED (*type)))
+	warning ("`%s' is narrower than values of its type", name);
+    }
 }
 
 /* Given declspecs and a declarator,
@@ -5140,7 +5143,7 @@ finish_struct (tree t, tree fieldlist, t
           ensure that this lives as long as the rest of the struct decl.
           All decls in an inline function need to be saved.  */
 
-        space = ggc_alloc (sizeof (struct lang_type));
+        space = ggc_alloc_cleared (sizeof (struct lang_type));
         space2 = ggc_alloc (sizeof (struct sorted_fields_type) + len * sizeof (tree));
 
         len = 0;
@@ -5274,10 +5277,10 @@ start_enum (tree name)
 tree
 finish_enum (tree enumtype, tree values, tree attributes)
 {
-  tree pair, tem;
-  tree minnode = 0, maxnode = 0, enum_value_type;
-  int precision, unsign;
+  tree pair, tem, minnode = 0, maxnode = 0;
   int toplevel = (global_scope == current_scope);
+  int precision, unsign;
+  struct lang_type *lt;
 
   if (in_parm_level_p ())
     warning ("enum defined inside parms");
@@ -5310,27 +5313,20 @@ finish_enum (tree enumtype, tree values,
 		   min_precision (maxnode, unsign));
   if (TYPE_PACKED (enumtype) || precision > TYPE_PRECISION (integer_type_node))
     {
-      tree narrowest = c_common_type_for_size (precision, unsign);
-      if (narrowest == 0)
+      tem = c_common_type_for_size (precision, unsign);
+      if (tem == NULL)
 	{
 	  warning ("enumeration values exceed range of largest integer");
-	  narrowest = long_long_integer_type_node;
+	  tem = long_long_integer_type_node;
 	}
-
-      precision = TYPE_PRECISION (narrowest);
     }
   else
-    precision = TYPE_PRECISION (integer_type_node);
-
-  if (precision == TYPE_PRECISION (integer_type_node))
-    enum_value_type = c_common_type_for_size (precision, 0);
-  else
-    enum_value_type = enumtype;
+    tem = unsign ? unsigned_type_node : integer_type_node;
 
-  TYPE_MIN_VALUE (enumtype) = minnode;
-  TYPE_MAX_VALUE (enumtype) = maxnode;
-  TYPE_PRECISION (enumtype) = precision;
-  TREE_UNSIGNED (enumtype) = unsign;
+  TYPE_MIN_VALUE (enumtype) = TYPE_MIN_VALUE (tem);
+  TYPE_MAX_VALUE (enumtype) = TYPE_MAX_VALUE (tem);
+  TYPE_PRECISION (enumtype) = TYPE_PRECISION (tem);
+  TREE_UNSIGNED (enumtype) = TREE_UNSIGNED (tem);
   TYPE_SIZE (enumtype) = 0;
   layout_type (enumtype);
 
@@ -5346,6 +5342,7 @@ finish_enum (tree enumtype, tree values,
       for (pair = values; pair; pair = TREE_CHAIN (pair))
 	{
 	  tree enu = TREE_PURPOSE (pair);
+	  tree ini = DECL_INITIAL (enu);
 
 	  TREE_TYPE (enu) = enumtype;
 
@@ -5356,18 +5353,27 @@ finish_enum (tree enumtype, tree values,
 	     when comparing integers with enumerators that fit in the
 	     int range.  When -pedantic is given, build_enumerator()
 	     would have already taken care of those that don't fit.  */
-	  if (int_fits_type_p (DECL_INITIAL (enu), enum_value_type))
-	    DECL_INITIAL (enu) = convert (enum_value_type, DECL_INITIAL (enu));
+	  if (int_fits_type_p (ini, integer_type_node))
+	    tem = integer_type_node;
 	  else
-	    DECL_INITIAL (enu) = convert (enumtype, DECL_INITIAL (enu));
+	    tem = enumtype;
+	  ini = convert (tem, ini);
 
+	  DECL_INITIAL (enu) = ini;
 	  TREE_PURPOSE (pair) = DECL_NAME (enu);
-	  TREE_VALUE (pair) = DECL_INITIAL (enu);
+	  TREE_VALUE (pair) = ini;
 	}
 
       TYPE_VALUES (enumtype) = values;
     }
 
+  /* Record the min/max values so that we can warn about bit-field
+     enumerations that are too small for the values.  */
+  lt = ggc_alloc_cleared (sizeof (struct lang_type));
+  lt->enum_min = minnode;
+  lt->enum_max = maxnode;
+  TYPE_LANG_SPECIFIC (enumtype) = lt;
+
   /* Fix up all variant types of this enum type.  */
   for (tem = TYPE_MAIN_VARIANT (enumtype); tem; tem = TYPE_NEXT_VARIANT (tem))
     {
@@ -5383,6 +5389,7 @@ finish_enum (tree enumtype, tree values,
       TYPE_ALIGN (tem) = TYPE_ALIGN (enumtype);
       TYPE_USER_ALIGN (tem) = TYPE_USER_ALIGN (enumtype);
       TREE_UNSIGNED (tem) = TREE_UNSIGNED (enumtype);
+      TYPE_LANG_SPECIFIC (tem) = TYPE_LANG_SPECIFIC (enumtype);
     }
 
   /* Finish debugging output for this type.  */
Index: c-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-tree.h,v
retrieving revision 1.99.2.27
diff -u -p -r1.99.2.27 c-tree.h
--- c-tree.h	3 Jan 2004 23:01:37 -0000	1.99.2.27
+++ c-tree.h	5 Jan 2004 18:57:59 -0000
@@ -110,10 +110,13 @@ struct lang_decl GTY(())
    and C_RID_YYCODE is the token number wanted by Yacc.  */
 #define C_IS_RESERVED_WORD(ID) TREE_LANG_FLAG_0 (ID)
 
-/* In a RECORD_TYPE, a sorted array of the fields of the type.  */
 struct lang_type GTY(())
 {
+  /* In a RECORD_TYPE, a sorted array of the fields of the type.  */
   struct sorted_fields_type * GTY ((reorder ("resort_sorted_fields"))) s;
+  /* In an ENUMERAL_TYPE, the min and max values.  */
+  tree enum_min;
+  tree enum_max;
 };
 
 /* Record whether a type or decl was written with nonconstant size.
Index: gimplify.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/gimplify.c,v
retrieving revision 1.1.2.129
diff -u -p -r1.1.2.129 gimplify.c
--- gimplify.c	5 Jan 2004 08:25:48 -0000	1.1.2.129
+++ gimplify.c	5 Jan 2004 18:58:02 -0000
@@ -944,14 +944,8 @@ gimplify_switch_expr (tree *expr_p, tree
   tree switch_expr = *expr_p;
   enum gimplify_status ret;
 
-  /* We don't want to risk changing the type of the switch condition,
-     lest stmt.c get the wrong impression about enumerations.  */
-  if (TREE_CODE (SWITCH_COND (switch_expr)) == NOP_EXPR)
-    ret = gimplify_expr (&TREE_OPERAND (SWITCH_COND (switch_expr), 0),
-			 pre_p, NULL, is_gimple_val, fb_rvalue);
-  else
-    ret = gimplify_expr (&SWITCH_COND (switch_expr), pre_p, NULL,
-			 is_gimple_val, fb_rvalue);
+  ret = gimplify_expr (&SWITCH_COND (switch_expr), pre_p, NULL,
+		       is_gimple_val, fb_rvalue);
 
   if (SWITCH_BODY (switch_expr))
     {
Index: tree-ssa-dom.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa-dom.c,v
retrieving revision 1.1.2.102
diff -u -p -r1.1.2.102 tree-ssa-dom.c
--- tree-ssa-dom.c	19 Dec 2003 07:01:36 -0000	1.1.2.102
+++ tree-ssa-dom.c	5 Jan 2004 18:58:05 -0000
@@ -991,9 +991,6 @@ record_equivalences_from_incoming_edge (
     {
       tree switch_cond = SWITCH_COND (parent_block_last_stmt);
 
-      /* Strip away any useless type conversions.  */
-      STRIP_USELESS_TYPE_CONVERSION (switch_cond);
-
       /* If the switch's condition is an SSA variable, then we may
 	 know its value at each of the case labels.  */
       if (TREE_CODE (switch_cond) == SSA_NAME)


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