This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix ICE in common_type (PR c/19342)
- From: Jakub Jelinek <jakub at redhat dot com>
- To: joseph at codesourcery dot com
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Wed, 19 Jan 2005 07:07:43 -0500
- Subject: [PATCH] Fix ICE in common_type (PR c/19342)
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
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