On Wed, Apr 22, 2020 at 01:33:45PM +0100, Richard Sandiford wrote: > Jakub Jelinek <ja...@redhat.com> writes: > > On Wed, Apr 22, 2020 at 12:17:02PM +0100, Richard Sandiford wrote: > >> But my point was that, if the DECL_NAME does actually act to exclude > > > > I'm fine with dropping DECL_NAME test there, on the other side would like to > > add > > && TYPE_SIZE (TREE_TYPE (field)) > > && !integer_zerop (TYPE_SIZE (TREE_TYPE (field))) > > in there because that is what all these empty bases should satisfy too. > > Sounds good to me FWIW.
Thus below in the patch form. Ok for trunk? > > /* Verify that other zero sized fields don't affect the > > ABI decisions. */ > > if (DECL_SIZE (field) && integer_zerop (DECL_SIZE (field))) > > gcc_assert (sub_count == 0); > > > > if (sub_count < 0) > > return -1; > > count += sub_count; > > ? > > I fear this will actually trip in practice, but I'd have to go back and > check. (This came up in the context of the SVE parameter-passing rules, > where we ended up deliberately checking DECL_SIZE to avoid zero-size > user-level decls.) > > E.g. I'd expect a :0 bitfield to have a zero size and an integer > TREE_TYPE, so the recursive call should return -1. AIUI we should > skip these kinds of bitfield too, but again that's just my understanding, > not a definitive statement. Indeed, struct S { int : 0; }; in C has (at least on x86) sizeof 0, so does struct T { struct S a, b, c, d; }; Sure, the backend needs to decide whether those change the ABI decisions or not. E.g. on rs6000 where I was considering similar check that assertion triggers on struct S { int : 0; }; struct T { struct S a, b, c, d; } t; struct U { struct T e; float f, g, h, i; } u; void foo (struct U); int bar (void) { foo (u); return 1; } 2020-04-22 Jakub Jelinek <ja...@redhat.com> PR target/94383 * calls.h (cxx17_empty_base_field_p): Declare. * calls.c (cxx17_empty_base_field_p): Define. --- gcc/calls.h.jj 2020-01-12 11:54:36.214416411 +0100 +++ gcc/calls.h 2020-04-22 11:44:09.037853379 +0200 @@ -135,5 +135,6 @@ extern tree get_attr_nonstring_decl (tre extern void maybe_warn_nonstring_arg (tree, tree); extern bool get_size_range (tree, tree[2], bool = false); extern rtx rtx_for_static_chain (const_tree, bool); +extern bool cxx17_empty_base_field_p (const_tree); #endif // GCC_CALLS_H --- gcc/calls.c.jj 2020-03-27 22:27:09.615964438 +0100 +++ gcc/calls.c 2020-04-22 11:44:17.621722376 +0200 @@ -6261,5 +6261,23 @@ must_pass_va_arg_in_stack (tree type) return targetm.calls.must_pass_in_stack (arg); } +/* Return true if FIELD is the C++17 empty base field that should + be ignored for ABI calling convention decisions in order to + maintain ABI compatibility between C++14 and earlier, which doesn't + add this FIELD to classes with empty bases, and C++17 and later + which does. */ + +bool +cxx17_empty_base_field_p (const_tree field) +{ + return (TREE_CODE (field) == FIELD_DECL + && DECL_ARTIFICIAL (field) + && RECORD_OR_UNION_TYPE_P (TREE_TYPE (field)) + && DECL_SIZE (field) + && integer_zerop (DECL_SIZE (field)) + && TYPE_SIZE (TREE_TYPE (field)) + && !integer_zerop (TYPE_SIZE (TREE_TYPE (field)))); +} + /* Tell the garbage collector about GTY markers in this source file. */ #include "gt-calls.h" Jakub