(root)/
gcc-13.2.0/
gcc/
testsuite/
gcc.dg/
analyzer/
stdarg-1-sysv_abi.c
       1  /* As per stdarg-1.c, but using the sysv_abi versions of the builtins.  */
       2  
       3  /* { dg-additional-options "-fno-analyzer-suppress-followups" } */
       4  /* { dg-do compile { target { x86_64-*-* && lp64 } } } */
       5  
       6  #include "analyzer-decls.h"
       7  
       8  /* Unpacking a va_list.  */
       9  
      10  static void __attribute__((noinline))
      11  __analyzer_called_by_test_1 (int placeholder, ...)
      12  {
      13    const char *s;
      14    int i;
      15    char c;
      16  
      17    __builtin_sysv_va_list ap;
      18    __builtin_sysv_va_start (ap, placeholder);
      19  
      20    s = __builtin_va_arg (ap, char *);
      21    __analyzer_eval (s[0] == 'f'); /* { dg-warning "TRUE" } */
      22  
      23    i = __builtin_va_arg (ap, int);
      24    __analyzer_eval (i == 1066); /* { dg-warning "TRUE" } */
      25  
      26    c = (char)__builtin_va_arg (ap, int);
      27    __analyzer_eval (c == '@'); /* { dg-warning "TRUE" } */
      28  
      29    __builtin_sysv_va_end (ap);
      30  }
      31  
      32  void test_1 (void)
      33  {
      34    __analyzer_called_by_test_1 (42, "foo", 1066, '@');
      35  }
      36  
      37  /* Unpacking a va_list passed from an intermediate function.  */
      38  
      39  static void __attribute__((noinline))
      40  __analyzer_test_2_inner (__builtin_sysv_va_list ap)
      41  {
      42    const char *s;
      43    int i;
      44    char c;
      45    
      46    s = __builtin_va_arg (ap, char *);
      47    __analyzer_eval (s[0] == 'f'); /* { dg-warning "TRUE" } */
      48  
      49    i = __builtin_va_arg (ap, int);
      50    __analyzer_eval (i == 1066); /* { dg-warning "TRUE" } */
      51  
      52    c = (char)__builtin_va_arg (ap, int);
      53    __analyzer_eval (c == '@'); /* { dg-warning "TRUE" } */
      54  }
      55  
      56  static void __attribute__((noinline))
      57  __analyzer_test_2_middle (int placeholder, ...)
      58  {
      59    __builtin_sysv_va_list ap;
      60    __builtin_sysv_va_start (ap, placeholder);
      61    __analyzer_test_2_inner (ap);
      62    __builtin_sysv_va_end (ap);
      63  }
      64  
      65  void test_2 (void)
      66  {
      67    __analyzer_test_2_middle (42, "foo", 1066, '@');
      68  }
      69  
      70  /* Not enough args.  */
      71  
      72  static void __attribute__((noinline))
      73  __analyzer_called_by_test_not_enough_args (int placeholder, ...)
      74  {
      75    const char *s;
      76    int i;
      77    
      78    __builtin_sysv_va_list ap;
      79    __builtin_sysv_va_start (ap, placeholder);
      80  
      81    s = __builtin_va_arg (ap, char *);
      82    __analyzer_eval (s[0] == 'f'); /* { dg-warning "TRUE" } */
      83  
      84    i = __builtin_va_arg (ap, int); /* { dg-warning "'ap' has no more arguments \\(1 consumed\\) \\\[CWE-685\\\]" } */
      85  
      86    __builtin_sysv_va_end (ap);
      87  }
      88  
      89  void test_not_enough_args (void)
      90  {
      91    __analyzer_called_by_test_not_enough_args (42, "foo");
      92  }
      93  
      94  /* Not enough args, with an intermediate function.  */
      95  
      96  static void __attribute__((noinline))
      97  __analyzer_test_not_enough_args_2_inner (__builtin_sysv_va_list ap)
      98  {
      99    const char *s;
     100    int i;
     101    
     102    s = __builtin_va_arg (ap, char *);
     103    __analyzer_eval (s[0] == 'f'); /* { dg-warning "TRUE" } */
     104  
     105    i = __builtin_va_arg (ap, int); /* { dg-warning "'ap' has no more arguments \\(1 consumed\\)" } */
     106  }
     107  
     108  static void __attribute__((noinline))
     109  __analyzer_test_not_enough_args_2_middle (int placeholder, ...)
     110  {
     111    __builtin_sysv_va_list ap;
     112    __builtin_sysv_va_start (ap, placeholder);
     113    __analyzer_test_not_enough_args_2_inner (ap);
     114    __builtin_sysv_va_end (ap);
     115  }
     116  
     117  void test_not_enough_args_2 (void)
     118  {
     119    __analyzer_test_not_enough_args_2_middle (42, "foo");
     120  }
     121  
     122  /* Excess args (not a problem).  */
     123  
     124  static void __attribute__((noinline))
     125  __analyzer_called_by_test_excess_args (int placeholder, ...)
     126  {
     127    const char *s;
     128    
     129    __builtin_sysv_va_list ap;
     130    __builtin_sysv_va_start (ap, placeholder);
     131  
     132    s = __builtin_va_arg (ap, char *);
     133    __analyzer_eval (s[0] == 'f'); /* { dg-warning "TRUE" } */
     134  
     135    __builtin_sysv_va_end (ap);
     136  }
     137  
     138  void test_excess_args (void)
     139  {
     140    __analyzer_called_by_test_excess_args (42, "foo", "bar");
     141  }
     142  
     143  /* Missing va_start.  */
     144  
     145  void test_missing_va_start (int placeholder, ...)
     146  {
     147    __builtin_sysv_va_list ap; /* { dg-message "region created on stack here" } */
     148    int i = __builtin_va_arg (ap, int); /* { dg-warning "use of uninitialized value 'ap'" } */
     149  }
     150  
     151  /* Missing va_end.  */
     152  
     153  void test_missing_va_end (int placeholder, ...)
     154  {
     155    int i;
     156    __builtin_sysv_va_list ap;
     157    __builtin_sysv_va_start (ap, placeholder); /* { dg-message "\\(1\\) 'va_start' called here" } */
     158    i = __builtin_va_arg (ap, int);
     159  } /* { dg-warning "missing call to 'va_end'" "warning" } */
     160  /* { dg-message "\\(2\\) missing call to 'va_end' to match 'va_start' at \\(1\\)" "final event" { target *-*-* } .-1 } */
     161  
     162  /* Missing va_end due to error-handling.  */
     163  
     164  int test_missing_va_end_2 (int placeholder, ...)
     165  {
     166    int i, j;
     167    __builtin_sysv_va_list ap;
     168    __builtin_sysv_va_start (ap, placeholder); /* { dg-message "\\(1\\) 'va_start' called here" } */
     169    i = __builtin_va_arg (ap, int);
     170    if (i == 42)
     171      {
     172        __builtin_sysv_va_end (ap);
     173        return -1;
     174      }
     175    j = __builtin_va_arg (ap, int);
     176    if (j == 1066) /* { dg-message "branch" } */
     177      return -1; /* { dg-message "here" } */
     178    __builtin_sysv_va_end (ap);
     179    return 0;
     180  } /* { dg-warning "missing call to 'va_end'" "warning" } */
     181  
     182  /* va_arg after va_end.  */
     183  
     184  void test_va_arg_after_va_end (int placeholder, ...)
     185  {
     186    int i;
     187    __builtin_sysv_va_list ap;
     188    __builtin_sysv_va_start (ap, placeholder);
     189    __builtin_sysv_va_end (ap); /* { dg-message "'va_end' called here" } */
     190    i = __builtin_va_arg (ap, int); /* { dg-warning "'va_arg' after 'va_end'" } */
     191  }
     192  
     193  /* Type mismatch: expect int, but passed a char *.  */
     194  
     195  static void __attribute__((noinline))
     196  __analyzer_called_by_test_type_mismatch_1 (int placeholder, ...)
     197  {
     198    int i;
     199    
     200    __builtin_sysv_va_list ap;
     201    __builtin_sysv_va_start (ap, placeholder);
     202  
     203    i = __builtin_va_arg (ap, int); /* { dg-warning "'va_arg' expected 'int' but received '\[^\n\r\]*' for variadic argument 1 of 'ap' \\\[CWE-686\\\]" } */
     204  
     205    __builtin_sysv_va_end (ap);
     206  }
     207  
     208  void test_type_mismatch_1 (void)
     209  {
     210    __analyzer_called_by_test_type_mismatch_1 (42, "foo");
     211  }
     212  
     213  /* Type mismatch: expect char *, but passed an int.  */
     214  
     215  static void __attribute__((noinline))
     216  __analyzer_called_by_test_type_mismatch_2 (int placeholder, ...)
     217  {
     218    const char *str;
     219    
     220    __builtin_sysv_va_list ap;
     221    __builtin_sysv_va_start (ap, placeholder);
     222  
     223    str = __builtin_va_arg (ap, const char *); /* { dg-warning "'va_arg' expected 'const char \\*' but received 'int' for variadic argument 1" } */
     224  
     225    __builtin_sysv_va_end (ap);
     226  }
     227  
     228  void test_type_mismatch_2 (void)
     229  {
     230    __analyzer_called_by_test_type_mismatch_2 (42, 1066);
     231  }
     232  
     233  /* As above, but with an intermediate function.  */
     234  
     235  static void __attribute__((noinline))
     236  __analyzer_test_type_mismatch_3_inner (__builtin_sysv_va_list ap)
     237  {
     238    const char *str;
     239    
     240    str = __builtin_va_arg (ap, const char *); /* { dg-warning "'va_arg' expected 'const char \\*' but received 'int' for variadic argument 1 of 'ap'" } */
     241  }
     242  
     243  static void __attribute__((noinline))
     244  __analyzer_test_type_mismatch_3_middle (int placeholder, ...)
     245  {
     246    __builtin_sysv_va_list ap;
     247    __builtin_sysv_va_start (ap, placeholder);
     248  
     249    __analyzer_test_type_mismatch_3_inner (ap);
     250  
     251    __builtin_sysv_va_end (ap);
     252  }
     253  
     254  void test_type_mismatch_3 (void)
     255  {
     256    __analyzer_test_type_mismatch_3_middle (42, 1066);
     257  }
     258  
     259  /* Multiple traversals of the args.  */
     260  
     261  static void __attribute__((noinline))
     262  __analyzer_called_by_test_multiple_traversals (int placeholder, ...)
     263  {
     264    __builtin_sysv_va_list ap;
     265  
     266    /* First traversal.  */
     267    {
     268      int i, j;
     269  
     270      __builtin_sysv_va_start (ap, placeholder);
     271  
     272      i = __builtin_va_arg (ap, int);
     273      __analyzer_eval (i == 1066); /* { dg-warning "TRUE" } */
     274  
     275      j = __builtin_va_arg (ap, int);
     276      __analyzer_eval (j == 42); /* { dg-warning "TRUE" } */
     277  
     278      __builtin_sysv_va_end (ap);
     279    }
     280  
     281    /* Second traversal.  */
     282    {
     283      int i, j;
     284  
     285      __builtin_sysv_va_start (ap, placeholder);
     286  
     287      i = __builtin_va_arg (ap, int);
     288      __analyzer_eval (i == 1066); /* { dg-warning "TRUE" } */
     289  
     290      j = __builtin_va_arg (ap, int);
     291      __analyzer_eval (j == 42); /* { dg-warning "TRUE" } */
     292  
     293      __builtin_sysv_va_end (ap);
     294    }
     295  }
     296  
     297  void test_multiple_traversals (void)
     298  {
     299    __analyzer_called_by_test_multiple_traversals (0, 1066, 42);
     300  }
     301  
     302  /* Multiple traversals, using va_copy.  */
     303  
     304  static void __attribute__((noinline))
     305  __analyzer_called_by_test_multiple_traversals_2 (int placeholder, ...)
     306  {
     307    int i, j;
     308    __builtin_sysv_va_list args1;
     309    __builtin_sysv_va_list args2;
     310  
     311    __builtin_sysv_va_start (args1, placeholder);
     312    __builtin_sysv_va_copy (args2, args1);
     313  
     314    /* First traversal.  */
     315    i = __builtin_va_arg (args1, int);
     316    __analyzer_eval (i == 1066); /* { dg-warning "TRUE" } */
     317    j = __builtin_va_arg (args1, int);
     318    __analyzer_eval (j == 42); /* { dg-warning "TRUE" } */
     319    __builtin_sysv_va_end (args1);
     320  
     321    /* Traversal of copy.  */
     322    i = __builtin_va_arg (args2, int);
     323    __analyzer_eval (i == 1066); /* { dg-warning "TRUE" } */
     324    j = __builtin_va_arg (args2, int);
     325    __analyzer_eval (j == 42); /* { dg-warning "TRUE" } */
     326    __builtin_sysv_va_end (args2);
     327  }
     328  
     329  void test_multiple_traversals_2 (void)
     330  {
     331    __analyzer_called_by_test_multiple_traversals_2 (0, 1066, 42);
     332  }
     333  
     334  /* Multiple traversals, using va_copy after a va_arg.  */
     335  
     336  static void __attribute__((noinline))
     337  __analyzer_called_by_test_multiple_traversals_3 (int placeholder, ...)
     338  {
     339    int i, j;
     340    __builtin_sysv_va_list args1;
     341    __builtin_sysv_va_list args2;
     342  
     343    __builtin_sysv_va_start (args1, placeholder);
     344  
     345    /* First traversal.  */
     346    i = __builtin_va_arg (args1, int);
     347    __analyzer_eval (i == 1066); /* { dg-warning "TRUE" } */
     348  
     349    /* va_copy after the first va_arg. */
     350    __builtin_sysv_va_copy (args2, args1);
     351  
     352    j = __builtin_va_arg (args1, int);
     353    __analyzer_eval (j == 42); /* { dg-warning "TRUE" } */
     354    __builtin_sysv_va_end (args1);
     355  
     356    /* Traversal of copy.  */
     357    j = __builtin_va_arg (args2, int);
     358    __analyzer_eval (j == 42); /* { dg-warning "TRUE" } */
     359    __builtin_sysv_va_end (args2);
     360  }
     361  
     362  void test_multiple_traversals_3 (void)
     363  {
     364    __analyzer_called_by_test_multiple_traversals_3 (0, 1066, 42);
     365  }
     366  
     367  /* va_copy after va_end.  */
     368  
     369  void test_va_copy_after_va_end (int placeholder, ...)
     370  {
     371    __builtin_sysv_va_list ap1, ap2;
     372    __builtin_sysv_va_start (ap1, placeholder);
     373    __builtin_sysv_va_end (ap1); /* { dg-message "'va_end' called here" } */
     374    __builtin_sysv_va_copy (ap2, ap1); /* { dg-warning "'va_copy' after 'va_end'" } */
     375    __builtin_sysv_va_end (ap2);
     376  }
     377  
     378  /* leak of va_copy.  */
     379  
     380  void test_leak_of_va_copy (int placeholder, ...)
     381  {
     382    __builtin_sysv_va_list ap1, ap2;
     383    __builtin_sysv_va_start (ap1, placeholder);
     384    __builtin_sysv_va_copy (ap2, ap1); /* { dg-message "'va_copy' called here" } */
     385    __builtin_sysv_va_end (ap1);
     386  } /* { dg-warning "missing call to 'va_end'" "warning" } */
     387    /* { dg-message "missing call to 'va_end' to match 'va_copy' at \\(1\\)" "final event" { target *-*-* } .-1 } */
     388  
     389  /* double va_end.  */
     390  
     391  void test_double_va_end (int placeholder, ...)
     392  {
     393    __builtin_sysv_va_list ap;
     394    __builtin_sysv_va_start (ap, placeholder);
     395    __builtin_sysv_va_end (ap); /* { dg-message "'va_end' called here" } */
     396    __builtin_sysv_va_end (ap); /* { dg-warning "'va_end' after 'va_end'" } */
     397  }
     398  
     399  /* double va_start.  */
     400  
     401  void test_double_va_start (int placeholder, ...)
     402  {
     403    int i;
     404    __builtin_sysv_va_list ap;
     405    __builtin_sysv_va_start (ap, placeholder); /* { dg-message "'va_start' called here" } */
     406    __builtin_sysv_va_start (ap, placeholder);  /* { dg-warning "missing call to 'va_end'" "warning" } */
     407    /* { dg-message "missing call to 'va_end' to match 'va_start' at \\(1\\)" "final event" { target *-*-* } .-1 } */
     408    __builtin_sysv_va_end (ap);
     409  }
     410  
     411  /* va_copy before va_start.  */
     412  
     413  void test_va_copy_before_va_start (int placeholder, ...)
     414  {
     415    __builtin_sysv_va_list ap1; /* { dg-message "region created on stack here" } */
     416    __builtin_sysv_va_list ap2;
     417    __builtin_sysv_va_copy (ap2, ap1); /* { dg-warning "use of uninitialized value 'ap1'" } */
     418    __builtin_sysv_va_end (ap2);
     419  }
     420  
     421  /* Verify that we complain about uses of a va_list after the function 
     422     in which va_start was called has returned.  */
     423  
     424  __builtin_sysv_va_list global_ap;
     425  
     426  static void __attribute__((noinline))
     427  __analyzer_called_by_test_va_arg_after_return (int placeholder, ...)
     428  {
     429    __builtin_sysv_va_start (global_ap, placeholder);
     430    __builtin_sysv_va_end (global_ap);
     431  }
     432  
     433  void test_va_arg_after_return (void)
     434  {
     435    int i;
     436    __analyzer_called_by_test_va_arg_after_return (42, 1066);
     437    i = __builtin_va_arg (global_ap, int); /* { dg-warning "dereferencing pointer 'global_ap' to within stale stack frame" } */
     438  }
     439  
     440  void pr107349 (void)
     441  {
     442    __builtin_sysv_va_list x,y;
     443    __builtin_sysv_va_copy(x,y); /* { dg-warning "use of uninitialized value 'y'" } */
     444  } /* { dg-warning "missing call to 'va_end'" } */