PATCH: PR objc/18971

Ziemowit Laski zlaski@apple.com
Fri Dec 24 21:53:00 GMT 2004


This was noticed by Alex, and it turned out that ObjC method parameters 
were not being properly decayed from arrays to pointers.  This patch 
hopefully fixes this, along with ObjC pretty-printing of array types.

I see absolutely no regressions with this, but I'll wait until next 
week before committing so that people may comment.  Happy holidays to 
all...

--Zem

[gcc/objc/ChangeLog]
2004-12-24  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-24  Alexander Malmberg  <alexander@malmberg.org>
             Ziemowit Laski  <zlaski@apple.com>

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



Index: gcc/objc/objc-act.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/objc/objc-act.c,v
retrieving revision 1.258
diff -u -3 -p -r1.258 objc-act.c
--- gcc/objc/objc-act.c 16 Dec 2004 01:10:36 -0000      1.258
+++ gcc/objc/objc-act.c 24 Dec 2004 21:36:05 -0000
@@ -5300,6 +5300,10 @@ get_arg_type_list (tree meth, int contex
      {
        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 +7481,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 +7953,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: gcc/testsuite/objc.dg/encode-5.m
===================================================================
RCS file: gcc/testsuite/objc.dg/encode-5.m
diff -N gcc/testsuite/objc.dg/encode-5.m
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ gcc/testsuite/objc.dg/encode-5.m    24 Dec 2004 21:36:19 -0000
@@ -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;
+}



More information about the Gcc-patches mailing list