* c-typeck.c (common_type): Prefer long long to long when same
authorjsm28 <jsm28@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 10 Apr 2004 18:47:50 +0000 (18:47 +0000)
committerjsm28 <jsm28@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 10 Apr 2004 18:47:50 +0000 (18:47 +0000)
precision.

testsuite:
* gcc.dg/c90-intprom-1.c, gcc.dg/c99-intprom-1.c: New tests.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@80584 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/c-typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/c90-intprom-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/c99-intprom-1.c [new file with mode: 0644]

index 44791b5..dd10d4e 100644 (file)
@@ -1,3 +1,8 @@
+2004-04-10  Joseph S. Myers  <jsm@polyomino.org.uk>
+
+       * c-typeck.c (common_type): Prefer long long to long when same
+       precision.
+
 2004-04-09  Zack Weinberg  <zack@codesourcery.com>
 
        PR 14887
index 26b8341..2170222 100644 (file)
@@ -274,7 +274,24 @@ common_type (tree t1, tree t2)
       else if (TYPE_PRECISION (t2) > TYPE_PRECISION (t1))
        return build_type_attribute_variant (t2, attributes);
 
-      /* Same precision.  Prefer longs to ints even when same size.  */
+      /* Same precision.  Prefer long longs to longs to ints when the
+        same precision, following the C99 rules on integer type rank
+        (which are equivalent to the C90 rules for C90 types).  */
+
+      if (TYPE_MAIN_VARIANT (t1) == long_long_unsigned_type_node
+         || TYPE_MAIN_VARIANT (t2) == long_long_unsigned_type_node)
+       return build_type_attribute_variant (long_long_unsigned_type_node,
+                                            attributes);
+
+      if (TYPE_MAIN_VARIANT (t1) == long_long_integer_type_node
+         || TYPE_MAIN_VARIANT (t2) == long_long_integer_type_node)
+       {
+         if (TYPE_UNSIGNED (t1) || TYPE_UNSIGNED (t2))
+            t1 = long_long_unsigned_type_node;
+         else
+            t1 = long_long_integer_type_node;
+         return build_type_attribute_variant (t1, attributes);
+       }
 
       if (TYPE_MAIN_VARIANT (t1) == long_unsigned_type_node
          || TYPE_MAIN_VARIANT (t2) == long_unsigned_type_node)
index 17cbd4d..040aac8 100644 (file)
@@ -1,3 +1,7 @@
+2004-04-10  Joseph S. Myers  <jsm@polyomino.org.uk>
+
+       * gcc.dg/c90-intprom-1.c, gcc.dg/c99-intprom-1.c: New tests.
+
 2004-04-09  Chris Demetriou  <cgd@broadcom.com>
 
        * g++.dg/other/packed1.C: Mark xfail for mips*- not mips-.
diff --git a/gcc/testsuite/gcc.dg/c90-intprom-1.c b/gcc/testsuite/gcc.dg/c90-intprom-1.c
new file mode 100644 (file)
index 0000000..78e4b39
--- /dev/null
@@ -0,0 +1,47 @@
+/* Test for integer promotion rules: C90 subset of types.  */
+/* Origin: Joseph Myers <jsm@polyomino.org.uk> */
+/* { dg-do compile } */
+/* { dg-options "-std=iso9899:1990 -pedantic-errors" } */
+
+#include <limits.h>
+
+#define CHECK(T1, T2, TC)                      \
+  do {                                         \
+    T1 a = 0;                                  \
+    T2 b = 0;                                  \
+    TC *c = 0;                                 \
+    __typeof__(a+b) *d = 0;                    \
+    c = d;                                     \
+    d = c;                                     \
+  } while (0)
+
+void
+f (void)
+{
+  /* One type is unsigned long.  */
+  CHECK(unsigned long, unsigned long, unsigned long);
+  CHECK(unsigned int, unsigned long, unsigned long);
+  CHECK(unsigned long, unsigned int, unsigned long);
+  CHECK(int, unsigned long, unsigned long);
+  CHECK(long, unsigned long, unsigned long);
+  CHECK(unsigned long, int, unsigned long);
+  CHECK(unsigned long, long, unsigned long);
+  /* long and unsigned int.  */
+#if LONG_MAX >= UINT_MAX
+  CHECK(unsigned int, long, long);
+  CHECK(long, unsigned int, long);
+#else
+  CHECK(unsigned int, long, unsigned long);
+  CHECK(long, unsigned int, unsigned long);
+#endif
+  /* One type is long.  */
+  CHECK(long, long, long);
+  CHECK(int, long, long);
+  CHECK(long, int, long);
+  /* One type is unsigned int.  */
+  CHECK(unsigned int, unsigned int, unsigned int);
+  CHECK(int, unsigned int, unsigned int);
+  CHECK(unsigned int, int, unsigned int);
+  /* Otherwise int.  */
+  CHECK(int, int, int);
+}
diff --git a/gcc/testsuite/gcc.dg/c99-intprom-1.c b/gcc/testsuite/gcc.dg/c99-intprom-1.c
new file mode 100644 (file)
index 0000000..0d7a33e
--- /dev/null
@@ -0,0 +1,77 @@
+/* Test for integer promotion rules: extended to long long by C99.  */
+/* Origin: Joseph Myers <jsm@polyomino.org.uk> */
+/* { dg-do compile } */
+/* { dg-options "-std=iso9899:1999 -pedantic-errors" } */
+
+#include <limits.h>
+
+#define CHECK(T1, T2, TC)                      \
+  do {                                         \
+    T1 a = 0;                                  \
+    T2 b = 0;                                  \
+    TC *c = 0;                                 \
+    __typeof__(a+b) *d = 0;                    \
+    c = d;                                     \
+    d = c;                                     \
+  } while (0)
+
+void
+f (void)
+{
+  /* Same type.  */
+  CHECK(int, int, int);
+  CHECK(unsigned int, unsigned int, unsigned int);
+  CHECK(long, long, long);
+  CHECK(unsigned long, unsigned long, unsigned long);
+  CHECK(long long, long long, long long);
+  CHECK(unsigned long long, unsigned long long, unsigned long long);
+  /* Both signed.  */
+  CHECK(int, long, long);
+  CHECK(int, long long, long long);
+  CHECK(long, int, long);
+  CHECK(long, long long, long long);
+  CHECK(long long, int, long long);
+  CHECK(long long, long, long long);
+  /* Both unsigned.  */
+  CHECK(unsigned int, unsigned long, unsigned long);
+  CHECK(unsigned int, unsigned long long, unsigned long long);
+  CHECK(unsigned long, unsigned int, unsigned long);
+  CHECK(unsigned long, unsigned long long, unsigned long long);
+  CHECK(unsigned long long, unsigned int, unsigned long long);
+  CHECK(unsigned long long, unsigned long, unsigned long long);
+  /* Unsigned of greater or equal rank.  */
+  CHECK(int, unsigned int, unsigned int);
+  CHECK(int, unsigned long, unsigned long);
+  CHECK(int, unsigned long long, unsigned long long);
+  CHECK(unsigned int, int, unsigned int);
+  CHECK(long, unsigned long, unsigned long);
+  CHECK(long, unsigned long long, unsigned long long);
+  CHECK(unsigned long, int, unsigned long);
+  CHECK(unsigned long, long, unsigned long);
+  CHECK(long long, unsigned long long, unsigned long long);
+  CHECK(unsigned long long, int, unsigned long long);
+  CHECK(unsigned long long, long, unsigned long long);
+  CHECK(unsigned long long, long long, unsigned long long);
+  /* Signed of greater rank.  */
+#if LONG_MAX >= UINT_MAX
+  CHECK(unsigned int, long, long);
+  CHECK(long, unsigned int, long);
+#else
+  CHECK(unsigned int, long, unsigned long);
+  CHECK(long, unsigned int, unsigned long);
+#endif
+#if LLONG_MAX >= UINT_MAX
+  CHECK(unsigned int, long long, long long);
+  CHECK(long long, unsigned int, long long);
+#else
+  CHECK(unsigned int, long long, unsigned long long);
+  CHECK(long long, unsigned int, unsigned long long);
+#endif
+#if LLONG_MAX >= ULONG_MAX
+  CHECK(unsigned long, long long, long long);
+  CHECK(long long, unsigned long, long long);
+#else
+  CHECK(unsigned long, long long, unsigned long long);
+  CHECK(long long, unsigned long, unsigned long long);
+#endif
+}