On Tue, Apr 28, 2020 at 04:23:24PM +0200, Andreas Krebbel via Gcc-patches wrote: > Given that this is something which hasn't been covered by the ABI so far I'm > not sure we really need > a -Wpsabi warning for that.
Attached are two (updated) versions of the patch on top of the powerpc+middle-end patch just posted. The first one emits two separate -Wpsabi warnings like powerpc, one for the -std=c++14 vs. -std=c++17 ABI difference and one for GCC 9 vs. 10 [[no_unique_address]] passing changes, the other one is silent about the second case. Will bootstrap/regtest both and you can choose. Jakub
2020-04-28 Jakub Jelinek <ja...@redhat.com> PR target/94704 * config/s390/s390.c (s390_function_arg_vector, s390_function_arg_float): Use DECL_FIELD_ABI_IGNORED instead of cxx17_empty_base_field_p. In -Wpsabi diagnostics use the type passed to the function rather than the type of the single element. Rename cxx17_empty_base_seen variable to empty_base_seen, change type to int, and adjust diagnostics depending on if the field has [[no_unique_attribute]] or not. * g++.target/s390/s390.exp: New file. * g++.target/s390/pr94704-1.C: New test. * g++.target/s390/pr94704-2.C: New test. * g++.target/s390/pr94704-3.C: New test. * g++.target/s390/pr94704-4.C: New test. --- gcc/config/s390/s390.c.jj 2020-04-28 16:15:39.542541382 +0200 +++ gcc/config/s390/s390.c 2020-04-28 17:20:06.087872951 +0200 @@ -11911,7 +11911,8 @@ s390_function_arg_vector (machine_mode m /* The ABI says that record types with a single member are treated just like that member would be. */ - bool cxx17_empty_base_seen = false; + int empty_base_seen = 0; + const_tree orig_type = type; while (TREE_CODE (type) == RECORD_TYPE) { tree field, single = NULL_TREE; @@ -11921,9 +11922,13 @@ s390_function_arg_vector (machine_mode m if (TREE_CODE (field) != FIELD_DECL) continue; - if (cxx17_empty_base_field_p (field)) + if (DECL_FIELD_ABI_IGNORED (field)) { - cxx17_empty_base_seen = true; + if (lookup_attribute ("no_unique_address", + DECL_ATTRIBUTES (field))) + empty_base_seen |= 2; + else + empty_base_seen |= 1; continue; } @@ -11949,16 +11954,23 @@ s390_function_arg_vector (machine_mode m if (!VECTOR_TYPE_P (type)) return false; - if (warn_psabi && cxx17_empty_base_seen) + if (warn_psabi && empty_base_seen) { static unsigned last_reported_type_uid; - unsigned uid = TYPE_UID (TYPE_MAIN_VARIANT (type)); + unsigned uid = TYPE_UID (TYPE_MAIN_VARIANT (orig_type)); if (uid != last_reported_type_uid) { 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 (empty_base_seen & 1) + inform (input_location, + "parameter passing for argument of type %qT when C++17 " + "is enabled changed to match C++14 in GCC 10.1", + orig_type); + else + inform (input_location, + "parameter passing for argument of type %qT with " + "%<[[no_unique_address]]%> members changed in GCC 10.1", + orig_type); } } return true; @@ -11983,7 +11995,8 @@ s390_function_arg_float (machine_mode mo /* The ABI says that record types with a single member are treated just like that member would be. */ - bool cxx17_empty_base_seen = false; + int empty_base_seen = 0; + const_tree orig_type = type; while (TREE_CODE (type) == RECORD_TYPE) { tree field, single = NULL_TREE; @@ -11992,9 +12005,13 @@ s390_function_arg_float (machine_mode mo { if (TREE_CODE (field) != FIELD_DECL) continue; - if (cxx17_empty_base_field_p (field)) + if (DECL_FIELD_ABI_IGNORED (field)) { - cxx17_empty_base_seen = true; + if (lookup_attribute ("no_unique_address", + DECL_ATTRIBUTES (field))) + empty_base_seen |= 2; + else + empty_base_seen |= 1; continue; } @@ -12013,16 +12030,23 @@ s390_function_arg_float (machine_mode mo if (TREE_CODE (type) != REAL_TYPE) return false; - if (warn_psabi && cxx17_empty_base_seen) + if (warn_psabi && empty_base_seen) { static unsigned last_reported_type_uid; - unsigned uid = TYPE_UID (TYPE_MAIN_VARIANT (type)); + unsigned uid = TYPE_UID (TYPE_MAIN_VARIANT (orig_type)); if (uid != last_reported_type_uid) { 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 (empty_base_seen & 1) + inform (input_location, + "parameter passing for argument of type %qT when C++17 " + "is enabled changed to match C++14 in GCC 10.1", + orig_type); + else + inform (input_location, + "parameter passing for argument of type %qT with " + "%<[[no_unique_address]]%> members changed in GCC 10.1", + orig_type); } } --- gcc/testsuite/g++.target/s390/s390.exp.jj 2020-04-28 17:10:05.282726486 +0200 +++ gcc/testsuite/g++.target/s390/s390.exp 2020-04-28 17:10:37.933240905 +0200 @@ -0,0 +1,44 @@ +# Specific regression driver for S390. +# Copyright (C) 2020 Free Software Foundation, Inc. +# +# This file is part of GCC. +# +# GCC is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GCC is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GCC; see the file COPYING3. If not see +# <http://www.gnu.org/licenses/>. */ + +# GCC testsuite that uses the `dg.exp' driver. + +# Exit immediately if this isn't a s390 target. +if {![istarget s390*-*-*] } then { + return +} + +# Load support procs. +load_lib g++-dg.exp + +global DEFAULT_CXXFLAGS +if ![info exists DEFAULT_CXXFLAGS] then { + set DEFAULT_CXXFLAGS " -pedantic-errors" +} + +# Initialize `dg'. +dg-init + +# Main loop. +dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.C]] \ + "" $DEFAULT_CXXFLAGS + +# All done. +dg-finish + --- gcc/testsuite/g++.target/s390/pr94704-1.C.jj 2020-04-28 16:33:53.431130852 +0200 +++ gcc/testsuite/g++.target/s390/pr94704-1.C 2020-04-28 17:30:04.542094168 +0200 @@ -0,0 +1,38 @@ +// PR target/94704 +// { dg-do compile } +// { dg-options "-O2 -std=c++14" } +// Test that for all the calls in this testcase the C++17 empty base +// artificial fields and [[no_unique_address]] empty class non-static +// data members are ignored in the decision whether passed arguments +// have a single floating point field. +// { dg-final { scan-assembler-times {(?n)^\s+ld\s+%f0,} 7 } } + +struct X { }; +struct Y { int : 0; }; +struct Z { int : 0; Y y; }; +struct U : public X { X q; }; +struct A { double a; }; +struct B : public X { double a; }; +struct C : public Y { double a; }; +struct D : public Z { double a; }; +struct E : public U { double a; }; +struct F { [[no_unique_address]] X x; double a; }; +struct G { [[no_unique_address]] Y y; double a; }; +struct H { [[no_unique_address]] Z z; double a; }; +struct I { [[no_unique_address]] U u; double a; }; +struct J { double a; [[no_unique_address]] X x; }; +struct K { double a; [[no_unique_address]] Y y; }; +struct L { double a; [[no_unique_address]] Z z; }; +struct M { double a; [[no_unique_address]] U u; }; +#define T(S, s) extern S s; extern void foo##s (S); int bar##s () { foo##s (s); return 0; } +// { dg-message "parameter passing for argument of type 'F' with '\\\[\\\[no_unique_address\\\]\\\]' members changed in GCC 10.1" "" { target *-*-* } .-1 } +// { dg-message "parameter passing for argument of type 'G' with '\\\[\\\[no_unique_address\\\]\\\]' members changed in GCC 10.1" "" { target *-*-* } .-2 } +// { dg-message "parameter passing for argument of type 'J' with '\\\[\\\[no_unique_address\\\]\\\]' members changed in GCC 10.1" "" { target *-*-* } .-3 } +// { dg-message "parameter passing for argument of type 'K' with '\\\[\\\[no_unique_address\\\]\\\]' members changed in GCC 10.1" "" { target *-*-* } .-4 } +T (A, a) +T (B, b) +T (C, c) +T (F, f) +T (G, g) +T (J, j) +T (K, k) --- gcc/testsuite/g++.target/s390/pr94704-2.C.jj 2020-04-28 16:33:53.431130852 +0200 +++ gcc/testsuite/g++.target/s390/pr94704-2.C 2020-04-28 17:30:38.568586476 +0200 @@ -0,0 +1,34 @@ +// PR target/94704 +// { dg-do compile } +// { dg-options "-O2 -std=c++14" } +// Test that for no calls in this testcase the C++17 empty base +// artificial fields and [[no_unique_address]] empty class non-static +// data members are ignored in the decision whether passed arguments +// have a single floating point field. +// { dg-final { scan-assembler-not {(?n)^\s+ld\s+%f0,} } } + +struct X { }; +struct Y { int : 0; }; +struct Z { int : 0; Y y; }; +struct U : public X { X q; }; +struct A { double a; }; +struct B : public X { double a; }; +struct C : public Y { double a; }; +struct D : public Z { double a; }; +struct E : public U { double a; }; +struct F { [[no_unique_address]] X x; double a; }; +struct G { [[no_unique_address]] Y y; double a; }; +struct H { [[no_unique_address]] Z z; double a; }; +struct I { [[no_unique_address]] U u; double a; }; +struct J { double a; [[no_unique_address]] X x; }; +struct K { double a; [[no_unique_address]] Y y; }; +struct L { double a; [[no_unique_address]] Z z; }; +struct M { double a; [[no_unique_address]] U u; }; +#define T(S, s) extern S s; extern void foo##s (S); int bar##s () { foo##s (s); return 0; } +// { dg-bogus "parameter passing for argument of type" } +T (D, d) +T (E, e) +T (H, h) +T (I, i) +T (L, l) +T (M, m) --- gcc/testsuite/g++.target/s390/pr94704-3.C.jj 2020-04-28 16:33:53.431130852 +0200 +++ gcc/testsuite/g++.target/s390/pr94704-3.C 2020-04-28 17:30:18.063892415 +0200 @@ -0,0 +1,40 @@ +// PR target/94704 +// { dg-do compile } +// { dg-options "-O2 -std=c++17" } +// Test that for all the calls in this testcase the C++17 empty base +// artificial fields and [[no_unique_address]] empty class non-static +// data members are ignored in the decision whether passed arguments +// have a single floating point field. +// { dg-final { scan-assembler-times {(?n)^\s+ld\s+%f0,} 7 } } + +struct X { }; +struct Y { int : 0; }; +struct Z { int : 0; Y y; }; +struct U : public X { X q; }; +struct A { double a; }; +struct B : public X { double a; }; +struct C : public Y { double a; }; +struct D : public Z { double a; }; +struct E : public U { double a; }; +struct F { [[no_unique_address]] X x; double a; }; +struct G { [[no_unique_address]] Y y; double a; }; +struct H { [[no_unique_address]] Z z; double a; }; +struct I { [[no_unique_address]] U u; double a; }; +struct J { double a; [[no_unique_address]] X x; }; +struct K { double a; [[no_unique_address]] Y y; }; +struct L { double a; [[no_unique_address]] Z z; }; +struct M { double a; [[no_unique_address]] U u; }; +#define T(S, s) extern S s; extern void foo##s (S); int bar##s () { foo##s (s); return 0; } +// { dg-message "parameter passing for argument of type 'B' when C\\+\\+17 is enabled changed to match C\\+\\+14 in GCC 10.1" "" { target *-*-* } .-1 } +// { dg-message "parameter passing for argument of type 'C' when C\\+\\+17 is enabled changed to match C\\+\\+14 in GCC 10.1" "" { target *-*-* } .-2 } +// { dg-message "parameter passing for argument of type 'F' with '\\\[\\\[no_unique_address\\\]\\\]' members changed in GCC 10.1" "" { target *-*-* } .-3 } +// { dg-message "parameter passing for argument of type 'G' with '\\\[\\\[no_unique_address\\\]\\\]' members changed in GCC 10.1" "" { target *-*-* } .-4 } +// { dg-message "parameter passing for argument of type 'J' with '\\\[\\\[no_unique_address\\\]\\\]' members changed in GCC 10.1" "" { target *-*-* } .-5 } +// { dg-message "parameter passing for argument of type 'K' with '\\\[\\\[no_unique_address\\\]\\\]' members changed in GCC 10.1" "" { target *-*-* } .-6 } +T (A, a) +T (B, b) +T (C, c) +T (F, f) +T (G, g) +T (J, j) +T (K, k) --- gcc/testsuite/g++.target/s390/pr94704-4.C.jj 2020-04-28 16:33:53.431130852 +0200 +++ gcc/testsuite/g++.target/s390/pr94704-4.C 2020-04-28 17:30:28.296739746 +0200 @@ -0,0 +1,34 @@ +// PR target/94704 +// { dg-do compile } +// { dg-options "-O2 -std=c++17" } +// Test that for no calls in this testcase the C++17 empty base +// artificial fields and [[no_unique_address]] empty class non-static +// data members are ignored in the decision whether passed arguments +// have a single floating point field. +// { dg-final { scan-assembler-not {(?n)^\s+ld\s+%f0,} } } + +struct X { }; +struct Y { int : 0; }; +struct Z { int : 0; Y y; }; +struct U : public X { X q; }; +struct A { double a; }; +struct B : public X { double a; }; +struct C : public Y { double a; }; +struct D : public Z { double a; }; +struct E : public U { double a; }; +struct F { [[no_unique_address]] X x; double a; }; +struct G { [[no_unique_address]] Y y; double a; }; +struct H { [[no_unique_address]] Z z; double a; }; +struct I { [[no_unique_address]] U u; double a; }; +struct J { double a; [[no_unique_address]] X x; }; +struct K { double a; [[no_unique_address]] Y y; }; +struct L { double a; [[no_unique_address]] Z z; }; +struct M { double a; [[no_unique_address]] U u; }; +#define T(S, s) extern S s; extern void foo##s (S); int bar##s () { foo##s (s); return 0; } +// { dg-bogus "parameter passing for argument of type" } +T (D, d) +T (E, e) +T (H, h) +T (I, i) +T (L, l) +T (M, m)
2020-04-28 Jakub Jelinek <ja...@redhat.com> PR target/94704 * config/s390/s390.c (s390_function_arg_vector, s390_function_arg_float): Use DECL_FIELD_ABI_IGNORED instead of cxx17_empty_base_field_p. In -Wpsabi diagnostics use the type passed to the function rather than the type of the single element. * g++.target/s390/s390.exp: New file. * g++.target/s390/pr94704-1.C: New test. * g++.target/s390/pr94704-2.C: New test. * g++.target/s390/pr94704-3.C: New test. * g++.target/s390/pr94704-4.C: New test. --- gcc/config/s390/s390.c.jj 2020-04-28 16:15:39.542541382 +0200 +++ gcc/config/s390/s390.c 2020-04-28 17:38:17.037864167 +0200 @@ -11912,6 +11912,7 @@ s390_function_arg_vector (machine_mode m /* The ABI says that record types with a single member are treated just like that member would be. */ bool cxx17_empty_base_seen = false; + const_tree orig_type = type; while (TREE_CODE (type) == RECORD_TYPE) { tree field, single = NULL_TREE; @@ -11921,9 +11922,11 @@ s390_function_arg_vector (machine_mode m if (TREE_CODE (field) != FIELD_DECL) continue; - if (cxx17_empty_base_field_p (field)) + if (DECL_FIELD_ABI_IGNORED (field)) { - cxx17_empty_base_seen = true; + if (!lookup_attribute ("no_unique_address", + DECL_ATTRIBUTES (field))) + cxx17_empty_base_seen = true; continue; } @@ -11952,13 +11955,14 @@ s390_function_arg_vector (machine_mode m if (warn_psabi && cxx17_empty_base_seen) { static unsigned last_reported_type_uid; - unsigned uid = TYPE_UID (TYPE_MAIN_VARIANT (type)); + unsigned uid = TYPE_UID (TYPE_MAIN_VARIANT (orig_type)); if (uid != last_reported_type_uid) { 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); + inform (input_location, + "parameter passing for argument of type %qT when C++17 " + "is enabled changed to match C++14 in GCC 10.1", + orig_type); } } return true; @@ -11984,6 +11988,7 @@ s390_function_arg_float (machine_mode mo /* The ABI says that record types with a single member are treated just like that member would be. */ bool cxx17_empty_base_seen = false; + const_tree orig_type = type; while (TREE_CODE (type) == RECORD_TYPE) { tree field, single = NULL_TREE; @@ -11992,9 +11997,11 @@ s390_function_arg_float (machine_mode mo { if (TREE_CODE (field) != FIELD_DECL) continue; - if (cxx17_empty_base_field_p (field)) + if (DECL_FIELD_ABI_IGNORED (field)) { - cxx17_empty_base_seen = true; + if (!lookup_attribute ("no_unique_address", + DECL_ATTRIBUTES (field))) + cxx17_empty_base_seen = true; continue; } @@ -12016,13 +12023,14 @@ s390_function_arg_float (machine_mode mo if (warn_psabi && cxx17_empty_base_seen) { static unsigned last_reported_type_uid; - unsigned uid = TYPE_UID (TYPE_MAIN_VARIANT (type)); + unsigned uid = TYPE_UID (TYPE_MAIN_VARIANT (orig_type)); if (uid != last_reported_type_uid) { 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); + inform (input_location, + "parameter passing for argument of type %qT when C++17 " + "is enabled changed to match C++14 in GCC 10.1", + orig_type); } } --- gcc/testsuite/g++.target/s390/s390.exp.jj 2020-04-28 17:10:05.282726486 +0200 +++ gcc/testsuite/g++.target/s390/s390.exp 2020-04-28 17:10:37.933240905 +0200 @@ -0,0 +1,44 @@ +# Specific regression driver for S390. +# Copyright (C) 2020 Free Software Foundation, Inc. +# +# This file is part of GCC. +# +# GCC is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GCC is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GCC; see the file COPYING3. If not see +# <http://www.gnu.org/licenses/>. */ + +# GCC testsuite that uses the `dg.exp' driver. + +# Exit immediately if this isn't a s390 target. +if {![istarget s390*-*-*] } then { + return +} + +# Load support procs. +load_lib g++-dg.exp + +global DEFAULT_CXXFLAGS +if ![info exists DEFAULT_CXXFLAGS] then { + set DEFAULT_CXXFLAGS " -pedantic-errors" +} + +# Initialize `dg'. +dg-init + +# Main loop. +dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.C]] \ + "" $DEFAULT_CXXFLAGS + +# All done. +dg-finish + --- gcc/testsuite/g++.target/s390/pr94704-1.C.jj 2020-04-28 16:33:53.431130852 +0200 +++ gcc/testsuite/g++.target/s390/pr94704-1.C 2020-04-28 17:38:59.895236862 +0200 @@ -0,0 +1,34 @@ +// PR target/94704 +// { dg-do compile } +// { dg-options "-O2 -std=c++14" } +// Test that for all the calls in this testcase the C++17 empty base +// artificial fields and [[no_unique_address]] empty class non-static +// data members are ignored in the decision whether passed arguments +// have a single floating point field. +// { dg-final { scan-assembler-times {(?n)^\s+ld\s+%f0,} 7 } } + +struct X { }; +struct Y { int : 0; }; +struct Z { int : 0; Y y; }; +struct U : public X { X q; }; +struct A { double a; }; +struct B : public X { double a; }; +struct C : public Y { double a; }; +struct D : public Z { double a; }; +struct E : public U { double a; }; +struct F { [[no_unique_address]] X x; double a; }; +struct G { [[no_unique_address]] Y y; double a; }; +struct H { [[no_unique_address]] Z z; double a; }; +struct I { [[no_unique_address]] U u; double a; }; +struct J { double a; [[no_unique_address]] X x; }; +struct K { double a; [[no_unique_address]] Y y; }; +struct L { double a; [[no_unique_address]] Z z; }; +struct M { double a; [[no_unique_address]] U u; }; +#define T(S, s) extern S s; extern void foo##s (S); int bar##s () { foo##s (s); return 0; } +T (A, a) +T (B, b) +T (C, c) +T (F, f) +T (G, g) +T (J, j) +T (K, k) --- gcc/testsuite/g++.target/s390/pr94704-2.C.jj 2020-04-28 16:33:53.431130852 +0200 +++ gcc/testsuite/g++.target/s390/pr94704-2.C 2020-04-28 17:30:38.568586476 +0200 @@ -0,0 +1,34 @@ +// PR target/94704 +// { dg-do compile } +// { dg-options "-O2 -std=c++14" } +// Test that for no calls in this testcase the C++17 empty base +// artificial fields and [[no_unique_address]] empty class non-static +// data members are ignored in the decision whether passed arguments +// have a single floating point field. +// { dg-final { scan-assembler-not {(?n)^\s+ld\s+%f0,} } } + +struct X { }; +struct Y { int : 0; }; +struct Z { int : 0; Y y; }; +struct U : public X { X q; }; +struct A { double a; }; +struct B : public X { double a; }; +struct C : public Y { double a; }; +struct D : public Z { double a; }; +struct E : public U { double a; }; +struct F { [[no_unique_address]] X x; double a; }; +struct G { [[no_unique_address]] Y y; double a; }; +struct H { [[no_unique_address]] Z z; double a; }; +struct I { [[no_unique_address]] U u; double a; }; +struct J { double a; [[no_unique_address]] X x; }; +struct K { double a; [[no_unique_address]] Y y; }; +struct L { double a; [[no_unique_address]] Z z; }; +struct M { double a; [[no_unique_address]] U u; }; +#define T(S, s) extern S s; extern void foo##s (S); int bar##s () { foo##s (s); return 0; } +// { dg-bogus "parameter passing for argument of type" } +T (D, d) +T (E, e) +T (H, h) +T (I, i) +T (L, l) +T (M, m) --- gcc/testsuite/g++.target/s390/pr94704-3.C.jj 2020-04-28 16:33:53.431130852 +0200 +++ gcc/testsuite/g++.target/s390/pr94704-3.C 2020-04-28 17:39:07.759121755 +0200 @@ -0,0 +1,36 @@ +// PR target/94704 +// { dg-do compile } +// { dg-options "-O2 -std=c++17" } +// Test that for all the calls in this testcase the C++17 empty base +// artificial fields and [[no_unique_address]] empty class non-static +// data members are ignored in the decision whether passed arguments +// have a single floating point field. +// { dg-final { scan-assembler-times {(?n)^\s+ld\s+%f0,} 7 } } + +struct X { }; +struct Y { int : 0; }; +struct Z { int : 0; Y y; }; +struct U : public X { X q; }; +struct A { double a; }; +struct B : public X { double a; }; +struct C : public Y { double a; }; +struct D : public Z { double a; }; +struct E : public U { double a; }; +struct F { [[no_unique_address]] X x; double a; }; +struct G { [[no_unique_address]] Y y; double a; }; +struct H { [[no_unique_address]] Z z; double a; }; +struct I { [[no_unique_address]] U u; double a; }; +struct J { double a; [[no_unique_address]] X x; }; +struct K { double a; [[no_unique_address]] Y y; }; +struct L { double a; [[no_unique_address]] Z z; }; +struct M { double a; [[no_unique_address]] U u; }; +#define T(S, s) extern S s; extern void foo##s (S); int bar##s () { foo##s (s); return 0; } +// { dg-message "parameter passing for argument of type 'B' when C\\+\\+17 is enabled changed to match C\\+\\+14 in GCC 10.1" "" { target *-*-* } .-1 } +// { dg-message "parameter passing for argument of type 'C' when C\\+\\+17 is enabled changed to match C\\+\\+14 in GCC 10.1" "" { target *-*-* } .-2 } +T (A, a) +T (B, b) +T (C, c) +T (F, f) +T (G, g) +T (J, j) +T (K, k) --- gcc/testsuite/g++.target/s390/pr94704-4.C.jj 2020-04-28 16:33:53.431130852 +0200 +++ gcc/testsuite/g++.target/s390/pr94704-4.C 2020-04-28 17:30:28.296739746 +0200 @@ -0,0 +1,34 @@ +// PR target/94704 +// { dg-do compile } +// { dg-options "-O2 -std=c++17" } +// Test that for no calls in this testcase the C++17 empty base +// artificial fields and [[no_unique_address]] empty class non-static +// data members are ignored in the decision whether passed arguments +// have a single floating point field. +// { dg-final { scan-assembler-not {(?n)^\s+ld\s+%f0,} } } + +struct X { }; +struct Y { int : 0; }; +struct Z { int : 0; Y y; }; +struct U : public X { X q; }; +struct A { double a; }; +struct B : public X { double a; }; +struct C : public Y { double a; }; +struct D : public Z { double a; }; +struct E : public U { double a; }; +struct F { [[no_unique_address]] X x; double a; }; +struct G { [[no_unique_address]] Y y; double a; }; +struct H { [[no_unique_address]] Z z; double a; }; +struct I { [[no_unique_address]] U u; double a; }; +struct J { double a; [[no_unique_address]] X x; }; +struct K { double a; [[no_unique_address]] Y y; }; +struct L { double a; [[no_unique_address]] Z z; }; +struct M { double a; [[no_unique_address]] U u; }; +#define T(S, s) extern S s; extern void foo##s (S); int bar##s () { foo##s (s); return 0; } +// { dg-bogus "parameter passing for argument of type" } +T (D, d) +T (E, e) +T (H, h) +T (I, i) +T (L, l) +T (M, m)