PR c++/13371
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 19 Dec 2003 20:25:22 +0000 (20:25 +0000)
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 19 Dec 2003 20:25:22 +0000 (20:25 +0000)
        * typeck.c (build_modify_expr): Stabilize lhs if we're narrowing.

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

gcc/cp/ChangeLog
gcc/cp/typeck.c
gcc/testsuite/g++.dg/init/bitfield2.C [new file with mode: 0644]

index ab064ba..6888140 100644 (file)
@@ -1,3 +1,8 @@
+2003-12-19  Jason Merrill  <jason@redhat.com>
+
+       PR c++/13371
+       * typeck.c (build_modify_expr): Stabilize lhs if we're narrowing.
+
 2003-12-18  Richard Henderson  <rth@redhat.com>
 
        * cp-tree.h (struct lang_type_header): Remove __extension__.
index 791ba21..56810e5 100644 (file)
@@ -4919,7 +4919,7 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
   tree newrhs = rhs;
   tree lhstype = TREE_TYPE (lhs);
   tree olhstype = lhstype;
-  tree olhs = lhs;
+  tree olhs = NULL_TREE;
 
   /* Avoid duplicate error messages from operands that had errors.  */
   if (lhs == error_mark_node || rhs == error_mark_node)
@@ -5149,6 +5149,15 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
 
       if (lhstype != TREE_TYPE (lhs))
        {
+         /* Avoid warnings converting integral types back into enums for
+            enum bit fields.  */
+         if (TREE_CODE (lhstype) == INTEGER_TYPE
+             && TREE_CODE (olhstype) == ENUMERAL_TYPE)
+           {
+             if (TREE_SIDE_EFFECTS (lhs))
+               lhs = stabilize_reference (lhs);
+             olhs = lhs;
+           }
          lhs = copy_node (lhs);
          TREE_TYPE (lhs) = lhstype;
        }
@@ -5221,10 +5230,7 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
 
   if (olhstype == TREE_TYPE (result))
     return result;
-  /* Avoid warnings converting integral types back into enums
-     for enum bit fields.  */
-  if (TREE_CODE (TREE_TYPE (result)) == INTEGER_TYPE
-      && TREE_CODE (olhstype) == ENUMERAL_TYPE)
+  if (olhs)
     {
       result = build (COMPOUND_EXPR, olhstype, result, olhs);
       TREE_NO_UNUSED_WARNING (result) = 1;
diff --git a/gcc/testsuite/g++.dg/init/bitfield2.C b/gcc/testsuite/g++.dg/init/bitfield2.C
new file mode 100644 (file)
index 0000000..e54b2e4
--- /dev/null
@@ -0,0 +1,33 @@
+// PR c++/13371
+// Bug: We were failing to properly protect the lhs on the line marked
+// "here" from multiple evaluation.
+
+// { dg-do run }
+
+extern "C" int printf (const char *, ...);
+
+enum E { E1, E2 };
+
+struct A
+{
+  E e : 8;
+  unsigned char c;
+};
+
+A ar[2];
+
+int c;
+
+int f()
+{
+  ++c;
+  printf ("f()\n");
+  return 0;
+}
+
+int main()
+{
+  ar[0].c = 0xff;
+  ar[f()].e = E1;              // here
+  return (c != 1 || ar[0].c != 0xff);
+}