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

--- Comment #7 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
So, does:
struct empty_base {};
struct S : public empty_base { struct{}a[1]; };
S s, a[5];

__attribute__((noipa)) void
foo (int x, ...)
{
  __builtin_va_list ap;
  __builtin_va_start (ap, x);
  if (x != 1 && x != 2)
    __builtin_abort ();
  if (__builtin_va_arg (ap, double) != 1.0)
    __builtin_abort ();
  if (x == 1)
    __builtin_va_arg (ap, S);
  if (__builtin_va_arg (ap, long long) != 2LL)
    __builtin_abort ();
  if (x == 1)
    {
      __builtin_va_arg (ap, S);
      __builtin_va_arg (ap, S);
    }
  __builtin_va_end (ap);
}

int
main ()
{
  foo (1, 1.0, s, 2LL, a[2], a[2]);
  foo (2, 1.0, 2LL);
}

FAIL too?  Seems the va_arg (sp, S); don't do anything, i.e. not to expect the
empty class with empty base to be passed at all, but on the caller side it
makes a change:
The first arg is passed in %ecx, second in both %xmm1 and %rdx it seems, and
2LL is passed in %r9 in the first call to foo and in $r8 in the second one.

Now, the question is what MSCV or other compilers do (e.g. clang), if they
match what GCC does on the caller side, or on the va_arg side (guess one needs
to sed -i -e 's/__builtin_//g;s/__attribute__((noipa)) //' in the testcase, and
add #include <cstdarg> and #include <cstdlib>.  

Seems even empty bases aren't needed, as struct S { struct{}a[1]; }; is treated
the same, or even just struct S {};

Reply via email to