In gcc/objc/: 2010-11-27 Nicola Pero <nicola.pero@meta-innovation.com>
In gcc/objc/: 2010-11-27 Nicola Pero <nicola.pero@meta-innovation.com> Implemented optional properties. * objc-act.h (PROPERTY_OPTIONAL): New. * objc-act.c (objc_add_property_declaration): Set PROPERTY_OPTIONAL if appropriate. (finish_class): When generating definitions of setter and getter methods associated with a property for a protocol, mark them as optional if the property is optional. (maybe_make_artificial_property_decl): Added 'getter_name' argument. Set PROPERTY_OPTIONAL. (objc_maybe_build_component_ref): Updated calls to maybe_make_artificial_property_decl. Added code for optional, readonly properties. (objc_build_class_component_ref): Updated call to maybe_make_artificial_property_decl. In gcc/testsuite/: 2010-11-27 Nicola Pero <nicola.pero@meta-innovation.com> * objc.dg/property/at-property-24.m: New. * objc.dg/property/at-property-25.m: New. * obj-c++.dg/property/at-property-24.mm: New. * obj-c++.dg/property/at-property-25.mm: New. From-SVN: r167197
This commit is contained in:
parent
c5589aa7e1
commit
2dd24dbdfe
@ -1,3 +1,20 @@
|
||||
2010-11-27 Nicola Pero <nicola.pero@meta-innovation.com>
|
||||
|
||||
Implemented optional properties.
|
||||
* objc-act.h (PROPERTY_OPTIONAL): New.
|
||||
* objc-act.c (objc_add_property_declaration): Set
|
||||
PROPERTY_OPTIONAL if appropriate.
|
||||
(finish_class): When generating definitions of setter and getter
|
||||
methods associated with a property for a protocol, mark them as
|
||||
optional if the property is optional.
|
||||
(maybe_make_artificial_property_decl): Added 'getter_name'
|
||||
argument. Set PROPERTY_OPTIONAL.
|
||||
(objc_maybe_build_component_ref): Updated calls to
|
||||
maybe_make_artificial_property_decl. Added code for optional,
|
||||
readonly properties.
|
||||
(objc_build_class_component_ref): Updated call to
|
||||
maybe_make_artificial_property_decl.
|
||||
|
||||
2010-11-27 Nicola Pero <nicola.pero@meta-innovation.com>
|
||||
|
||||
* objc-act.c (objc_build_struct): Fixed loops that save and
|
||||
|
@ -1181,7 +1181,7 @@ objc_add_property_declaration (location_t location, tree decl,
|
||||
/* An existing property was found; check that it has the same
|
||||
types, or it is compatible. */
|
||||
location_t original_location = DECL_SOURCE_LOCATION (x);
|
||||
|
||||
|
||||
if (PROPERTY_NONATOMIC (x) != parsed_property_nonatomic)
|
||||
{
|
||||
warning_at (location, 0,
|
||||
@ -1293,6 +1293,13 @@ objc_add_property_declaration (location_t location, tree decl,
|
||||
PROPERTY_IVAR_NAME (property_decl) = NULL_TREE;
|
||||
PROPERTY_DYNAMIC (property_decl) = 0;
|
||||
|
||||
/* Remember the fact that the property was found in the @optional
|
||||
section in a @protocol, or not. */
|
||||
if (objc_method_optional_flag)
|
||||
PROPERTY_OPTIONAL (property_decl) = 1;
|
||||
else
|
||||
PROPERTY_OPTIONAL (property_decl) = 0;
|
||||
|
||||
/* Note that PROPERTY_GETTER_NAME is always set for all
|
||||
PROPERTY_DECLs, and PROPERTY_SETTER_NAME is always set for all
|
||||
PROPERTY_DECLs where PROPERTY_READONLY == 0. Any time we deal
|
||||
@ -1310,18 +1317,22 @@ objc_add_property_declaration (location_t location, tree decl,
|
||||
in the implementation, and failing that, the protocol list)
|
||||
provided for a 'setter' or 'getter' for 'component' with default
|
||||
names (ie, if 'component' is "name", then search for "name" and
|
||||
"setName:"). If any is found, then create an artificial property
|
||||
that uses them. Return NULL_TREE if 'getter' or 'setter' could not
|
||||
be found. */
|
||||
"setName:"). It is also possible to specify a different
|
||||
'getter_name' (this is used for @optional readonly properties). If
|
||||
any is found, then create an artificial property that uses them.
|
||||
Return NULL_TREE if 'getter' or 'setter' could not be found. */
|
||||
static tree
|
||||
maybe_make_artificial_property_decl (tree interface, tree implementation,
|
||||
tree protocol_list, tree component, bool is_class)
|
||||
tree protocol_list, tree component, bool is_class,
|
||||
tree getter_name)
|
||||
{
|
||||
tree getter_name = component;
|
||||
tree setter_name = get_identifier (objc_build_property_setter_name (component));
|
||||
tree getter = NULL_TREE;
|
||||
tree setter = NULL_TREE;
|
||||
|
||||
if (getter_name == NULL_TREE)
|
||||
getter_name = component;
|
||||
|
||||
/* First, check the @interface and all superclasses. */
|
||||
if (interface)
|
||||
{
|
||||
@ -1401,6 +1412,7 @@ maybe_make_artificial_property_decl (tree interface, tree implementation,
|
||||
PROPERTY_ASSIGN_SEMANTICS (property_decl) = 0;
|
||||
PROPERTY_IVAR_NAME (property_decl) = NULL_TREE;
|
||||
PROPERTY_DYNAMIC (property_decl) = 0;
|
||||
PROPERTY_OPTIONAL (property_decl) = 0;
|
||||
|
||||
if (!getter)
|
||||
PROPERTY_HAS_NO_GETTER (property_decl) = 1;
|
||||
@ -1481,7 +1493,7 @@ objc_maybe_build_component_ref (tree object, tree property_ident)
|
||||
properties. */
|
||||
if (!IS_CLASS (rtype))
|
||||
x = lookup_property_in_protocol_list (rprotos, property_ident);
|
||||
|
||||
|
||||
if (x == NULL_TREE)
|
||||
{
|
||||
/* Ok, no property. Maybe it was an
|
||||
@ -1493,7 +1505,25 @@ objc_maybe_build_component_ref (tree object, tree property_ident)
|
||||
NULL_TREE,
|
||||
rprotos,
|
||||
property_ident,
|
||||
IS_CLASS (rtype));
|
||||
IS_CLASS (rtype),
|
||||
NULL_TREE);
|
||||
}
|
||||
else if (PROPERTY_OPTIONAL (x) && PROPERTY_READONLY (x))
|
||||
{
|
||||
/* This is a special, complicated case. If the
|
||||
property is optional, and is read-only, then the
|
||||
property is always used for reading, but an
|
||||
eventual existing non-property setter can be used
|
||||
for writing. We create an artificial property
|
||||
decl copying the getter from the optional
|
||||
property, and looking up the setter in the
|
||||
interface. */
|
||||
x = maybe_make_artificial_property_decl (NULL_TREE,
|
||||
NULL_TREE,
|
||||
rprotos,
|
||||
property_ident,
|
||||
false,
|
||||
PROPERTY_GETTER_NAME (x));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1538,7 +1568,22 @@ objc_maybe_build_component_ref (tree object, tree property_ident)
|
||||
x = maybe_make_artificial_property_decl
|
||||
(interface_type, implementation, NULL_TREE,
|
||||
property_ident,
|
||||
(TREE_CODE (objc_method_context) == CLASS_METHOD_DECL));
|
||||
(TREE_CODE (objc_method_context) == CLASS_METHOD_DECL),
|
||||
NULL_TREE);
|
||||
}
|
||||
else if (PROPERTY_OPTIONAL (x) && PROPERTY_READONLY (x))
|
||||
{
|
||||
tree implementation = NULL_TREE;
|
||||
|
||||
if (t == self_decl)
|
||||
implementation = objc_implementation_context;
|
||||
|
||||
x = maybe_make_artificial_property_decl (interface_type,
|
||||
implementation,
|
||||
NULL_TREE,
|
||||
property_ident,
|
||||
false,
|
||||
PROPERTY_GETTER_NAME (x));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1603,8 +1648,25 @@ objc_maybe_build_component_ref (tree object, tree property_ident)
|
||||
implementation,
|
||||
protocol_list,
|
||||
property_ident,
|
||||
IS_CLASS (rtype));
|
||||
IS_CLASS (rtype),
|
||||
NULL_TREE);
|
||||
}
|
||||
else if (PROPERTY_OPTIONAL (x) && PROPERTY_READONLY (x))
|
||||
{
|
||||
tree implementation = NULL_TREE;
|
||||
|
||||
if (objc_implementation_context
|
||||
&& CLASS_NAME (objc_implementation_context)
|
||||
== OBJC_TYPE_NAME (interface_type))
|
||||
implementation = objc_implementation_context;
|
||||
|
||||
x = maybe_make_artificial_property_decl (interface_type,
|
||||
implementation,
|
||||
protocol_list,
|
||||
property_ident,
|
||||
false,
|
||||
PROPERTY_GETTER_NAME (x));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1703,7 +1765,7 @@ objc_build_class_component_ref (tree class_name, tree property_ident)
|
||||
|
||||
x = maybe_make_artificial_property_decl (rtype, NULL_TREE, NULL_TREE,
|
||||
property_ident,
|
||||
true);
|
||||
true, NULL_TREE);
|
||||
|
||||
if (x)
|
||||
{
|
||||
@ -10534,7 +10596,10 @@ finish_class (tree klass)
|
||||
getter_decl = build_method_decl (INSTANCE_METHOD_DECL,
|
||||
rettype, PROPERTY_GETTER_NAME (x),
|
||||
NULL_TREE, false);
|
||||
objc_add_method (objc_interface_context, getter_decl, false, false);
|
||||
if (PROPERTY_OPTIONAL (x))
|
||||
objc_add_method (objc_interface_context, getter_decl, false, true);
|
||||
else
|
||||
objc_add_method (objc_interface_context, getter_decl, false, false);
|
||||
METHOD_PROPERTY_CONTEXT (getter_decl) = x;
|
||||
}
|
||||
|
||||
@ -10574,7 +10639,10 @@ finish_class (tree klass)
|
||||
ret_type, selector,
|
||||
build_tree_list (NULL_TREE, NULL_TREE),
|
||||
false);
|
||||
objc_add_method (objc_interface_context, setter_decl, false, false);
|
||||
if (PROPERTY_OPTIONAL (x))
|
||||
objc_add_method (objc_interface_context, setter_decl, false, true);
|
||||
else
|
||||
objc_add_method (objc_interface_context, setter_decl, false, false);
|
||||
METHOD_PROPERTY_CONTEXT (setter_decl) = x;
|
||||
}
|
||||
}
|
||||
|
@ -113,6 +113,11 @@ typedef enum objc_property_assign_semantics {
|
||||
setter, it is set to 1. */
|
||||
#define PROPERTY_HAS_NO_SETTER(DECL) DECL_LANG_FLAG_4 (DECL)
|
||||
|
||||
/* PROPERTY_OPTIONAL can be 0 or 1. Normally it is 0, but if this is
|
||||
a property declared as @optional in a @protocol, then it is set to
|
||||
1. */
|
||||
#define PROPERTY_OPTIONAL(DECL) DECL_LANG_FLAG_5 (DECL)
|
||||
|
||||
/* PROPERTY_REF. A PROPERTY_REF represents an 'object.property'
|
||||
expression. It is normally used for property access, but when
|
||||
the Objective-C 2.0 "dot-syntax" (object.component) is used
|
||||
|
@ -1,3 +1,10 @@
|
||||
2010-11-27 Nicola Pero <nicola.pero@meta-innovation.com>
|
||||
|
||||
* objc.dg/property/at-property-24.m: New.
|
||||
* objc.dg/property/at-property-25.m: New.
|
||||
* obj-c++.dg/property/at-property-24.mm: New.
|
||||
* obj-c++.dg/property/at-property-25.mm: New.
|
||||
|
||||
2010-11-27 Nicola Pero <nicola.pero@meta-innovation.com>
|
||||
|
||||
* objc.dg/protocol-qualifier-1.m: New.
|
||||
|
118
gcc/testsuite/obj-c++.dg/property/at-property-24.mm
Normal file
118
gcc/testsuite/obj-c++.dg/property/at-property-24.mm
Normal file
@ -0,0 +1,118 @@
|
||||
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010. */
|
||||
/* { dg-do run } */
|
||||
/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
|
||||
|
||||
/* Test @optional @properties. */
|
||||
|
||||
#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
|
||||
|
||||
/* Use a different getters/setters, so that the only way to compile
|
||||
object.countX is to find the actual @property. */
|
||||
@protocol count
|
||||
@required
|
||||
/* @required + @synthesize. */
|
||||
@property (getter=number1, setter=setNumber1:) int count1;
|
||||
/* @required + manual setters/getters. */
|
||||
@property (getter=number2, setter=setNumber2:) int count2;
|
||||
|
||||
@optional
|
||||
/* @optional + @synthesize. */
|
||||
@property (getter=number3, setter=setNumber3:) int count3;
|
||||
/* @optional + manual setters/getters. */
|
||||
@property (getter=number4, setter=setNumber4:) int count4;
|
||||
|
||||
@optional
|
||||
/* @optional + readonly, with a setter added in the class itself. */
|
||||
@property (readonly, getter=number5) int count5;
|
||||
@end
|
||||
|
||||
@interface MySubClass : MyRootClass <count>
|
||||
{
|
||||
int count1;
|
||||
int count2;
|
||||
int count3;
|
||||
int count4;
|
||||
int count5;
|
||||
}
|
||||
- (void) setCount5: (int)value;
|
||||
@end
|
||||
|
||||
@implementation MySubClass
|
||||
@synthesize count1;
|
||||
- (int) number2
|
||||
{
|
||||
return count2;
|
||||
}
|
||||
- (void) setNumber2: (int)value
|
||||
{
|
||||
count2 = value;
|
||||
}
|
||||
@synthesize count3;
|
||||
- (int) number4
|
||||
{
|
||||
return count4;
|
||||
}
|
||||
- (void) setNumber4: (int)value
|
||||
{
|
||||
count4 = value;
|
||||
}
|
||||
- (int) number5
|
||||
{
|
||||
return count5;
|
||||
}
|
||||
- (void) setCount5: (int)value
|
||||
{
|
||||
count5 = value;
|
||||
}
|
||||
@end
|
||||
|
||||
int main (void)
|
||||
{
|
||||
MySubClass *object = [[MySubClass alloc] init];
|
||||
|
||||
/* First, test that @required and @optional properties work as
|
||||
expected if implemented either via @synthesize or manually. */
|
||||
object.count1 = 44;
|
||||
if (object.count1 != 44)
|
||||
abort ();
|
||||
|
||||
object.count2 = 88;
|
||||
if (object.count2 != 88)
|
||||
abort ();
|
||||
|
||||
object.count3 = 77;
|
||||
if (object.count3 != 77)
|
||||
abort ();
|
||||
|
||||
object.count4 = 11;
|
||||
if (object.count4 != 11)
|
||||
abort ();
|
||||
|
||||
/* Now, test the complication: @optional @property which is
|
||||
readonly, but which has a setter manually implemented.
|
||||
Apparently it is possible to use the dotsyntax and the @optional
|
||||
@property getter is used when reading, while the manual setter is
|
||||
used when writing. */
|
||||
object.count5 = 99;
|
||||
if (object.count5 != 99)
|
||||
abort ();
|
||||
|
||||
return 0;
|
||||
}
|
87
gcc/testsuite/obj-c++.dg/property/at-property-25.mm
Normal file
87
gcc/testsuite/obj-c++.dg/property/at-property-25.mm
Normal file
@ -0,0 +1,87 @@
|
||||
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010. */
|
||||
/* { dg-do compile } */
|
||||
|
||||
/* Test warnings and non-warnings with @optional @properties. */
|
||||
|
||||
#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 count
|
||||
@optional
|
||||
@property int count1;
|
||||
@property (readonly) int count2;
|
||||
@end
|
||||
|
||||
|
||||
/* A class that implements all the properties. */
|
||||
@interface MySubClass1 : MyRootClass <count>
|
||||
{
|
||||
int count1;
|
||||
int count2;
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation MySubClass1
|
||||
@synthesize count1;
|
||||
@synthesize count2;
|
||||
@end
|
||||
|
||||
|
||||
/* A class that implements nothing; no warnings as the properties are
|
||||
all optional. */
|
||||
@interface MySubClass2 : MyRootClass <count>
|
||||
@end
|
||||
|
||||
@implementation MySubClass2
|
||||
@end
|
||||
|
||||
|
||||
@protocol count2
|
||||
@required
|
||||
@property int count1;
|
||||
@property (readonly) int count2;
|
||||
@end
|
||||
|
||||
/* A class that implements all the properties. */
|
||||
@interface MySubClass3 : MyRootClass <count2>
|
||||
{
|
||||
int count1;
|
||||
int count2;
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation MySubClass3
|
||||
@synthesize count1;
|
||||
@synthesize count2;
|
||||
@end
|
||||
|
||||
|
||||
/* A class that implements nothing; warnings as the properties are
|
||||
all required. */
|
||||
@interface MySubClass4 : MyRootClass <count2>
|
||||
@end
|
||||
|
||||
@implementation MySubClass4
|
||||
@end
|
||||
|
||||
/* { dg-warning "incomplete implementation of class" "" { target *-*-* } 81 } */
|
||||
/* { dg-warning "method definition for ..setCount1:. not found" "" { target *-*-* } 81 } */
|
||||
/* { dg-warning "method definition for ..count1. not found" "" { target *-*-* } 81 } */
|
||||
/* { dg-warning "method definition for ..count2. not found" "" { target *-*-* } 81 } */
|
||||
/* { dg-warning "class .MySubClass4. does not fully implement the .count2. protocol" "" { target *-*-* } 81 } */
|
118
gcc/testsuite/objc.dg/property/at-property-24.m
Normal file
118
gcc/testsuite/objc.dg/property/at-property-24.m
Normal file
@ -0,0 +1,118 @@
|
||||
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010. */
|
||||
/* { dg-do run } */
|
||||
/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
|
||||
|
||||
/* Test @optional @properties. */
|
||||
|
||||
#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
|
||||
|
||||
/* Use a different getters/setters, so that the only way to compile
|
||||
object.countX is to find the actual @property. */
|
||||
@protocol count
|
||||
@required
|
||||
/* @required + @synthesize. */
|
||||
@property (getter=number1, setter=setNumber1:) int count1;
|
||||
/* @required + manual setters/getters. */
|
||||
@property (getter=number2, setter=setNumber2:) int count2;
|
||||
|
||||
@optional
|
||||
/* @optional + @synthesize. */
|
||||
@property (getter=number3, setter=setNumber3:) int count3;
|
||||
/* @optional + manual setters/getters. */
|
||||
@property (getter=number4, setter=setNumber4:) int count4;
|
||||
|
||||
@optional
|
||||
/* @optional + readonly, with a setter added in the class itself. */
|
||||
@property (readonly, getter=number5) int count5;
|
||||
@end
|
||||
|
||||
@interface MySubClass : MyRootClass <count>
|
||||
{
|
||||
int count1;
|
||||
int count2;
|
||||
int count3;
|
||||
int count4;
|
||||
int count5;
|
||||
}
|
||||
- (void) setCount5: (int)value;
|
||||
@end
|
||||
|
||||
@implementation MySubClass
|
||||
@synthesize count1;
|
||||
- (int) number2
|
||||
{
|
||||
return count2;
|
||||
}
|
||||
- (void) setNumber2: (int)value
|
||||
{
|
||||
count2 = value;
|
||||
}
|
||||
@synthesize count3;
|
||||
- (int) number4
|
||||
{
|
||||
return count4;
|
||||
}
|
||||
- (void) setNumber4: (int)value
|
||||
{
|
||||
count4 = value;
|
||||
}
|
||||
- (int) number5
|
||||
{
|
||||
return count5;
|
||||
}
|
||||
- (void) setCount5: (int)value
|
||||
{
|
||||
count5 = value;
|
||||
}
|
||||
@end
|
||||
|
||||
int main (void)
|
||||
{
|
||||
MySubClass *object = [[MySubClass alloc] init];
|
||||
|
||||
/* First, test that @required and @optional properties work as
|
||||
expected if implemented either via @synthesize or manually. */
|
||||
object.count1 = 44;
|
||||
if (object.count1 != 44)
|
||||
abort ();
|
||||
|
||||
object.count2 = 88;
|
||||
if (object.count2 != 88)
|
||||
abort ();
|
||||
|
||||
object.count3 = 77;
|
||||
if (object.count3 != 77)
|
||||
abort ();
|
||||
|
||||
object.count4 = 11;
|
||||
if (object.count4 != 11)
|
||||
abort ();
|
||||
|
||||
/* Now, test the complication: @optional @property which is
|
||||
readonly, but which has a setter manually implemented.
|
||||
Apparently it is possible to use the dotsyntax and the @optional
|
||||
@property getter is used when reading, while the manual setter is
|
||||
used when writing. */
|
||||
object.count5 = 99;
|
||||
if (object.count5 != 99)
|
||||
abort ();
|
||||
|
||||
return 0;
|
||||
}
|
87
gcc/testsuite/objc.dg/property/at-property-25.m
Normal file
87
gcc/testsuite/objc.dg/property/at-property-25.m
Normal file
@ -0,0 +1,87 @@
|
||||
/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010. */
|
||||
/* { dg-do compile } */
|
||||
|
||||
/* Test warnings and non-warnings with @optional @properties. */
|
||||
|
||||
#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 count
|
||||
@optional
|
||||
@property int count1;
|
||||
@property (readonly) int count2;
|
||||
@end
|
||||
|
||||
|
||||
/* A class that implements all the properties. */
|
||||
@interface MySubClass1 : MyRootClass <count>
|
||||
{
|
||||
int count1;
|
||||
int count2;
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation MySubClass1
|
||||
@synthesize count1;
|
||||
@synthesize count2;
|
||||
@end
|
||||
|
||||
|
||||
/* A class that implements nothing; no warnings as the properties are
|
||||
all optional. */
|
||||
@interface MySubClass2 : MyRootClass <count>
|
||||
@end
|
||||
|
||||
@implementation MySubClass2
|
||||
@end
|
||||
|
||||
|
||||
@protocol count2
|
||||
@required
|
||||
@property int count1;
|
||||
@property (readonly) int count2;
|
||||
@end
|
||||
|
||||
/* A class that implements all the properties. */
|
||||
@interface MySubClass3 : MyRootClass <count2>
|
||||
{
|
||||
int count1;
|
||||
int count2;
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation MySubClass3
|
||||
@synthesize count1;
|
||||
@synthesize count2;
|
||||
@end
|
||||
|
||||
|
||||
/* A class that implements nothing; warnings as the properties are
|
||||
all required. */
|
||||
@interface MySubClass4 : MyRootClass <count2>
|
||||
@end
|
||||
|
||||
@implementation MySubClass4
|
||||
@end
|
||||
|
||||
/* { dg-warning "incomplete implementation of class" "" { target *-*-* } 81 } */
|
||||
/* { dg-warning "method definition for ..setCount1:. not found" "" { target *-*-* } 81 } */
|
||||
/* { dg-warning "method definition for ..count1. not found" "" { target *-*-* } 81 } */
|
||||
/* { dg-warning "method definition for ..count2. not found" "" { target *-*-* } 81 } */
|
||||
/* { dg-warning "class .MySubClass4. does not fully implement the .count2. protocol" "" { target *-*-* } 81 } */
|
Loading…
Reference in New Issue
Block a user