From a8a7d0f371619116481bde713b2d90aae5f6a37e Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Sun, 12 Apr 2009 08:11:20 +0000 Subject: [PATCH] implement rdar://6780761, making sema reject some code that otherwise crashes codegen. llvm-svn: 68891 --- .../clang/Basic/DiagnosticSemaKinds.td | 5 ++++ clang/lib/Sema/Sema.h | 2 +- clang/lib/Sema/SemaExpr.cpp | 25 +++++++++++++------ clang/lib/Sema/SemaExprObjC.cpp | 8 +++--- clang/lib/Sema/SemaOverload.cpp | 14 ++++++----- clang/test/SemaObjC/method-bad-param.m | 6 +++++ 6 files changed, 41 insertions(+), 19 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 5b3ecb92992d..6c76e4aa2700 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -1190,6 +1190,11 @@ def err_typecheck_call_too_many_args : Error< def warn_call_wrong_number_of_arguments : Warning< "too %select{few|many}0 arguments in call to %1">; 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< "cannot pass object of non-POD type %0 through variadic " "%select{function|block|method}1; call will abort at runtime">; diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index 8138379af7c1..5018833267d1 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -2210,7 +2210,7 @@ public: // DefaultVariadicArgumentPromotion - Like DefaultArgumentPromotion, but // 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 // operands and then handles various conversions that are common to binary diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index f2820df93e8d..e380f78ad056 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -154,16 +154,25 @@ void Sema::DefaultArgumentPromotion(Expr *&Expr) { UsualUnaryConversions(Expr); } -// DefaultVariadicArgumentPromotion - Like DefaultArgumentPromotion, but -// will warn if the resulting type is not a POD type. -void Sema::DefaultVariadicArgumentPromotion(Expr *&Expr, VariadicCallType CT) { +/// DefaultVariadicArgumentPromotion - Like DefaultArgumentPromotion, but +/// will warn if the resulting type is not a POD type, and rejects ObjC +/// interfaces passed by value. This returns true if the argument type is +/// completely illegal. +bool Sema::DefaultVariadicArgumentPromotion(Expr *&Expr, VariadicCallType CT) { DefaultArgumentPromotion(Expr); - if (!Expr->getType()->isPODType()) { - Diag(Expr->getLocStart(), - diag::warn_cannot_pass_non_pod_arg_to_vararg) << - Expr->getType() << CT; + if (Expr->getType()->isObjCInterfaceType()) { + Diag(Expr->getLocStart(), + diag::err_cannot_pass_objc_interface_to_vararg) + << 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). for (unsigned i = NumArgsInProto; i != NumArgs; i++) { Expr *Arg = Args[i]; - DefaultVariadicArgumentPromotion(Arg, CallType); + Invalid |= DefaultVariadicArgumentPromotion(Arg, CallType); Call->setArg(i, Arg); } } diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp index 54a18ac832a2..8d8fae035a1e 100644 --- a/clang/lib/Sema/SemaExprObjC.cpp +++ b/clang/lib/Sema/SemaExprObjC.cpp @@ -164,7 +164,7 @@ bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs, unsigned NumNamedArgs = Sel.getNumArgs(); assert(NumArgs >= NumNamedArgs && "Too few arguments for selector!"); - bool anyIncompatibleArgs = false; + bool IsError = false; for (unsigned i = 0; i < NumNamedArgs; i++) { Expr *argExpr = Args[i]; assert(argExpr && "CheckMessageArgumentTypes(): missing expression"); @@ -183,7 +183,7 @@ bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs, if (Args[i] != argExpr) // The expression was converted. Args[i] = argExpr; // Make sure we store the converted expression. - anyIncompatibleArgs |= + IsError |= DiagnoseAssignmentResult(Result, argExpr->getLocStart(), lhsType, rhsType, argExpr, "sending"); } @@ -191,7 +191,7 @@ bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs, // Promote additional arguments to variadic methods. if (Method->isVariadic()) { for (unsigned i = NumNamedArgs; i < NumArgs; ++i) - DefaultVariadicArgumentPromotion(Args[i], VariadicMethod); + IsError |= DefaultVariadicArgumentPromotion(Args[i], VariadicMethod); } else { // Check for extra arguments to non-variadic methods. if (NumArgs != NumNamedArgs) { @@ -203,7 +203,7 @@ bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs, } } - return anyIncompatibleArgs; + return IsError; } bool Sema::isSelfExpr(Expr *RExpr) { diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 0a12a71bb74f..875a38253dab 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -4178,11 +4178,13 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, else if (NumArgs > NumArgsInProto) NumArgsToCheck = NumArgsInProto; + bool IsError = false; + // Initialize the implicit object parameter. - if (PerformObjectArgumentInitialization(Object, Method)) - return true; + IsError |= PerformObjectArgumentInitialization(Object, Method); TheCall->setArg(0, Object); + // Check the argument types. for (unsigned i = 0; i != NumArgsToCheck; i++) { Expr *Arg; @@ -4191,8 +4193,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, // Pass the argument. QualType ProtoArgType = Proto->getArgType(i); - if (PerformCopyInitialization(Arg, ProtoArgType, "passing")) - return true; + IsError |= PerformCopyInitialization(Arg, ProtoArgType, "passing"); } else { 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). for (unsigned i = NumArgsInProto; i != NumArgs; i++) { Expr *Arg = Args[i]; - - DefaultVariadicArgumentPromotion(Arg, VariadicMethod); + IsError |= DefaultVariadicArgumentPromotion(Arg, VariadicMethod); TheCall->setArg(i + 1, Arg); } } + if (IsError) return true; + return CheckFunctionCall(Method, TheCall.take()).release(); } diff --git a/clang/test/SemaObjC/method-bad-param.m b/clang/test/SemaObjC/method-bad-param.m index 824f72d29be5..f797188669ad 100644 --- a/clang/test/SemaObjC/method-bad-param.m +++ b/clang/test/SemaObjC/method-bad-param.m @@ -22,3 +22,9 @@ 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}} + +// 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}} +}