diff options
author | Jason Merrill <jason@redhat.com> | 2020-07-09 15:11:12 -0400 |
---|---|---|
committer | Jason Merrill <jason@redhat.com> | 2020-07-10 08:36:09 -0400 |
commit | 3bb330022ce47a3e8966a9930f392e497c608f59 (patch) | |
tree | 5663267fc76cf730efc3fc650640f56aa822589a /gcc/cp | |
parent | 8614106f121db118f9db260b9949883485d0bbf6 (diff) | |
download | gcc-3bb330022ce47a3e8966a9930f392e497c608f59.zip gcc-3bb330022ce47a3e8966a9930f392e497c608f59.tar.gz gcc-3bb330022ce47a3e8966a9930f392e497c608f59.tar.bz2 |
c++: [[no_unique_address]] fixes. [PR96105]
We were wrongly checking is_empty_class on the result of strip_array_types
rather than the actual field type. We weren't considering the alignment of
the data member. We needed to handle unions the same way as
layout_nonempty_base_or_field.
gcc/cp/ChangeLog:
PR c++/96105
PR c++/96052
PR c++/95976
* class.c (check_field_decls): An array of empty classes is not an
empty data member.
(layout_empty_base_or_field): Handle explicit alignment.
Fix union handling.
gcc/testsuite/ChangeLog:
PR c++/96105
PR c++/96052
PR c++/95976
* g++.dg/cpp2a/no_unique_address4.C: New test.
* g++.dg/cpp2a/no_unique_address5.C: New test.
* g++.dg/cpp2a/no_unique_address6.C: New test.
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/class.c | 27 |
1 files changed, 20 insertions, 7 deletions
diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 08d3b37..ed8f952 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -3719,7 +3719,8 @@ check_field_decls (tree t, tree *access_decls, /* We don't treat zero-width bitfields as making a class non-empty. */ ; - else if (field_poverlapping_p (field) && is_empty_class (type)) + else if (field_poverlapping_p (field) + && is_empty_class (TREE_TYPE (field))) /* Empty data members also don't make a class non-empty. */ CLASSTYPE_CONTAINS_EMPTY_CLASS_P (t) = 1; else @@ -4386,15 +4387,20 @@ layout_empty_base_or_field (record_layout_info rli, tree binfo_or_decl, /* This routine should only be used for empty classes. */ gcc_assert (is_empty_class (type)); - alignment = size_int (CLASSTYPE_ALIGN_UNIT (type)); + + if (decl && DECL_USER_ALIGN (decl)) + alignment = size_int (DECL_ALIGN_UNIT (decl)); + else + alignment = size_int (CLASSTYPE_ALIGN_UNIT (type)); /* This is an empty base class. We first try to put it at offset zero. */ tree offset = size_zero_node; - if (layout_conflict_p (type, - offset, - offsets, - /*vbases_p=*/0)) + if (TREE_CODE (rli->t) != UNION_TYPE + && layout_conflict_p (type, + offset, + offsets, + /*vbases_p=*/0)) { /* That didn't work. Now, we move forward from the next available spot in the class. */ @@ -4414,7 +4420,14 @@ layout_empty_base_or_field (record_layout_info rli, tree binfo_or_decl, } } - if (CLASSTYPE_USER_ALIGN (type)) + if (decl && DECL_USER_ALIGN (decl)) + { + rli->record_align = MAX (rli->record_align, DECL_ALIGN (decl)); + if (warn_packed) + rli->unpacked_align = MAX (rli->unpacked_align, DECL_ALIGN (decl)); + TYPE_USER_ALIGN (rli->t) = 1; + } + else if (CLASSTYPE_USER_ALIGN (type)) { rli->record_align = MAX (rli->record_align, CLASSTYPE_ALIGN (type)); if (warn_packed) |