aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Sema/SemaExpr.cpp34
-rw-r--r--test/CodeGenCXX/vararg-non-pod.cpp16
-rw-r--r--test/SemaCXX/vararg-non-pod.cpp9
3 files changed, 49 insertions, 10 deletions
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 6bccdaeb24..ce929d58ee 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -449,13 +449,13 @@ ExprResult Sema::DefaultVariadicArgumentPromotion(Expr *E, VariadicCallType CT,
if (FDecl && FDecl->getBuiltinID() == Builtin::BI__builtin_va_start)
return Owned(E);
+ // Don't allow one to pass an Objective-C interface to a vararg.
if (E->getType()->isObjCObjectType() &&
- DiagRuntimeBehavior(E->getLocStart(), 0,
- PDiag(diag::err_cannot_pass_objc_interface_to_vararg)
- << E->getType() << CT))
+ DiagRuntimeBehavior(E->getLocStart(), 0,
+ PDiag(diag::err_cannot_pass_objc_interface_to_vararg)
+ << E->getType() << CT))
return ExprError();
-
- // C++ [expr.call]p7 prohibits non-POD types.
+
if (!E->getType()->isPODType()) {
// C++0x [expr.call]p7:
// Passing a potentially-evaluated argument of class type (Clause 9)
@@ -477,8 +477,28 @@ ExprResult Sema::DefaultVariadicArgumentPromotion(Expr *E, VariadicCallType CT,
} else if (DiagRuntimeBehavior(E->getLocStart(), 0,
PDiag(diag::warn_cannot_pass_non_pod_arg_to_vararg)
<< getLangOptions().CPlusPlus0x << E->getType()
- << CT))
- return ExprError();
+ << CT)) {
+ // Turn this into a trap.
+ CXXScopeSpec SS;
+ UnqualifiedId Name;
+ Name.setIdentifier(PP.getIdentifierInfo("__builtin_trap"),
+ E->getLocStart());
+ ExprResult TrapFn = ActOnIdExpression(TUScope, SS, Name, true, false);
+ if (TrapFn.isInvalid())
+ return ExprError();
+
+ ExprResult Call = ActOnCallExpr(TUScope, TrapFn.get(), E->getLocStart(),
+ MultiExprArg(), E->getLocEnd());
+ if (Call.isInvalid())
+ return ExprError();
+
+ ExprResult Comma = ActOnBinOp(TUScope, E->getLocStart(), tok::comma,
+ Call.get(), E);
+ if (Comma.isInvalid())
+ return ExprError();
+
+ E = Comma.get();
+ }
}
return Owned(E);
diff --git a/test/CodeGenCXX/vararg-non-pod.cpp b/test/CodeGenCXX/vararg-non-pod.cpp
new file mode 100644
index 0000000000..6c6f459ce5
--- /dev/null
+++ b/test/CodeGenCXX/vararg-non-pod.cpp
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -Wno-error=non-pod-varargs -emit-llvm -o - %s | FileCheck %s
+
+struct X {
+ X();
+ X(const X&);
+ ~X();
+};
+
+void vararg(...);
+
+// CHECK: define void @_Z4test1X
+void test(X x) {
+ // CHECK: call void @llvm.trap()
+ vararg(x);
+ // CHECK: ret void
+}
diff --git a/test/SemaCXX/vararg-non-pod.cpp b/test/SemaCXX/vararg-non-pod.cpp
index 55ec9418cd..df0080fac9 100644
--- a/test/SemaCXX/vararg-non-pod.cpp
+++ b/test/SemaCXX/vararg-non-pod.cpp
@@ -56,15 +56,18 @@ void t4()
}
class E {
- E(int, ...);
+ E(int, ...); // expected-note 2{{implicitly declared private here}}
};
void t5()
{
C c(10);
- E e(10, c); // expected-warning{{cannot pass object of non-POD type 'C' through variadic constructor; call will abort at runtime}}
- (void)E(10, c); // expected-warning{{cannot pass object of non-POD type 'C' through variadic constructor; call will abort at runtime}}
+ E e(10, c); // expected-warning{{cannot pass object of non-POD type 'C' through variadic constructor; call will abort at runtime}} \
+ // expected-error{{calling a private constructor of class 'E'}}
+ (void)E(10, c); // expected-warning{{cannot pass object of non-POD type 'C' through variadic constructor; call will abort at runtime}} \
+ // expected-error{{calling a private constructor of class 'E'}}
+
}
// PR5761: unevaluated operands and the non-POD warning