diff options
-rw-r--r-- | gcc/objc/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/objc/objc-act.c | 45 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/objc.dg/encode-5.m | 78 |
4 files changed, 130 insertions, 6 deletions
diff --git a/gcc/objc/ChangeLog b/gcc/objc/ChangeLog index b0216ae..04b94c0 100644 --- a/gcc/objc/ChangeLog +++ b/gcc/objc/ChangeLog @@ -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 diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c index b77e441..0952500 100644 --- a/gcc/objc/objc-act.c +++ b/gcc/objc/objc-act.c @@ -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; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index c381350..5bb8957 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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 index 0000000..f2cb693 --- /dev/null +++ b/gcc/testsuite/objc.dg/encode-5.m @@ -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; +} |