re PR objc/18971 (Can't send messages to methods with arrays as parameters)
authorZiemowit Laski <zlaski@gcc.gnu.org>
Thu, 30 Dec 2004 10:18:18 +0000 (10:18 +0000)
committerZiemowit Laski <zlaski@gcc.gnu.org>
Thu, 30 Dec 2004 10:18:18 +0000 (10:18 +0000)
[gcc/objc/ChangeLog]
2004-12-30  Ziemowit Laski  <zlaski@apple.com>

        PR objc/18971
        * objc-act.c (get_arg_type_list, start_method_def): Decay
        array arguments into pointers.
        (gen_type_name_0): Learn to pretty-print array types.

[gcc/testsuite/ChangeLog]
2004-12-30  Alexander Malmberg  <alexander@malmberg.org>
            Ziemowit Laski  <zlaski@apple.com>

        PR objc/18971
        * objc.dg/encode-5.m: New test.

From-SVN: r92731

gcc/objc/ChangeLog
gcc/objc/objc-act.c
gcc/testsuite/ChangeLog
gcc/testsuite/objc.dg/encode-5.m [new file with mode: 0644]

index b0216ae81d05c6b8dd111bdb20831083b28e57f1..04b94c0eb224ababfb4c93f5a2498768bcc4982a 100644 (file)
@@ -1,3 +1,10 @@
+2004-12-30  Ziemowit Laski  <zlaski@apple.com>
+
+       PR objc/18971
+       * objc-act.c (get_arg_type_list, start_method_def): Decay
+       array arguments into pointers.
+       (gen_type_name_0): Learn to pretty-print array types.
+
 2004-12-15  Ziemowit Laski  <zlaski@apple.com>
 
        * objc-act.c (build_private_template): Change to return 'void'; do
index b77e44145824691cce8ece59201c81a28ee6bb3c..09525007b9f6db1ba649bc556256cf7a7b7ba4e0 100644 (file)
@@ -5300,6 +5300,10 @@ get_arg_type_list (tree meth, int context, int superflag)
     {
       tree arg_type = TREE_VALUE (TREE_TYPE (akey));
 
+      /* Decay arrays into pointers.  */
+      if (TREE_CODE (arg_type) == ARRAY_TYPE)
+       arg_type = build_pointer_type (TREE_TYPE (arg_type));
+
       chainon (arglist, build_tree_list (NULL_TREE, arg_type));
     }
 
@@ -7473,9 +7477,13 @@ start_method_def (tree method)
   parmlist = METHOD_SEL_ARGS (method);
   while (parmlist)
     {
-      tree parm = build_decl (PARM_DECL, KEYWORD_ARG_NAME (parmlist),
-                             TREE_VALUE (TREE_TYPE (parmlist)));
+      tree type = TREE_VALUE (TREE_TYPE (parmlist)), parm;
+
+      /* Decay arrays into pointers.  */
+      if (TREE_CODE (type) == ARRAY_TYPE)
+       type = build_pointer_type (TREE_TYPE (type));
 
+      parm = build_decl (PARM_DECL, KEYWORD_ARG_NAME (parmlist), type);
       objc_push_parm (parm);
       parmlist = TREE_CHAIN (parmlist);
     }
@@ -7941,14 +7949,39 @@ gen_type_name_0 (tree type)
 
   if (TYPE_P (type) && TYPE_NAME (type))
     type = TYPE_NAME (type);
-  else if (POINTER_TYPE_P (type))
+  else if (POINTER_TYPE_P (type) || TREE_CODE (type) == ARRAY_TYPE)
     {
-      gen_type_name_0 (TREE_TYPE (type));
+      tree inner = TREE_TYPE (type);
+
+      while (TREE_CODE (inner) == ARRAY_TYPE)
+       inner = TREE_TYPE (inner);
+
+      gen_type_name_0 (inner);
       
-      if (!POINTER_TYPE_P (TREE_TYPE (type)))
+      if (!POINTER_TYPE_P (inner))
        strcat (errbuf, " ");
 
-      strcat (errbuf, "*");
+      if (POINTER_TYPE_P (type))
+       strcat (errbuf, "*");
+      else
+       while (type != inner)
+         {
+           strcat (errbuf, "[");
+
+           if (TYPE_DOMAIN (type))
+             {
+               char sz[20];
+
+               sprintf (sz, HOST_WIDE_INT_PRINT_DEC,
+                        (TREE_INT_CST_LOW 
+                         (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) + 1));
+               strcat (errbuf, sz);
+             }
+
+           strcat (errbuf, "]");
+           type = TREE_TYPE (type);
+         }
+
       goto exit_function;
     }
 
index c38135052f6cac1c1344fac069255c5346d0c0f8..5bb895777e0627dee693b66484805ef23f9fa008 100644 (file)
@@ -1,3 +1,9 @@
+2004-12-30  Alexander Malmberg  <alexander@malmberg.org>
+           Ziemowit Laski  <zlaski@apple.com>
+
+        PR objc/18971
+       * objc.dg/encode-5.m: New test.
+
 2004-12-29  Richard Henderson  <rth@redhat.com>
 
        * gcc.dg/20040813-1.c: Disable for alpha and ia64.
diff --git a/gcc/testsuite/objc.dg/encode-5.m b/gcc/testsuite/objc.dg/encode-5.m
new file mode 100644 (file)
index 0000000..f2cb693
--- /dev/null
@@ -0,0 +1,78 @@
+/* Check if array arguments of ObjC methods are decayed to pointer types
+   in a proper fashion:
+     (1) The _encodings_ for the array arguments should remain to be '[4i]' and
+         such, since this has been the case since at least gcc 3.3.
+     (2) However, when building the static C functions out of ObjC method signatures,
+         we need to decay the arrays into pointers (as C does).
+     (3) If array size is not known (e.g., 'int a[]'), then the type shall be
+         encoded as a pointer.  */
+
+/* Contributed by Alexander Malmberg <alexander@malmberg.org>  */
+
+#include <objc/Object.h>
+#include <stdlib.h>
+#include <stdio.h>
+#define CHECK_IF(expr) if(!(expr)) abort()
+
+#ifdef __NEXT_RUNTIME__
+#define METHOD Method
+#define OBJC_GETCLASS objc_getClass
+#define CLASS_GETINSTANCEMETHOD class_getInstanceMethod
+#else
+#include <objc/objc-api.h>
+#define METHOD Method_t
+#define OBJC_GETCLASS objc_get_class
+#define CLASS_GETINSTANCEMETHOD class_get_instance_method
+#endif
+
+@interface Test : Object
+{ float j; }
+-(void) test2: (int [5])a with: (int [])b;
+-(id) test3: (Test **)b; /* { dg-warning "previous declaration of .\\-\\(id\\)test3:\\(Test \\*\\*\\)b." } */
+@end
+
+@implementation Test
+-(void) test2: (int [5])a with: (int [])b
+{
+  a[3] = *b;
+}
+-(void) test3: (Test [3][4])b {  /* { dg-warning "conflicting types for .\\-\\(void\\)test3:\\(Test \\\[3\\\]\\\[4\\\]\\)b." } */
+}
+@end
+
+int bb[6] = { 0, 1, 2, 3, 4, 5 };
+int *b = bb;
+Test *cc[4];
+Test **c = cc;
+
+int offs1, offs2, offs3, offs4, offs5, offs6;
+
+int main(int argc, char **argv)
+{
+  Class testClass = OBJC_GETCLASS("Test");
+  METHOD meth;
+
+  cc[0] = [Test new];
+  CHECK_IF (bb[3] == 3);
+  [*c test2: b with: bb + 4];
+  CHECK_IF (bb[3] == 4);
+  bb[3] = 0;
+  [*c test2: bb with: bb + 5];
+  CHECK_IF (bb[3] == 5);
+
+  meth = CLASS_GETINSTANCEMETHOD(testClass, @selector(test2:with:));
+  offs1 = offs2 = offs3 = offs4 = offs5 = offs6 = -1;
+  sscanf(meth->method_types, "v%d@%d:%d[%di]%d^i%d", &offs1, &offs2, &offs3,
+      &offs4, &offs5, &offs6);
+  CHECK_IF (!offs2 && offs4 == 5 && offs3 > 0);
+  CHECK_IF (offs5 == 2 * offs3 && offs6 == 3 * offs3 && offs1 == 4 * offs3);
+  
+  meth = CLASS_GETINSTANCEMETHOD(testClass, @selector(test3:));
+  offs1 = offs2 = offs3 = offs4 = offs5 = offs6 = -1;
+  sscanf(meth->method_types, "v%d@%d:%d[%d[%d{Test=#f}]]%d", &offs1, &offs2, &offs3,
+      &offs4, &offs5, &offs6);
+  CHECK_IF (!offs2 && offs4 == 3 && offs5 == 4 && offs3 > 0);
+  CHECK_IF (offs6 == 2 * offs3 && offs1 == 3 * offs3);
+  
+  return 0;
+}