aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/class.c
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2020-07-09 15:11:12 -0400
committerJason Merrill <jason@redhat.com>2020-07-10 08:36:40 -0400
commite47dfca5aa473e77fdff95d631dc39de87a41eec (patch)
tree53f7d6d930a736ba88080c98544721a4d7da1f82 /gcc/cp/class.c
parenta6645a826f58b68f68dff30e6e6e78542099d0cc (diff)
downloadgcc-e47dfca5aa473e77fdff95d631dc39de87a41eec.zip
gcc-e47dfca5aa473e77fdff95d631dc39de87a41eec.tar.gz
gcc-e47dfca5aa473e77fdff95d631dc39de87a41eec.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/class.c')
-rw-r--r--gcc/cp/class.c27
1 files changed, 20 insertions, 7 deletions
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 7b5f166..14380c7 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -3718,7 +3718,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
@@ -4385,15 +4386,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. */
@@ -4413,7 +4419,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)