PR c++/78897 - constexpr union
authorJason Merrill <jason@redhat.com>
Fri, 10 Feb 2017 18:50:30 +0000 (13:50 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Fri, 10 Feb 2017 18:50:30 +0000 (13:50 -0500)
* constexpr.c (cxx_eval_store_expression): A store to a union member
erases a previous store to another member.

From-SVN: r245341

gcc/cp/ChangeLog
gcc/cp/constexpr.c
gcc/testsuite/g++.dg/cpp1y/constexpr-union1.C [new file with mode: 0644]

index 68c5d9d1cd9a5bdf39dc4309b530689e63528426..be51428cc5bbb66b63e6f684b2ce1b604c04287a 100644 (file)
@@ -1,5 +1,9 @@
 2017-02-10  Jason Merrill  <jason@redhat.com>
 
+       PR c++/78897 - constexpr union
+       * constexpr.c (cxx_eval_store_expression): A store to a union member
+       erases a previous store to another member.
+
        PR c++/71285 - member of fold-expression
        * semantics.c (finish_unary_fold_expr)
        (finish_binary_fold_expr): Use null type for fold-expressions.
index bb45f1e805998a0ccd17c40f2dfe71e3972963a0..bfdde9e911dd28a246cd99130cc5cd7027288307 100644 (file)
@@ -3466,6 +3466,11 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
          tree fields = TYPE_FIELDS (DECL_CONTEXT (index));
          unsigned HOST_WIDE_INT idx;
 
+         if (code == UNION_TYPE && CONSTRUCTOR_NELTS (*valp)
+             && CONSTRUCTOR_ELT (*valp, 0)->index != index)
+           /* Changing active member.  */
+           vec_safe_truncate (CONSTRUCTOR_ELTS (*valp), 0);
+
          for (idx = 0;
               vec_safe_iterate (CONSTRUCTOR_ELTS (*valp), idx, &cep);
               idx++, fields = DECL_CHAIN (fields))
diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-union1.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-union1.C
new file mode 100644 (file)
index 0000000..8aed6d9
--- /dev/null
@@ -0,0 +1,11 @@
+// PR c++/78897
+// { dg-do compile { target c++14 } }
+
+struct Optional {
+  constexpr Optional() : _dummy{} { _value = 1; }
+  union {
+    int _dummy;
+    int _value;
+  };
+};
+Optional opt{};