Hi Richard, > -----Original Message----- > From: Richard Sandiford <richard.sandif...@arm.com> > Sent: 29 April 2020 11:04 > To: gcc-patches@gcc.gnu.org > Cc: ni...@redhat.com; Richard Earnshaw <richard.earns...@arm.com>; > Ramana Radhakrishnan <ramana.radhakrish...@arm.com>; Kyrylo > Tkachov <kyrylo.tkac...@arm.com> > Subject: [PATCH] arm: Fix parameter passing for [[no_unique_address]] > > This patch makes the ABI code ignore zero-sized [[no_unique_address]] > fields when deciding whether something is a HFA or HVA. > > For the tests, I wanted an -march setting that was stable enough > to use check-function-bodies and also wanted to force -mfloat-abi=hard. > I couldn't see any existing way of doing both together, since most > arm-related effective-target keywords are agnostic about the choice > between -mfloat-abi=softfp and -mfloat-abi=hard. I therefore added > a new effective-target keyword for this combination. > > I used the arm_arch_* framework for the effective-target rather than > writing a new set of custom Tcl routines. This has the nice property > of separating the "compile and assemble" cases from the "link and run" > cases. I only need compilation to work for the new tests, so requiring > linking to work would be an unnecessary restriction. > > However, including an ABI requirement is arguably stretching what the > list was originally intended to handle. The name arm_arch_v8a_hard > doesn't fit very naturally with some of the NEON-based tests. > On the other hand, the naming convention isn't entirely consistent, > so any choice would be inconsistent with something. > > Like with the aarch64 patch, clang produces equivalent code for all > tests except unions Q and R, which clang passes in s0 rather than r0. > I think this is a clang bug, since the "x" field contains a single-byte > FDT and so shouldn't be ignored.
Worth reporting it? > > Tested on arm-linux-gnueabihf and armeb-eabi. OK to install? Ok. Thanks, Kyrill > > Richard > > > 2020-04-29 Richard Sandiford <richard.sandif...@arm.com> > > gcc/ > * doc/sourcebuild.texi (arm_arch_v8a_hard_ok): Document new > effective-target keyword. > (arm_arch_v8a_hard_multilib): Likewise. > (arm_arch_v8a_hard): Document new dg-add-options keyword. > * config/arm/arm.c (arm_return_in_memory): Note that the APCS > code is deprecated and has not been updated to handle > DECL_FIELD_ABI_IGNORED. > (WARN_PSABI_EMPTY_CXX17_BASE): New constant. > (WARN_PSABI_NO_UNIQUE_ADDRESS): Likewise. > (aapcs_vfp_sub_candidate): Replace the boolean pointer parameter > avoid_cxx17_empty_base with a pointer to a bitmask. Ignore fields > whose DECL_FIELD_ABI_IGNORED bit is set when determining > whether > something actually is a HFA or HVA. Record whether we see a > [[no_unique_address]] field that previous GCCs would not have > ignored in this way. > (aapcs_vfp_is_call_or_return_candidate): Update the calls to > aapcs_vfp_sub_candidate and report a -Wpsabi warning for the > [[no_unique_address]] case. Use TYPE_MAIN_VARIANT in the > diagnostic messages. > (arm_needs_doubleword_align): Add a comment explaining why we > consider even zero-sized fields. > > gcc/testsuite/ > * lib/target-supports.exp: Add v8a_hard to the list of arm_arch_* > targets. > * g++.target/arm/no_unique_address_1.C: New test. > * g++.target/arm/no_unique_address_2.C: Likewise. > --- > gcc/config/arm/arm.c | 108 +++++++--- > gcc/doc/sourcebuild.texi | 15 ++ > .../g++.target/arm/no_unique_address_1.C | 201 ++++++++++++++++++ > .../g++.target/arm/no_unique_address_2.C | 201 ++++++++++++++++++ > gcc/testsuite/lib/target-supports.exp | 1 + > 5 files changed, 498 insertions(+), 28 deletions(-) > create mode 100644 gcc/testsuite/g++.target/arm/no_unique_address_1.C > create mode 100644 gcc/testsuite/g++.target/arm/no_unique_address_2.C > > diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi > index b69612024be..d8da77d5ba4 100644 > --- a/gcc/doc/sourcebuild.texi > +++ b/gcc/doc/sourcebuild.texi > @@ -1829,6 +1829,16 @@ Some multilibs may be incompatible with these > options. > ARM target supports @code{-mfpu=vfp3 -mfloat-abi=softfp}. > Some multilibs may be incompatible with these options. > > +@item arm_arch_v8a_hard_ok > +The compiler is targeting @code{arm*-*-*} and can compile and assemble > code > +using the options @code{-march=armv8-a -mfpu=neon-fp-armv8 -mfloat- > abi=hard}. > +This is not enough to guarantee that linking works. > + > +@item arm_arch_v8a_hard_multilib > +The compiler is targeting @code{arm*-*-*} and can build programs using > +the options @code{-march=armv8-a -mfpu=neon-fp-armv8 -mfloat- > abi=hard}. > +The target can also run the resulting binaries. > + > @item arm_v8_vfp_ok > ARM target supports @code{-mfpu=fp-armv8 -mfloat-abi=softfp}. > Some multilibs may be incompatible with these options. > @@ -2586,6 +2596,11 @@ the > @ref{arm_neon_fp16_ok,,arm_neon_fp16_ok effective target keyword}. > arm vfp3 floating point support; see > the @ref{arm_vfp3_ok,,arm_vfp3_ok effective target keyword}. > > +@item arm_arch_v8a_hard > +Add options for ARMv8-A and the hard-float variant of the AAPCS, > +if this is supported by the compiler; see the > +@ref{arm_arch_v8a_hard_ok,,arm_arch_v8a_hard_ok} effective target > keyword. > + > @item arm_v8_1a_neon > Add options for ARMv8.1-A with Adv.SIMD support, if this is supported > by the target; see the @ref{arm_v8_1a_neon_ok,,arm_v8_1a_neon_ok} > diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c > index 30a2a3aeb0e..dcaae7bf7aa 100644 > --- a/gcc/config/arm/arm.c > +++ b/gcc/config/arm/arm.c > @@ -5963,6 +5963,8 @@ arm_return_in_memory (const_tree type, > const_tree fntype) > > /* Find the first field, ignoring non FIELD_DECL things which will > have been created by C++. */ > + /* NOTE: This code is deprecated and has not been updated to handle > + DECL_FIELD_ABI_IGNORED. */ > for (field = TYPE_FIELDS (type); > field && TREE_CODE (field) != FIELD_DECL; > field = DECL_CHAIN (field)) > @@ -6135,23 +6137,42 @@ aapcs_vfp_cum_init (CUMULATIVE_ARGS *pcum > ATTRIBUTE_UNUSED, > pcum->aapcs_vfp_reg_alloc = 0; > } > > +/* Bitmasks that indicate whether earlier versions of GCC would have > + taken a different path through the ABI logic. This should result in > + a -Wpsabi warning if the earlier path led to a different ABI decision. > + > + WARN_PSABI_EMPTY_CXX17_BASE > + Indicates that the type includes an artificial empty C++17 base field > + that, prior to GCC 10.1, would prevent the type from being treated as > + a HFA or HVA. See PR94711 for details. > + > + WARN_PSABI_NO_UNIQUE_ADDRESS > + Indicates that the type includes an empty [[no_unique_address]] field > + that, prior to GCC 10.1, would prevent the type from being treated as > + a HFA or HVA. */ > +const unsigned int WARN_PSABI_EMPTY_CXX17_BASE = 1U << 0; > +const unsigned int WARN_PSABI_NO_UNIQUE_ADDRESS = 1U << 1; > + > /* Walk down the type tree of TYPE counting consecutive base elements. > 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. > > - 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. */ > + The WARN_PSABI_FLAGS argument allows the caller to check whether this > + function has changed its behavior relative to earlier versions of GCC. > + Normally the argument should be nonnull and point to a zero-initialized > + variable. The function then records whether the ABI decision might > + be affected by a known fix to the ABI logic, setting the associated > + WARN_PSABI_* bits if so. > + > + When the argument is instead a null pointer, the function tries to > + simulate the behavior of GCC before all such ABI fixes were made. > + This is useful to check whether the function returns something > + different after the ABI fixes. */ > static int > aapcs_vfp_sub_candidate (const_tree type, machine_mode *modep, > - bool *avoid_cxx17_empty_base) > + unsigned int *warn_psabi_flags) > { > machine_mode mode; > HOST_WIDE_INT size; > @@ -6224,7 +6245,7 @@ aapcs_vfp_sub_candidate (const_tree type, > machine_mode *modep, > return -1; > > count = aapcs_vfp_sub_candidate (TREE_TYPE (type), modep, > - avoid_cxx17_empty_base); > + warn_psabi_flags); > if (count == -1 > || !index > || !TYPE_MAX_VALUE (index) > @@ -6262,20 +6283,30 @@ aapcs_vfp_sub_candidate (const_tree type, > machine_mode *modep, > if (TREE_CODE (field) != FIELD_DECL) > continue; > > - /* Ignore C++17 empty base fields, while their type indicates they > - contain padding, this is only sometimes contributed to the > derived > - class. > - When the padding is contributed to the derived class that's > - caught by the general test for padding below. */ > - if (cxx17_empty_base_field_p (field) > - && avoid_cxx17_empty_base) > + if (DECL_FIELD_ABI_IGNORED (field)) > { > - *avoid_cxx17_empty_base = true; > - continue; > + /* See whether this is something that earlier versions of > + GCC failed to ignore. */ > + unsigned int flag; > + if (lookup_attribute ("no_unique_address", > + DECL_ATTRIBUTES (field))) > + flag = WARN_PSABI_NO_UNIQUE_ADDRESS; > + else if (cxx17_empty_base_field_p (field)) > + flag = WARN_PSABI_EMPTY_CXX17_BASE; > + else > + /* No compatibility problem. */ > + continue; > + > + /* Simulate the old behavior when WARN_PSABI_FLAGS is > null. */ > + if (warn_psabi_flags) > + { > + *warn_psabi_flags |= flag; > + continue; > + } > } > > sub_count = aapcs_vfp_sub_candidate (TREE_TYPE (field), modep, > - avoid_cxx17_empty_base); > + warn_psabi_flags); > if (sub_count < 0) > return -1; > count += sub_count; > @@ -6309,7 +6340,7 @@ aapcs_vfp_sub_candidate (const_tree type, > machine_mode *modep, > continue; > > sub_count = aapcs_vfp_sub_candidate (TREE_TYPE (field), modep, > - avoid_cxx17_empty_base); > + warn_psabi_flags); > if (sub_count < 0) > return -1; > count = count > sub_count ? count : sub_count; > @@ -6371,24 +6402,32 @@ aapcs_vfp_is_call_or_return_candidate (enum > arm_pcs pcs_variant, > out from the mode. */ > if (type) > { > - bool avoided = false; > - int ag_count = aapcs_vfp_sub_candidate (type, &new_mode, &avoided); > + unsigned int warn_psabi_flags = 0; > + int ag_count = aapcs_vfp_sub_candidate (type, &new_mode, > + &warn_psabi_flags); > if (ag_count > 0 && ag_count <= 4) > { > static unsigned last_reported_type_uid; > unsigned uid = TYPE_UID (TYPE_MAIN_VARIANT (type)); > int alt; > if (warn_psabi > - && avoided > + && warn_psabi_flags > && 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); > + /* Use TYPE_MAIN_VARIANT to strip any redundant const > + qualification. */ > + if (warn_psabi_flags & WARN_PSABI_NO_UNIQUE_ADDRESS) > + inform (input_location, "parameter passing for argument of " > + "type %qT with %<[[no_unique_address]]%> > members " > + "changed in GCC 10.1", TYPE_MAIN_VARIANT (type)); > + else if (warn_psabi_flags & WARN_PSABI_EMPTY_CXX17_BASE) > + 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_MAIN_VARIANT (type)); > } > *count = ag_count; > } > @@ -6933,7 +6972,20 @@ arm_needs_doubleword_align (machine_mode > mode, const_tree type) > > int ret = 0; > int ret2 = 0; > - /* Record/aggregate types: Use greatest member alignment of any > member. */ > + /* Record/aggregate types: Use greatest member alignment of any > member. > + > + Note that we explicitly consider zero-sized fields here, even though > + they don't map to AAPCS machine types. For example, in: > + > + struct __attribute__((aligned(8))) empty {}; > + > + struct s { > + [[no_unique_address]] empty e; > + int x; > + }; > + > + "s" contains only one Fundamental Data Type (the int field) > + but gains 8-byte alignment and size thanks to "e". */ > for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) > if (DECL_ALIGN (field) > PARM_BOUNDARY) > { > diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target- > supports.exp > index f416d5cafda..13761491e63 100644 > --- a/gcc/testsuite/lib/target-supports.exp > +++ b/gcc/testsuite/lib/target-supports.exp > @@ -4443,6 +4443,7 @@ foreach { armfunc armflag armdefs } { > v7ve "-march=armv7ve -marm" > "__ARM_ARCH_7A__ && __ARM_FEATURE_IDIV" > v8a "-march=armv8-a" __ARM_ARCH_8A__ > + v8a_hard "-march=armv8-a -mfpu=neon-fp-armv8 -mfloat-abi=hard" > __ARM_ARCH_8A__ > v8_1a "-march=armv8.1-a" __ARM_ARCH_8A__ > v8_2a "-march=armv8.2-a" __ARM_ARCH_8A__ > v8r "-march=armv8-r" __ARM_ARCH_8R__ > diff --git a/gcc/testsuite/g++.target/arm/no_unique_address_1.C > b/gcc/testsuite/g++.target/arm/no_unique_address_1.C > new file mode 100644 > index 00000000000..038aa00a499 > --- /dev/null > +++ b/gcc/testsuite/g++.target/arm/no_unique_address_1.C > @@ -0,0 +1,201 @@ > +/* { dg-require-effective-target arm_arch_v8a_hard_ok } */ > +/* { dg-options "-std=c++11 -O -foptimize-sibling-calls" } */ > +/* { dg-add-options arm_arch_v8a_hard } */ > +/* { dg-final { check-function-bodies "**" "" "" } } */ > + > +struct X { }; > +struct Y { int : 0; }; > +struct Z { int : 0; Y y; }; > +struct W : public X { X q; }; > + > +struct A { float a; }; > + > +struct B : public X { float a; }; > +struct C : public Y { float a; }; > +struct D : public Z { float a; }; > +struct E : public W { float a; }; > + > +struct F { [[no_unique_address]] X x; float a; }; > +struct G { [[no_unique_address]] Y y; float a; }; > +struct H { [[no_unique_address]] Z z; float a; }; > +struct I { [[no_unique_address]] W w; float a; }; > + > +struct J { float a; [[no_unique_address]] X x; float b; }; > +struct K { float a; [[no_unique_address]] Y y; float b; }; > +struct L { float a; [[no_unique_address]] Z z; float b; }; > +struct M { float a; [[no_unique_address]] W w; float b; }; > + > +struct N : public A { float b; }; > +struct O { [[no_unique_address]] A a; float b; }; > + > +struct P : public Y { int : 0; float a, b, c, d; }; > + > +union Q { X x; float a; }; > +union R { [[no_unique_address]] X x; float a; }; > + > +union S { A a; float b; }; > +union T { F f; float b; }; > +union U { N n; O o; }; > + > +typedef S Salias; > +typedef T Talias; > +typedef U Ualias; > + > +#define T(S, s) extern int callee_##s (S) > + > +/* > +** _Z8caller_aR1A: > +** vldr.32 s0, \[r0\] > +** b .* > +*/ > +T (A, a); int caller_a (A &a) { return callee_a (a); } /* { dg-bogus > {argument of > type 'A'} } */ > + > +/* > +** _Z8caller_bR1B: > +** vldr.32 s0, \[r0\] > +** b .* > +*/ > +T (B, b); int caller_b (B &b) { return callee_b (b); } /* { dg-bogus > {argument > of type 'B'} } */ > + > +/* > +** _Z8caller_cR1C: > +** vldr.32 s0, \[r0\] > +** b .* > +*/ > +T (C, c); int caller_c (C &c) { return callee_c (c); } /* { dg-bogus > {argument of > type 'C'} } */ > + > +/* > +** _Z8caller_dR1D: > +** ldm r0, {r0, r1} > +** b .* > +*/ > +T (D, d); int caller_d (D &d) { return callee_d (d); } /* { dg-bogus > {argument > of type 'D'} } */ > + > +/* > +** _Z8caller_eR1E: > +** ldm r0, {r0, r1} > +** b .* > +*/ > +T (E, e); int caller_e (E &e) { return callee_e (e); } /* { dg-bogus > {argument of > type 'E'} } */ > + > +/* > +** _Z8caller_fR1F: > +** vldr.32 s0, \[r0\] > +** b .* > +*/ > +T (F, f); int caller_f (F &f) { return callee_f (f); } /* { dg-message > {parameter > passing for argument of type 'F' with '\[\[no_unique_address\]\]' members > changed in GCC 10.1} } */ > + > +/* > +** _Z8caller_gR1G: > +** vldr.32 s0, \[r0\] > +** b .* > +*/ > +T (G, g); int caller_g (G &g) { return callee_g (g); } /* { dg-message > {parameter passing for argument of type 'G' with > '\[\[no_unique_address\]\]' members changed in GCC 10.1} } */ > + > +/* > +** _Z8caller_hR1H: > +** ldm r0, {r0, r1} > +** b .* > +*/ > +T (H, h); int caller_h (H &h) { return callee_h (h); } /* { dg-bogus > {argument > of type 'H'} } */ > + > +/* > +** _Z8caller_iR1I: > +** ldm r0, {r0, r1} > +** b .* > +*/ > +T (I, i); int caller_i (I &i) { return callee_i (i); } /* { dg-bogus > {argument of type > 'I'} } */ > + > +/* > +** _Z8caller_jR1J: > +** vldr.32 s0, \[r0\] > +** vldr.32 s1, \[r0, #4\] > +** b .* > +*/ > +T (J, j); int caller_j (J &j) { return callee_j (j); } /* { dg-message > {parameter > passing for argument of type 'J' with '\[\[no_unique_address\]\]' members > changed in GCC 10.1} } */ > + > +/* > +** _Z8caller_kR1K: > +** vldr.32 s0, \[r0\] > +** vldr.32 s1, \[r0, #4\] > +** b .* > +*/ > +T (K, k); int caller_k (K &k) { return callee_k (k); } /* { dg-message > {parameter > passing for argument of type 'K' with '\[\[no_unique_address\]\]' members > changed in GCC 10.1} } */ > + > +/* > +** _Z8caller_lR1L: > +** ldm r0, {r0, r1, r2} > +** b .* > +*/ > +T (L, l); int caller_l (L &l) { return callee_l (l); } /* { dg-bogus > {argument of > type 'L'} } */ > + > +/* > +** _Z8caller_mR1M: > +** ldm r0, {r0, r1, r2} > +** b .* > +*/ > +T (M, m); int caller_m (M &m) { return callee_m (m); } /* { dg-bogus > {argument of type 'M'} } */ > + > +/* > +** _Z8caller_nR1N: > +** vldr.32 s0, \[r0\] > +** vldr.32 s1, \[r0, #4\] > +** b .* > +*/ > +T (N, n); int caller_n (N &n) { return callee_n (n); } /* { dg-bogus > {argument > of type 'N'} } */ > + > +/* > +** _Z8caller_oR1O: > +** vldr.32 s0, \[r0\] > +** vldr.32 s1, \[r0, #4\] > +** b .* > +*/ > +T (O, o); int caller_o (O &o) { return callee_o (o); } /* { dg-bogus > {argument > of type 'O'} } */ > + > +/* > +** _Z8caller_pR1P: > +** vldr.32 s0, \[r0\] > +** vldr.32 s1, \[r0, #4\] > +** vldr.32 s2, \[r0, #8\] > +** vldr.32 s3, \[r0, #12\] > +** b .* > +*/ > +T (P, p); int caller_p (P &p) { return callee_p (p); } /* { dg-bogus > {argument of > type 'P'} } */ > + > +/* > +** _Z8caller_qR1Q: > +** ldr r0, \[r0\] > +** b .* > +*/ > +T (Q, q); int caller_q (Q &q) { return callee_q (q); } /* { dg-bogus > {argument > of type 'Q'} } */ > + > +/* > +** _Z8caller_rR1R: > +** ldr r0, \[r0\] > +** b .* > +*/ > +T (R, r); int caller_r (R &r) { return callee_r (r); } /* { dg-bogus > {argument of > type 'R'} } */ > + > +/* > +** _Z8caller_sR1S: > +** vldr.32 s0, \[r0\] @ int > +** b .* > +*/ > +T (Salias, s); int caller_s (Salias &s) { return callee_s (s); } /* { > dg-bogus > {argument of type 'S'} } */ > + > +/* > +** _Z8caller_tR1T: > +** vldr.32 s0, \[r0\] @ int > +** b .* > +*/ > +T (Talias, t); int caller_t (Talias &t) { return callee_t (t); } /* { > dg-message > {parameter passing for argument of type 'T' with '\[\[no_unique_address\]\]' > members changed in GCC 10.1} } */ > + > +/* > +** _Z8caller_uR1U: > +** vldr.32 s0, \[r0\] > +** vldr.32 s1, \[r0, #4\] > +** b .* > +*/ > +T (Ualias, u); int caller_u (Ualias &u) { return callee_u (u); } /* { > dg-bogus > {argument of type 'U'} } */ > + > +/* { dg-bogus {argument of type 'const} "should not be printed as const" > { target *-*-*} 0 } */ > diff --git a/gcc/testsuite/g++.target/arm/no_unique_address_2.C > b/gcc/testsuite/g++.target/arm/no_unique_address_2.C > new file mode 100644 > index 00000000000..8be5de2539a > --- /dev/null > +++ b/gcc/testsuite/g++.target/arm/no_unique_address_2.C > @@ -0,0 +1,201 @@ > +/* { dg-require-effective-target arm_arch_v8a_hard_ok } */ > +/* { dg-options "-std=c++17 -O -foptimize-sibling-calls" } */ > +/* { dg-add-options arm_arch_v8a_hard } */ > +/* { dg-final { check-function-bodies "**" "" "" } } */ > + > +struct X { }; > +struct Y { int : 0; }; > +struct Z { int : 0; Y y; }; > +struct W : public X { X q; }; > + > +struct A { float a; }; > + > +struct B : public X { float a; }; > +struct C : public Y { float a; }; > +struct D : public Z { float a; }; > +struct E : public W { float a; }; > + > +struct F { [[no_unique_address]] X x; float a; }; > +struct G { [[no_unique_address]] Y y; float a; }; > +struct H { [[no_unique_address]] Z z; float a; }; > +struct I { [[no_unique_address]] W w; float a; }; > + > +struct J { float a; [[no_unique_address]] X x; float b; }; > +struct K { float a; [[no_unique_address]] Y y; float b; }; > +struct L { float a; [[no_unique_address]] Z z; float b; }; > +struct M { float a; [[no_unique_address]] W w; float b; }; > + > +struct N : public A { float b; }; > +struct O { [[no_unique_address]] A a; float b; }; > + > +struct P : public Y { int : 0; float a, b, c, d; }; > + > +union Q { X x; float a; }; > +union R { [[no_unique_address]] X x; float a; }; > + > +union S { A a; float b; }; > +union T { F f; float b; }; > +union U { N n; O o; }; > + > +typedef S Salias; > +typedef T Talias; > +typedef U Ualias; > + > +#define T(S, s) extern int callee_##s (S) > + > +/* > +** _Z8caller_aR1A: > +** vldr.32 s0, \[r0\] > +** b .* > +*/ > +T (A, a); int caller_a (A &a) { return callee_a (a); } /* { dg-bogus > {argument of > type 'A'} } */ > + > +/* > +** _Z8caller_bR1B: > +** vldr.32 s0, \[r0\] > +** b .* > +*/ > +T (B, b); int caller_b (B &b) { return callee_b (b); } /* { dg-message > {parameter passing for argument of type 'B' when C\+\+17 is enabled > changed to match C\+\+14 in GCC 10.1} } */ > + > +/* > +** _Z8caller_cR1C: > +** vldr.32 s0, \[r0\] > +** b .* > +*/ > +T (C, c); int caller_c (C &c) { return callee_c (c); } /* { dg-message > {parameter > passing for argument of type 'C' when C\+\+17 is enabled changed to match > C\+\+14 in GCC 10.1} } */ > + > +/* > +** _Z8caller_dR1D: > +** ldm r0, {r0, r1} > +** b .* > +*/ > +T (D, d); int caller_d (D &d) { return callee_d (d); } /* { dg-bogus > {argument > of type 'D'} } */ > + > +/* > +** _Z8caller_eR1E: > +** ldm r0, {r0, r1} > +** b .* > +*/ > +T (E, e); int caller_e (E &e) { return callee_e (e); } /* { dg-bogus > {argument of > type 'E'} } */ > + > +/* > +** _Z8caller_fR1F: > +** vldr.32 s0, \[r0\] > +** b .* > +*/ > +T (F, f); int caller_f (F &f) { return callee_f (f); } /* { dg-message > {parameter > passing for argument of type 'F' with '\[\[no_unique_address\]\]' members > changed in GCC 10.1} } */ > + > +/* > +** _Z8caller_gR1G: > +** vldr.32 s0, \[r0\] > +** b .* > +*/ > +T (G, g); int caller_g (G &g) { return callee_g (g); } /* { dg-message > {parameter passing for argument of type 'G' with > '\[\[no_unique_address\]\]' members changed in GCC 10.1} } */ > + > +/* > +** _Z8caller_hR1H: > +** ldm r0, {r0, r1} > +** b .* > +*/ > +T (H, h); int caller_h (H &h) { return callee_h (h); } /* { dg-bogus > {argument > of type 'H'} } */ > + > +/* > +** _Z8caller_iR1I: > +** ldm r0, {r0, r1} > +** b .* > +*/ > +T (I, i); int caller_i (I &i) { return callee_i (i); } /* { dg-bogus > {argument of type > 'I'} } */ > + > +/* > +** _Z8caller_jR1J: > +** vldr.32 s0, \[r0\] > +** vldr.32 s1, \[r0, #4\] > +** b .* > +*/ > +T (J, j); int caller_j (J &j) { return callee_j (j); } /* { dg-message > {parameter > passing for argument of type 'J' with '\[\[no_unique_address\]\]' members > changed in GCC 10.1} } */ > + > +/* > +** _Z8caller_kR1K: > +** vldr.32 s0, \[r0\] > +** vldr.32 s1, \[r0, #4\] > +** b .* > +*/ > +T (K, k); int caller_k (K &k) { return callee_k (k); } /* { dg-message > {parameter > passing for argument of type 'K' with '\[\[no_unique_address\]\]' members > changed in GCC 10.1} } */ > + > +/* > +** _Z8caller_lR1L: > +** ldm r0, {r0, r1, r2} > +** b .* > +*/ > +T (L, l); int caller_l (L &l) { return callee_l (l); } /* { dg-bogus > {argument of > type 'L'} } */ > + > +/* > +** _Z8caller_mR1M: > +** ldm r0, {r0, r1, r2} > +** b .* > +*/ > +T (M, m); int caller_m (M &m) { return callee_m (m); } /* { dg-bogus > {argument of type 'M'} } */ > + > +/* > +** _Z8caller_nR1N: > +** vldr.32 s0, \[r0\] > +** vldr.32 s1, \[r0, #4\] > +** b .* > +*/ > +T (N, n); int caller_n (N &n) { return callee_n (n); } /* { dg-bogus > {argument > of type 'N'} } */ > + > +/* > +** _Z8caller_oR1O: > +** vldr.32 s0, \[r0\] > +** vldr.32 s1, \[r0, #4\] > +** b .* > +*/ > +T (O, o); int caller_o (O &o) { return callee_o (o); } /* { dg-bogus > {argument > of type 'O'} } */ > + > +/* > +** _Z8caller_pR1P: > +** vldr.32 s0, \[r0\] > +** vldr.32 s1, \[r0, #4\] > +** vldr.32 s2, \[r0, #8\] > +** vldr.32 s3, \[r0, #12\] > +** b .* > +*/ > +T (P, p); int caller_p (P &p) { return callee_p (p); } /* { dg-message > {parameter passing for argument of type 'P' when C\+\+17 is enabled > changed to match C\+\+14 in GCC 10.1} } */ > + > +/* > +** _Z8caller_qR1Q: > +** ldr r0, \[r0\] > +** b .* > +*/ > +T (Q, q); int caller_q (Q &q) { return callee_q (q); } /* { dg-bogus > {argument > of type 'Q'} } */ > + > +/* > +** _Z8caller_rR1R: > +** ldr r0, \[r0\] > +** b .* > +*/ > +T (R, r); int caller_r (R &r) { return callee_r (r); } /* { dg-bogus > {argument of > type 'R'} } */ > + > +/* > +** _Z8caller_sR1S: > +** vldr.32 s0, \[r0\] @ int > +** b .* > +*/ > +T (Salias, s); int caller_s (Salias &s) { return callee_s (s); } /* { > dg-bogus > {argument of type 'S'} } */ > + > +/* > +** _Z8caller_tR1T: > +** vldr.32 s0, \[r0\] @ int > +** b .* > +*/ > +T (Talias, t); int caller_t (Talias &t) { return callee_t (t); } /* { > dg-message > {parameter passing for argument of type 'T' with '\[\[no_unique_address\]\]' > members changed in GCC 10.1} } */ > + > +/* > +** _Z8caller_uR1U: > +** vldr.32 s0, \[r0\] > +** vldr.32 s1, \[r0, #4\] > +** b .* > +*/ > +T (Ualias, u); int caller_u (Ualias &u) { return callee_u (u); } /* { > dg-bogus > {argument of type 'U'} } */ > + > +/* { dg-bogus {argument of type 'const} "should not be printed as const" > { target *-*-*} 0 } */