"too few arguments to %select{function|block|method}0 call")
DIAG(err_typecheck_call_too_many_args, ERROR,
"too many arguments to %select{function|block|method}0 call")
+DIAG(warn_cannot_pass_non_pod_arg_to_vararg, WARNING,
+ "cannot pass object of non-POD type %0 through variadic "
+ "%select{function|block|method}1; call will abort at runtime")
DIAG(err_typecheck_closure_too_many_args, ERROR,
"too many arguments to closure call")
DIAG(err_typecheck_call_invalid_ordered_compare, ERROR,
// Promote the arguments (C99 6.5.2.2p7).
for (unsigned i = NumArgsInProto; i != NumArgs; i++) {
Expr *Arg = Args[i];
+ if (!Arg->getType()->isPODType()) {
+ int CallType = 0;
+ if (Fn->getType()->isBlockPointerType())
+ CallType = 1; // Block
+ else if (isa<MemberExpr>(Fn))
+ CallType = 2;
+
+ Diag(Arg->getLocStart(),
+ diag::warn_cannot_pass_non_pod_arg_to_vararg) <<
+ Arg->getType() << CallType;
+ }
DefaultArgumentPromotion(Arg);
Call->setArg(i, Arg);
}
// Promote additional arguments to variadic methods.
if (Method->isVariadic()) {
- for (unsigned i = NumNamedArgs; i < NumArgs; ++i)
+ for (unsigned i = NumNamedArgs; i < NumArgs; ++i) {
+ if (!Args[i]->getType()->isPODType()) {
+ Diag(Args[i]->getLocStart(),
+ diag::warn_cannot_pass_non_pod_arg_to_vararg) <<
+ Args[i]->getType() << 2; // Method
+ }
+
DefaultArgumentPromotion(Args[i]);
+ }
} else {
// Check for extra arguments to non-variadic methods.
if (NumArgs != NumNamedArgs) {
// Promote the arguments (C99 6.5.2.2p7).
for (unsigned i = NumArgsInProto; i != NumArgs; i++) {
Expr *Arg = Args[i];
+
+ if (!Arg->getType()->isPODType()) {
+ Diag(Arg->getLocStart(),
+ diag::warn_cannot_pass_non_pod_arg_to_vararg) <<
+ Arg->getType() << 2; // Method
+ }
+
DefaultArgumentPromotion(Arg);
TheCall->setArg(i + 1, Arg);
}
--- /dev/null
+// RUN: clang -fsyntax-only -verify -fblocks %s
+
+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); // expected-warning{{cannot pass object of non-POD type 'class C' through variadic function; call will abort at runtime}}
+}
+
+void t2()
+{
+ C c(10);
+
+ c.g(10, c); // expected-warning{{cannot pass object of non-POD type 'class C' through variadic method; call will abort at runtime}}
+
+ C::h(10, c); // expected-warning{{cannot pass object of non-POD type 'class C' through variadic function; call will abort at runtime}}
+}
+
+int (^block)(int, ...);
+
+void t3()
+{
+ C c(10);
+
+ block(10, c); // expected-warning{{cannot pass object of non-POD type 'class C' through variadic block; call will abort at runtime}}
+}
+
+class D {
+public:
+ void operator() (int a, ...);
+};
+
+void t4()
+{
+ C c(10);
+
+ D d;
+
+ d(10, c); // expected-warning{{Line 48: cannot pass object of non-POD type 'class C' through variadic method; call will abort at runtime}}
+}
--- /dev/null
+// RUN: clang -fsyntax-only -verify %s
+
+class C {
+public:
+ C(int);
+};
+
+@interface D
+- (void)g:(int)a, ...;
+@end
+
+void t1(D *d)
+{
+ C c(10);
+
+ [d g:10, c]; // expected-warning{{cannot pass object of non-POD type 'class C' through variadic method; call will abort at runtime}}
+}
+