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
This commit is contained in:
Nicola Pero 2010-12-10 09:38:52 +00:00 committed by Nicola Pero
parent aff7f4c416
commit ec3e9f8267
19 changed files with 812 additions and 76 deletions

View File

@ -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> 2010-12-10 Iain Sandoe <iains@gcc.gnu.org>
* config/darwin.c: Remove c-tree.h and c-lang.h * config/darwin.c: Remove c-tree.h and c-lang.h

View File

@ -6743,6 +6743,8 @@ c_parser_expr_list (c_parser *parser, bool convert_p, bool fold_p,
objc-class-instance-variables[opt] objc-class-instance-variables[opt]
@interface identifier ( identifier ) objc-protocol-refs[opt] @interface identifier ( identifier ) objc-protocol-refs[opt]
objc-methodprotolist @end objc-methodprotolist @end
@interface identifier ( ) objc-protocol-refs[opt]
objc-methodprotolist @end
@implementation identifier ( identifier ) @implementation identifier ( identifier )
objc-superclass: objc-superclass:
@ -6777,17 +6779,29 @@ c_parser_objc_class_definition (c_parser *parser, tree attributes)
c_parser_consume_token (parser); c_parser_consume_token (parser);
if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)) if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
{ {
/* We have a category or class extension. */
tree id2; tree id2;
tree proto = NULL_TREE; tree proto = NULL_TREE;
c_parser_consume_token (parser); c_parser_consume_token (parser);
if (c_parser_next_token_is_not (parser, CPP_NAME)) if (c_parser_next_token_is_not (parser, CPP_NAME))
{ {
c_parser_error (parser, "expected identifier"); 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); c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
return; return;
} }
}
else
{
id2 = c_parser_peek_token (parser)->value; id2 = c_parser_peek_token (parser)->value;
c_parser_consume_token (parser); c_parser_consume_token (parser);
}
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
if (!iface_p) if (!iface_p)
{ {

View File

@ -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> 2010-12-09 Nathan Froyd <froydnj@codesourcery.com>
* call.c (print_conversion_rejection): Indent messages two spaces. * call.c (print_conversion_rejection): Indent messages two spaces.

View File

@ -22435,12 +22435,15 @@ cp_parser_objc_protocol_declaration (cp_parser* parser, tree attributes)
/* Parse an Objective-C superclass or category. */ /* Parse an Objective-C superclass or category. */
static void static void
cp_parser_objc_superclass_or_category (cp_parser *parser, tree *super, cp_parser_objc_superclass_or_category (cp_parser *parser,
tree *categ) bool iface_p,
tree *super,
tree *categ, bool *is_class_extension)
{ {
cp_token *next = cp_lexer_peek_token (parser->lexer); cp_token *next = cp_lexer_peek_token (parser->lexer);
*super = *categ = NULL_TREE; *super = *categ = NULL_TREE;
*is_class_extension = false;
if (next->type == CPP_COLON) if (next->type == CPP_COLON)
{ {
cp_lexer_consume_token (parser->lexer); /* Eat ':'. */ 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) else if (next->type == CPP_OPEN_PAREN)
{ {
cp_lexer_consume_token (parser->lexer); /* Eat '('. */ cp_lexer_consume_token (parser->lexer); /* Eat '('. */
/* 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); *categ = cp_parser_identifier (parser);
cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); 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) cp_parser_objc_class_interface (cp_parser* parser, tree attributes)
{ {
tree name, super, categ, protos; tree name, super, categ, protos;
bool is_class_extension;
cp_lexer_consume_token (parser->lexer); /* Eat '@interface'. */ cp_lexer_consume_token (parser->lexer); /* Eat '@interface'. */
name = cp_parser_identifier (parser); name = cp_parser_identifier (parser);
@ -22472,11 +22486,12 @@ cp_parser_objc_class_interface (cp_parser* parser, tree attributes)
*/ */
return; 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); protos = cp_parser_objc_protocol_refs_opt (parser);
/* We have either a class or a category on our hands. */ /* 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); objc_start_category_interface (name, categ, protos, attributes);
else else
{ {
@ -22495,6 +22510,7 @@ static void
cp_parser_objc_class_implementation (cp_parser* parser) cp_parser_objc_class_implementation (cp_parser* parser)
{ {
tree name, super, categ; tree name, super, categ;
bool is_class_extension;
cp_lexer_consume_token (parser->lexer); /* Eat '@implementation'. */ cp_lexer_consume_token (parser->lexer); /* Eat '@implementation'. */
name = cp_parser_identifier (parser); name = cp_parser_identifier (parser);
@ -22508,7 +22524,8 @@ cp_parser_objc_class_implementation (cp_parser* parser)
*/ */
return; 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. */ /* We have either a class or a category on our hands. */
if (categ) if (categ)

View File

@ -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> 2010-12-08 Nicola Pero <nicola.pero@meta-innovation.com>
* objc-act.c (objc_build_throw_stmt): Check that the argument of * objc-act.c (objc_build_throw_stmt): Check that the argument of

View File

@ -402,6 +402,12 @@ static bool objc_method_optional_flag = false;
static int objc_collecting_ivars = 0; 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 #define BUFSIZE 1024
static char *errbuf; /* Buffer for error diagnostics */ 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" "category attributes are not available in this version"
" of the compiler, (ignored)"); " 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 objc_interface_context
= start_class (CATEGORY_INTERFACE_TYPE, klass, categ, protos, NULL_TREE); = start_class (CATEGORY_INTERFACE_TYPE, klass, categ, protos, NULL_TREE);
objc_ivar_chain objc_ivar_chain
@ -778,6 +789,7 @@ objc_finish_interface (void)
finish_class (objc_interface_context); finish_class (objc_interface_context);
objc_interface_context = NULL_TREE; objc_interface_context = NULL_TREE;
objc_method_optional_flag = false; objc_method_optional_flag = false;
objc_in_class_extension = false;
} }
void void
@ -952,6 +964,7 @@ objc_add_property_declaration (location_t location, tree decl,
is readwrite). */ is readwrite). */
bool property_readonly = false; bool property_readonly = false;
objc_property_assign_semantics property_assign_semantics = OBJC_PROPERTY_ASSIGN; objc_property_assign_semantics property_assign_semantics = OBJC_PROPERTY_ASSIGN;
bool property_extension_in_class_extension = false;
if (flag_objc1_only) if (flag_objc1_only)
error_at (input_location, "%<@property%> is not available in Objective-C 1.0"); error_at (input_location, "%<@property%> is not available in Objective-C 1.0");
@ -1125,10 +1138,23 @@ objc_add_property_declaration (location_t location, tree decl,
/* Check for duplicate property declarations. We first check the /* Check for duplicate property declarations. We first check the
immediate context for a property with the same name. Any such 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)) for (x = CLASS_PROPERTY_DECL (objc_interface_context); x; x = TREE_CHAIN (x))
{ {
if (PROPERTY_NAME (x) == DECL_NAME (decl)) if (PROPERTY_NAME (x) == DECL_NAME (decl))
{
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); location_t original_location = DECL_SOURCE_LOCATION (x);
@ -1139,32 +1165,38 @@ objc_add_property_declaration (location_t location, tree decl,
return; return;
} }
} }
}
/* We now need to check for existing property declarations (in the /* If x is not NULL_TREE, we must be in a class extension and we're
superclass, other categories or protocols) and check that the new extending a readonly property. In that case, no point in
declaration is not in conflict with existing ones. */ 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 /* Search for a previous, existing declaration of a property
the same name in superclasses, protocols etc. If one is found, with the same name in superclasses, protocols etc. If one is
it will be in the 'x' variable. */ found, it will be in the 'x' variable. */
x = NULL_TREE;
/* Note that, for simplicity, the following may search again the /* Note that, for simplicity, the following may search again the
local context. That's Ok as nothing will be found (else we'd 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 have thrown an error above); it's only a little inefficient,
the code is simpler. */ but the code is simpler. */
switch (TREE_CODE (objc_interface_context)) switch (TREE_CODE (objc_interface_context))
{ {
case CLASS_INTERFACE_TYPE: case CLASS_INTERFACE_TYPE:
/* Look up the property in the current @interface (which will /* Look up the property in the current @interface (which
find nothing), then its protocols and categories and will find nothing), then its protocols and categories and
superclasses. */ superclasses. */
x = lookup_property (objc_interface_context, DECL_NAME (decl)); x = lookup_property (objc_interface_context, DECL_NAME (decl));
break; break;
case CATEGORY_INTERFACE_TYPE: case CATEGORY_INTERFACE_TYPE:
/* Look up the property in the main @interface, then protocols /* Look up the property in the main @interface, then
and categories (one of them is ours, and will find nothing) protocols and categories (one of them is ours, and will
and superclasses. */ find nothing) and superclasses. */
x = lookup_property (lookup_interface (CLASS_NAME (objc_interface_context)), x = lookup_property (lookup_interface (CLASS_NAME (objc_interface_context)),
DECL_NAME (decl)); DECL_NAME (decl));
break; break;
@ -1180,6 +1212,7 @@ objc_add_property_declaration (location_t location, tree decl,
default: default:
gcc_unreachable (); gcc_unreachable ();
} }
}
if (x != NULL_TREE) if (x != NULL_TREE)
{ {
@ -1278,6 +1311,17 @@ objc_add_property_declaration (location_t location, tree decl,
inform (original_location, "originally specified here"); inform (original_location, "originally specified here");
return; 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. */ /* Create a PROPERTY_DECL node. */
@ -9417,19 +9461,22 @@ check_protocols (tree proto_list, const char *type, tree name)
} }
} }
/* Make sure that the class CLASS_NAME is defined /* Make sure that the class CLASS_NAME is defined CODE says which kind
CODE says which kind of thing CLASS_NAME ought to be. of thing CLASS_NAME ought to be. It can be CLASS_INTERFACE_TYPE,
It can be CLASS_INTERFACE_TYPE, CLASS_IMPLEMENTATION_TYPE, CLASS_IMPLEMENTATION_TYPE, CATEGORY_INTERFACE_TYPE, or
CATEGORY_INTERFACE_TYPE, or CATEGORY_IMPLEMENTATION_TYPE. */ 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 static tree
start_class (enum tree_code code, tree class_name, tree super_name, start_class (enum tree_code code, tree class_name, tree super_name,
tree protocol_list, tree attributes) tree protocol_list, tree attributes)
{ {
tree klass, decl; tree klass = NULL_TREE;
tree decl;
#ifdef OBJCPLUS #ifdef OBJCPLUS
if (current_namespace != global_namespace) { if (current_namespace != global_namespace)
{
error ("Objective-C declarations may only appear in global scope"); error ("Objective-C declarations may only appear in global scope");
} }
#endif /* OBJCPLUS */ #endif /* OBJCPLUS */
@ -9442,8 +9489,14 @@ start_class (enum tree_code code, tree class_name, tree super_name,
objc_implementation_context = NULL_TREE; objc_implementation_context = NULL_TREE;
} }
/* 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); klass = make_node (code);
TYPE_LANG_SLOT_1 (klass) = make_tree_vec (CLASS_LANG_SLOT_ELTS); TYPE_LANG_SLOT_1 (klass) = make_tree_vec (CLASS_LANG_SLOT_ELTS);
}
/* Check for existence of the super class, if one was specified. Note /* 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 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,
} }
} }
if (code != CATEGORY_INTERFACE_TYPE || super_name != NULL_TREE)
{
CLASS_NAME (klass) = class_name; CLASS_NAME (klass) = class_name;
CLASS_SUPER_NAME (klass) = super_name; CLASS_SUPER_NAME (klass) = super_name;
CLASS_CLS_METHODS (klass) = NULL_TREE; CLASS_CLS_METHODS (klass) = NULL_TREE;
}
if (! objc_is_class_name (class_name) if (! objc_is_class_name (class_name)
&& (decl = lookup_name (class_name))) && (decl = lookup_name (class_name)))
@ -9592,13 +9648,33 @@ start_class (enum tree_code code, tree class_name, tree super_name,
if (TREE_DEPRECATED (class_category_is_assoc_with)) if (TREE_DEPRECATED (class_category_is_assoc_with))
warning (OPT_Wdeprecated_declarations, "class %qE is deprecated", warning (OPT_Wdeprecated_declarations, "class %qE is deprecated",
class_name); class_name);
add_category (class_category_is_assoc_with, klass);
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) if (protocol_list)
CLASS_PROTOCOL_LIST (klass) CLASS_PROTOCOL_LIST (klass)
= lookup_and_install_protocols (protocol_list); = lookup_and_install_protocols (protocol_list);
} }
}
}
break; break;
case CATEGORY_IMPLEMENTATION_TYPE: case CATEGORY_IMPLEMENTATION_TYPE:
@ -9673,6 +9749,8 @@ continue_class (tree klass)
} }
case CLASS_INTERFACE_TYPE: case CLASS_INTERFACE_TYPE:
{ {
if (objc_in_class_extension)
return NULL_TREE;
#ifdef OBJCPLUS #ifdef OBJCPLUS
push_lang_context (lang_name_c); push_lang_context (lang_name_c);
#endif /* OBJCPLUS */ #endif /* OBJCPLUS */

View File

@ -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> 2010-12-09 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
PR target/46057 PR target/46057

View File

@ -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 } */

View File

@ -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 } */

View File

@ -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

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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

View File

@ -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 } */

View File

@ -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 } */

View File

@ -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

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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