diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 60146201490..ae76071825d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2004-10-25 David Ayers + + * c-common.h: Remove RID_ID. + * c-parse.in: Remove OBJECTNAME and references to RID_ID. + (typespec_reserved_attr): Add rule for TYPENAME + non_empty_protocolrefs. + (yylexname): Remove special handling of RID_ID. + 2004-10-25 James E Wilson * doc/invoke.texi (-fcrossjumping): Not enabled at -O. diff --git a/gcc/c-common.h b/gcc/c-common.h index 77e2c279bc3..95aaf8c115a 100644 --- a/gcc/c-common.h +++ b/gcc/c-common.h @@ -92,7 +92,7 @@ enum rid RID_CONSTCAST, RID_DYNCAST, RID_REINTCAST, RID_STATCAST, /* Objective-C */ - RID_ID, RID_AT_ENCODE, RID_AT_END, + RID_AT_ENCODE, RID_AT_END, RID_AT_CLASS, RID_AT_ALIAS, RID_AT_DEFS, RID_AT_PRIVATE, RID_AT_PROTECTED, RID_AT_PUBLIC, RID_AT_PROTOCOL, RID_AT_SELECTOR, diff --git a/gcc/c-parse.in b/gcc/c-parse.in index 7f6f4f491d7..dbeee723988 100644 --- a/gcc/c-parse.in +++ b/gcc/c-parse.in @@ -178,7 +178,7 @@ do { \ Objective C, so that the token codes are the same in both. */ %token AT_INTERFACE AT_IMPLEMENTATION AT_END AT_SELECTOR AT_DEFS AT_ENCODE %token CLASSNAME AT_PUBLIC AT_PRIVATE AT_PROTECTED AT_PROTOCOL -%token OBJECTNAME AT_CLASS AT_ALIAS +%token AT_CLASS AT_ALIAS %token AT_THROW AT_TRY AT_CATCH AT_FINALLY AT_SYNCHRONIZED %token OBJC_STRING @@ -259,7 +259,7 @@ do { \ %type selectorarg keywordnamelist keywordname objcencodeexpr %type non_empty_protocolrefs protocolrefs identifier_list objcprotocolexpr -%type CLASSNAME OBJECTNAME OBJC_STRING OBJC_TYPE_QUAL +%type CLASSNAME OBJC_STRING OBJC_TYPE_QUAL %type superclass objc_quals objc_qual objc_typename %type objc_try_catch_stmt optellipsis @@ -472,7 +472,6 @@ identifier: IDENTIFIER | TYPENAME @@ifobjc - | OBJECTNAME | CLASSNAME @@end_ifobjc ; @@ -1281,7 +1280,7 @@ typespec_nonreserved_nonattr: | CLASSNAME protocolrefs { $$.kind = ctsk_objc; $$.spec = objc_get_protocol_qualified_type ($1, $2); } - | OBJECTNAME protocolrefs + | TYPENAME non_empty_protocolrefs { $$.kind = ctsk_objc; $$.spec = objc_get_protocol_qualified_type ($1, $2); } @@ -1567,10 +1566,6 @@ after_type_declarator: { $$ = make_pointer_declarator ($2, $3); } | TYPENAME { $$ = build_id_declarator ($1); } -@@ifobjc - | OBJECTNAME - { $$ = build_id_declarator ($1); } -@@end_ifobjc ; /* Kinds of declarator that can appear in a parameter list @@ -1589,10 +1584,6 @@ parm_declarator_starttypename: { $$ = set_array_declarator_inner ($2, $1, false); } | TYPENAME { $$ = build_id_declarator ($1); } -@@ifobjc - | OBJECTNAME - { $$ = build_id_declarator ($1); } -@@end_ifobjc ; parm_declarator_nostarttypename: @@ -2884,7 +2875,6 @@ selector: IDENTIFIER | TYPENAME | CLASSNAME - | OBJECTNAME | reservedwords ; @@ -3144,7 +3134,6 @@ static const struct resword reswords[] = { "while", RID_WHILE, 0 }, @@ifobjc - { "id", RID_ID, D_OBJC }, /* These objc keywords are recognized only immediately after an '@'. */ @@ -3287,7 +3276,6 @@ static const short rid_to_yy[RID_MAX] = /* RID_STATCAST */ 0, /* Objective C */ - /* RID_ID */ OBJECTNAME, /* RID_AT_ENCODE */ AT_ENCODE, /* RID_AT_END */ AT_END, /* RID_AT_CLASS */ AT_CLASS, @@ -3356,15 +3344,6 @@ yylexname (void) enum rid rid_code = C_RID_CODE (yylval.ttype); @@ifobjc - /* Turn non-typedefed refs to "id" into plain identifiers; this - allows constructs like "void foo(id id);" to work. */ - if (rid_code == RID_ID) - { - decl = lookup_name (yylval.ttype); - if (decl == NULL_TREE || TREE_CODE (decl) != TYPE_DECL) - return IDENTIFIER; - } - if (!OBJC_IS_AT_KEYWORD (rid_code) && (!OBJC_IS_PQ_KEYWORD (rid_code) || objc_pq_context)) @@end_ifobjc @@ -3527,7 +3506,6 @@ yyprint (FILE *file, int yychar, YYSTYPE yyl) { case IDENTIFIER: case TYPENAME: - case OBJECTNAME: case TYPESPEC: case TYPE_QUAL: case SCSPEC: diff --git a/gcc/objc/ChangeLog b/gcc/objc/ChangeLog index b904fa0ee5e..f781a1cefd5 100644 --- a/gcc/objc/ChangeLog +++ b/gcc/objc/ChangeLog @@ -1,3 +1,22 @@ +2004-10-25 Ziemowit Laski + David Ayers + + * objc-act.c (objc_comptypes): Use IS_PROTOCOL_QUALIFIED_UNTYPED + instead of IS_PROTOCOL_QUALIFIED_ID; add comparisons for: + 'Class != id '; 'Class != *'; + 'Class == id' and 'Class == Class'. + (objc_is_id): Add test for 'super'. + (objc_finish_message_expr): Allow for messaging of 'Class ' + receivers; if class methods are not found in protocol lists, search + for instance methods therein and warn if one is found. Look in + global hash tables for suitable method as a last resort when messaging + 'id ', 'Class ' and invalid receiver types. + (objc_add_method): Insert instance methods listed in protocols into + the global class method hash table. + * objc-act.h (IS_PROTOCOL_QUALIFIED_ID): Rename to + IS_PROTOCOL_QUALIFIED_UNTYPED and allow for 'Class ' in + addition to 'id '. + 2004-10-21 Andrew Pinski PR objc/17923 diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c index 34550959482..21b279d5397 100644 --- a/gcc/objc/objc-act.c +++ b/gcc/objc/objc-act.c @@ -866,8 +866,8 @@ objc_comptypes (tree lhs, tree rhs, int reflexive) && TREE_CODE (rhs) == POINTER_TYPE && TREE_CODE (TREE_TYPE (rhs)) == RECORD_TYPE) { - int lhs_is_proto = IS_PROTOCOL_QUALIFIED_ID (lhs); - int rhs_is_proto = IS_PROTOCOL_QUALIFIED_ID (rhs); + int lhs_is_proto = IS_PROTOCOL_QUALIFIED_UNTYPED (lhs); + int rhs_is_proto = IS_PROTOCOL_QUALIFIED_UNTYPED (rhs); if (lhs_is_proto) { @@ -878,6 +878,11 @@ objc_comptypes (tree lhs, tree rhs, int reflexive) /* = */ if (rhs_is_proto) { + /* Class != id ; + id != Class */ + if (IS_ID (lhs) != IS_ID (rhs)) + return 0; + rproto_list = TYPE_PROTOCOL_LIST (rhs); if (!reflexive) @@ -942,6 +947,10 @@ objc_comptypes (tree lhs, tree rhs, int reflexive) tree rname = OBJC_TYPE_NAME (TREE_TYPE (rhs)); tree rinter; + /* Class != * */ + if (IS_CLASS (lhs)) + return 0; + /* Make sure the protocol is supported by the object on the rhs. */ for (lproto = lproto_list; lproto; lproto = TREE_CHAIN (lproto)) @@ -985,15 +994,15 @@ objc_comptypes (tree lhs, tree rhs, int reflexive) } return 1; } - /* = id */ + /* id = id; Class = id */ else if (objc_is_object_id (TREE_TYPE (rhs))) { return 1; } - /* = Class */ + /* id != Class; Class = Class */ else if (objc_is_class_id (TREE_TYPE (rhs))) { - return 0; + return IS_CLASS (lhs); } /* = ?? : let comptypes decide. */ return -1; @@ -1003,6 +1012,10 @@ objc_comptypes (tree lhs, tree rhs, int reflexive) /* * = */ if (TYPED_OBJECT (TREE_TYPE (lhs))) { + /* * != Class */ + if (IS_CLASS (rhs)) + return 0; + if (reflexive) { tree rname = OBJC_TYPE_NAME (TREE_TYPE (lhs)); @@ -1062,15 +1075,15 @@ objc_comptypes (tree lhs, tree rhs, int reflexive) else return 0; } - /* id = */ + /* id = id ; id = Class */ else if (objc_is_object_id (TREE_TYPE (lhs))) { return 1; } - /* Class = */ + /* Class != id ; Class = Class */ else if (objc_is_class_id (TREE_TYPE (lhs))) { - return 0; + return IS_CLASS (rhs); } /* ??? = : let comptypes decide */ else @@ -2714,7 +2727,8 @@ objc_is_id (tree type) /* NB: This function may be called before the ObjC front-end has been initialized, in which case OBJC_OBJECT_TYPE will (still) be NULL. */ - return (objc_object_type && type && (IS_ID (type) || IS_CLASS (type)) + return (objc_object_type && type + && (IS_ID (type) || IS_CLASS (type) || IS_SUPER (type)) ? type : NULL_TREE); } @@ -5567,25 +5581,35 @@ objc_finish_message_expr (tree receiver, tree sel_name, tree method_params) { if (!rtype) rtype = xref_tag (RECORD_TYPE, class_tree); - else if (IS_ID (rtype)) + else { + class_tree = (IS_CLASS (rtype) ? objc_class_name : NULL_TREE); rprotos = TYPE_PROTOCOL_LIST (rtype); rtype = NULL_TREE; } - else - { - class_tree = objc_class_name; - OBJC_SET_TYPE_NAME (rtype, class_tree); - } if (rprotos) - method_prototype - = lookup_method_in_protocol_list (rprotos, sel_name, - class_tree != NULL_TREE); - if (!method_prototype && !rprotos) - method_prototype - = lookup_method_in_hash_lists (sel_name, - class_tree != NULL_TREE); + { + /* If messaging 'id ' or 'Class ', first search + in protocols themselves for the method prototype. */ + method_prototype + = lookup_method_in_protocol_list (rprotos, sel_name, + class_tree != NULL_TREE); + + /* If messaging 'Class ' but did not find a class method + prototype, search for an instance method instead, and warn + about having done so. */ + if (!method_prototype && !rtype && class_tree != NULL_TREE) + { + method_prototype + = lookup_method_in_protocol_list (rprotos, sel_name, 0); + + if (method_prototype) + warning ("found `-%s' instead of `+%s' in protocol(s)", + IDENTIFIER_POINTER (sel_name), + IDENTIFIER_POINTER (sel_name)); + } + } } else { @@ -5642,10 +5666,28 @@ objc_finish_message_expr (tree receiver, tree sel_name, tree method_params) { warning ("invalid receiver type `%s'", gen_type_name (orig_rtype)); + /* After issuing the "invalid receiver" warning, perform method + lookup as if we were messaging 'id'. */ rtype = rprotos = NULL_TREE; } } + + /* For 'id' or 'Class' receivers, search in the global hash table + as a last resort. For all receivers, warn if protocol searches + have failed. */ + if (!method_prototype) + { + if (rprotos) + warning ("`%c%s' not found in protocol(s)", + (class_tree ? '+' : '-'), + IDENTIFIER_POINTER (sel_name)); + + if (!rtype) + method_prototype + = lookup_method_in_hash_lists (sel_name, class_tree != NULL_TREE); + } + if (!method_prototype) { static bool warn_missing_methods = false; @@ -5655,10 +5697,14 @@ objc_finish_message_expr (tree receiver, tree sel_name, tree method_params) IDENTIFIER_POINTER (OBJC_TYPE_NAME (rtype)), (class_tree ? '+' : '-'), IDENTIFIER_POINTER (sel_name)); - if (rprotos) - warning ("`%c%s' not implemented by protocol(s)", + /* If we are messaging an 'id' or 'Class' object and made it here, + then we have failed to find _any_ instance or class method, + respectively. */ + else + warning ("no `%c%s' method found", (class_tree ? '+' : '-'), IDENTIFIER_POINTER (sel_name)); + if (!warn_missing_methods) { warning ("(Messages without a matching method signature"); @@ -6160,13 +6206,16 @@ objc_add_method (tree class, tree method, int is_class) add_method_to_hash_list (nst_method_hash_list, method); /* Instance methods in root classes (and categories thereof) - may acts as class methods as a last resort. */ + may act as class methods as a last resort. We also add + instance methods listed in @protocol declarations to + the class hash table, on the assumption that @protocols + may be adopted by root classes or categories. */ if (TREE_CODE (class) == CATEGORY_INTERFACE_TYPE || TREE_CODE (class) == CATEGORY_IMPLEMENTATION_TYPE) class = lookup_interface (CLASS_NAME (class)); - if (TREE_CODE (class) != PROTOCOL_INTERFACE_TYPE - && !CLASS_SUPER_NAME (class)) + if (TREE_CODE (class) == PROTOCOL_INTERFACE_TYPE + || !CLASS_SUPER_NAME (class)) add_method_to_hash_list (cls_method_hash_list, method); } diff --git a/gcc/objc/objc-act.h b/gcc/objc/objc-act.h index 52eeb448cfa..d13e3742f1c 100644 --- a/gcc/objc/objc-act.h +++ b/gcc/objc/objc-act.h @@ -277,8 +277,8 @@ extern GTY(()) tree objc_global_trees[OCTI_MAX]; (POINTER_TYPE_P (TYPE) && TREE_TYPE (TYPE) == TREE_TYPE (objc_object_type)) #define IS_CLASS(TYPE) \ (POINTER_TYPE_P (TYPE) && TREE_TYPE (TYPE) == TREE_TYPE (objc_class_type)) -#define IS_PROTOCOL_QUALIFIED_ID(TYPE) \ - (IS_ID (TYPE) && TYPE_PROTOCOL_LIST (TYPE)) +#define IS_PROTOCOL_QUALIFIED_UNTYPED(TYPE) \ + ((IS_ID (TYPE) || IS_CLASS (TYPE)) && TYPE_PROTOCOL_LIST (TYPE)) #define IS_SUPER(TYPE) \ (POINTER_TYPE_P (TYPE) && TREE_TYPE (TYPE) == objc_super_template) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 68b98b29c15..a0768c31742 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,18 @@ +2004-10-25 David Ayers + Ziemowit Laski + + * objc.dg/call-super-2.m: Add messages to 'Class '; update + diagnostics when messaging 'id '. + * objc.dg/class-protocol-1.m: New test. + * objc.dg/desig-init-1.m: Add message to an invalid receiver using + a non-existent method signature. + * objc.dg/method-5.m, objc.dg/method-6.m, objc.dg/proto-hier-1.m: + Update diagnostics when messaging with non-existent method signature. + * objc.dg/proto-hier-2.m: Adjust wording of diagnostic. + * objc.dg/proto-lossage-1.m, objc.dg/proto-lossage-4.m: Messages to + invalid receivers are now resolved as if messaging 'id'; remove + extraneous diagnostics. + 2004-10-25 Joseph S. Myers PR c/16667 diff --git a/gcc/testsuite/objc.dg/call-super-2.m b/gcc/testsuite/objc.dg/call-super-2.m index 41eafc83780..be8a89fdc7b 100644 --- a/gcc/testsuite/objc.dg/call-super-2.m +++ b/gcc/testsuite/objc.dg/call-super-2.m @@ -46,15 +46,14 @@ + (int) class_func1 { int i = (size_t)[self class_func0]; /* { dg-warning ".Derived. may not respond to .\\+class_func0." } */ - /* { dg-warning "Messages without a matching method signature" "" { target *-*-* } 48 } */ - /* { dg-warning "will be assumed to return .id. and accept" "" { target *-*-* } 48 } */ - /* { dg-warning ".\.\.\.. as arguments" "" { target *-*-* } 48 } */ return i + (size_t)[super class_func0]; /* { dg-warning ".Object. may not respond to .\\+class_func0." } */ } + (int) class_func2 { - int i = [(id )self class_func0]; - return i + [(id )super class_func0]; + int i = [(id )self class_func0]; /* { dg-warning ".\\-class_func0. not found in protocol" } */ + i += [(id )super class_func0]; /* { dg-warning ".\\-class_func0. not found in protocol" } */ + i += [(Class )self class_func0]; + return i + [(Class )super class_func0]; } + (int) class_func3 { @@ -120,16 +119,18 @@ } + (int) categ_class_func2 { - int i = [(id )self class_func0]; - return i + [(id )super class_func0]; + int i = [(id )self class_func0]; /* { dg-warning ".\\-class_func0. not found in protocol" } */ + i += [(id )super class_func0]; /* { dg-warning ".\\-class_func0. not found in protocol" } */ + i += [(Class )self class_func0]; + return i + [(Class )super class_func0]; } - (int) categ_instance_func1 { int i = (size_t)[self instance_func0]; /* { dg-warning ".Derived. may not respond to .\\-instance_func0." } */ i += [(Derived *)self categ_instance_func2]; i += (size_t)[(Object *)self categ_instance_func2]; /* { dg-warning ".Object. may not respond to .\\-categ_instance_func2." } */ - /* { dg-warning ".\\-categ_instance_func2. not implemented by protocol" "" { target *-*-* } 130 } */ - i += (size_t)[(id )self categ_instance_func2]; /* { dg-warning ".\\-categ_instance_func2. not implemented by protocol" } */ + /* { dg-warning ".\\-categ_instance_func2. not found in protocol" "" { target *-*-* } 131 } */ + i += (size_t)[(id )self categ_instance_func2]; /* { dg-warning ".\\-categ_instance_func2. not found in protocol" } */ i += [(id)self categ_instance_func2]; return i + (size_t)[super instance_func0]; /* { dg-warning ".Object. may not respond to .\\-instance_func0." } */ } @@ -138,3 +139,7 @@ return [(id )super instance_func0]; } @end + +/* { dg-warning "Messages without a matching method signature" "" { target *-*-* } 0 } */ +/* { dg-warning "will be assumed to return .id. and accept" "" { target *-*-* } 0 } */ +/* { dg-warning ".\.\.\.. as arguments" "" { target *-*-* } 0 } */ diff --git a/gcc/testsuite/objc.dg/class-protocol-1.m b/gcc/testsuite/objc.dg/class-protocol-1.m new file mode 100644 index 00000000000..ffa2435f5c0 --- /dev/null +++ b/gcc/testsuite/objc.dg/class-protocol-1.m @@ -0,0 +1,441 @@ +/* Check Class types */ +/* Author: David Ayers */ +/* { dg-do compile } */ + +#include +#include + +@protocol MyProto1 ++(void)doItClass1; +-(void)doItInstance1; +@end + +@protocol MyProto2 ++(void)doItClass2; +-(void)doItInstance2; +@end + +@interface MyClass1 +{ + Class isa; +} +@end +@implementation MyClass1 ++(void)doItClass1{} +-(void)doItInstance1{} +@end + +@interface MyClass2 : MyClass1 +@end +@implementation MyClass2 ++(void)doItClass2{} +-(void)doItInstance2{} +@end + +@interface MyClass3 +{ + Class isa; +} +@end +@interface MyClass4 : MyClass3 +@end + +/*----------------------------------------*/ + +Class cls = 0; +Class clsP1 = 0; +Class clsP2 = 0; + +void +testSimple(void) +{ + [cls doItClass1]; + [cls doItInstance1]; + [cls doItClass2]; + [cls doItInstance2]; + + [clsP1 doItClass1]; + [clsP1 doItInstance1]; /* { dg-warning "instead of" } */ + [clsP1 doItClass2]; /* { dg-warning "not found in protocol" } */ + [clsP1 doItInstance2]; /* { dg-warning "not found in protocol" } */ + + [clsP2 doItClass1]; /* { dg-warning "not found in protocol" } */ + [clsP2 doItInstance1]; /* { dg-warning "not found in protocol" } */ + [clsP2 doItClass2]; + [clsP2 doItInstance2]; /* { dg-warning "instead of" } */ + + [MyClass1 doItClass1]; + [MyClass1 doItInstance1]; + [MyClass1 doItClass2]; /* { dg-warning "may not respond to" } */ + [MyClass1 doItInstance2]; /* { dg-warning "may not respond to" } */ + + [MyClass2 doItClass1]; + [MyClass2 doItInstance1]; + [MyClass2 doItClass2]; + [MyClass2 doItInstance2]; /* { dg-warning "may not respond to" } */ + + [MyClass3 doItClass1]; /* { dg-warning "may not respond to" } */ + [MyClass3 doItInstance1]; /* { dg-warning "may not respond to" } */ + + [MyClass4 doItClass1]; + [MyClass4 doItInstance1]; /* { dg-warning "may not respond to" } */ +} + +/*----------------------------------------*/ +/* Protocols declared by categories */ + +@protocol MyProto3 ++(void)doItClass3; +-(void)doItInstance3; +@end +@protocol MyProto4 ++(void)doItClass4; +-(void)doItInstance4; +@end + +@interface MyClass1 (Category1) +@end +@interface MyClass2 (Category2) +@end + +void +testCategory(void) +{ + [cls doItClass3]; + [cls doItInstance3]; + [cls doItClass4]; + [cls doItInstance4]; + + [MyClass1 doItClass3]; + [MyClass1 doItInstance3]; + [MyClass1 doItClass4]; /* { dg-warning "may not respond" } */ + [MyClass1 doItInstance4]; /* { dg-warning "may not respond" } */ + + [MyClass2 doItClass3]; + [MyClass2 doItInstance3]; + [MyClass2 doItClass4]; + [MyClass2 doItInstance4]; /* { dg-warning "may not respond" } */ + +} + +/*----------------------------------------*/ +/* Inherited protocols declared by categories */ + +@protocol MyProto5 ++(void)doItClass5; +-(void)doItInstance5; +@end + +@protocol MyProto6 ++(void)doItClass6; +-(void)doItInstance6; +@end + +@interface MyClass1 (Category3) +@end +@interface MyClass2 (Category4) +@end + +Class clsP5 = 0; +Class clsP6 = 0; + +void +testCategoryInherited(void) +{ + [cls doItClass5]; + [cls doItInstance5]; + [cls doItClass6]; + [cls doItInstance6]; + + [clsP5 doItClass1]; + [clsP5 doItInstance1]; /* { dg-warning "instead of" } */ + [clsP5 doItClass2]; /* { dg-warning "not found in protocol" } */ + [clsP5 doItInstance2]; /* { dg-warning "not found in protocol" } */ + + [clsP6 doItClass1]; /* { dg-warning "not found in protocol" } */ + [clsP6 doItInstance1]; /* { dg-warning "not found in protocol" } */ + [clsP6 doItClass2]; + [clsP6 doItInstance2]; /* { dg-warning "instead of" } */ + + + [MyClass1 doItClass5]; + [MyClass1 doItInstance5]; + [MyClass1 doItClass6]; /* { dg-warning "may not respond" } */ + [MyClass1 doItInstance6]; /* { dg-warning "may not respond" } */ + + [MyClass2 doItClass5]; + [MyClass2 doItInstance5]; + [MyClass2 doItClass6]; + [MyClass2 doItInstance6]; /* { dg-warning "may not respond" } */ + +} + +/*----------------------------------------*/ +/* Forward declared root protocols */ + +@protocol FwProto; + +@interface MyClass1 (Forward) +@end + +Class clsP7 = 0; + +void +testForwardeDeclared1(void) +{ + [cls doItClass7]; /* { dg-warning "no .\\+doItClass7. method found" } */ + [cls doItInstance7]; /* { dg-warning "no .\\+doItInstance7. method found" } */ + + [clsP7 doItClass7]; /* { dg-warning "not found in protocol" } */ + /* { dg-warning "no .\\+doItClass7. method found" "" { target *-*-* } 189 } */ + [clsP7 doItInstance7]; /* { dg-warning "not found in protocol" } */ + /* { dg-warning "no .\\+doItInstance7. method found" "" { target *-*-* } 191 } */ + + [MyClass1 doItClass7]; /* { dg-warning "may not respond" } */ + [MyClass1 doItInstance7]; /* { dg-warning "may not respond" } */ + + [MyClass2 doItClass7]; /* { dg-warning "may not respond" } */ + [MyClass2 doItInstance7]; /* { dg-warning "may not respond" } */ + +} + +@protocol FwProto ++(void)doItClass7; +-(void)doItInstance7; +@end + +void +testForwardeDeclared2(void) +{ + [cls doItClass7]; + [cls doItInstance7]; + + [clsP7 doItClass7]; + [clsP7 doItInstance7]; /* { dg-warning "instead of" } */ + + [MyClass1 doItClass7]; + [MyClass1 doItInstance7]; + + [MyClass2 doItClass7]; + [MyClass2 doItInstance7]; +} + +/*----------------------------------------*/ +/* Inherited non root protocols */ + +@protocol MyProto8 ++(void)doItClass8; +-(void)doItInstance8; +@end + +@protocol MyProto9 ++(void)doItClass9; +-(void)doItInstance9; +@end + +@interface MyClass1 (InheritedNonRoot) +@end + +Class clsP8 = 0; +Class clsP9 = 0; + +void +testInheritedNonRoot(void) +{ + [cls doItClass8]; + [cls doItInstance8]; + [cls doItClass9]; + [cls doItInstance9]; + + [clsP8 doItClass8]; + [clsP8 doItInstance8]; /* { dg-warning "instead of" } */ + [clsP8 doItClass9]; /* { dg-warning "not found in protocol" } */ + [clsP8 doItInstance9]; /* { dg-warning "not found in protocol" } */ + + [clsP9 doItClass8]; + [clsP9 doItInstance8]; /* { dg-warning "instead of" } */ + [clsP9 doItClass9]; + [clsP9 doItInstance9]; /* { dg-warning "instead of" } */ + + [MyClass1 doItClass8]; + [MyClass1 doItInstance8]; + [MyClass1 doItClass9]; + [MyClass1 doItInstance9]; + + [MyClass2 doItClass8]; + [MyClass2 doItInstance8]; + [MyClass2 doItClass9]; + [MyClass2 doItInstance9]; + +} + +/*----------------------------------------*/ +/* Prototype mismatch */ + +@protocol MyOtherProto1 ++(id)doItClass1; +-(id)doItInstance1; +@end +@interface MyOtherClass1 +@end + +Class oclsP1; + +void +testPrototypeMismatch(void) +{ + id tmp1 = [oclsP1 doItClass1]; + id tmp2 = [oclsP1 doItInstance1]; /* { dg-warning "instead of" } */ + + [clsP1 doItClass1]; + [clsP1 doItInstance1]; /* { dg-warning "instead of" } */ +} + +id obj = nil; +id objP1 = nil; +id objP2 = nil; +id objP5 = nil; +int num = 0; +void *ptr = 0; + +MyClass1 *mc1 = nil; + +void +testComptypes(void) +{ + { /* id , id */ + objP1 == objP2; /* { dg-warning "lacks a cast" } */ + objP2 == objP1; /* { dg-warning "lacks a cast" } */ + + objP1 == objP5; + objP5 == objP1; + } + { /* id , SomeClass * */ + mc1 == objP1; + objP1 == mc1; + + mc1 == objP2; /* { dg-warning "does not implement" } */ + objP2 == mc1; /* { dg-warning "does not implement" } */ + } + { /* id , id */ + obj == objP1; + objP1 == obj; + } + { /* id , Class */ + cls == objP1; /* { dg-warning "lacks a cast" } */ + objP1 == cls; /* { dg-warning "lacks a cast" } */ + } + { /* id , non-ObjC */ + num == objP1; /* { dg-warning "between pointer" } */ + objP1 == num; /* { dg-warning "between pointer" } */ + + ptr == objP1; + objP1 == ptr; + } + { /* Class , Class */ + clsP1 == clsP2; /* { dg-warning "lacks a cast" } */ + clsP2 == clsP1; /* { dg-warning "lacks a cast" } */ + + clsP1 == clsP5; + clsP5 == clsP1; + } + { /* Class , SomeClass * */ + mc1 == clsP1; /* { dg-warning "lacks a cast" } */ + clsP1 == mc1; /* { dg-warning "lacks a cast" } */ + } + { /* Class , id */ + obj == clsP1; + clsP1 == obj; + } + { /* Class , Class */ + cls == clsP1; + clsP1 == cls; + } + { /* Class , non-ObjC */ + num == clsP1; /* { dg-warning "between pointer" } */ + clsP1 == num; /* { dg-warning "between pointer" } */ + + ptr == clsP1; + clsP1 == ptr; + } + { /* Class , id */ + clsP1 == objP1; /* { dg-warning "lacks a cast" } */ + objP1 == clsP1; /* { dg-warning "lacks a cast" } */ + } + + { /* id , id */ + objP1 = objP2; /* { dg-warning "does not conform" } */ + objP2 = objP1; /* { dg-warning "does not conform" } */ + + objP1 = objP5; + objP5 = objP1; /* { dg-warning "does not conform" } */ + } + { /* id , SomeClass * */ + mc1 = objP1; /* { dg-warning "incompatible" } */ /* FIXME: should be "" */ + objP1 = mc1; + + mc1 = objP2; /* { dg-warning "incompatible" } */ /* FIXME: should be "does not implement" */ + objP2 = mc1; /* { dg-warning "does not implement" } */ + } + { /* id , id */ + obj = objP1; + objP1 = obj; + } + { /* id , Class */ + cls = objP1; /* { dg-warning "incompatible" } */ + objP1 = cls; /* { dg-warning "incompatible" } */ + } + { /* id , non-ObjC */ + num = objP1; /* { dg-warning "makes integer" } */ + objP1 = num; /* { dg-warning "makes pointer" } */ + + ptr = objP1; + objP1 = ptr; + } + { /* Class , Class */ + clsP1 = clsP2; /* { dg-warning "does not conform" } */ + clsP2 = clsP1; /* { dg-warning "does not conform" } */ + + clsP1 = clsP5; + clsP5 = clsP1; /* { dg-warning "does not conform" } */ + } + { /* Class , SomeClass * */ + /* These combinations should always elicit a warning. */ + mc1 = clsP1; /* { dg-warning "incompatible" } */ + clsP1 = mc1; /* { dg-warning "incompatible" } */ + + mc1 = clsP2; /* { dg-warning "incompatible" } */ + clsP2 = mc1; /* { dg-warning "incompatible" } */ + } + { /* Class , id */ + obj = clsP1; + clsP1 = obj; + } + { /* Class , Class */ + cls = clsP1; + clsP1 = cls; + } + { /* Class , non-ObjC */ + num = clsP1; /* { dg-warning "makes integer" } */ + clsP1 = num; /* { dg-warning "makes pointer" } */ + + ptr = clsP1; + clsP1 = ptr; + } + { /* Class , id */ + clsP1 = objP1; /* { dg-warning "incompatible" } */ + objP1 = clsP1; /* { dg-warning "incompatible" } */ + } +} + +int main () +{ + testSimple(); + testCategory(); + testCategoryInherited(); + return(0); +} + +/* { dg-warning "Messages without a matching method signature" "" { target *-*-* } 0 } */ +/* { dg-warning "will be assumed to return .id. and accept" "" { target *-*-* } 0 } */ +/* { dg-warning ".\.\.\.. as arguments" "" { target *-*-* } 0 } */ diff --git a/gcc/testsuite/objc.dg/desig-init-1.m b/gcc/testsuite/objc.dg/desig-init-1.m index cd56324f403..6ef710b51ff 100644 --- a/gcc/testsuite/objc.dg/desig-init-1.m +++ b/gcc/testsuite/objc.dg/desig-init-1.m @@ -4,7 +4,8 @@ /* { dg-options "-std=gnu99" } */ /* { dg-do run } */ -#include +#include +#include #include #include @@ -18,19 +19,20 @@ + (int) meth1 { return 45; } + (int) meth2 { return 21; } + (void) doTests { - int arr[6] = { + int arr[7] = { 0, [Cls meth1], [2 + 1] = 3, - [2 * 2 ... 5] = (size_t)[0 meth2], /* { dg-warning "invalid receiver type" } */ - /* { dg-warning "Messages without a matching method signature" "" { target *-*-* } 25 } */ - /* { dg-warning "will be assumed to return .id. and accept" "" { target *-*-* } 25 } */ - /* { dg-warning ".\.\.\.. as arguments" "" { target *-*-* } 25 } */ - [2] [Cls meth2] + [2 * 2 ... 5] = (size_t)[0 meth4], /* { dg-warning "invalid receiver type" } */ + /* { dg-warning "no .\\-meth4. method found" "" { target *-*-* } 26 } */ + [2] [Cls meth2], + /* Since invalid receivers are treated as 'id' for purposes of message + lookup, we _should_ find a meth2 to call below. */ + [6] = (int)[0 meth2] /* { dg-warning "invalid receiver type" } */ }; if (arr[0] != 0 || arr[1] != 45 || arr[2] != 21 || arr[3] != 3) - abort (); /* { dg-warning "implicit declaration" } */ + abort (); printf ("%s\n", [super name]); printf ("%d %d %d %d %d %d\n", arr[0], arr[1], arr[2], arr[3], arr[4], arr[5]); @@ -41,3 +43,7 @@ int main(void) { [Cls doTests]; return 0; } + +/* { dg-warning "Messages without a matching method signature" "" { target *-*-* } 0 } */ +/* { dg-warning "will be assumed to return .id. and accept" "" { target *-*-* } 0 } */ +/* { dg-warning ".\.\.\.. as arguments" "" { target *-*-* } 0 } */ diff --git a/gcc/testsuite/objc.dg/method-5.m b/gcc/testsuite/objc.dg/method-5.m index e2332ea8bd7..37677a1ccaa 100644 --- a/gcc/testsuite/objc.dg/method-5.m +++ b/gcc/testsuite/objc.dg/method-5.m @@ -9,10 +9,12 @@ typedef struct NotAClass { void foo(UnderSpecified *u, NotAClass *n) { [n nonexistent_method]; /* { dg-warning "invalid receiver type" } */ - /* { dg-warning "Messages without a matching method signature" "" { target *-*-* } 11 } */ - /* { dg-warning "will be assumed to return .id. and accept" "" { target *-*-* } 11 } */ - /* { dg-warning ".\.\.\.. as arguments" "" { target *-*-* } 11 } */ + /* { dg-warning "no .\\-nonexistent_method. method found" "" { target *-*-* } 11 } */ [NotAClass nonexistent_method]; /* { dg-error ".NotAClass. is not an Objective\\-C class name or alias" } */ [u nonexistent_method]; /* { dg-warning ".UnderSpecified. may not respond to .\\-nonexistent_method." } */ [UnderSpecified nonexistent_method]; /* { dg-warning ".UnderSpecified. may not respond to .\\+nonexistent_method." } */ } + +/* { dg-warning "Messages without a matching method signature" "" { target *-*-* } 0 } */ +/* { dg-warning "will be assumed to return .id. and accept" "" { target *-*-* } 0 } */ +/* { dg-warning ".\.\.\.. as arguments" "" { target *-*-* } 0 } */ diff --git a/gcc/testsuite/objc.dg/method-6.m b/gcc/testsuite/objc.dg/method-6.m index 8bed64bee1a..a4c1323fac8 100644 --- a/gcc/testsuite/objc.dg/method-6.m +++ b/gcc/testsuite/objc.dg/method-6.m @@ -22,7 +22,7 @@ void foo(void) { /* { dg-warning "using .\\-\\(unsigned( int)?\\)port." "" { target *-*-* } 9 } */ /* { dg-warning "also found .\\+\\(Protocol \\*\\)port." "" { target *-*-* } 14 } */ - [receiver starboard]; /* { dg-warning ".Class. may not respond to .\\+starboard." } */ + [receiver starboard]; /* { dg-warning "no .\\+starboard. method found" } */ /* { dg-warning "Messages without a matching method signature" "" { target *-*-* } 25 } */ /* { dg-warning "will be assumed to return .id. and accept" "" { target *-*-* } 25 } */ /* { dg-warning ".\.\.\.. as arguments" "" { target *-*-* } 25 } */ diff --git a/gcc/testsuite/objc.dg/proto-hier-1.m b/gcc/testsuite/objc.dg/proto-hier-1.m index 154e6b62d73..99dcbc56773 100644 --- a/gcc/testsuite/objc.dg/proto-hier-1.m +++ b/gcc/testsuite/objc.dg/proto-hier-1.m @@ -48,9 +48,11 @@ int foo(void) { id stupidVar; [stupidVar boo]; [stupidVar foo]; - [stupidVar anotherMsg]; /* { dg-warning ".\-anotherMsg. not implemented by protocol" } */ - /* { dg-warning "Messages without a matching method signature" "" { target *-*-* } 51 } */ - /* { dg-warning "will be assumed to return .id. and accept" "" { target *-*-* } 51 } */ - /* { dg-warning ".\.\.\.. as arguments" "" { target *-*-* } 51 } */ + [stupidVar anotherMsg]; /* { dg-warning ".\\-anotherMsg. not found in protocol" } */ + /* { dg-warning "no .\\-anotherMsg. method found" "" { target *-*-* } 51 } */ return 0; } + +/* { dg-warning "Messages without a matching method signature" "" { target *-*-* } 0 } */ +/* { dg-warning "will be assumed to return .id. and accept" "" { target *-*-* } 0 } */ +/* { dg-warning ".\.\.\.. as arguments" "" { target *-*-* } 0 } */ diff --git a/gcc/testsuite/objc.dg/proto-hier-2.m b/gcc/testsuite/objc.dg/proto-hier-2.m index 453de89e5bf..819cf4a5089 100644 --- a/gcc/testsuite/objc.dg/proto-hier-2.m +++ b/gcc/testsuite/objc.dg/proto-hier-2.m @@ -41,7 +41,7 @@ typedef struct id one = [self anotherDataSource]; i = i - 1; - // Do not issue warning about my_method not implemented by protocol + // Do not issue warning about my_method not found in protocol return [(one ? [self mainDataSource] : one) my_method:i]; } diff --git a/gcc/testsuite/objc.dg/proto-lossage-1.m b/gcc/testsuite/objc.dg/proto-lossage-1.m index 1186f8fd9ff..2f7eb986140 100644 --- a/gcc/testsuite/objc.dg/proto-lossage-1.m +++ b/gcc/testsuite/objc.dg/proto-lossage-1.m @@ -35,14 +35,10 @@ typedef struct objc_object { struct objc_class *class_pointer; } *id; return (id )plate1; /* { dg-bogus "does not conform" } */ } - (int) getValue { - int i = [plate1 someValue]; /* { dg-warning ".\\-someValue. not implemented by protocol\\(s\\)" } */ - /* { dg-warning "\\(Messages without a matching method signature" "" { target *-*-* } 38 } */ - /* { dg-warning "will be assumed to return .id. and accept" "" { target *-*-* } 38 } */ - /* { dg-warning ".\.\.\.. as arguments\.\\)" "" { target *-*-* } 38 } */ - /* { dg-warning "initialization makes integer from pointer without a cast" "" { target *-*-* } 38 } */ + int i = [plate1 someValue]; /* { dg-warning ".\\-someValue. not found in protocol\\(s\\)" } */ - int j = [(id )plate1 someValue]; /* { dg-bogus "not implemented by protocol" } */ - int k = [(id)plate1 someValue]; /* { dg-bogus "not implemented by protocol" } */ + int j = [(id )plate1 someValue]; /* { dg-bogus "not found in protocol" } */ + int k = [(id)plate1 someValue]; /* { dg-bogus "not found in protocol" } */ return i + j + k; } @end diff --git a/gcc/testsuite/objc.dg/proto-lossage-4.m b/gcc/testsuite/objc.dg/proto-lossage-4.m index 447e67e12e6..8df169da4ee 100644 --- a/gcc/testsuite/objc.dg/proto-lossage-4.m +++ b/gcc/testsuite/objc.dg/proto-lossage-4.m @@ -19,23 +19,20 @@ long foo(void) { Obj *objrcvr; Obj *objrcvr2; - receiver += [receiver someValue]; /* { dg-warning "invalid receiver type .long int." } */ -/* { dg-warning "Messages without a matching method signature" "" { target *-*-* } 22 } */ -/* { dg-warning "will be assumed to return .id. and accept" "" { target *-*-* } 22 } */ -/* { dg-warning ".\.\.\.. as arguments" "" { target *-*-* } 22 } */ -/* { dg-warning "assignment makes integer from pointer without a cast" "" { target *-*-* } 22 } */ + /* NB: Since 'receiver' is an invalid ObjC message receiver, the compiler + should warn but then search for methods as if we were messaging 'id'. */ + receiver += [receiver someValue]; /* { dg-warning "invalid receiver type .long int." } */ receiver += [receiver anotherValue]; /* { dg-warning "invalid receiver type .long int." } */ -/* { dg-warning "assignment makes integer from pointer without a cast" "" { target *-*-* } 28 } */ - + receiver += [(Obj *)receiver someValue]; /* { dg-warning ".Obj. may not respond to .\\-someValue." } */ -/* { dg-warning "assignment makes integer from pointer without a cast" "" { target *-*-* } 31 } */ +/* { dg-warning "assignment makes integer from pointer without a cast" "" { target *-*-* } 28 } */ receiver += [(Obj *)receiver anotherValue]; receiver += [(Obj *)receiver someValue]; receiver += [(Obj *)receiver anotherValue]; receiver += [objrcvr someValue]; /* { dg-warning ".Obj. may not respond to .\\-someValue." } */ -/* { dg-warning "assignment makes integer from pointer without a cast" "" { target *-*-* } 37 } */ +/* { dg-warning "assignment makes integer from pointer without a cast" "" { target *-*-* } 34 } */ receiver += [objrcvr anotherValue]; receiver += [(Obj *)objrcvr someValue]; @@ -43,9 +40,13 @@ long foo(void) { receiver += [objrcvr2 someValue]; receiver += [objrcvr2 anotherValue]; receiver += [(Obj *)objrcvr2 someValue]; /* { dg-warning ".Obj. may not respond to .\\-someValue." } */ -/* { dg-warning "assignment makes integer from pointer without a cast" "" { target *-*-* } 45 } */ +/* { dg-warning "assignment makes integer from pointer without a cast" "" { target *-*-* } 42 } */ receiver += [(Obj *)objrcvr2 anotherValue]; return receiver; } + +/* { dg-warning "Messages without a matching method signature" "" { target *-*-* } 0 } */ +/* { dg-warning "will be assumed to return .id. and accept" "" { target *-*-* } 0 } */ +/* { dg-warning ".\.\.\.. as arguments" "" { target *-*-* } 0 } */