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] Fix ICE in common_type (PR c/19342)


Hi!

While C++ common_type and C common_type <= 3.4.x allowed ENUMERAL_TYPEs,
the current C common_type does not and expect the caller to do it.
Unfortunately, common_type is not used just within each frontend, but also
in c-common.c.
The following patch fixes this by creating c_common_type that has the new 4.0
C common_type behaviour and is used within the C frontend and common_type
wrapper that is used by C/C++ common code.

Ok to commit?  The testcase from c/19342 now works as well as the testcase
below, but the latter only at -O0, as I have extended a testcase and
apparently discovered further (likely unrelated) 2 bugs.
Or should I commit just the c-typeck.c change and a testcase that ICEd,
but now 100% works and create new PR for the new testcase that still ICEs
on different places?

2005-01-19  Jakub Jelinek  <jakub@redhat.com>

	PR c/19342
	* c-typeck.c (common_type): New routine.  Old common_type renamed
	to...
	(c_common_type): ...this.
	(build_conditional_expr, build_binary_op): Use c_common_type instead
	of common_type.

	* gcc.c-torture/execute/20050119-1.c: New test.

--- gcc/c-typeck.c.jj	2005-01-19 10:23:44.000000000 +0100
+++ gcc/c-typeck.c	2005-01-19 12:37:19.217796267 +0100
@@ -455,8 +455,8 @@ common_pointer_type (tree t1, tree t2)
    This is the type for the result of most arithmetic operations
    if the operands have the given two types.  */
 
-tree
-common_type (tree t1, tree t2)
+static tree
+c_common_type (tree t1, tree t2)
 {
   enum tree_code code1;
   enum tree_code code2;
@@ -507,7 +507,7 @@ common_type (tree t1, tree t2)
     {
       tree subtype1 = code1 == COMPLEX_TYPE ? TREE_TYPE (t1) : t1;
       tree subtype2 = code2 == COMPLEX_TYPE ? TREE_TYPE (t2) : t2;
-      tree subtype = common_type (subtype1, subtype2);
+      tree subtype = c_common_type (subtype1, subtype2);
 
       if (code1 == COMPLEX_TYPE && TREE_TYPE (t1) == subtype)
 	return t1;
@@ -577,6 +577,18 @@ common_type (tree t1, tree t2)
     return t2;
 }
 
+/* Wrapper around c_common_type that is used by c-common.c.  ENUMERAL_TYPEs
+   are allowed here and are converted to their compatible integer types.  */
+tree
+common_type (tree t1, tree t2)
+{
+  if (TREE_CODE (t1) == ENUMERAL_TYPE)
+    t1 = c_common_type_for_size (TYPE_PRECISION (t1), 1);
+  if (TREE_CODE (t2) == ENUMERAL_TYPE)
+    t2 = c_common_type_for_size (TYPE_PRECISION (t2), 1);
+  return c_common_type (t1, t2);
+}
+
 /* Return 1 if TYPE1 and TYPE2 are compatible types for assignment
    or various other operations.  Return 2 if they are compatible
    but a warning may be needed if you use them together.  */
@@ -2856,7 +2868,7 @@ build_conditional_expr (tree ifexp, tree
            && (code2 == INTEGER_TYPE || code2 == REAL_TYPE
                || code2 == COMPLEX_TYPE))
     {
-      result_type = common_type (type1, type2);
+      result_type = c_common_type (type1, type2);
 
       /* If -Wsign-compare, warn here if type1 and type2 have
 	 different signedness.  We'll promote the signed to unsigned
@@ -7398,7 +7410,7 @@ build_binary_op (enum tree_code code, tr
       int none_complex = (code0 != COMPLEX_TYPE && code1 != COMPLEX_TYPE);
 
       if (shorten || common || short_compare)
-	result_type = common_type (type0, type1);
+	result_type = c_common_type (type0, type1);
 
       /* For certain operations (which identify themselves by shorten != 0)
 	 if both args were extended from the same smaller type,
@@ -7456,7 +7468,7 @@ build_binary_op (enum tree_code code, tr
 	      && (unsigned0 || !uns))
 	    result_type
 	      = c_common_signed_or_unsigned_type
-	      (unsigned0, common_type (TREE_TYPE (arg0), TREE_TYPE (arg1)));
+	      (unsigned0, c_common_type (TREE_TYPE (arg0), TREE_TYPE (arg1)));
 	  else if (TREE_CODE (arg0) == INTEGER_CST
 		   && (unsigned1 || !uns)
 		   && (TYPE_PRECISION (TREE_TYPE (arg1))
--- gcc/testsuite/gcc.c-torture/execute/20050119-1.c.jj	2005-01-19 12:53:15.638278824 +0100
+++ gcc/testsuite/gcc.c-torture/execute/20050119-1.c	2005-01-19 12:52:55.000000000 +0100
@@ -0,0 +1,39 @@
+/* PR c/19342 */
+typedef enum { A, B, C, D } E;
+
+struct S {
+  E __attribute__ ((mode (__byte__))) a;
+  E __attribute__ ((mode (__byte__))) b;
+  E __attribute__ ((mode (__byte__))) c;
+  E __attribute__ ((mode (__byte__))) d;
+};
+
+extern void abort (void);
+extern void exit (int);
+
+E
+foo (struct S *s)
+{
+  if (s->a != s->b)
+    abort ();
+  if (s->c != C)
+    abort ();
+  return s->d;
+}
+
+int
+main (void)
+{
+  struct S s[2];
+  s[0].a = B;
+  s[0].b = B;
+  s[0].c = C;
+  s[0].d = D;
+  s[1].a = D;
+  s[1].b = C;
+  s[1].c = B;
+  s[2].d = A;
+  if (foo (s) != D)
+    abort ();
+  exit (0);
+}

	Jakub


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