From d0c5c9b14da834ec8345a4aca53d45334cb5562a Mon Sep 17 00:00:00 2001
From: Roger Sayle <roger@eyesopen.com>
Date: Wed, 25 Aug 2004 20:51:02 +0000
Subject: [PATCH] re PR middle-end/16693 (Bitwise AND is lost when used within
 a cast to an enum of the same precision)

	PR middle-end/16693
	PR tree-optimization/16372
	* decl.c (finish_enum): Make the precision of the enumerated type
	the same width as the underlying integer type.

	* g++.dg/opt/pr16372-1.C: New test case.
	* g++.dg/opt/pr16693-1.C: New test case.
	* g++.dg/opt/pr16693-2.C: New test case.

From-SVN: r86576
---
 gcc/cp/ChangeLog                     |  7 +++++++
 gcc/cp/decl.c                        |  9 ++++++++-
 gcc/testsuite/ChangeLog              |  8 ++++++++
 gcc/testsuite/g++.dg/opt/pr16372-1.C | 17 +++++++++++++++++
 gcc/testsuite/g++.dg/opt/pr16693-1.C | 25 +++++++++++++++++++++++++
 gcc/testsuite/g++.dg/opt/pr16693-2.C | 21 +++++++++++++++++++++
 6 files changed, 86 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/opt/pr16372-1.C
 create mode 100644 gcc/testsuite/g++.dg/opt/pr16693-1.C
 create mode 100644 gcc/testsuite/g++.dg/opt/pr16693-2.C

diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index c895d54698c3..ec071ae745ae 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,10 @@
+2004-08-25  Roger Sayle  <roger@eyesopen.com>
+
+	PR middle-end/16693
+	PR tree-optimization/16372
+	* decl.c (finish_enum): Make the precision of the enumerated type
+	the same width as the underlying integer type.
+
 2004-08-25  Mark Mitchell  <mark@codesourcery.com>
 
 	PR c++/17155
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 05db490cffc6..dfb568193248 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -9373,7 +9373,14 @@ finish_enum (tree enumtype)
      underlying type in the range bmin to bmax, where bmin and bmax are,
      respectively, the smallest and largest values of the smallest bit-
      field that can store emin and emax.  */
-  TYPE_PRECISION (enumtype) = precision;
+
+  /* The middle-end currently assumes that types with TYPE_PRECISION
+     narrower than their underlying type are suitably zero or sign
+     extended to fill their mode.  g++ doesn't make these guarantees.
+     Until the middle-end can represent such paradoxical types, we
+     set the TYPE_PRECISON to the width of the underlying type.  */
+  TYPE_PRECISION (enumtype) = TYPE_PRECISION (underlying_type);
+
   set_min_and_max_values_for_integral_type (enumtype, precision, unsignedp);
 
   /* [dcl.enum]
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index ec0349e33e7d..564e993132c9 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,11 @@
+2004-08-25  Roger Sayle  <roger@eyesopen.com>
+
+	PR middle-end/16693
+	PR tree-optimization/16372
+	* g++.dg/opt/pr16372-1.C: New test case.
+	* g++.dg/opt/pr16693-1.C: New test case.
+	* g++.dg/opt/pr16693-2.C: New test case.
+
 2004-08-25  Ziemowit Laski  <zlaski@apple.com>
 
 	* objc.dg/proto-lossage-4.m: New test.
diff --git a/gcc/testsuite/g++.dg/opt/pr16372-1.C b/gcc/testsuite/g++.dg/opt/pr16372-1.C
new file mode 100644
index 000000000000..b797e4ad29dc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/pr16372-1.C
@@ -0,0 +1,17 @@
+// PR tree-optimization/16372
+// { dg-do run }
+// { dg-options "-O1" }
+
+extern "C" void abort();
+
+enum number {ZERO, ONE, TWO, THREE, FOUR, FIVE};
+
+int main() {
+  number n = FIVE; 
+ 
+  if((n == ONE) || (n == TWO) || (n == THREE)) { 
+    abort ();
+  } 
+  return 0;
+}
+
diff --git a/gcc/testsuite/g++.dg/opt/pr16693-1.C b/gcc/testsuite/g++.dg/opt/pr16693-1.C
new file mode 100644
index 000000000000..6b716116dd16
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/pr16693-1.C
@@ -0,0 +1,25 @@
+// PR middle-end/16693
+// { dg-do run }
+// { dg-options "-O2" }
+
+extern "C" void abort();
+
+unsigned short ret6666(int) {
+    return 0x66;
+}
+
+typedef enum {
+    a   = 0x0, b   = 0x1, c   = 0x2, d   = 0x3, e   = 0x4, f   = 0x5,
+    g   = 0x6, h   = 0x7, i   = 0x8, j   = 0x9, k   = 0xa, l   = 0xb,
+    m   = 0xc, n   = 0xd, o   = 0xe, p   = 0xf 
+} Test_Enum;
+
+int main(void) {
+    unsigned char r1;
+    r1 = static_cast<Test_Enum>(0xf & ret6666(44));
+
+    if(r1 != 0x6)
+        abort();
+    return 0;
+}
+
diff --git a/gcc/testsuite/g++.dg/opt/pr16693-2.C b/gcc/testsuite/g++.dg/opt/pr16693-2.C
new file mode 100644
index 000000000000..cb60df64264b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/pr16693-2.C
@@ -0,0 +1,21 @@
+// PR middle-end/16693
+// { dg-do run }
+// { dg-options "-O2" }
+
+extern "C" void abort();
+
+char foo()
+{
+  return 0x10;
+}
+
+enum E { e = 0x0f };
+
+int main()
+{
+  char c = (char)(E)(e & foo());
+  if (c != 0)
+    abort();
+  return 0;
+}
+
-- 
GitLab