1 // RUN: %clang_cc1 -std=c++03 -Wno-c++11-extensions -triple i386-pc-unknown -verify %s 2 // RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin9 -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, ...) { // expected-warning 0-1{{deprecated}} 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@+2 {{'va_start' cannot be used outside a function}} 26 // expected-error@+1 {{default argument references parameter 'a'}} 27 void meth(int a, int b = (__builtin_va_start(ap, a), 0)) {} 28 }; 29 } 30 31 // Ensure the correct behavior for promotable type UB checking. 32 void promotable(int a, ...) { 33 enum Unscoped1 { One = 0x7FFFFFFF }; 34 (void)__builtin_va_arg(ap, Unscoped1); // ok 35 36 enum Unscoped2 { Two = 0xFFFFFFFF }; 37 (void)__builtin_va_arg(ap, Unscoped2); // ok 38 39 enum class Scoped { Three }; 40 (void)__builtin_va_arg(ap, Scoped); // ok 41 42 enum Fixed : int { Four }; 43 (void)__builtin_va_arg(ap, Fixed); // ok 44 45 enum FixedSmall : char { Five }; 46 (void)__builtin_va_arg(ap, FixedSmall); // expected-warning {{second argument to 'va_arg' is of promotable type 'FixedSmall'; this va_arg has undefined behavior because arguments will be promoted to 'int'}} 47 48 enum FixedLarge : long long { Six }; 49 (void)__builtin_va_arg(ap, FixedLarge); // ok 50 51 // Ensure that qualifiers are ignored. 52 (void)__builtin_va_arg(ap, const volatile int); // ok 53 54 // Ensure that signed vs unsigned doesn't matter either. 55 (void)__builtin_va_arg(ap, unsigned int); 56 } 57 58 #if __cplusplus >= 201103L 59 // We used to have bugs identifying the correct enclosing function scope in a 60 // lambda. 61 62 void fixed_lambda_varargs_function(int a, ...) { 63 [](int b) { 64 __builtin_va_start(ap, b); // expected-error {{'va_start' used in function with fixed args}} 65 }(42); 66 } 67 void varargs_lambda_fixed_function(int a) { 68 [](int b, ...) { 69 __builtin_va_start(ap, b); // correct 70 }(42); 71 } 72 73 auto fixed_lambda_global = [](int f) { 74 __builtin_va_start(ap, f); // expected-error {{'va_start' used in function with fixed args}} 75 }; 76 auto varargs_lambda_global = [](int f, ...) { 77 __builtin_va_start(ap, f); // correct 78 }; 79 80 void record_member_init(int a, ...) { 81 struct Foo { 82 int a = 0; 83 // expected-error@+1 {{'va_start' cannot be used outside a function}} 84 int b = (__builtin_va_start(ap, a), 0); 85 }; 86 } 87 #endif 88