зеркало из https://github.com/microsoft/clang-1.git
Fix our handling of the warning when one tries to pass a
non-POD/non-trivial object throuugh a C-style varargs. The warning itself was default-mapped to error, but can be downgraded, but we were treating it in Sema like a hard error, silently dropping the call. Instead, treat this problem like a warning, and do what the warning says we do: abort at runtime. To do so, we fake up a __builtin_trap() expression that gets evaluated as part of the argument. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@131805 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
4d509341bd
Коммит
930a9abb7e
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
|
|
Загрузка…
Ссылка в новой задаче