From 126e660935733b9141a2bc23dec3ed25fa339310 Mon Sep 17 00:00:00 2001
From: Jakub Jelinek <jakub@redhat.com>
Date: Mon, 21 Mar 2011 18:57:34 +0100
Subject: [PATCH] re PR c/42544 (Bad codegen with signed short cast to unsigned
 int, then promoted to unsigned long long)

	PR c/42544
	PR c/48197
	* c-common.c (shorten_compare): If primopN is first sign-extended
	to opN and then zero-extended to result type, set primopN to opN.

	* gcc.c-torture/execute/pr42544.c: New test.
	* gcc.c-torture/execute/pr48197.c: New test.

From-SVN: r171252
---
 gcc/ChangeLog                                 |  7 ++++++
 gcc/c-family/c-common.c                       | 14 +++++++++++
 gcc/testsuite/ChangeLog                       |  7 ++++++
 gcc/testsuite/gcc.c-torture/execute/pr42544.c | 14 +++++++++++
 gcc/testsuite/gcc.c-torture/execute/pr48197.c | 25 +++++++++++++++++++
 5 files changed, 67 insertions(+)
 create mode 100644 gcc/testsuite/gcc.c-torture/execute/pr42544.c
 create mode 100644 gcc/testsuite/gcc.c-torture/execute/pr48197.c

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 921109aa3188..7296dec723bb 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2011-03-20  Jakub Jelinek  <jakub@redhat.com>
+
+	PR c/42544
+	PR c/48197
+	* c-common.c (shorten_compare): If primopN is first sign-extended
+	to opN and then zero-extended to result type, set primopN to opN.
+
 2011-03-21  Daniel Jacobowitz  <dan@codesourcery.com>
 
 	* config/arm/unwind-arm.c (__gnu_unwind_pr_common): Correct test
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 3f1b964401f7..33af3d82eae9 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -3301,6 +3301,20 @@ shorten_compare (tree *op0_ptr, tree *op1_ptr, tree *restype_ptr,
   primop0 = get_narrower (op0, &unsignedp0);
   primop1 = get_narrower (op1, &unsignedp1);
 
+  /* If primopN is first sign-extended from primopN's precision to opN's
+     precision, then zero-extended from opN's precision to
+     *restype_ptr precision, shortenings might be invalid.  */
+  if (TYPE_PRECISION (TREE_TYPE (primop0)) < TYPE_PRECISION (TREE_TYPE (op0))
+      && TYPE_PRECISION (TREE_TYPE (op0)) < TYPE_PRECISION (*restype_ptr)
+      && !unsignedp0
+      && TYPE_UNSIGNED (TREE_TYPE (op0)))
+    primop0 = op0;
+  if (TYPE_PRECISION (TREE_TYPE (primop1)) < TYPE_PRECISION (TREE_TYPE (op1))
+      && TYPE_PRECISION (TREE_TYPE (op1)) < TYPE_PRECISION (*restype_ptr)
+      && !unsignedp1
+      && TYPE_UNSIGNED (TREE_TYPE (op1)))
+    primop1 = op1;
+
   /* Handle the case that OP0 does not *contain* a conversion
      but it *requires* conversion to FINAL_TYPE.  */
 
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 97fa329bb007..cc8d1458ebce 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,10 @@
+2011-03-20  Jakub Jelinek  <jakub@redhat.com>
+
+	PR c/42544
+	PR c/48197
+	* gcc.c-torture/execute/pr42544.c: New test.
+	* gcc.c-torture/execute/pr48197.c: New test.
+
 2011-03-21  Michael Meissner  <meissner@linux.vnet.ibm.com>
 
 	PR preprocessor/48192
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr42544.c b/gcc/testsuite/gcc.c-torture/execute/pr42544.c
new file mode 100644
index 000000000000..c5951b06a176
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr42544.c
@@ -0,0 +1,14 @@
+/* PR c/42544 */
+
+extern void abort (void);
+
+int
+main ()
+{
+  signed short s = -1;
+  if (sizeof (long long) == sizeof (unsigned int))
+    return 0;
+  if ((unsigned int) s >= 0x100000000ULL)
+    abort ();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr48197.c b/gcc/testsuite/gcc.c-torture/execute/pr48197.c
new file mode 100644
index 000000000000..37812c07b0cc
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr48197.c
@@ -0,0 +1,25 @@
+/* PR c/48197 */
+
+extern void abort (void);
+static int y = 0x8000;
+
+int
+main ()
+{
+  unsigned int x = (short)y;
+  if (sizeof (0LL) == sizeof (0U))
+    return 0;
+  if (0LL > (0U ^ (short)-0x8000))
+    abort ();
+  if (0LL > (0U ^ x))
+    abort ();
+  if (0LL > (0U ^ (short)y))
+    abort ();
+  if ((0U ^ (short)-0x8000) < 0LL)
+    abort ();
+  if ((0U ^ x) < 0LL)
+    abort ();
+  if ((0U ^ (short)y) < 0LL)
+    abort ();
+  return 0;
+}
-- 
GitLab