This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
PATCH: PR objc/18971
- From: Ziemowit Laski <zlaski at apple dot com>
- To: "gcc-patches at gcc dot gnu dot org Patches" <gcc-patches at gcc dot gnu dot org>
- Cc: Alexander Malmberg <alexander at malmberg dot org>
- Date: Fri, 24 Dec 2004 13:52:48 -0800
- Subject: PATCH: PR objc/18971
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;
+}