(root)/
gcc-13.2.0/
gcc/
testsuite/
gcc.dg/
va-arg-pack-len-1.c
       1  /* { dg-do run } */
       2  /* { dg-options "-O2" } */
       3  
       4  #include <stdarg.h>
       5  
       6  extern int error_open_missing_mode (void)
       7    __attribute__((__error__ ("open with O_CREAT needs 3 arguments, only 2 were given")));
       8  extern int warn_open_too_many_arguments (void)
       9    __attribute__((__warning__ ("open called with more than 3 arguments")));
      10  extern void abort (void);
      11  
      12  char expected_char;
      13  
      14  __attribute__((noinline)) int
      15  myopen2 (const char *path, int oflag)
      16  {
      17    if (expected_char++ != path[0] || path[1] != '\0')
      18      abort ();
      19    switch (path[0])
      20      {
      21      case 'f':
      22        if (oflag != 0x2)
      23  	abort ();
      24        break;
      25      case 'g':
      26        if (oflag != 0x43)
      27  	abort ();
      28        /* In real __open_2 this would terminate the program:
      29  	 open with O_CREAT without third argument.  */
      30        return -6;
      31      default:
      32        abort ();
      33      }
      34    return 0;
      35  }
      36  
      37  __attribute__((noinline)) int
      38  myopenva (const char *path, int oflag, ...)
      39  {
      40    int mode = 0;
      41    va_list ap;
      42    if ((oflag & 0x40) != 0)
      43      {
      44        va_start (ap, oflag);
      45        mode = va_arg (ap, int);
      46        va_end (ap);
      47      }
      48    if (expected_char++ != path[0] || path[1] != '\0')
      49      abort ();
      50    switch (path[0])
      51      {
      52      case 'a':
      53        if (oflag != 0x43 || mode != 0644)
      54  	abort ();
      55        break;
      56      case 'b':
      57        if (oflag != 0x3)
      58  	abort ();
      59        break;
      60      case 'c':
      61        if (oflag != 0x2)
      62  	abort ();
      63        break;
      64      case 'd':
      65        if (oflag != 0x43 || mode != 0600)
      66  	abort ();
      67        break;
      68      case 'e':
      69        if (oflag != 0x3)
      70  	abort ();
      71        break;
      72      default:
      73        abort ();
      74      }
      75    return 0;
      76  }
      77  
      78  extern inline __attribute__((always_inline, gnu_inline)) int
      79  myopen (const char *path, int oflag, ...)
      80  {
      81    if (__builtin_va_arg_pack_len () > 1)
      82      warn_open_too_many_arguments ();
      83  
      84    if (__builtin_constant_p (oflag))
      85      {
      86        if ((oflag & 0x40) != 0 && __builtin_va_arg_pack_len () < 1)
      87  	{
      88  	  error_open_missing_mode ();
      89  	  return myopen2 (path, oflag);
      90  	}
      91        return myopenva (path, oflag, __builtin_va_arg_pack ());
      92      }
      93  
      94    if (__builtin_va_arg_pack_len () < 1)
      95      return myopen2 (path, oflag);
      96  
      97    return myopenva (path, oflag, __builtin_va_arg_pack ());
      98  }
      99  
     100  volatile int l0;
     101  
     102  int
     103  main (void)
     104  {
     105    expected_char = 'a';
     106    if (myopen ("a", 0x43, 0644))
     107      abort ();
     108    if (myopen ("b", 0x3, 0755))
     109      abort ();
     110    if (myopen ("c", 0x2))
     111      abort ();
     112    if (myopen ("d", l0 + 0x43, 0600))
     113      abort ();
     114    if (myopen ("e", l0 + 0x3, 0700))
     115      abort ();
     116    if (myopen ("f", l0 + 0x2))
     117      abort ();
     118    /* Invalid use of myopen, but only detectable at runtime.  */
     119    if (myopen ("g", l0 + 0x43) != -6)
     120      abort ();
     121    return 0;
     122  }