1 // RUN: %clang_cc1 -std=c++03 -verify %s
2 // RUN: %clang_cc1 -std=c++11 -verify %s
3 
4 __builtin_va_list ap;
5 
6 class string;
7 void f(const string& s, ...) {  // expected-note {{parameter of type 'const string &' is declared here}}
8   __builtin_va_start(ap, s); // expected-warning {{passing an object of reference type to 'va_start' has undefined behavior}}
9 }
10 
11 void g(register int i, ...) {
12   __builtin_va_start(ap, i); // UB in C, OK in C++
13 }
14 
15 // Don't crash when there is no last parameter.
16 void no_params(...) {
17   int a;
18   __builtin_va_start(ap, a); // expected-warning {{second argument to 'va_start' is not the last named parameter}}
19 }
20 
21 // Reject this. The __builtin_va_start would execute in Foo's non-variadic
22 // default ctor.
23 void record_context(int a, ...) {
24   struct Foo {
25     // expected-error@+1 {{'va_start' cannot be used outside a function}}
26     void meth(int a, int b = (__builtin_va_start(ap, a), 0)) {}
27   };
28 }
29 
30 #if __cplusplus >= 201103L
31 // We used to have bugs identifying the correct enclosing function scope in a
32 // lambda.
33 
34 void fixed_lambda_varargs_function(int a, ...) {
35   [](int b) {
36     __builtin_va_start(ap, b); // expected-error {{'va_start' used in function with fixed args}}
37   }(42);
38 }
39 void varargs_lambda_fixed_function(int a) {
40   [](int b, ...) {
41     __builtin_va_start(ap, b); // correct
42   }(42);
43 }
44 
45 auto fixed_lambda_global = [](int f) {
46   __builtin_va_start(ap, f); // expected-error {{'va_start' used in function with fixed args}}
47 };
48 auto varargs_lambda_global = [](int f, ...) {
49   __builtin_va_start(ap, f); // correct
50 };
51 
52 void record_member_init(int a, ...) {
53   struct Foo {
54     int a = 0;
55     // expected-error@+1 {{'va_start' cannot be used outside a function}}
56     int b = (__builtin_va_start(ap, a), 0);
57   };
58 }
59 #endif
60