[C++ PATCH] Fix up ?: type mismatches due to bitfields at genericization time (PR c++/37146)

Jakub Jelinek jakub@redhat.com
Fri Oct 10 13:57:00 GMT 2008


Hi!

In the PR Mark said he considers all the testcases with mismatching
precision of bitfields in ?: on LHS or RHS valid, so this patch
just fixes up COND_EXPRs when passing them over from the FE to the
middle-end (at this point we know it is rvalue, not lvalue).

Bootstrapped/regtested on x86_64-linux, ok for trunk?

2008-10-10  Jakub Jelinek  <jakub@redhat.com>

	PR c++/37146
	* cp-gimplify.c (cp_genericize_r): Fix up bitfield operands of
	COND_EXPR.

	* g++.dg/torture/pr37146-1.C: New test.
	* g++.dg/torture/pr37146-2.C: New test.
	* g++.dg/expr/bitfield10.C: New test.

--- gcc/cp/cp-gimplify.c.jj	2008-10-07 20:09:53.000000000 +0200
+++ gcc/cp/cp-gimplify.c	2008-10-10 09:52:19.000000000 +0200
@@ -803,6 +803,34 @@ cp_genericize_r (tree *stmt_p, int *walk
 		      CLEANUP_BODY (stmt),
 		      CLEANUP_EXPR (stmt));
 
+  /* COND_EXPR might have incompatible types in branches if one or both
+     arms are bitfields.  Fix it up now.  */
+  else if (TREE_CODE (stmt) == COND_EXPR)
+    {
+      tree type_left
+	= (TREE_OPERAND (stmt, 1)
+	   ? is_bitfield_expr_with_lowered_type (TREE_OPERAND (stmt, 1))
+	   : NULL_TREE);
+      tree type_right
+	= (TREE_OPERAND (stmt, 2)
+	   ? is_bitfield_expr_with_lowered_type (TREE_OPERAND (stmt, 2))
+	   : NULL_TREE);
+      if (type_left)
+	{
+	  TREE_OPERAND (stmt, 1)
+	    = fold_convert (type_left, TREE_OPERAND (stmt, 1));
+	  gcc_assert (useless_type_conversion_p (TREE_TYPE (stmt),
+						 type_left));
+	}
+      if (type_right)
+	{
+	  TREE_OPERAND (stmt, 2)
+	    = fold_convert (type_right, TREE_OPERAND (stmt, 2));
+	  gcc_assert (useless_type_conversion_p (TREE_TYPE (stmt),
+						 type_right));
+	}
+    }
+
   pointer_set_insert (p_set, *stmt_p);
 
   return NULL;
--- gcc/testsuite/g++.dg/torture/pr37146-1.C.jj	2008-10-09 17:20:10.000000000 +0200
+++ gcc/testsuite/g++.dg/torture/pr37146-1.C	2008-10-09 17:20:44.000000000 +0200
@@ -0,0 +1,83 @@
+// PR c++/37146
+// { dg-do run }
+
+extern "C" void abort ();
+int a, b;
+struct A { int i:8; int j:8; int k:16; int l:32; } c;
+
+void
+f1 (int x, int y)
+{
+  (x ? a : b) = y;
+}
+
+void
+f2 (int x, int y)
+{
+  (x ? c.i : c.j) = y;
+}
+
+void
+f3 (int x, int y)
+{
+  (x ? c.i : a) = y;
+}
+
+void
+f4 (int x, int y)
+{
+  (x ? c.i : c.k) = y;
+}
+
+void
+f5 (int x, int y)
+{
+  (x ? c.l : b) = y;
+}
+
+#define CHECK(var, exp)		\
+  do				\
+    {				\
+      if (var != exp)		\
+	 abort ();		\
+      var = -1;			\
+      if (a != -1		\
+	  || b != -1		\
+	  || c.i != -1		\
+	  || c.j != -1		\
+	  || c.k != -1		\
+	  || c.l != -1)		\
+	abort ();		\
+    }				\
+  while (0)
+
+int
+main ()
+{
+  a = -1;
+  b = -1;
+  c.i = -1;
+  c.j = -1;
+  c.k = -1;
+  c.l = -1;
+  f1 (1, 264);
+  CHECK (a, 264);
+  f1 (0, 264);
+  CHECK (b, 264);
+  f2 (1, 112);
+  CHECK (c.i, 112);
+  f2 (0, 112);
+  CHECK (c.j, 112);
+  f3 (1, 26);
+  CHECK (c.i, 26);
+  f3 (0, 26);
+  CHECK (a, 26);
+  f4 (1, 107);
+  CHECK (c.i, 107);
+  f4 (0, 107);
+  CHECK (c.k, 107);
+  f5 (1, 95);
+  CHECK (c.l, 95);
+  f5 (0, 95);
+  CHECK (b, 95);
+}
--- gcc/testsuite/g++.dg/torture/pr37146-2.C.jj	2008-10-10 10:03:12.000000000 +0200
+++ gcc/testsuite/g++.dg/torture/pr37146-2.C	2008-10-10 09:59:18.000000000 +0200
@@ -0,0 +1,67 @@
+// PR c++/37146
+// { dg-do run }
+
+extern "C" void abort ();
+int a, b;
+struct A { int i:8; int j:8; int k:16; int l:32; } c;
+
+int
+f1 (int x)
+{
+  return x ? a : b;
+}
+
+int
+f2 (int x)
+{
+  return x ? c.i : c.j;
+}
+
+int
+f3 (int x)
+{
+  return x ? c.i : a;
+}
+
+int
+f4 (int x)
+{
+  return x ? c.i : c.k;
+}
+
+int
+f5 (int x)
+{
+  return x ? c.l : b;
+}
+
+int
+main ()
+{
+  a = 17;
+  b = 18;
+  c.i = 19;
+  c.j = 20;
+  c.k = 21;
+  c.l = 22;
+  if (f1 (1) != a)
+    abort ();
+  if (f1 (0) != b)
+    abort ();
+  if (f2 (1) != c.i)
+    abort ();
+  if (f2 (0) != c.j)
+    abort ();
+  if (f3 (1) != c.i)
+    abort ();
+  if (f3 (0) != a)
+    abort ();
+  if (f4 (1) != c.i)
+    abort ();
+  if (f4 (0) != c.k)
+    abort ();
+  if (f5 (1) != c.l)
+    abort ();
+  if (f5 (0) != b)
+    abort ();
+}
--- gcc/testsuite/g++.dg/expr/bitfield10.C.jj	2008-10-10 10:03:57.000000000 +0200
+++ gcc/testsuite/g++.dg/expr/bitfield10.C	2008-10-10 09:59:09.000000000 +0200
@@ -0,0 +1,16 @@
+// PR c++/37146
+// { dg-do compile }
+
+enum E { E0 = 0, E1 = 'E' };
+
+struct S
+{
+  E s0 : 8;
+  enum E foo (bool, E);
+};
+
+E
+S::foo (bool a, E b)
+{
+  return a ? s0 : b;
+}

	Jakub



More information about the Gcc-patches mailing list