1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273
|
// RUN: %clang_cc1 -fsyntax-only -verify -fblocks %s -Wno-error=non-pod-varargs
// RUN: %clang_cc1 -fsyntax-only -verify -fblocks -std=c++98 %s -Wno-error=non-pod-varargs
// RUN: %clang_cc1 -fsyntax-only -verify -fblocks -std=c++11 %s -Wno-error=non-pod-varargs
// Check that the warning is still there under -fms-compatibility.
// RUN: %clang_cc1 -fsyntax-only -verify -fblocks %s -Wno-error=non-pod-varargs -fms-compatibility
// RUN: %clang_cc1 -fsyntax-only -verify -fblocks -std=c++98 %s -Wno-error=non-pod-varargs -fms-compatibility
// RUN: %clang_cc1 -fsyntax-only -verify -fblocks -std=c++11 %s -Wno-error=non-pod-varargs -fms-compatibility
extern char version[];
class C {
public:
C(int);
void g(int a, ...);
static void h(int a, ...);
};
void g(int a, ...);
void t1()
{
C c(10);
g(10, c);
#if __cplusplus <= 199711L
// expected-warning@-2 {{cannot pass object of non-POD type 'C' through variadic function; call will abort at runtime}}
#endif
g(10, version);
void (*ptr)(int, ...) = g;
ptr(10, c);
#if __cplusplus <= 199711L
// expected-warning@-2 {{cannot pass object of non-POD type 'C' through variadic function; call will abort at runtime}}
#endif
ptr(10, version);
}
void t2()
{
C c(10);
c.g(10, c);
#if __cplusplus <= 199711L
// expected-warning@-2 {{cannot pass object of non-POD type 'C' through variadic method; call will abort at runtime}}
#endif
c.g(10, version);
void (C::*ptr)(int, ...) = &C::g;
(c.*ptr)(10, c);
#if __cplusplus <= 199711L
// expected-warning@-2 {{cannot pass object of non-POD type 'C' through variadic method; call will abort at runtime}}
#endif
(c.*ptr)(10, version);
C::h(10, c);
#if __cplusplus <= 199711L
// expected-warning@-2 {{cannot pass object of non-POD type 'C' through variadic function; call will abort at runtime}}
#endif
C::h(10, version);
void (*static_ptr)(int, ...) = &C::h;
static_ptr(10, c);
#if __cplusplus <= 199711L
// expected-warning@-2 {{cannot pass object of non-POD type 'C' through variadic function; call will abort at runtime}}
#endif
static_ptr(10, version);
}
int (^block)(int, ...);
void t3()
{
C c(10);
block(10, c);
#if __cplusplus <= 199711L
// expected-warning@-2 {{cannot pass object of non-POD type 'C' through variadic block; call will abort at runtime}}
#endif
block(10, version);
}
class D {
public:
void operator() (int a, ...);
};
void t4()
{
C c(10);
D d;
d(10, c);
#if __cplusplus <= 199711L
// expected-warning@-2 {{cannot pass object of non-POD type 'C' through variadic method; call will abort at runtime}}
#endif
d(10, version);
}
class E {
E(int, ...); // expected-note 2{{implicitly declared private here}}
};
void t5()
{
C c(10);
E e(10, c);
#if __cplusplus <= 199711L
// expected-warning@-2 {{cannot pass object of non-POD type 'C' through variadic constructor; call will abort at runtime}}
#endif
// expected-error@-4 {{calling a private constructor of class 'E'}}
(void)E(10, c);
#if __cplusplus <= 199711L
// expected-warning@-2 {{cannot pass object of non-POD type 'C' through variadic constructor; call will abort at runtime}}
#endif
// expected-error@-4 {{calling a private constructor of class 'E'}}
}
// PR5761: unevaluated operands and the non-POD warning
class Foo {
public:
Foo() {}
};
int Helper(...);
const int size = sizeof(Helper(Foo()));
namespace std {
class type_info { };
}
struct Base { virtual ~Base(); };
Base &get_base(...);
int eat_base(...);
void test_typeid(Base &base) {
(void)typeid(get_base(base));
#if __cplusplus <= 199711L
// expected-warning@-2 {{cannot pass object of non-POD type 'Base' through variadic function; call will abort at runtime}}
#else
// expected-warning@-4 {{cannot pass object of non-trivial type 'Base' through variadic function; call will abort at runtime}}
#endif
// expected-warning@-6 {{expression with side effects will be evaluated despite being used as an operand to 'typeid'}}
(void)typeid(eat_base(base)); // okay
}
// rdar://7985267 - Shouldn't warn, doesn't actually use __builtin_va_start is
// magic.
void t6(Foo somearg, ... ) {
__builtin_va_list list;
__builtin_va_start(list, somearg);
}
// __builtin_stdarg_start is a compatibility alias for __builtin_va_start,
// it should behave the same
void t6b(Foo somearg, ... ) {
__builtin_va_list list;
__builtin_stdarg_start(list, somearg); // second argument to 'va_start' is not the last named parameter [-Wvarargs]
}
void t7(int n, ...) {
__builtin_va_list list;
__builtin_va_start(list, n);
(void)__builtin_va_arg(list, C); // expected-warning{{second argument to 'va_arg' is of non-POD type 'C'}}
__builtin_va_end(list);
}
struct Abstract {
virtual void doit() = 0; // expected-note{{unimplemented pure virtual method}}
};
void t8(int n, ...) {
__builtin_va_list list;
__builtin_va_start(list, n);
(void)__builtin_va_arg(list, Abstract); // expected-error{{second argument to 'va_arg' is of abstract type 'Abstract'}}
__builtin_va_end(list);
}
int t9(int n) {
// Make sure the error works in potentially-evaluated sizeof
return (int)sizeof(*(Helper(Foo()), (int (*)[n])0));
#if __cplusplus <= 199711L
// expected-warning@-2 {{cannot pass object of non-POD type 'Foo' through variadic function; call will abort at runtime}}
#endif
}
// PR14057
namespace t10 {
struct F {
F();
};
struct S {
void operator()(F, ...);
};
void foo() {
S s;
F f;
s.operator()(f);
s(f);
}
}
namespace t11 {
typedef void(*function_ptr)(int, ...);
typedef void(C::*member_ptr)(int, ...);
typedef void(^block_ptr)(int, ...);
function_ptr get_f_ptr();
member_ptr get_m_ptr();
block_ptr get_b_ptr();
function_ptr arr_f_ptr[5];
member_ptr arr_m_ptr[5];
block_ptr arr_b_ptr[5];
void test() {
C c(10);
(get_f_ptr())(10, c);
#if __cplusplus <= 199711L
// expected-warning@-2 {{cannot pass object of non-POD type 'C' through variadic function; call will abort at runtime}}
#endif
(get_f_ptr())(10, version);
(c.*get_m_ptr())(10, c);
#if __cplusplus <= 199711L
// expected-warning@-2 {{cannot pass object of non-POD type 'C' through variadic method; call will abort at runtime}}
#endif
(c.*get_m_ptr())(10, version);
(get_b_ptr())(10, c);
#if __cplusplus <= 199711L
// expected-warning@-2 {{cannot pass object of non-POD type 'C' through variadic block; call will abort at runtime}}
#endif
(get_b_ptr())(10, version);
(arr_f_ptr[3])(10, c);
#if __cplusplus <= 199711L
// expected-warning@-2 {{cannot pass object of non-POD type 'C' through variadic function; call will abort at runtime}}
#endif
(arr_f_ptr[3])(10, version);
(c.*arr_m_ptr[3])(10, c);
#if __cplusplus <= 199711L
// expected-warning@-2 {{cannot pass object of non-POD type 'C' through variadic method; call will abort at runtime}}
#endif
(c.*arr_m_ptr[3])(10, version);
(arr_b_ptr[3])(10, c);
#if __cplusplus <= 199711L
// expected-warning@-2 {{cannot pass object of non-POD type 'C' through variadic block; call will abort at runtime}}
#endif
(arr_b_ptr[3])(10, version);
}
}
|