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 (void)__builtin_va_arg(ap, bool); // expected-warning {{second argument to 'va_arg' is of promotable type 'bool'; this va_arg has undefined behavior because arguments will be promoted to 'int'}} 58 } 59 60 #if __cplusplus >= 201103L 61 // We used to have bugs identifying the correct enclosing function scope in a 62 // lambda. 63 64 void fixed_lambda_varargs_function(int a, ...) { 65 [](int b) { 66 __builtin_va_start(ap, b); // expected-error {{'va_start' used in function with fixed args}} 67 }(42); 68 } 69 void varargs_lambda_fixed_function(int a) { 70 [](int b, ...) { 71 __builtin_va_start(ap, b); // correct 72 }(42); 73 } 74 75 auto fixed_lambda_global = [](int f) { 76 __builtin_va_start(ap, f); // expected-error {{'va_start' used in function with fixed args}} 77 }; 78 auto varargs_lambda_global = [](int f, ...) { 79 __builtin_va_start(ap, f); // correct 80 }; 81 82 void record_member_init(int a, ...) { 83 struct Foo { 84 int a = 0; 85 // expected-error@+1 {{'va_start' cannot be used outside a function}} 86 int b = (__builtin_va_start(ap, a), 0); 87 }; 88 } 89 #endif 90