diff options
author | Daniel Dunbar <daniel@zuster.org> | 2008-09-11 00:50:25 +0000 |
---|---|---|
committer | Daniel Dunbar <daniel@zuster.org> | 2008-09-11 00:50:25 +0000 |
commit | ce05c8eb49d6216ae1e2c12dcd9114d9515d6e8f (patch) | |
tree | 45f19aca0ed38ac52b0e706d2bddff7e7612de3d | |
parent | 16211a2cc7d67f1fd0daa23fe30f666d8e8bbd19 (diff) | |
download | bcm5719-llvm-ce05c8eb49d6216ae1e2c12dcd9114d9515d6e8f.tar.gz bcm5719-llvm-ce05c8eb49d6216ae1e2c12dcd9114d9515d6e8f.zip |
Fix two bugs exposed by array passing assert:
(1) Additional arguments to variadic methods should have default
promotions applied.
(2) Additional arguments to non-variadic methods were allowed.
llvm-svn: 56084
-rw-r--r-- | clang/lib/Sema/Sema.h | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExprObjC.cpp | 34 | ||||
-rw-r--r-- | clang/test/CodeGenObjC/message-arrays.m | 15 | ||||
-rw-r--r-- | clang/test/SemaObjC/message.m | 7 |
4 files changed, 49 insertions, 9 deletions
diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index a88ce8e3dbe..f45e49ff018 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -965,7 +965,7 @@ private: /// \param Method - May be null. /// \param [out] ReturnType - The return type of the send. /// \return true iff there were any incompatible types. - bool CheckMessageArgumentTypes(Expr **Args, Selector Sel, + bool CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs, Selector Sel, ObjCMethodDecl *Method, const char *PrefixStr, SourceLocation lbrac, SourceLocation rbrac, QualType &ReturnType); diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp index 08177e67696..390baed9a33 100644 --- a/clang/lib/Sema/SemaExprObjC.cpp +++ b/clang/lib/Sema/SemaExprObjC.cpp @@ -107,12 +107,11 @@ Sema::ExprResult Sema::ParseObjCProtocolExpression(IdentifierInfo *ProtocolId, return new ObjCProtocolExpr(t, PDecl, AtLoc, RParenLoc); } -bool Sema::CheckMessageArgumentTypes(Expr **Args, Selector Sel, - ObjCMethodDecl *Method, +bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs, + Selector Sel, ObjCMethodDecl *Method, const char *PrefixStr, SourceLocation lbrac, SourceLocation rbrac, QualType &ReturnType) { - unsigned NumArgs = Sel.getNumArgs(); if (!Method) { // Apply default argument promotion as for (C99 6.5.2.2p6). for (unsigned i = 0; i != NumArgs; i++) @@ -126,8 +125,11 @@ bool Sema::CheckMessageArgumentTypes(Expr **Args, Selector Sel, ReturnType = Method->getResultType(); } + unsigned NumNamedArgs = Sel.getNumArgs(); + assert(NumArgs >= NumNamedArgs && "Too few arguments for selector!"); + bool anyIncompatibleArgs = false; - for (unsigned i = 0; i < NumArgs; i++) { + for (unsigned i = 0; i < NumNamedArgs; i++) { Expr *argExpr = Args[i]; assert(argExpr && "CheckMessageArgumentTypes(): missing expression"); @@ -149,6 +151,22 @@ bool Sema::CheckMessageArgumentTypes(Expr **Args, Selector Sel, DiagnoseAssignmentResult(Result, argExpr->getLocStart(), lhsType, rhsType, argExpr, "sending"); } + + // Promote additional arguments to variadic methods. + if (Method->isVariadic()) { + for (unsigned i = NumNamedArgs; i < NumArgs; ++i) + DefaultArgumentPromotion(Args[i]); + } else { + // Check for extra arguments to non-variadic methods. + if (NumArgs != NumNamedArgs) { + Diag(Args[NumNamedArgs]->getLocStart(), + diag::err_typecheck_call_too_many_args, + Method->getSourceRange(), + SourceRange(Args[NumNamedArgs]->getLocStart(), + Args[NumArgs-1]->getLocEnd())); + } + } + return anyIncompatibleArgs; } @@ -220,7 +238,7 @@ Sema::ExprResult Sema::ActOnClassMessage( if (!Method) Method = ClassDecl->lookupInstanceMethod(Sel); - if (CheckMessageArgumentTypes(ArgExprs, Sel, Method, "+", + if (CheckMessageArgumentTypes(ArgExprs, NumArgs, Sel, Method, "+", lbrac, rbrac, returnType)) return true; @@ -259,7 +277,7 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel, ObjCMethodDecl *Method = InstanceMethodPool[Sel].Method; if (!Method) Method = FactoryMethodPool[Sel].Method; - if (CheckMessageArgumentTypes(ArgExprs, Sel, Method, "-", + if (CheckMessageArgumentTypes(ArgExprs, NumArgs, Sel, Method, "-", lbrac, rbrac, returnType)) return true; return new ObjCMessageExpr(RExpr, Sel, returnType, Method, lbrac, rbrac, @@ -280,7 +298,7 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel, Method = FactoryMethodPool[Sel].Method; if (!Method) Method = InstanceMethodPool[Sel].Method; - if (CheckMessageArgumentTypes(ArgExprs, Sel, Method, "-", + if (CheckMessageArgumentTypes(ArgExprs, NumArgs, Sel, Method, "-", lbrac, rbrac, returnType)) return true; return new ObjCMessageExpr(RExpr, Sel, returnType, Method, lbrac, rbrac, @@ -344,7 +362,7 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel, if (!Method) Method = InstanceMethodPool[Sel].Method; } - if (CheckMessageArgumentTypes(ArgExprs, Sel, Method, "-", + if (CheckMessageArgumentTypes(ArgExprs, NumArgs, Sel, Method, "-", lbrac, rbrac, returnType)) return true; return new ObjCMessageExpr(RExpr, Sel, returnType, Method, lbrac, rbrac, diff --git a/clang/test/CodeGenObjC/message-arrays.m b/clang/test/CodeGenObjC/message-arrays.m new file mode 100644 index 00000000000..55b5d9b84ef --- /dev/null +++ b/clang/test/CodeGenObjC/message-arrays.m @@ -0,0 +1,15 @@ +// RUN: clang -emit-llvm -o %t %s + +void f0(id a) { + // This should have an implicit cast + [ a print: "hello" ]; +} + +@interface A +-(void) m: (int) arg0, ...; +@end + +int f1(A *a) { + // This should also get an implicit cast (for the vararg) + [a m: 1, "test"]; +} diff --git a/clang/test/SemaObjC/message.m b/clang/test/SemaObjC/message.m index 9c9289b6b85..69a6535a4a9 100644 --- a/clang/test/SemaObjC/message.m +++ b/clang/test/SemaObjC/message.m @@ -61,3 +61,10 @@ extern Class NSClassFromObject(id object); } @end +@interface I0 +-(void) nonVararg: (int) x; +@end + +int f0(I0 *ob) { + [ ob nonVararg: 0, 1, 2]; // expected-error {{too many arguments to function}} +} |