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>
* 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]
@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)
{

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>
* 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. */
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)

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>
* 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;
/* 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. */
/* 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;
/* 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))
/* 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)
{
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))
/* 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. */
/* 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 */

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