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)

Reply via email to