diff options
author | Nicola Pero <nicola.pero@meta-innovation.com> | 2010-12-10 09:38:52 +0000 |
---|---|---|
committer | Nicola Pero <nicola@gcc.gnu.org> | 2010-12-10 09:38:52 +0000 |
commit | ec3e9f826773a7aa4cfc135b4cc9e2de222bc137 (patch) | |
tree | 1455b598d50eb7e482cbb74cb6884dc439905ab7 | |
parent | aff7f4c416f03bcadf563a3f73896ddabd8da844 (diff) | |
download | gcc-ec3e9f826773a7aa4cfc135b4cc9e2de222bc137.zip gcc-ec3e9f826773a7aa4cfc135b4cc9e2de222bc137.tar.gz gcc-ec3e9f826773a7aa4cfc135b4cc9e2de222bc137.tar.bz2 |
In gcc/: 2010-12-10 Nicola Pero <nicola.pero@meta-innovation.com>
In gcc/:
2010-12-10 Nicola Pero <nicola.pero@meta-innovation.com>
* c-parser.c (c_parser_objc_class_definition): Recognize
Objective-C 2.0 class extensions.
In gcc/cp/:
2010-12-10 Nicola Pero <nicola.pero@meta-innovation.com>
* parser.c (cp_parser_objc_superclass_or_category): Recognize
Objective-C 2.0 class extensions. Added iface_p and
is_class_extension arguments.
(cp_parser_objc_class_interface): Updated call to
cp_parser_objc_superclass_or_category.
(cp_parser_objc_class_implementation): Same change.
In gcc/objc/:
2010-12-10 Nicola Pero <nicola.pero@meta-innovation.com>
* objc-act.c (objc_in_class_extension): New.
(objc_start_category_interface): If -fobjc-std=objc1
was specified, produce an error if a class extension is used.
(objc_finish_interface): Reset objc_in_class_extension to false.
(objc_add_property_declaration): Allow a class extension to extend
readonly properties in the main @interface to be readwrite.
(start_class): Added code to deal with class extensions. In that
case, return the existing interface after adding any additional
protocols to it and setting objc_in_class_extension to true.
(continue_class): If in a class extension, do not generate the
instance variable template.
In gcc/testsuite/:
2010-12-10 Nicola Pero <nicola.pero@meta-innovation.com>
* objc.dg/class-extension-1.m: New.
* objc.dg/class-extension-2.m: New.
* objc.dg/class-extension-3.m: New.
* objc.dg/property/at-property-26.m: New.
* objc.dg/property/at-property-27.m: New.
* objc.dg/property/at-property-28.m: New.
* obj-c++.dg/class-extension-1.mm: New.
* obj-c++.dg/class-extension-2.mm: New.
* obj-c++.dg/class-extension-3.mm: New.
* obj-c++.dg/property/at-property-26.mm: New.
* obj-c++.dg/property/at-property-27.mm: New.
* obj-c++.dg/property/at-property-28.mm: New.
From-SVN: r167680
-rw-r--r-- | gcc/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/c-parser.c | 24 | ||||
-rw-r--r-- | gcc/cp/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/cp/parser.c | 29 | ||||
-rw-r--r-- | gcc/objc/ChangeLog | 14 | ||||
-rw-r--r-- | gcc/objc/objc-act.c | 206 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 15 | ||||
-rw-r--r-- | gcc/testsuite/obj-c++.dg/class-extension-1.mm | 30 | ||||
-rw-r--r-- | gcc/testsuite/obj-c++.dg/class-extension-2.mm | 56 | ||||
-rw-r--r-- | gcc/testsuite/obj-c++.dg/class-extension-3.mm | 26 | ||||
-rw-r--r-- | gcc/testsuite/obj-c++.dg/property/at-property-26.mm | 85 | ||||
-rw-r--r-- | gcc/testsuite/obj-c++.dg/property/at-property-27.mm | 66 | ||||
-rw-r--r-- | gcc/testsuite/obj-c++.dg/property/at-property-28.mm | 29 | ||||
-rw-r--r-- | gcc/testsuite/objc.dg/class-extension-1.m | 30 | ||||
-rw-r--r-- | gcc/testsuite/objc.dg/class-extension-2.m | 56 | ||||
-rw-r--r-- | gcc/testsuite/objc.dg/class-extension-3.m | 26 | ||||
-rw-r--r-- | gcc/testsuite/objc.dg/property/at-property-26.m | 85 | ||||
-rw-r--r-- | gcc/testsuite/objc.dg/property/at-property-27.m | 66 | ||||
-rw-r--r-- | gcc/testsuite/objc.dg/property/at-property-28.m | 29 |
19 files changed, 811 insertions, 75 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2dd440c..66ece2c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2010-12-10 Nicola Pero <nicola.pero@meta-innovation.com> + + * c-parser.c (c_parser_objc_class_definition): Recognize + Objective-C 2.0 class extensions. + 2010-12-10 Iain Sandoe <iains@gcc.gnu.org> * config/darwin.c: Remove c-tree.h and c-lang.h diff --git a/gcc/c-parser.c b/gcc/c-parser.c index 6faaacf..8238506 100644 --- a/gcc/c-parser.c +++ b/gcc/c-parser.c @@ -6743,6 +6743,8 @@ c_parser_expr_list (c_parser *parser, bool convert_p, bool fold_p, objc-class-instance-variables[opt] @interface identifier ( identifier ) objc-protocol-refs[opt] objc-methodprotolist @end + @interface identifier ( ) objc-protocol-refs[opt] + objc-methodprotolist @end @implementation identifier ( identifier ) objc-superclass: @@ -6777,17 +6779,29 @@ c_parser_objc_class_definition (c_parser *parser, tree attributes) c_parser_consume_token (parser); if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)) { + /* We have a category or class extension. */ tree id2; tree proto = NULL_TREE; c_parser_consume_token (parser); if (c_parser_next_token_is_not (parser, CPP_NAME)) { - c_parser_error (parser, "expected identifier"); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); - return; + if (iface_p && c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) + { + /* We have a class extension. */ + id2 = NULL_TREE; + } + else + { + c_parser_error (parser, "expected identifier or %<)%>"); + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); + return; + } + } + else + { + id2 = c_parser_peek_token (parser)->value; + c_parser_consume_token (parser); } - id2 = c_parser_peek_token (parser)->value; - c_parser_consume_token (parser); c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); if (!iface_p) { diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 0ebc422..a78f82c 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,12 @@ +2010-12-10 Nicola Pero <nicola.pero@meta-innovation.com> + + * parser.c (cp_parser_objc_superclass_or_category): Recognize + Objective-C 2.0 class extensions. Added iface_p and + is_class_extension arguments. + (cp_parser_objc_class_interface): Updated call to + cp_parser_objc_superclass_or_category. + (cp_parser_objc_class_implementation): Same change. + 2010-12-09 Nathan Froyd <froydnj@codesourcery.com> * call.c (print_conversion_rejection): Indent messages two spaces. diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index ab533f4..4c8ca72 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -22435,12 +22435,15 @@ cp_parser_objc_protocol_declaration (cp_parser* parser, tree attributes) /* Parse an Objective-C superclass or category. */ static void -cp_parser_objc_superclass_or_category (cp_parser *parser, tree *super, - tree *categ) +cp_parser_objc_superclass_or_category (cp_parser *parser, + bool iface_p, + tree *super, + tree *categ, bool *is_class_extension) { cp_token *next = cp_lexer_peek_token (parser->lexer); *super = *categ = NULL_TREE; + *is_class_extension = false; if (next->type == CPP_COLON) { cp_lexer_consume_token (parser->lexer); /* Eat ':'. */ @@ -22449,7 +22452,17 @@ cp_parser_objc_superclass_or_category (cp_parser *parser, tree *super, else if (next->type == CPP_OPEN_PAREN) { cp_lexer_consume_token (parser->lexer); /* Eat '('. */ - *categ = cp_parser_identifier (parser); + + /* If there is no category name, and this is an @interface, we + have a class extension. */ + if (iface_p && cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN)) + { + *categ = NULL_TREE; + *is_class_extension = true; + } + else + *categ = cp_parser_identifier (parser); + cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); } } @@ -22460,6 +22473,7 @@ static void cp_parser_objc_class_interface (cp_parser* parser, tree attributes) { tree name, super, categ, protos; + bool is_class_extension; cp_lexer_consume_token (parser->lexer); /* Eat '@interface'. */ name = cp_parser_identifier (parser); @@ -22472,11 +22486,12 @@ cp_parser_objc_class_interface (cp_parser* parser, tree attributes) */ return; } - cp_parser_objc_superclass_or_category (parser, &super, &categ); + cp_parser_objc_superclass_or_category (parser, true, &super, &categ, + &is_class_extension); protos = cp_parser_objc_protocol_refs_opt (parser); /* We have either a class or a category on our hands. */ - if (categ) + if (categ || is_class_extension) objc_start_category_interface (name, categ, protos, attributes); else { @@ -22495,6 +22510,7 @@ static void cp_parser_objc_class_implementation (cp_parser* parser) { tree name, super, categ; + bool is_class_extension; cp_lexer_consume_token (parser->lexer); /* Eat '@implementation'. */ name = cp_parser_identifier (parser); @@ -22508,7 +22524,8 @@ cp_parser_objc_class_implementation (cp_parser* parser) */ return; } - cp_parser_objc_superclass_or_category (parser, &super, &categ); + cp_parser_objc_superclass_or_category (parser, false, &super, &categ, + &is_class_extension); /* We have either a class or a category on our hands. */ if (categ) diff --git a/gcc/objc/ChangeLog b/gcc/objc/ChangeLog index 09cc1f6..f079cb5 100644 --- a/gcc/objc/ChangeLog +++ b/gcc/objc/ChangeLog @@ -1,3 +1,17 @@ +2010-12-10 Nicola Pero <nicola.pero@meta-innovation.com> + + * objc-act.c (objc_in_class_extension): New. + (objc_start_category_interface): If -fobjc-std=objc1 + was specified, produce an error if a class extension is used. + (objc_finish_interface): Reset objc_in_class_extension to false. + (objc_add_property_declaration): Allow a class extension to extend + readonly properties in the main @interface to be readwrite. + (start_class): Added code to deal with class extensions. In that + case, return the existing interface after adding any additional + protocols to it and setting objc_in_class_extension to true. + (continue_class): If in a class extension, do not generate the + instance variable template. + 2010-12-08 Nicola Pero <nicola.pero@meta-innovation.com> * objc-act.c (objc_build_throw_stmt): Check that the argument of diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c index 1b815df..131ce55 100644 --- a/gcc/objc/objc-act.c +++ b/gcc/objc/objc-act.c @@ -402,6 +402,12 @@ static bool objc_method_optional_flag = false; static int objc_collecting_ivars = 0; +/* Flag that is set to 'true' while we are processing a class + extension. Since a class extension just "reopens" the main + @interface, this can be used to determine if we are in the main + @interface, or in a class extension. */ +static bool objc_in_class_extension = false; + #define BUFSIZE 1024 static char *errbuf; /* Buffer for error diagnostics */ @@ -748,6 +754,11 @@ objc_start_category_interface (tree klass, tree categ, "category attributes are not available in this version" " of the compiler, (ignored)"); } + if (categ == NULL_TREE) + { + if (flag_objc1_only) + error_at (input_location, "class extensions are not available in Objective-C 1.0"); + } objc_interface_context = start_class (CATEGORY_INTERFACE_TYPE, klass, categ, protos, NULL_TREE); objc_ivar_chain @@ -778,6 +789,7 @@ objc_finish_interface (void) finish_class (objc_interface_context); objc_interface_context = NULL_TREE; objc_method_optional_flag = false; + objc_in_class_extension = false; } void @@ -952,6 +964,7 @@ objc_add_property_declaration (location_t location, tree decl, is readwrite). */ bool property_readonly = false; objc_property_assign_semantics property_assign_semantics = OBJC_PROPERTY_ASSIGN; + bool property_extension_in_class_extension = false; if (flag_objc1_only) error_at (input_location, "%<@property%> is not available in Objective-C 1.0"); @@ -1125,60 +1138,80 @@ objc_add_property_declaration (location_t location, tree decl, /* Check for duplicate property declarations. We first check the immediate context for a property with the same name. Any such - declarations are an error. */ + declarations are an error, unless this is a class extension and + we are extending a property from readonly to readwrite. */ for (x = CLASS_PROPERTY_DECL (objc_interface_context); x; x = TREE_CHAIN (x)) { if (PROPERTY_NAME (x) == DECL_NAME (decl)) { - location_t original_location = DECL_SOURCE_LOCATION (x); - - error_at (location, "redeclaration of property %qD", decl); - - if (original_location != UNKNOWN_LOCATION) - inform (original_location, "originally specified here"); - return; - } + if (objc_in_class_extension + && property_readonly == 0 + && PROPERTY_READONLY (x) == 1) + { + /* This is a class extension, and we are extending an + existing readonly property to a readwrite one. + That's fine. :-) */ + property_extension_in_class_extension = true; + break; + } + else + { + location_t original_location = DECL_SOURCE_LOCATION (x); + + error_at (location, "redeclaration of property %qD", decl); + + if (original_location != UNKNOWN_LOCATION) + inform (original_location, "originally specified here"); + return; + } + } } - /* We now need to check for existing property declarations (in the - superclass, other categories or protocols) and check that the new - declaration is not in conflict with existing ones. */ + /* If x is not NULL_TREE, we must be in a class extension and we're + extending a readonly property. In that case, no point in + searching for another declaration. */ + if (x == NULL_TREE) + { + /* We now need to check for existing property declarations (in + the superclass, other categories or protocols) and check that + the new declaration is not in conflict with existing + ones. */ - /* Search for a previous, existing declaration of a property with - the same name in superclasses, protocols etc. If one is found, - it will be in the 'x' variable. */ - x = NULL_TREE; + /* Search for a previous, existing declaration of a property + with the same name in superclasses, protocols etc. If one is + found, it will be in the 'x' variable. */ - /* Note that, for simplicity, the following may search again the - local context. That's Ok as nothing will be found (else we'd - have thrown an error above); it's only a little inefficient, but - the code is simpler. */ - switch (TREE_CODE (objc_interface_context)) - { - case CLASS_INTERFACE_TYPE: - /* Look up the property in the current @interface (which will - find nothing), then its protocols and categories and - superclasses. */ - x = lookup_property (objc_interface_context, DECL_NAME (decl)); - break; - case CATEGORY_INTERFACE_TYPE: - /* Look up the property in the main @interface, then protocols - and categories (one of them is ours, and will find nothing) - and superclasses. */ - x = lookup_property (lookup_interface (CLASS_NAME (objc_interface_context)), - DECL_NAME (decl)); - break; - case PROTOCOL_INTERFACE_TYPE: - /* Looks up the property in any protocols attached to the - current protocol. */ - if (PROTOCOL_LIST (objc_interface_context)) + /* Note that, for simplicity, the following may search again the + local context. That's Ok as nothing will be found (else we'd + have thrown an error above); it's only a little inefficient, + but the code is simpler. */ + switch (TREE_CODE (objc_interface_context)) { - x = lookup_property_in_protocol_list (PROTOCOL_LIST (objc_interface_context), - DECL_NAME (decl)); + case CLASS_INTERFACE_TYPE: + /* Look up the property in the current @interface (which + will find nothing), then its protocols and categories and + superclasses. */ + x = lookup_property (objc_interface_context, DECL_NAME (decl)); + break; + case CATEGORY_INTERFACE_TYPE: + /* Look up the property in the main @interface, then + protocols and categories (one of them is ours, and will + find nothing) and superclasses. */ + x = lookup_property (lookup_interface (CLASS_NAME (objc_interface_context)), + DECL_NAME (decl)); + break; + case PROTOCOL_INTERFACE_TYPE: + /* Looks up the property in any protocols attached to the + current protocol. */ + if (PROTOCOL_LIST (objc_interface_context)) + { + x = lookup_property_in_protocol_list (PROTOCOL_LIST (objc_interface_context), + DECL_NAME (decl)); + } + break; + default: + gcc_unreachable (); } - break; - default: - gcc_unreachable (); } if (x != NULL_TREE) @@ -1278,6 +1311,17 @@ objc_add_property_declaration (location_t location, tree decl, inform (original_location, "originally specified here"); return; } + + /* If we are in a class extension and we're extending a readonly + property in the main @interface, we'll just update the + existing property with the readwrite flag and potentially the + new setter name. */ + if (property_extension_in_class_extension) + { + PROPERTY_READONLY (x) = 0; + PROPERTY_SETTER_NAME (x) = parsed_property_setter_ident; + return; + } } /* Create a PROPERTY_DECL node. */ @@ -9417,21 +9461,24 @@ check_protocols (tree proto_list, const char *type, tree name) } } -/* Make sure that the class CLASS_NAME is defined - CODE says which kind of thing CLASS_NAME ought to be. - It can be CLASS_INTERFACE_TYPE, CLASS_IMPLEMENTATION_TYPE, - CATEGORY_INTERFACE_TYPE, or CATEGORY_IMPLEMENTATION_TYPE. */ - +/* Make sure that the class CLASS_NAME is defined CODE says which kind + of thing CLASS_NAME ought to be. It can be CLASS_INTERFACE_TYPE, + CLASS_IMPLEMENTATION_TYPE, CATEGORY_INTERFACE_TYPE, or + CATEGORY_IMPLEMENTATION_TYPE. For a CATEGORY_INTERFACE_TYPE, + SUPER_NAME is the name of the category. For a class extension, + CODE is CATEGORY_INTERFACE_TYPE and SUPER_NAME is NULL_TREE. */ static tree start_class (enum tree_code code, tree class_name, tree super_name, tree protocol_list, tree attributes) { - tree klass, decl; + tree klass = NULL_TREE; + tree decl; #ifdef OBJCPLUS - if (current_namespace != global_namespace) { - error ("Objective-C declarations may only appear in global scope"); - } + if (current_namespace != global_namespace) + { + error ("Objective-C declarations may only appear in global scope"); + } #endif /* OBJCPLUS */ if (objc_implementation_context) @@ -9442,8 +9489,14 @@ start_class (enum tree_code code, tree class_name, tree super_name, objc_implementation_context = NULL_TREE; } - klass = make_node (code); - TYPE_LANG_SLOT_1 (klass) = make_tree_vec (CLASS_LANG_SLOT_ELTS); + /* If this is a class extension, we'll be "reopening" the existing + CLASS_INTERFACE_TYPE, so in that case there is no need to create + a new node. */ + if (code != CATEGORY_INTERFACE_TYPE || super_name != NULL_TREE) + { + klass = make_node (code); + TYPE_LANG_SLOT_1 (klass) = make_tree_vec (CLASS_LANG_SLOT_ELTS); + } /* Check for existence of the super class, if one was specified. Note that we must have seen an @interface, not just a @class. If we @@ -9473,9 +9526,12 @@ start_class (enum tree_code code, tree class_name, tree super_name, } } - CLASS_NAME (klass) = class_name; - CLASS_SUPER_NAME (klass) = super_name; - CLASS_CLS_METHODS (klass) = NULL_TREE; + if (code != CATEGORY_INTERFACE_TYPE || super_name != NULL_TREE) + { + CLASS_NAME (klass) = class_name; + CLASS_SUPER_NAME (klass) = super_name; + CLASS_CLS_METHODS (klass) = NULL_TREE; + } if (! objc_is_class_name (class_name) && (decl = lookup_name (class_name))) @@ -9592,15 +9648,35 @@ start_class (enum tree_code code, tree class_name, tree super_name, if (TREE_DEPRECATED (class_category_is_assoc_with)) warning (OPT_Wdeprecated_declarations, "class %qE is deprecated", class_name); - add_category (class_category_is_assoc_with, klass); - } - if (protocol_list) - CLASS_PROTOCOL_LIST (klass) - = lookup_and_install_protocols (protocol_list); + if (super_name == NULL_TREE) + { + /* This is a class extension. Get the original + interface, and continue working on it. */ + objc_in_class_extension = true; + klass = class_category_is_assoc_with; + + if (protocol_list) + { + /* Append protocols to the original protocol + list. */ + CLASS_PROTOCOL_LIST (klass) + = chainon (CLASS_PROTOCOL_LIST (klass), + lookup_and_install_protocols (protocol_list)); + } + } + else + { + add_category (class_category_is_assoc_with, klass); + + if (protocol_list) + CLASS_PROTOCOL_LIST (klass) + = lookup_and_install_protocols (protocol_list); + } + } } break; - + case CATEGORY_IMPLEMENTATION_TYPE: /* Reset for multiple classes per file. */ method_slot = 0; @@ -9673,6 +9749,8 @@ continue_class (tree klass) } case CLASS_INTERFACE_TYPE: { + if (objc_in_class_extension) + return NULL_TREE; #ifdef OBJCPLUS push_lang_context (lang_name_c); #endif /* OBJCPLUS */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 2ccdde3..afba479 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,18 @@ +2010-12-10 Nicola Pero <nicola.pero@meta-innovation.com> + + * objc.dg/class-extension-1.m: New. + * objc.dg/class-extension-2.m: New. + * objc.dg/class-extension-3.m: New. + * objc.dg/property/at-property-26.m: New. + * objc.dg/property/at-property-27.m: New. + * objc.dg/property/at-property-28.m: New. + * obj-c++.dg/class-extension-1.mm: New. + * obj-c++.dg/class-extension-2.mm: New. + * obj-c++.dg/class-extension-3.mm: New. + * obj-c++.dg/property/at-property-26.mm: New. + * obj-c++.dg/property/at-property-27.mm: New. + * obj-c++.dg/property/at-property-28.mm: New. + 2010-12-09 John David Anglin <dave.anglin@nrc-cnrc.gc.ca> PR target/46057 diff --git a/gcc/testsuite/obj-c++.dg/class-extension-1.mm b/gcc/testsuite/obj-c++.dg/class-extension-1.mm new file mode 100644 index 0000000..eab59c4 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/class-extension-1.mm @@ -0,0 +1,30 @@ +/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, December 2010. */ +/* { dg-do compile } */ + +/* This test tests the basic of class extensions. */ + +#include <objc/objc.h> + +@interface MyObject +{ + Class isa; +} +- (int) test; +@end + +@interface MyObject () +- (int) test2; +- (int) test3; +@end + +@implementation MyObject +- (int) test +{ + return 20; +} +- (int) test2 +{ + return 20; +} +@end /* { dg-warning "incomplete implementation of class .MyObject." } */ + /* { dg-warning "method definition for .-test3. not found" "" { target *-*-* } 29 } */ diff --git a/gcc/testsuite/obj-c++.dg/class-extension-2.mm b/gcc/testsuite/obj-c++.dg/class-extension-2.mm new file mode 100644 index 0000000..79b126f --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/class-extension-2.mm @@ -0,0 +1,56 @@ +/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, December 2010. */ +/* { dg-do compile } */ + +/* This test tests class extensions and protocols. */ + +#include <objc/objc.h> + +/* First, a simple test where a plain class has a protocol attached to + it in a class extension. */ +@interface MyObject +{ + Class isa; +} +@end + +@protocol MyProtocol +- (void) test; +@end + +@interface MyObject () <MyProtocol> +@end + +@implementation MyObject +@end /* { dg-warning "incomplete implementation of class .MyObject." } */ + /* { dg-warning "method definition for .-test. not found" "" { target *-*-* } 24 } */ + /* { dg-warning "class .MyObject. does not fully implement the .MyProtocol. protocol" "" { target *-*-* } 24 } */ + + + +/* Second, a more interesting test where protocols are added from the + main class and from two different class extensions. */ +@interface MyObject2 : MyObject <MyProtocol> +@end + +@protocol MyProtocol2 +- (void) test2; +@end + +@protocol MyProtocol3 +- (void) test3; +@end + +@interface MyObject2 () <MyProtocol2> +@end + +@interface MyObject2 () <MyProtocol3> +@end + +@implementation MyObject2 +@end /* { dg-warning "incomplete implementation of class .MyObject2." } */ + /* { dg-warning "method definition for .-test. not found" "" { target *-*-* } 50 } */ + /* { dg-warning "class .MyObject2. does not fully implement the .MyProtocol. protocol" "" { target *-*-* } 50 } */ + /* { dg-warning "method definition for .-test2. not found" "" { target *-*-* } 50 } */ + /* { dg-warning "class .MyObject2. does not fully implement the .MyProtocol2. protocol" "" { target *-*-* } 50 } */ + /* { dg-warning "method definition for .-test3. not found" "" { target *-*-* } 50 } */ + /* { dg-warning "class .MyObject2. does not fully implement the .MyProtocol3. protocol" "" { target *-*-* } 50 } */ diff --git a/gcc/testsuite/obj-c++.dg/class-extension-3.mm b/gcc/testsuite/obj-c++.dg/class-extension-3.mm new file mode 100644 index 0000000..8feb5c9 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/class-extension-3.mm @@ -0,0 +1,26 @@ +/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, December 2010. */ +/* { dg-do compile } */ + +/* This test tests warnings on class extensions. */ + +#include <objc/objc.h> + +@interface MyObject +{ + Class isa; + int count; +} +- (int) test; +@property int count; /* { dg-warning "originally specified here" } */ +@end + +@interface MyObject () +- (void) test; /* { dg-error "duplicate declaration of method .-test." } */ +@end + +@interface MyObject () +@end + +@interface MyObject () +@property int count; /* { dg-error "redeclaration of property .count." } */ +@end diff --git a/gcc/testsuite/obj-c++.dg/property/at-property-26.mm b/gcc/testsuite/obj-c++.dg/property/at-property-26.mm new file mode 100644 index 0000000..c45757e --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/property/at-property-26.mm @@ -0,0 +1,85 @@ +/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, December 2010. */ +/* { dg-do run } */ +/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */ + +/* Test @properties in class extensions. */ + +#include <stdlib.h> +#include <objc/objc.h> +#include <objc/runtime.h> + +@interface MyRootClass +{ + Class isa; +} ++ (id) initialize; ++ (id) alloc; +- (id) init; +@end + +@implementation MyRootClass ++ (id) initialize { return self; } ++ (id) alloc { return class_createInstance (self, 0); } +- (id) init { return self; } +@end + +@protocol count4 +/* Use a different getters/setters, so that the only way to compile + object.countX is to find the actual @property. */ +@property (getter=number4, setter=setNumber4:) int count4; +@end + +@interface MySubClass : MyRootClass +{ + int count1; + int count2; + int count3; + int count4; +} +@property (getter=number1, setter=setNumber1:) int count1; +@end + +@interface MySubClass () +@property (getter=number2, setter=setNumber2:) int count2; +@end + +@interface MySubClass () <count4> +@property (getter=number3, setter=setNumber3:) int count3; +@end + +@implementation MySubClass +@synthesize count1; +@synthesize count2; +- (int) number3 +{ + return count3; +} +- (void) setNumber3: (int)value +{ + count3 = value; +} +@synthesize count4; +@end + +int main (void) +{ + MySubClass *object = [[MySubClass alloc] init]; + + object.count1 = 20; + if (object.count1 != 20) + abort (); + + object.count2 = 11; + if (object.count2 != 11) + abort (); + + object.count3 = 19; + if (object.count3 != 19) + abort (); + + object.count4 = 74; + if (object.count4 != 74) + abort (); + + return 0; +} diff --git a/gcc/testsuite/obj-c++.dg/property/at-property-27.mm b/gcc/testsuite/obj-c++.dg/property/at-property-27.mm new file mode 100644 index 0000000..7278346 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/property/at-property-27.mm @@ -0,0 +1,66 @@ +/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, December 2010. */ +/* { dg-do run } */ +/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */ + +/* Test overriding a readonly @property with a readwrite one in a class extension. */ + +#include <stdlib.h> +#include <objc/objc.h> +#include <objc/runtime.h> + +@interface MyRootClass +{ + Class isa; +} ++ (id) initialize; ++ (id) alloc; +- (id) init; +@end + +@implementation MyRootClass ++ (id) initialize { return self; } ++ (id) alloc { return class_createInstance (self, 0); } +- (id) init { return self; } +@end + +@protocol count2 +/* Use a different getters/setters, so that the only way to compile + object.countX is to find the actual @property. */ +@property (readonly, getter=number2) int count2; +@end + +@interface MySubClass : MyRootClass +{ + int count1; + int count2; +} +@property (readonly, getter=number1) int count1; +@end + +@interface MySubClass () +@property (readwrite, getter=number1, setter=setNumber1:) int count1; +@end + +@interface MySubClass () <count2> +@property (readwrite, getter=number2, setter=setNumber2:) int count2; +@end + +@implementation MySubClass +@synthesize count1; +@synthesize count2; +@end + +int main (void) +{ + MySubClass *object = [[MySubClass alloc] init]; + + object.count1 = 20; + if (object.count1 != 20) + abort (); + + object.count2 = 11; + if (object.count2 != 11) + abort (); + + return 0; +} diff --git a/gcc/testsuite/obj-c++.dg/property/at-property-28.mm b/gcc/testsuite/obj-c++.dg/property/at-property-28.mm new file mode 100644 index 0000000..23b357c --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/property/at-property-28.mm @@ -0,0 +1,29 @@ +/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, December 2010. */ +/* { dg-do compile } */ + +/* Test errors when extending a property in a class extension. */ + +#include <objc/objc.h> +#include <objc/runtime.h> + +@interface MyRootClass +{ + Class isa; +} +@property (readonly, retain) id property1; /* { dg-warning "originally specified here" } */ +@property (readonly) int property2; /* { dg-warning "originally specified here" } */ +@property (readonly, getter=y) int property3; /* { dg-warning "originally specified here" } */ +@property (readonly) int property4; /* Ok */ +@property (readonly) int property5; /* { dg-warning "originally specified here" } */ +@end + +@interface MyRootClass () +@property (readwrite, copy) id property1; /* { dg-warning "assign semantics attributes of property .property1. conflict with previous declaration" } */ +@property (readwrite, nonatomic) int property2; /* { dg-warning ".nonatomic. attribute of property .property2. conflicts with previous declaration" } */ +@property (readwrite, getter=x) int property3; /* { dg-warning ".getter. attribute of property .property3. conflicts with previous declaration" } */ +@property (readwrite) int property4; /* Ok */ +@property (readwrite) float property5; /* { dg-warning "type of property .property5. conflicts with previous declaration" } */ +@end + + + diff --git a/gcc/testsuite/objc.dg/class-extension-1.m b/gcc/testsuite/objc.dg/class-extension-1.m new file mode 100644 index 0000000..eab59c4 --- /dev/null +++ b/gcc/testsuite/objc.dg/class-extension-1.m @@ -0,0 +1,30 @@ +/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, December 2010. */ +/* { dg-do compile } */ + +/* This test tests the basic of class extensions. */ + +#include <objc/objc.h> + +@interface MyObject +{ + Class isa; +} +- (int) test; +@end + +@interface MyObject () +- (int) test2; +- (int) test3; +@end + +@implementation MyObject +- (int) test +{ + return 20; +} +- (int) test2 +{ + return 20; +} +@end /* { dg-warning "incomplete implementation of class .MyObject." } */ + /* { dg-warning "method definition for .-test3. not found" "" { target *-*-* } 29 } */ diff --git a/gcc/testsuite/objc.dg/class-extension-2.m b/gcc/testsuite/objc.dg/class-extension-2.m new file mode 100644 index 0000000..79b126f --- /dev/null +++ b/gcc/testsuite/objc.dg/class-extension-2.m @@ -0,0 +1,56 @@ +/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, December 2010. */ +/* { dg-do compile } */ + +/* This test tests class extensions and protocols. */ + +#include <objc/objc.h> + +/* First, a simple test where a plain class has a protocol attached to + it in a class extension. */ +@interface MyObject +{ + Class isa; +} +@end + +@protocol MyProtocol +- (void) test; +@end + +@interface MyObject () <MyProtocol> +@end + +@implementation MyObject +@end /* { dg-warning "incomplete implementation of class .MyObject." } */ + /* { dg-warning "method definition for .-test. not found" "" { target *-*-* } 24 } */ + /* { dg-warning "class .MyObject. does not fully implement the .MyProtocol. protocol" "" { target *-*-* } 24 } */ + + + +/* Second, a more interesting test where protocols are added from the + main class and from two different class extensions. */ +@interface MyObject2 : MyObject <MyProtocol> +@end + +@protocol MyProtocol2 +- (void) test2; +@end + +@protocol MyProtocol3 +- (void) test3; +@end + +@interface MyObject2 () <MyProtocol2> +@end + +@interface MyObject2 () <MyProtocol3> +@end + +@implementation MyObject2 +@end /* { dg-warning "incomplete implementation of class .MyObject2." } */ + /* { dg-warning "method definition for .-test. not found" "" { target *-*-* } 50 } */ + /* { dg-warning "class .MyObject2. does not fully implement the .MyProtocol. protocol" "" { target *-*-* } 50 } */ + /* { dg-warning "method definition for .-test2. not found" "" { target *-*-* } 50 } */ + /* { dg-warning "class .MyObject2. does not fully implement the .MyProtocol2. protocol" "" { target *-*-* } 50 } */ + /* { dg-warning "method definition for .-test3. not found" "" { target *-*-* } 50 } */ + /* { dg-warning "class .MyObject2. does not fully implement the .MyProtocol3. protocol" "" { target *-*-* } 50 } */ diff --git a/gcc/testsuite/objc.dg/class-extension-3.m b/gcc/testsuite/objc.dg/class-extension-3.m new file mode 100644 index 0000000..9564bf0 --- /dev/null +++ b/gcc/testsuite/objc.dg/class-extension-3.m @@ -0,0 +1,26 @@ +/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, December 2010. */ +/* { dg-do compile } */ + +/* This test tests warnings on class extensions. */ + +#include <objc/objc.h> + +@interface MyObject +{ + Class isa; + int count; +} +- (int) test; +@property int count; /* { dg-message "originally specified here" } */ +@end + +@interface MyObject () +- (void) test; /* { dg-error "duplicate declaration of method .-test." } */ +@end + +@interface MyObject () +@end + +@interface MyObject () +@property int count; /* { dg-error "redeclaration of property .count." } */ +@end diff --git a/gcc/testsuite/objc.dg/property/at-property-26.m b/gcc/testsuite/objc.dg/property/at-property-26.m new file mode 100644 index 0000000..c45757e --- /dev/null +++ b/gcc/testsuite/objc.dg/property/at-property-26.m @@ -0,0 +1,85 @@ +/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, December 2010. */ +/* { dg-do run } */ +/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */ + +/* Test @properties in class extensions. */ + +#include <stdlib.h> +#include <objc/objc.h> +#include <objc/runtime.h> + +@interface MyRootClass +{ + Class isa; +} ++ (id) initialize; ++ (id) alloc; +- (id) init; +@end + +@implementation MyRootClass ++ (id) initialize { return self; } ++ (id) alloc { return class_createInstance (self, 0); } +- (id) init { return self; } +@end + +@protocol count4 +/* Use a different getters/setters, so that the only way to compile + object.countX is to find the actual @property. */ +@property (getter=number4, setter=setNumber4:) int count4; +@end + +@interface MySubClass : MyRootClass +{ + int count1; + int count2; + int count3; + int count4; +} +@property (getter=number1, setter=setNumber1:) int count1; +@end + +@interface MySubClass () +@property (getter=number2, setter=setNumber2:) int count2; +@end + +@interface MySubClass () <count4> +@property (getter=number3, setter=setNumber3:) int count3; +@end + +@implementation MySubClass +@synthesize count1; +@synthesize count2; +- (int) number3 +{ + return count3; +} +- (void) setNumber3: (int)value +{ + count3 = value; +} +@synthesize count4; +@end + +int main (void) +{ + MySubClass *object = [[MySubClass alloc] init]; + + object.count1 = 20; + if (object.count1 != 20) + abort (); + + object.count2 = 11; + if (object.count2 != 11) + abort (); + + object.count3 = 19; + if (object.count3 != 19) + abort (); + + object.count4 = 74; + if (object.count4 != 74) + abort (); + + return 0; +} diff --git a/gcc/testsuite/objc.dg/property/at-property-27.m b/gcc/testsuite/objc.dg/property/at-property-27.m new file mode 100644 index 0000000..7278346 --- /dev/null +++ b/gcc/testsuite/objc.dg/property/at-property-27.m @@ -0,0 +1,66 @@ +/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, December 2010. */ +/* { dg-do run } */ +/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */ + +/* Test overriding a readonly @property with a readwrite one in a class extension. */ + +#include <stdlib.h> +#include <objc/objc.h> +#include <objc/runtime.h> + +@interface MyRootClass +{ + Class isa; +} ++ (id) initialize; ++ (id) alloc; +- (id) init; +@end + +@implementation MyRootClass ++ (id) initialize { return self; } ++ (id) alloc { return class_createInstance (self, 0); } +- (id) init { return self; } +@end + +@protocol count2 +/* Use a different getters/setters, so that the only way to compile + object.countX is to find the actual @property. */ +@property (readonly, getter=number2) int count2; +@end + +@interface MySubClass : MyRootClass +{ + int count1; + int count2; +} +@property (readonly, getter=number1) int count1; +@end + +@interface MySubClass () +@property (readwrite, getter=number1, setter=setNumber1:) int count1; +@end + +@interface MySubClass () <count2> +@property (readwrite, getter=number2, setter=setNumber2:) int count2; +@end + +@implementation MySubClass +@synthesize count1; +@synthesize count2; +@end + +int main (void) +{ + MySubClass *object = [[MySubClass alloc] init]; + + object.count1 = 20; + if (object.count1 != 20) + abort (); + + object.count2 = 11; + if (object.count2 != 11) + abort (); + + return 0; +} diff --git a/gcc/testsuite/objc.dg/property/at-property-28.m b/gcc/testsuite/objc.dg/property/at-property-28.m new file mode 100644 index 0000000..de51224 --- /dev/null +++ b/gcc/testsuite/objc.dg/property/at-property-28.m @@ -0,0 +1,29 @@ +/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, December 2010. */ +/* { dg-do compile } */ + +/* Test errors when extending a property in a class extension. */ + +#include <objc/objc.h> +#include <objc/runtime.h> + +@interface MyRootClass +{ + Class isa; +} +@property (readonly, retain) id property1; /* { dg-message "originally specified here" } */ +@property (readonly) int property2; /* { dg-message "originally specified here" } */ +@property (readonly, getter=y) int property3; /* { dg-message "originally specified here" } */ +@property (readonly) int property4; /* Ok */ +@property (readonly) int property5; /* { dg-message "originally specified here" } */ +@end + +@interface MyRootClass () +@property (readwrite, copy) id property1; /* { dg-warning "assign semantics attributes of property .property1. conflict with previous declaration" } */ +@property (readwrite, nonatomic) int property2; /* { dg-warning ".nonatomic. attribute of property .property2. conflicts with previous declaration" } */ +@property (readwrite, getter=x) int property3; /* { dg-warning ".getter. attribute of property .property3. conflicts with previous declaration" } */ +@property (readwrite) int property4; /* Ok */ +@property (readwrite) float property5; /* { dg-warning "type of property .property5. conflicts with previous declaration" } */ +@end + + + |