summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Dunbar <daniel@zuster.org>2008-09-11 00:50:25 +0000
committerDaniel Dunbar <daniel@zuster.org>2008-09-11 00:50:25 +0000
commitce05c8eb49d6216ae1e2c12dcd9114d9515d6e8f (patch)
tree45f19aca0ed38ac52b0e706d2bddff7e7612de3d
parent16211a2cc7d67f1fd0daa23fe30f666d8e8bbd19 (diff)
downloadbcm5719-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.h2
-rw-r--r--clang/lib/Sema/SemaExprObjC.cpp34
-rw-r--r--clang/test/CodeGenObjC/message-arrays.m15
-rw-r--r--clang/test/SemaObjC/message.m7
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}}
+}
OpenPOWER on IntegriCloud