c++: Reject changing active member of union during initialization [PR94066]
authorPatrick Palka <ppalka@redhat.com>
Thu, 19 Mar 2020 13:58:28 +0000 (09:58 -0400)
committerPatrick Palka <ppalka@redhat.com>
Sat, 21 Mar 2020 13:49:05 +0000 (09:49 -0400)
commitb599bf9d6d1e180d350b71e51e08a66a1bb1546a
tree321079315130779d91bf88f1ee540ee8eab081dd
parent497498c878d48754318e486428e2aa30854020b9
c++: Reject changing active member of union during initialization [PR94066]

This patch adds a check to detect changing the active union member during
initialization of another member of the union in cxx_eval_store_expression.  It
uses the CONSTRUCTOR_NO_CLEARING flag as a proxy for whether the non-empty
CONSTRUCTOR of UNION_TYPE we're assigning to is in the process of being
initialized.

This patch additionally fixes an issue in reduced_constant_expression_p where we
were returning false for an uninitialized union with no active member.  This
lets us correctly reject the uninitialized use in the testcase
testconstexpr-union4.C that we weren't before.

gcc/cp/ChangeLog:

PR c++/94066
* constexpr.c (reduced_constant_expression_p) [CONSTRUCTOR]: Properly
handle unions without an initializer.
(cxx_eval_component_reference): Emit a different diagnostic when the
constructor element corresponding to a union member is NULL.
(cxx_eval_bare_aggregate): When constructing a union, always set the
active union member before evaluating the initializer.  Relax assertion
that verifies the index of the constructor element we're initializing
hasn't been changed.
(cxx_eval_store_expression): Diagnose changing the active union member
while the union is in the process of being initialized.  After setting
an active union member, clear CONSTRUCTOR_NO_CLEARING on the underlying
CONSTRUCTOR.
(cxx_eval_constant_expression) [PLACEHOLDER_EXPR]: Don't re-reduce a
CONSTRUCTOR returned by lookup_placeholder.

gcc/testsuite/ChangeLog:

PR c++/94066
* g++.dg/cpp1y/constexpr-union2.C: New test.
* g++.dg/cpp1y/constexpr-union3.C: New test.
* g++.dg/cpp1y/constexpr-union4.C: New test.
* g++.dg/cpp1y/constexpr-union5.C: New test.
* g++.dg/cpp1y/pr94066.C: New test.
* g++.dg/cpp1y/pr94066-2.C: New test.
* g++.dg/cpp1y/pr94066-3.C: New test.
* g++.dg/cpp2a/constexpr-union1.C: New test.
gcc/cp/ChangeLog
gcc/cp/constexpr.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp1y/constexpr-union2.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1y/constexpr-union3.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1y/constexpr-union4.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1y/constexpr-union5.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1y/pr94066-2.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1y/pr94066-3.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1y/pr94066.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp2a/constexpr-union1.C [new file with mode: 0644]