/* Test AAPCS64 layout and __builtin_va_arg.

   This test covers a corner case where a composite type parameter fits in one
   register: we do not need a double-word alignment when accessing it in the
   va_arg stack area.  */

/* { dg-do run { target aarch64*-*-* } } */

#ifndef IN_FRAMEWORK
#define AAPCS64_TEST_STDARG
#define TESTFILE "va_arg-17.c"
#include "type-def.h"

enum E6 { e6_0, e6_1, e6_2, e6_3, e6_65533 = 65533, e6_65534, e6_65535 };
typedef enum E6 Tal16E6 __attribute__((aligned (16)));
typedef unsigned int Tuint;

int fails;

union S2844 {
  Tuint a:((((10) - 1) & 31) + 1);
  Tal16E6 __attribute__((aligned (2), packed)) b:31;
  struct{}c[0];
} ;
union S2844 s2844;
union S2844 a2844[5];

#define HAS_DATA_INIT_FUNC
void init_data ()
{
  memset (&s2844, '\0', sizeof (s2844));
  memset (a2844, '\0', sizeof (a2844));
  s2844.a = 799U;
  a2844[2].a = 586U;
}

#include "abitest.h"
#else
  ARG       (int          , 1        , W0 , LAST_NAMED_ARG_ID)
  DOTS
  ANON_PROMOTED  (float   , 1.0f, double, 1.0, D0, 1)
  ANON      (union S2844  , s2844    , X1 , 2)
  ANON      (long long    , 2LL      , X2 , 3)
  ANON      (union  S2844 , a2844[2] , X3 , 4)
  LAST_ANON (union  S2844 , a2844[2] , X4 , 5)
#endif

#if 0
  /* This test is derived from a case generated by struct-layout-1.exp:  */

enum E6 { e6_0, e6_1, e6_2, e6_3, e6_65533 = 65533, e6_65534, e6_65535 };
typedef enum E6 Tal16E6 __attribute__((aligned (16)));
typedef unsigned int Tuint;

int fails;

union S2844 {
  Tuint a:((((10) - 1) & 31) + 1);
  Tal16E6 __attribute__((aligned (2), packed)) b:31;
  struct{}c[0];
} ;
union S2844 s2844;
union S2844 a2844[5];

typedef __builtin_va_list __gnuc_va_list;
typedef __gnuc_va_list va_list;

void check2844va (int z, ...) {
  union S2844 arg, *p;
  va_list ap;

  __builtin_va_start(ap,z);
  if (__builtin_va_arg(ap,double) != 1.0)
    printf ("fail %d.%d\n", 2844, 0), ++fails;

  p = &s2844;
  arg = __builtin_va_arg(ap,union S2844);  /* This would fail.  */
  if (p->a != arg.a)
    printf ("fail %d.%d\n", 2844, 1), ++fails;

  if (__builtin_va_arg(ap,long long) != 3LL)
    printf ("fail %d.%d\n", 2844, 2), ++fails;

  p = &a2844[2];
  arg = __builtin_va_arg(ap,union S2844);  /* This would fail.  */
  if (p->a != arg.a)
    printf ("fail %d.%d\n", 2844, 3), ++fails;

  arg = __builtin_va_arg(ap,union S2844);  /* This would fail.  */
  if (p->a != arg.a)
    printf ("fail %d.%d\n", 2844, 4), ++fails;

  __builtin_va_end(ap);
}

int main (void) {
  int i, j;
  memset (&s2844, '\0', sizeof (s2844));
  memset (a2844, '\0', sizeof (a2844));
  s2844.a = 799U;
  a2844[2].a = 586U;
  check2844va (1, 1.0, s2844, 2LL, a2844[2], a2844[2]);
  exit (fails != 0);
}
#endif /* 0 */
