implement rdar://6780761, making sema reject some code that otherwise
crashes codegen. llvm-svn: 68891
This commit is contained in:
parent
ce6bcf0847
commit
a8a7d0f371
|
@ -1190,6 +1190,11 @@ def err_typecheck_call_too_many_args : Error<
|
||||||
def warn_call_wrong_number_of_arguments : Warning<
|
def warn_call_wrong_number_of_arguments : Warning<
|
||||||
"too %select{few|many}0 arguments in call to %1">;
|
"too %select{few|many}0 arguments in call to %1">;
|
||||||
def err_deleted_function_use : Error<"attempt to use a deleted function">;
|
def err_deleted_function_use : Error<"attempt to use a deleted function">;
|
||||||
|
|
||||||
|
def err_cannot_pass_objc_interface_to_vararg : Error<
|
||||||
|
"cannot pass object with interface type %0 by-value through variadic "
|
||||||
|
"%select{function|block|method}1">;
|
||||||
|
|
||||||
def warn_cannot_pass_non_pod_arg_to_vararg : Warning<
|
def warn_cannot_pass_non_pod_arg_to_vararg : Warning<
|
||||||
"cannot pass object of non-POD type %0 through variadic "
|
"cannot pass object of non-POD type %0 through variadic "
|
||||||
"%select{function|block|method}1; call will abort at runtime">;
|
"%select{function|block|method}1; call will abort at runtime">;
|
||||||
|
|
|
@ -2210,7 +2210,7 @@ public:
|
||||||
|
|
||||||
// DefaultVariadicArgumentPromotion - Like DefaultArgumentPromotion, but
|
// DefaultVariadicArgumentPromotion - Like DefaultArgumentPromotion, but
|
||||||
// will warn if the resulting type is not a POD type.
|
// will warn if the resulting type is not a POD type.
|
||||||
void DefaultVariadicArgumentPromotion(Expr *&Expr, VariadicCallType CT);
|
bool DefaultVariadicArgumentPromotion(Expr *&Expr, VariadicCallType CT);
|
||||||
|
|
||||||
// UsualArithmeticConversions - performs the UsualUnaryConversions on it's
|
// UsualArithmeticConversions - performs the UsualUnaryConversions on it's
|
||||||
// operands and then handles various conversions that are common to binary
|
// operands and then handles various conversions that are common to binary
|
||||||
|
|
|
@ -154,16 +154,25 @@ void Sema::DefaultArgumentPromotion(Expr *&Expr) {
|
||||||
UsualUnaryConversions(Expr);
|
UsualUnaryConversions(Expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// DefaultVariadicArgumentPromotion - Like DefaultArgumentPromotion, but
|
/// DefaultVariadicArgumentPromotion - Like DefaultArgumentPromotion, but
|
||||||
// will warn if the resulting type is not a POD type.
|
/// will warn if the resulting type is not a POD type, and rejects ObjC
|
||||||
void Sema::DefaultVariadicArgumentPromotion(Expr *&Expr, VariadicCallType CT) {
|
/// interfaces passed by value. This returns true if the argument type is
|
||||||
|
/// completely illegal.
|
||||||
|
bool Sema::DefaultVariadicArgumentPromotion(Expr *&Expr, VariadicCallType CT) {
|
||||||
DefaultArgumentPromotion(Expr);
|
DefaultArgumentPromotion(Expr);
|
||||||
|
|
||||||
if (!Expr->getType()->isPODType()) {
|
if (Expr->getType()->isObjCInterfaceType()) {
|
||||||
Diag(Expr->getLocStart(),
|
Diag(Expr->getLocStart(),
|
||||||
diag::warn_cannot_pass_non_pod_arg_to_vararg) <<
|
diag::err_cannot_pass_objc_interface_to_vararg)
|
||||||
Expr->getType() << CT;
|
<< Expr->getType() << CT;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!Expr->getType()->isPODType())
|
||||||
|
Diag(Expr->getLocStart(), diag::warn_cannot_pass_non_pod_arg_to_vararg)
|
||||||
|
<< Expr->getType() << CT;
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2223,7 +2232,7 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
|
||||||
// Promote the arguments (C99 6.5.2.2p7).
|
// Promote the arguments (C99 6.5.2.2p7).
|
||||||
for (unsigned i = NumArgsInProto; i != NumArgs; i++) {
|
for (unsigned i = NumArgsInProto; i != NumArgs; i++) {
|
||||||
Expr *Arg = Args[i];
|
Expr *Arg = Args[i];
|
||||||
DefaultVariadicArgumentPromotion(Arg, CallType);
|
Invalid |= DefaultVariadicArgumentPromotion(Arg, CallType);
|
||||||
Call->setArg(i, Arg);
|
Call->setArg(i, Arg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -164,7 +164,7 @@ bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs,
|
||||||
unsigned NumNamedArgs = Sel.getNumArgs();
|
unsigned NumNamedArgs = Sel.getNumArgs();
|
||||||
assert(NumArgs >= NumNamedArgs && "Too few arguments for selector!");
|
assert(NumArgs >= NumNamedArgs && "Too few arguments for selector!");
|
||||||
|
|
||||||
bool anyIncompatibleArgs = false;
|
bool IsError = false;
|
||||||
for (unsigned i = 0; i < NumNamedArgs; i++) {
|
for (unsigned i = 0; i < NumNamedArgs; i++) {
|
||||||
Expr *argExpr = Args[i];
|
Expr *argExpr = Args[i];
|
||||||
assert(argExpr && "CheckMessageArgumentTypes(): missing expression");
|
assert(argExpr && "CheckMessageArgumentTypes(): missing expression");
|
||||||
|
@ -183,7 +183,7 @@ bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs,
|
||||||
if (Args[i] != argExpr) // The expression was converted.
|
if (Args[i] != argExpr) // The expression was converted.
|
||||||
Args[i] = argExpr; // Make sure we store the converted expression.
|
Args[i] = argExpr; // Make sure we store the converted expression.
|
||||||
|
|
||||||
anyIncompatibleArgs |=
|
IsError |=
|
||||||
DiagnoseAssignmentResult(Result, argExpr->getLocStart(), lhsType, rhsType,
|
DiagnoseAssignmentResult(Result, argExpr->getLocStart(), lhsType, rhsType,
|
||||||
argExpr, "sending");
|
argExpr, "sending");
|
||||||
}
|
}
|
||||||
|
@ -191,7 +191,7 @@ bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs,
|
||||||
// Promote additional arguments to variadic methods.
|
// Promote additional arguments to variadic methods.
|
||||||
if (Method->isVariadic()) {
|
if (Method->isVariadic()) {
|
||||||
for (unsigned i = NumNamedArgs; i < NumArgs; ++i)
|
for (unsigned i = NumNamedArgs; i < NumArgs; ++i)
|
||||||
DefaultVariadicArgumentPromotion(Args[i], VariadicMethod);
|
IsError |= DefaultVariadicArgumentPromotion(Args[i], VariadicMethod);
|
||||||
} else {
|
} else {
|
||||||
// Check for extra arguments to non-variadic methods.
|
// Check for extra arguments to non-variadic methods.
|
||||||
if (NumArgs != NumNamedArgs) {
|
if (NumArgs != NumNamedArgs) {
|
||||||
|
@ -203,7 +203,7 @@ bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return anyIncompatibleArgs;
|
return IsError;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Sema::isSelfExpr(Expr *RExpr) {
|
bool Sema::isSelfExpr(Expr *RExpr) {
|
||||||
|
|
|
@ -4178,11 +4178,13 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
|
||||||
else if (NumArgs > NumArgsInProto)
|
else if (NumArgs > NumArgsInProto)
|
||||||
NumArgsToCheck = NumArgsInProto;
|
NumArgsToCheck = NumArgsInProto;
|
||||||
|
|
||||||
|
bool IsError = false;
|
||||||
|
|
||||||
// Initialize the implicit object parameter.
|
// Initialize the implicit object parameter.
|
||||||
if (PerformObjectArgumentInitialization(Object, Method))
|
IsError |= PerformObjectArgumentInitialization(Object, Method);
|
||||||
return true;
|
|
||||||
TheCall->setArg(0, Object);
|
TheCall->setArg(0, Object);
|
||||||
|
|
||||||
|
|
||||||
// Check the argument types.
|
// Check the argument types.
|
||||||
for (unsigned i = 0; i != NumArgsToCheck; i++) {
|
for (unsigned i = 0; i != NumArgsToCheck; i++) {
|
||||||
Expr *Arg;
|
Expr *Arg;
|
||||||
|
@ -4191,8 +4193,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
|
||||||
|
|
||||||
// Pass the argument.
|
// Pass the argument.
|
||||||
QualType ProtoArgType = Proto->getArgType(i);
|
QualType ProtoArgType = Proto->getArgType(i);
|
||||||
if (PerformCopyInitialization(Arg, ProtoArgType, "passing"))
|
IsError |= PerformCopyInitialization(Arg, ProtoArgType, "passing");
|
||||||
return true;
|
|
||||||
} else {
|
} else {
|
||||||
Arg = new (Context) CXXDefaultArgExpr(Method->getParamDecl(i));
|
Arg = new (Context) CXXDefaultArgExpr(Method->getParamDecl(i));
|
||||||
}
|
}
|
||||||
|
@ -4205,12 +4206,13 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
|
||||||
// Promote the arguments (C99 6.5.2.2p7).
|
// Promote the arguments (C99 6.5.2.2p7).
|
||||||
for (unsigned i = NumArgsInProto; i != NumArgs; i++) {
|
for (unsigned i = NumArgsInProto; i != NumArgs; i++) {
|
||||||
Expr *Arg = Args[i];
|
Expr *Arg = Args[i];
|
||||||
|
IsError |= DefaultVariadicArgumentPromotion(Arg, VariadicMethod);
|
||||||
DefaultVariadicArgumentPromotion(Arg, VariadicMethod);
|
|
||||||
TheCall->setArg(i + 1, Arg);
|
TheCall->setArg(i + 1, Arg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (IsError) return true;
|
||||||
|
|
||||||
return CheckFunctionCall(Method, TheCall.take()).release();
|
return CheckFunctionCall(Method, TheCall.take()).release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,3 +22,9 @@
|
||||||
|
|
||||||
void somefunc(foo x) {} // expected-error {{Objective-C interface type 'foo' cannot be passed by value}}
|
void somefunc(foo x) {} // expected-error {{Objective-C interface type 'foo' cannot be passed by value}}
|
||||||
foo somefunc2() {} // expected-error {{Objective-C interface type 'foo' cannot be returned by value}}
|
foo somefunc2() {} // expected-error {{Objective-C interface type 'foo' cannot be returned by value}}
|
||||||
|
|
||||||
|
// rdar://6780761
|
||||||
|
void f0(foo *a0) {
|
||||||
|
extern void g0(int x, ...);
|
||||||
|
g0(1, *(foo*)0); // expected-error {{cannot pass object with interface type 'foo' by-value through variadic function}}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue