mips: Fix C++14 vs. C++17 ABI incompatibility on mips64
This fixes tmpdir-g++.dg-struct-layout-1/{t032,t059} failure. Clang++ also ignores C++17 empty bases in return values. gcc/ * config/mips/mips.cc (mips_fpr_return_fields): Ignore cxx17_empty_base_field_p fields and set an indicator. (mips_return_in_msb): Adjust for mips_fpr_return_fields change. (mips_function_value_1): Inform psABI change about C++17 empty bases. gcc/testsuite/ * g++.target/mips/cxx17_empty_base.C: New test.
This commit is contained in:
parent
5df29fe79d
commit
eac5c12c18
@ -6318,12 +6318,21 @@ mips_callee_copies (cumulative_args_t, const function_arg_info &arg)
|
||||
The C++ FE used to remove zero-width bit-fields in GCC 11 and earlier.
|
||||
To make a proper diagnostic, this function will set
|
||||
HAS_CXX_ZERO_WIDTH_BF to true once a C++ zero-width bit-field shows up,
|
||||
and then ignore it. Then the caller can determine if this zero-width
|
||||
bit-field will make a difference and emit a -Wpsabi inform. */
|
||||
and then ignore it.
|
||||
|
||||
We had failed to ignore C++17 empty bases in GCC 7, 8, 9, 10, and 11.
|
||||
This caused an ABI incompatibility between C++14 and C++17. This is
|
||||
fixed now and to make a proper diagnostic, this function will set
|
||||
HAS_CXX17_EMPTY_BASE to true once a C++17 empty base shows up, and
|
||||
then ignore it.
|
||||
|
||||
The caller should use the value of HAS_CXX17_EMPTY_BASE and/or
|
||||
HAS_CXX_ZERO_WIDTH_BF to emit a proper -Wpsabi inform. */
|
||||
|
||||
static int
|
||||
mips_fpr_return_fields (const_tree valtype, tree *fields,
|
||||
bool *has_cxx_zero_width_bf)
|
||||
bool *has_cxx_zero_width_bf,
|
||||
bool *has_cxx17_empty_base)
|
||||
{
|
||||
tree field;
|
||||
int i;
|
||||
@ -6340,6 +6349,12 @@ mips_fpr_return_fields (const_tree valtype, tree *fields,
|
||||
if (TREE_CODE (field) != FIELD_DECL)
|
||||
continue;
|
||||
|
||||
if (cxx17_empty_base_field_p (field))
|
||||
{
|
||||
*has_cxx17_empty_base = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (DECL_FIELD_CXX_ZERO_WIDTH_BIT_FIELD (field))
|
||||
{
|
||||
*has_cxx_zero_width_bf = true;
|
||||
@ -6375,8 +6390,13 @@ mips_return_in_msb (const_tree valtype)
|
||||
|
||||
tree fields[2];
|
||||
bool has_cxx_zero_width_bf = false;
|
||||
|
||||
/* Its value is not used. */
|
||||
bool has_cxx17_empty_base = false;
|
||||
|
||||
return (mips_fpr_return_fields (valtype, fields,
|
||||
&has_cxx_zero_width_bf) == 0
|
||||
&has_cxx_zero_width_bf,
|
||||
&has_cxx17_empty_base) == 0
|
||||
|| has_cxx_zero_width_bf);
|
||||
}
|
||||
|
||||
@ -6473,11 +6493,18 @@ mips_function_value_1 (const_tree valtype, const_tree fn_decl_or_type,
|
||||
mode = promote_function_mode (valtype, mode, &unsigned_p, func, 1);
|
||||
|
||||
bool has_cxx_zero_width_bf = false;
|
||||
bool has_cxx17_empty_base = false;
|
||||
int use_fpr = mips_fpr_return_fields (valtype, fields,
|
||||
&has_cxx_zero_width_bf);
|
||||
&has_cxx_zero_width_bf,
|
||||
&has_cxx17_empty_base);
|
||||
|
||||
/* If has_cxx_zero_width_bf and has_cxx17_empty_base are both
|
||||
true, it *happens* that there is no ABI change. So we won't
|
||||
inform in this case. */
|
||||
if (TARGET_HARD_FLOAT
|
||||
&& warn_psabi
|
||||
&& has_cxx_zero_width_bf
|
||||
&& !has_cxx17_empty_base
|
||||
&& use_fpr != 0)
|
||||
{
|
||||
static unsigned last_reported_type_uid;
|
||||
@ -6499,6 +6526,27 @@ mips_function_value_1 (const_tree valtype, const_tree fn_decl_or_type,
|
||||
if (has_cxx_zero_width_bf)
|
||||
use_fpr = 0;
|
||||
|
||||
if (TARGET_HARD_FLOAT
|
||||
&& warn_psabi
|
||||
&& use_fpr != 0
|
||||
&& has_cxx17_empty_base)
|
||||
{
|
||||
static unsigned last_reported_type_uid;
|
||||
unsigned uid = TYPE_UID (TYPE_MAIN_VARIANT (valtype));
|
||||
if (uid != last_reported_type_uid)
|
||||
{
|
||||
static const char *url
|
||||
= CHANGES_ROOT_URL
|
||||
"gcc-12/changes.html#mips_cxx17_empty_bases";
|
||||
inform (input_location,
|
||||
"the ABI for returning a value with C++17 empty "
|
||||
"bases but otherwise an aggregate with only one or "
|
||||
"two floating-point fields was changed in GCC "
|
||||
"%{12.1%}", url);
|
||||
last_reported_type_uid = uid;
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle structures whose fields are returned in $f0/$f2. */
|
||||
switch (use_fpr)
|
||||
{
|
||||
|
20
gcc/testsuite/g++.target/mips/cxx17_empty_base.C
Normal file
20
gcc/testsuite/g++.target/mips/cxx17_empty_base.C
Normal file
@ -0,0 +1,20 @@
|
||||
// { dg-do compile }
|
||||
// { dg-options "-O2 -std=c++17 -mabi=64 -mhard-float" }
|
||||
// { dg-final { scan-assembler "\\\$f0" } }
|
||||
|
||||
struct empty {};
|
||||
|
||||
struct foo : empty
|
||||
{
|
||||
double a;
|
||||
double b;
|
||||
};
|
||||
|
||||
struct foo
|
||||
make_foo(void) // { dg-message "the ABI for returning a value with C\\\+\\\+17 empty bases but otherwise an aggregate with only one or two floating-point fields was changed in GCC 12.1" }
|
||||
{
|
||||
struct foo ret;
|
||||
ret.a = 114;
|
||||
ret.b = 514;
|
||||
return ret;
|
||||
}
|
Loading…
Reference in New Issue
Block a user