c++: Copy elision and [[no_unique_address]]. [PR93711]
authorJason Merrill <jason@redhat.com>
Wed, 12 Aug 2020 09:45:02 +0000 (05:45 -0400)
committerJason Merrill <jason@redhat.com>
Fri, 14 Aug 2020 16:58:48 +0000 (12:58 -0400)
commit320054784250e572cb75d6f69ab44b2330d61d8b
tree527b83bfa30fdf702800a08a693826eb77ae7dcc
parent4c58a32f4784eb6a77c1ba8608d3d52e3a4cdc40
c++: Copy elision and [[no_unique_address]]. [PR93711]

We don't elide a copy from a function returning a class by value into a base
because that can overwrite data laid out in the tail padding of the base
class; we need to handle [[no_unique_address]] fields the same way, or we
ICE when the middle-end wants to create a temporary object of a
TYPE_NEEDS_CONSTRUCTING type.

This means that we can't always express initialization of a field with
INIT_EXPR from a TARGET_EXPR the way we usually do, so I needed
to change several places that were assuming that was sufficient.

This also fixes 90254, the same problem with C++17 aggregate initialization
of a base.

gcc/cp/ChangeLog:

PR c++/90254
PR c++/93711
* cp-tree.h (unsafe_return_slot_p): Declare.
* call.c (is_base_field_ref): Rename to unsafe_return_slot_p.
(build_over_call): Check unsafe_return_slot_p.
(build_special_member_call): Likewise.
* init.c (expand_default_init): Likewise.
* typeck2.c (split_nonconstant_init_1): Likewise.

gcc/testsuite/ChangeLog:

PR c++/90254
PR c++/93711
* g++.dg/cpp1z/aggr-base10.C: New test.
* g++.dg/cpp2a/no_unique_address7.C: New test.
* g++.dg/cpp2a/no_unique_address7a.C: New test.
gcc/cp/call.c
gcc/cp/cp-tree.h
gcc/cp/init.c
gcc/cp/typeck2.c
gcc/testsuite/g++.dg/cpp1z/aggr-base10.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp2a/no_unique_address7.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp2a/no_unique_address7a.C [new file with mode: 0644]