From 5c97093ba7feef2235c45233a2a1175c8c168b4c Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Fri, 10 Feb 2017 13:50:30 -0500 Subject: [PATCH] PR c++/78897 - constexpr union * 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 | 4 ++++ gcc/cp/constexpr.c | 5 +++++ gcc/testsuite/g++.dg/cpp1y/constexpr-union1.C | 11 +++++++++++ 3 files changed, 20 insertions(+) create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-union1.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 68c5d9d1cd9..be51428cc5b 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,9 @@ 2017-02-10 Jason Merrill + 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. diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index bb45f1e8059..bfdde9e911d 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 00000000000..8aed6d9bf55 --- /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{}; -- 2.30.2