]> granicus.if.org Git - clang/commitdiff
Fix two bugs exposed by array passing assert:
authorDaniel Dunbar <daniel@zuster.org>
Thu, 11 Sep 2008 00:50:25 +0000 (00:50 +0000)
committerDaniel Dunbar <daniel@zuster.org>
Thu, 11 Sep 2008 00:50:25 +0000 (00:50 +0000)
(1) Additional arguments to variadic methods should have default
promotions applied.

(2) Additional arguments to non-variadic methods were allowed.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@56084 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/Sema.h
lib/Sema/SemaExprObjC.cpp
test/CodeGenObjC/message-arrays.m [new file with mode: 0644]
test/SemaObjC/message.m

index a88ce8e3dbe9fcb68e77cc73d1c1854856ca3437..f45e49ff018991e08be47e030ab72417fa00fb8e 100644 (file)
@@ -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);  
index 08177e6769635aeaa12f2b2f1a7d5d88c411b73f..390baed9a33521f7df4ef71e6fc3f64f942bc4af 100644 (file)
@@ -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/test/CodeGenObjC/message-arrays.m b/test/CodeGenObjC/message-arrays.m
new file mode 100644 (file)
index 0000000..55b5d9b
--- /dev/null
@@ -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"];
+}
index 9c9289b6b8584ad9acd311150e45966b40ea1a5a..69a6535a4a9cea44b49deef9e9b395d2573a7d2b 100644 (file)
@@ -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}}
+}