https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94707
--- Comment #4 from Jakub Jelinek <jakub at gcc dot gnu.org> --- Updated incomplete patch on top of https://gcc.gnu.org/pipermail/gcc-patches/2020-April/544276.html I've handled one rs6000_discover_homogeneous_aggregate caller where it wasn't that hard to figure out how to report different decisions based on if GCC 7/8/9 with -std=c++17 would make the aggregate non-homogeneous because of the C++17 empty base artificial FIELD_DECL and we'd return true because of that, while in -std=c++14 and in patched GCC trunk we'd return false. But I'm getting lost in all the other spots, figuring out if we made different decisions is harder. --- gcc/config/rs6000/rs6000-internal.h.jj 2020-03-20 09:11:36.229903622 +0100 +++ gcc/config/rs6000/rs6000-internal.h 2020-04-22 11:31:23.943522525 +0200 @@ -129,7 +129,8 @@ extern int rs6000_darwin64_struct_check_ extern bool rs6000_discover_homogeneous_aggregate (machine_mode mode, const_tree type, machine_mode *elt_mode, - int *n_elts); + int *n_elts, + bool *cxx17_empty_base_seen); extern void rs6000_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED, HOST_WIDE_INT delta, --- gcc/config/rs6000/rs6000-call.c.jj 2020-03-30 22:53:40.746640328 +0200 +++ gcc/config/rs6000/rs6000-call.c 2020-04-22 12:06:00.066843119 +0200 @@ -5528,7 +5528,8 @@ const struct altivec_builtin_types altiv sub-tree. */ static int -rs6000_aggregate_candidate (const_tree type, machine_mode *modep) +rs6000_aggregate_candidate (const_tree type, machine_mode *modep, + bool *cxx17_empty_base_seen) { machine_mode mode; HOST_WIDE_INT size; @@ -5598,7 +5599,8 @@ rs6000_aggregate_candidate (const_tree t || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST) return -1; - count = rs6000_aggregate_candidate (TREE_TYPE (type), modep); + count = rs6000_aggregate_candidate (TREE_TYPE (type), modep, + cxx17_empty_base_seen); if (count == -1 || !index || !TYPE_MAX_VALUE (index) @@ -5636,7 +5638,15 @@ rs6000_aggregate_candidate (const_tree t if (TREE_CODE (field) != FIELD_DECL) continue; - sub_count = rs6000_aggregate_candidate (TREE_TYPE (field), modep); + if (cxx17_empty_base_field_p (field)) + { + if (cxx17_empty_base_seen) + *cxx17_empty_base_seen = true; + continue; + } + + sub_count = rs6000_aggregate_candidate (TREE_TYPE (field), modep, + cxx17_empty_base_seen); if (sub_count < 0) return -1; count += sub_count; @@ -5669,7 +5679,8 @@ rs6000_aggregate_candidate (const_tree t if (TREE_CODE (field) != FIELD_DECL) continue; - sub_count = rs6000_aggregate_candidate (TREE_TYPE (field), modep); + sub_count = rs6000_aggregate_candidate (TREE_TYPE (field), modep, + cxx17_empty_base_seen); if (sub_count < 0) return -1; count = count > sub_count ? count : sub_count; @@ -5700,7 +5711,8 @@ rs6000_aggregate_candidate (const_tree t bool rs6000_discover_homogeneous_aggregate (machine_mode mode, const_tree type, machine_mode *elt_mode, - int *n_elts) + int *n_elts, + bool *cxx17_empty_base_seen) { /* Note that we do not accept complex types at the top level as homogeneous aggregates; these types are handled via the @@ -5710,7 +5722,8 @@ rs6000_discover_homogeneous_aggregate (m && AGGREGATE_TYPE_P (type)) { machine_mode field_mode = VOIDmode; - int field_count = rs6000_aggregate_candidate (type, &field_mode); + int field_count = rs6000_aggregate_candidate (type, &field_mode, + cxx17_empty_base_seen); if (field_count > 0) { @@ -5734,6 +5747,8 @@ rs6000_discover_homogeneous_aggregate (m *elt_mode = mode; if (n_elts) *n_elts = 1; + if (cxx17_empty_base_seen) + *cxx17_empty_base_seen = false; return false; } @@ -5790,9 +5805,14 @@ rs6000_return_in_memory (const_tree type } /* The ELFv2 ABI returns homogeneous VFP aggregates in registers */ + bool cxx17_empty_base_seen = false; if (rs6000_discover_homogeneous_aggregate (TYPE_MODE (type), type, - NULL, NULL)) - return false; + NULL, NULL, + &cxx17_empty_base_seen)) + { + if (!cxx17_empty_base_seen || !warn_psabi) + return false; + } /* The ELFv2 ABI returns aggregates up to 16B in registers */ if (DEFAULT_ABI == ABI_ELFv2 && AGGREGATE_TYPE_P (type) @@ -5802,7 +5822,21 @@ rs6000_return_in_memory (const_tree type if (AGGREGATE_TYPE_P (type) && (aix_struct_return || (unsigned HOST_WIDE_INT) int_size_in_bytes (type) > 8)) - return true; + { + if (cxx17_empty_base_seen) + { + inform (input_location, + "prior to GCC 10, parameters of type %qT were passed " + "incorrectly for C++17", type); + return false; + } + + return true; + } + + /* The ELFv2 ABI returns homogeneous VFP aggregates in registers. */ + if (cxx17_empty_base_seen) + return false; /* Allow -maltivec -mabi=no-altivec without warning. Altivec vector modes only exist for GCC vector types if -maltivec. */ @@ -6141,7 +6175,8 @@ rs6000_function_arg_boundary (machine_mo machine_mode elt_mode; int n_elts; - rs6000_discover_homogeneous_aggregate (mode, type, &elt_mode, &n_elts); + rs6000_discover_homogeneous_aggregate (mode, type, &elt_mode, &n_elts, + NULL); if (DEFAULT_ABI == ABI_V4 && (GET_MODE_SIZE (mode) == 8 @@ -6409,7 +6444,8 @@ rs6000_function_arg_advance_1 (CUMULATIV machine_mode elt_mode; int n_elts; - rs6000_discover_homogeneous_aggregate (mode, type, &elt_mode, &n_elts); + rs6000_discover_homogeneous_aggregate (mode, type, &elt_mode, &n_elts, + NULL); /* Only tick off an argument if we're not recursing. */ if (depth == 0) @@ -6993,7 +7029,9 @@ rs6000_function_arg (cumulative_args_t c return GEN_INT (cum->call_cookie & ~CALL_LIBCALL); } - rs6000_discover_homogeneous_aggregate (mode, type, &elt_mode, &n_elts); + bool cxx17_empty_base_seen = false; + rs6000_discover_homogeneous_aggregate (mode, type, &elt_mode, &n_elts, + &cxx17_empty_base_seen); if (TARGET_MACHO && rs6000_darwin64_struct_check_p (mode, type)) { @@ -7229,7 +7267,7 @@ rs6000_arg_partial_bytes (cumulative_arg int n_elts; rs6000_discover_homogeneous_aggregate (arg.mode, arg.type, - &elt_mode, &n_elts); + &elt_mode, &n_elts, NULL); if (DEFAULT_ABI == ABI_V4) return 0; --- gcc/config/rs6000/rs6000.c.jj 2020-04-17 08:49:49.040683868 +0200 +++ gcc/config/rs6000/rs6000.c 2020-04-22 12:06:34.988310057 +0200 @@ -22428,7 +22428,8 @@ rs6000_function_value (const_tree valtyp mode = TYPE_MODE (valtype); /* The ELFv2 ABI returns homogeneous VFP aggregates in registers. */ - if (rs6000_discover_homogeneous_aggregate (mode, valtype, &elt_mode, &n_elts)) + if (rs6000_discover_homogeneous_aggregate (mode, valtype, &elt_mode, &n_elts, + NULL)) { int first_reg, n_regs;