1  /* __builtin_va_arg_pack () builtin tests.  */
       2  
       3  #include <stdarg.h>
       4  
       5  extern void abort (void);
       6  
       7  int v1 = 8;
       8  long int v2 = 3;
       9  void *v3 = (void *) &v2;
      10  struct A { char c[16]; } v4 = { "foo" };
      11  long double v5 = 40;
      12  char seen[20];
      13  int cnt;
      14  
      15  __attribute__ ((noinline)) int
      16  foo1 (int x, int y, ...)
      17  {
      18    int i;
      19    long int l;
      20    void *v;
      21    struct A a;
      22    long double ld;
      23    va_list ap;
      24  
      25    va_start (ap, y);
      26    if (x < 0 || x >= 20 || seen[x])
      27      abort ();
      28    seen[x] = ++cnt;
      29    if (y != 6)
      30      abort ();
      31    i = va_arg (ap, int);
      32    if (i != 5)
      33      abort ();
      34    switch (x)
      35      {
      36      case 0:
      37        i = va_arg (ap, int);
      38        if (i != 9 || v1 != 9)
      39  	abort ();
      40        a = va_arg (ap, struct A);
      41        if (__builtin_memcmp (a.c, v4.c, sizeof (a.c)) != 0)
      42  	abort ();
      43        v = (void *) va_arg (ap, struct A *);
      44        if (v != (void *) &v4)
      45  	abort ();
      46        l = va_arg (ap, long int);
      47        if (l != 3 || v2 != 4)
      48  	abort ();
      49        break;
      50      case 1:
      51        ld = va_arg (ap, long double);
      52        if (ld != 41 || v5 != ld)
      53  	abort ();
      54        i = va_arg (ap, int);
      55        if (i != 8)
      56  	abort ();
      57        v = va_arg (ap, void *);
      58        if (v != &v2)
      59  	abort ();
      60        break;
      61      case 2:
      62        break;
      63      default:
      64        abort ();
      65      }
      66    va_end (ap);
      67    return x;
      68  }
      69  
      70  __attribute__ ((noinline)) int
      71  foo2 (int x, int y, ...)
      72  {
      73    long long int ll;
      74    void *v;
      75    struct A a, b;
      76    long double ld;
      77    va_list ap;
      78  
      79    va_start (ap, y);
      80    if (x < 0 || x >= 20 || seen[x])
      81      abort ();
      82    seen[x] = ++cnt | 64;
      83    if (y != 10)
      84      abort ();
      85    switch (x)
      86      {
      87      case 11:
      88        break;
      89      case 12:
      90        ld = va_arg (ap, long double);
      91        if (ld != 41 || v5 != 40)
      92  	abort ();
      93        a = va_arg (ap, struct A);
      94        if (__builtin_memcmp (a.c, v4.c, sizeof (a.c)) != 0)
      95  	abort ();
      96        b = va_arg (ap, struct A);
      97        if (__builtin_memcmp (b.c, v4.c, sizeof (b.c)) != 0)
      98  	abort ();
      99        v = va_arg (ap, void *);
     100        if (v != &v2)
     101  	abort ();
     102        ll = va_arg (ap, long long int);
     103        if (ll != 16LL)
     104  	abort ();
     105        break;
     106      case 2:
     107        break;
     108      default:
     109        abort ();
     110      }
     111    va_end (ap);
     112    return x + 8;
     113  }
     114  
     115  __attribute__ ((noinline)) int
     116  foo3 (void)
     117  {
     118    return 6;
     119  }
     120  
     121  extern inline __attribute__ ((always_inline, gnu_inline)) int
     122  bar (int x, ...)
     123  {
     124    if (x < 10)
     125      return foo1 (x, foo3 (), 5, __builtin_va_arg_pack ());
     126    return foo2 (x, foo3 () + 4, __builtin_va_arg_pack ());
     127  }
     128  
     129  int
     130  main (void)
     131  {
     132    if (bar (0, ++v1, v4, &v4, v2++) != 0)
     133      abort ();
     134    if (bar (1, ++v5, 8, v3) != 1)
     135      abort ();
     136    if (bar (2) != 2)
     137      abort ();
     138    if (bar (v1 + 2) != 19)
     139      abort ();
     140    if (bar (v1 + 3, v5--, v4, v4, v3, 16LL) != 20)
     141      abort ();
     142    return 0;
     143  }