aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicola Pero <nicola.pero@meta-innovation.com>2010-12-10 09:38:52 +0000
committerNicola Pero <nicola@gcc.gnu.org>2010-12-10 09:38:52 +0000
commitec3e9f826773a7aa4cfc135b4cc9e2de222bc137 (patch)
tree1455b598d50eb7e482cbb74cb6884dc439905ab7
parentaff7f4c416f03bcadf563a3f73896ddabd8da844 (diff)
downloadgcc-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/ChangeLog5
-rw-r--r--gcc/c-parser.c24
-rw-r--r--gcc/cp/ChangeLog9
-rw-r--r--gcc/cp/parser.c29
-rw-r--r--gcc/objc/ChangeLog14
-rw-r--r--gcc/objc/objc-act.c206
-rw-r--r--gcc/testsuite/ChangeLog15
-rw-r--r--gcc/testsuite/obj-c++.dg/class-extension-1.mm30
-rw-r--r--gcc/testsuite/obj-c++.dg/class-extension-2.mm56
-rw-r--r--gcc/testsuite/obj-c++.dg/class-extension-3.mm26
-rw-r--r--gcc/testsuite/obj-c++.dg/property/at-property-26.mm85
-rw-r--r--gcc/testsuite/obj-c++.dg/property/at-property-27.mm66
-rw-r--r--gcc/testsuite/obj-c++.dg/property/at-property-28.mm29
-rw-r--r--gcc/testsuite/objc.dg/class-extension-1.m30
-rw-r--r--gcc/testsuite/objc.dg/class-extension-2.m56
-rw-r--r--gcc/testsuite/objc.dg/class-extension-3.m26
-rw-r--r--gcc/testsuite/objc.dg/property/at-property-26.m85
-rw-r--r--gcc/testsuite/objc.dg/property/at-property-27.m66
-rw-r--r--gcc/testsuite/objc.dg/property/at-property-28.m29
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
+
+
+