https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77728

--- Comment #18 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
If you want a testcase for aarch64, e.g.
template <int N>
struct alignas (16) A { char p[16]; };
A<0> v;
template <int N>
struct B
{
  typedef A<N> T;
  int i, j, k, l;
};
int
foo (int a, B<0> b)
{
  return a + b.i;
}
int
bar (int a, B<1> b)
{
  return a + b.i;
}
struct C
{
  static int h alignas (16);
  int i, j, k, l;
};
int
baz (int a, C b)
{
  return a + b.i;
}

will do the job, there is a warning on foo's b argument, because A<0> has been
instantiated first and when instantiating B<0>, we already see A<0>'s alignment
and use it when creating the TYPE_DECL.  Compared to that, for B<1> we don't
have it instantiated yet, so when TYPE_DECL is created, it gets minimal
alignment.  You might want to create e.g. a compat testcase from it too, have
caller of foo with the A<0> v; in it and callee without and vice versa, check
if it is able to pass the argument around properly.  Similarly with baz (in
that case it actually was a stable (but wrong) ABI before, the baz caller and
callee would agree, but they now don't in between unpatched and patched GCC.
For ARM you can easily adjust the testcase by s/16/8/g, and maybe removing k
and l fields too.

Comments on the patch:

#include "print-tree.h"
you don't really need this, that is from some debugging, right?

  unsigned int alignment ; // alignment for FIELD_DECLS in function arguments.
extraneous space before ;, not sure if it is a good idea to mix // and /*
comments and on the next line it is way too long, so maybe better use /* */
comments above each field.

 {
+
+  unsigned int alignment = 0;
+  unsigned int warning_alignment = 0;
extraneous vertical space.  Also, what is the point to have a struct containing
those 2 fields and auto vars mirroring that?  Just use the struct all the time?

alignment = std::max (alignment, DECL_ALIGN (field));
I think we usually use MAX rather than std::max.

+      if (nregs == 2 && (a.warning_alignment == 16 * BITS_PER_UNIT) && ncrn %
2)
+         if (a.warning_alignment < a.alignment
+             && warn_psabi)
+           warning (0, "Parameter passing changed for argument");
The if condition fits on one line.  Do you need the ()s around
a.warning_alignment == 16 * BITS_PER_UNIT?  Can't it be written as
      if (warn_psabi
          && nregs == 2
          && a.warning_alignment == 16 * BITS_PER_UNIT
          && a.alignment != 16 * BITS_PER_UNIT
          && ncrn % 2)
?  That is what is actually tested originally, whether alignment == 16 *
BITS_PER_UNIT.  Also, warnings should not start with capital letter.
And it would be nice to tell user which argument it is (does cumulative_args_t
track the argument number or could it?).

 on_stack:
   pcum->aapcs_stack_words = size / UNITS_PER_WORD;
-  if (aarch64_function_arg_alignment (mode, type) == 16 * BITS_PER_UNIT)
+  struct aarch64_fn_arg_alignment ab = aarch64_function_arg_alignment (mode,
type);
+  if (ab.alignment == 16 * BITS_PER_UNIT)
     pcum->aapcs_stack_size = ROUND_UP (pcum->aapcs_stack_size,
                                       16 / UNITS_PER_WORD);
No warning here, if ab.alignment is not 16 * BITS_PER_UNIT, but
ab.warning_alignment is and warn_psabi is on?  I must say I don't really know
exactly what pcum->aapcs_stack_size influence, but doesn't it influence the ABI
when the function is varargs?  I mean, with the above testcase, something like:
void
foo (int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int
k, int l, int m, B<0> n, ...)
with/without the A<0> v; early?

   if (alignment < PARM_BOUNDARY)
     alignment = PARM_BOUNDARY;
   if (alignment > STACK_BOUNDARY)
     alignment = STACK_BOUNDARY;
+
+  if (a.warning_alignment < PARM_BOUNDARY)
+    a.warning_alignment = PARM_BOUNDARY;
+
+  if (a.warning_alignment > STACK_BOUNDARY)
+    a.warning_alignment = STACK_BOUNDARY;
+
Isn't the above candidate for MAX/MIN to put it into fewer lines?

+  if (a.warning_alignment > alignment
+      && warn_psabi)
+    warning (0, "Parameter passing changed for argument in
function_arg_boundary");
+
+  

Again, condition can fit onto a single line.  Due to MAX/MIN, I guess the only
possible values of those 2 are 64 and 128, so the comparison is fine.  But
again, warning should not start with a capital letter and mentioning "in
function_arg_boundary" is not helpful to the users, much better would be to
tell which argument it is or something similar.  And, perhaps remove the
alignment variable and always use a.alignment?  There is also extra vertical
space before return.

+  align =  a.alignment / BITS_PER_UNIT;
Extraneous whitespace after =.

Reply via email to