274 lines
7.0 KiB
C++
274 lines
7.0 KiB
C++
// 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);
|
|
}
|
|
}
|