diff mbox

C++ PATCH for c++/78897 (ICE with constexpr and union)

Message ID CADzB+2kYY0h_gn6dt_RXrFdGimOFehxYE6FwC4dbmWFNf1qmVQ@mail.gmail.com
State New
Headers show

Commit Message

Jason Merrill Feb. 10, 2017, 6:49 p.m. UTC
When we process a store that changes the active member of a union, we
need to forget about other members.

Tested x86_64-pc-linux-gnu, applying to trunk.
commit 23c02701a1f2d115b9b88ccd88e1d3a26674ab14
Author: Jason Merrill <jason@redhat.com>
Date:   Fri Feb 10 12:35:49 2017 -0500

            PR c++/78897 - constexpr union
    
            * constexpr.c (cxx_eval_store_expression): A store to a union member
            erases a previous store to another member.
diff mbox

Patch

diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index bb45f1e..bfdde9e 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -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
index 0000000..8aed6d9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-union1.C
@@ -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{};