diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 69f07c4f663..71c480a24c6 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2020-04-23 Matthew Malcomson + Jakub Jelinek + + PR target/94383 + * config/aarch64/aarch64.c (aapcs_vfp_sub_candidate): Account for C++17 + empty base class artificial fields. + (aarch64_vfp_is_call_or_return_candidate): Warn when ABI PCS decision is + different after this fix. + 2020-04-23 Jakub Jelinek PR target/94707 diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index f728ac530a4..a81b0b2ac04 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -16442,9 +16442,19 @@ aarch64_member_type_forces_blk (const_tree field_or_array, machine_mode mode) If *MODEP is VOIDmode, then set it to the first valid floating point type. If a non-floating point type is found, or if a floating point type that doesn't match a non-VOIDmode *MODEP is found, then return -1, - otherwise return the count in the sub-tree. */ + otherwise return the count in the sub-tree. + + The AVOID_CXX17_EMPTY_BASE argument is to allow the caller to check whether + this function has changed its behavior after the fix for PR94384 -- this fix + is to avoid artificial fields in empty base classes. + When called with this argument as a NULL pointer this function does not + avoid the artificial fields -- this is useful to check whether the function + returns something different after the fix. + When called pointing at a value, this function avoids such artificial fields + and sets the value to TRUE when one of these fields has been set. */ static int -aapcs_vfp_sub_candidate (const_tree type, machine_mode *modep) +aapcs_vfp_sub_candidate (const_tree type, machine_mode *modep, + bool *avoid_cxx17_empty_base) { machine_mode mode; HOST_WIDE_INT size; @@ -16520,7 +16530,8 @@ aapcs_vfp_sub_candidate (const_tree type, machine_mode *modep) || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST) return -1; - count = aapcs_vfp_sub_candidate (TREE_TYPE (type), modep); + count = aapcs_vfp_sub_candidate (TREE_TYPE (type), modep, + avoid_cxx17_empty_base); if (count == -1 || !index || !TYPE_MAX_VALUE (index) @@ -16558,7 +16569,18 @@ aapcs_vfp_sub_candidate (const_tree type, machine_mode *modep) if (TREE_CODE (field) != FIELD_DECL) continue; - sub_count = aapcs_vfp_sub_candidate (TREE_TYPE (field), modep); + /* Ignore C++17 empty base fields, while their type indicates + they do contain padding, they have zero size and thus don't + contain any padding. */ + if (cxx17_empty_base_field_p (field) + && avoid_cxx17_empty_base) + { + *avoid_cxx17_empty_base = true; + continue; + } + + sub_count = aapcs_vfp_sub_candidate (TREE_TYPE (field), modep, + avoid_cxx17_empty_base); if (sub_count < 0) return -1; count += sub_count; @@ -16591,7 +16613,8 @@ aapcs_vfp_sub_candidate (const_tree type, machine_mode *modep) if (TREE_CODE (field) != FIELD_DECL) continue; - sub_count = aapcs_vfp_sub_candidate (TREE_TYPE (field), modep); + sub_count = aapcs_vfp_sub_candidate (TREE_TYPE (field), modep, + avoid_cxx17_empty_base); if (sub_count < 0) return -1; count = count > sub_count ? count : sub_count; @@ -16718,10 +16741,26 @@ aarch64_vfp_is_call_or_return_candidate (machine_mode mode, } else if (type && composite_p) { - int ag_count = aapcs_vfp_sub_candidate (type, &new_mode); - + bool avoided = false; + int ag_count = aapcs_vfp_sub_candidate (type, &new_mode, &avoided); if (ag_count > 0 && ag_count <= HA_MAX_NUM_FLDS) { + static unsigned last_reported_type_uid; + unsigned uid = TYPE_UID (TYPE_MAIN_VARIANT (type)); + int alt; + if (warn_psabi + && avoided + && uid != last_reported_type_uid + && ((alt = aapcs_vfp_sub_candidate (type, &new_mode, NULL)) + != ag_count)) + { + gcc_assert (alt == -1); + last_reported_type_uid = uid; + inform (input_location, "parameter passing for argument of type " + "%qT when C++17 is enabled changed to match C++14 " + "in GCC 10.1", type); + } + if (is_ha != NULL) *is_ha = true; *count = ag_count; }