From 25bf03837aac94d1deb2d0b87f442cd65d23bbea Mon Sep 17 00:00:00 2001 From: nicola Date: Sun, 14 Nov 2010 11:11:18 +0000 Subject: [PATCH] In gcc/objc/: 2010-11-14 Nicola Pero * objc-act.c (objc_add_property_declaration): Check that the decl we received from the parser is a FIELD_DECL; reject array and bitfield properties. Convert the warning when a property is readonly and a setter is specified into an error. Convert errors when a property declaration does not match a property declaration in a superclass into warnings. (objc_add_synthesize_declaration_for_property): Use DECL_BIT_FIELD_TYPE to determine the type of an instance variable if it is a bitfield. Throw an error if we are asked to synthesize setters/getters for a bitfield instance variable but the property is not appropriate - it must be assign and nonatomic. If the property is readonly, allow the instance variable type to be a specialization of the property type. (objc_type_valid_for_messaging): Fixed returning 'false' for a Class qualified with a protocol when the 'accept_classes' argument is 'false'. In gcc/testsuite/: 2010-11-14 Nicola Pero * objc.dg/property/at-property-21.m: New. * objc.dg/property/at-property-22.m: New. * objc.dg/property/at-property-23.m: New. * objc.dg/property/synthesize-9.m: New. * objc.dg/property/synthesize-10.m: New. * objc.dg/property/synthesize-11.m: New. * obj-c++.dg/property/at-property-21.mm: New. * obj-c++.dg/property/at-property-22.mm: New. * obj-c++.dg/property/at-property-23.mm: New. * obj-c++.dg/property/synthesize-9.mm: New. * obj-c++.dg/property/synthesize-10.mm: New. * obj-c++.dg/property/synthesize-11.mm: New. * objc.dg/property/at-property-4.m: Updated to match new compiler where some errors have been converted into warnings and vice versa. * objc.dg/property/at-property-16.m: Same change. * objc.dg/property/at-property-18.m: Same change. * objc.dg/property/property-neg-5.m: Same change. * obj-c++.dg/property/at-property-4.mm: Same change. * obj-c++.dg/property/at-property-16.mm: Same change. * obj-c++.dg/property/at-property-18.mm: Same change. * obj-c++.dg/property/property-neg-5.mm: Same change. * obj-c++.dg/property/dynamic-2.mm: Enable tests that were commented out because of testsuite problems; I found out that using dg-warning instead of dg-message gets them to work. * obj-c++.dg/property/property-neg-3.mm: Same change. * obj-c++.dg/property/synthesize-6.mm: Same change. * obj-c++.dg/property/at-property-5.mm: Same change. * obj-c++.dg/property/at-property-14.mm: Same change. * obj-c++.dg/property/at-property-18.mm: Same change. * obj-c++.dg/property/at-property-16.mm: Same change (in this file, some tests still do not work due to some other testsuite issue). git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@166730 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/objc/ChangeLog | 19 +++ gcc/objc/objc-act.c | 114 ++++++++++++-- gcc/testsuite/ChangeLog | 36 +++++ .../obj-c++.dg/property/at-property-14.mm | 12 +- .../obj-c++.dg/property/at-property-16.mm | 46 +++--- .../obj-c++.dg/property/at-property-18.mm | 35 ++--- .../obj-c++.dg/property/at-property-21.mm | 23 +++ .../obj-c++.dg/property/at-property-22.mm | 172 +++++++++++++++++++++ .../obj-c++.dg/property/at-property-23.mm | 18 +++ gcc/testsuite/obj-c++.dg/property/at-property-4.mm | 2 +- gcc/testsuite/obj-c++.dg/property/at-property-5.mm | 12 +- gcc/testsuite/obj-c++.dg/property/dynamic-2.mm | 6 +- .../obj-c++.dg/property/property-neg-3.mm | 6 +- .../obj-c++.dg/property/property-neg-5.mm | 2 +- gcc/testsuite/obj-c++.dg/property/synthesize-10.mm | 53 +++++++ gcc/testsuite/obj-c++.dg/property/synthesize-11.mm | 31 ++++ gcc/testsuite/obj-c++.dg/property/synthesize-6.mm | 12 +- gcc/testsuite/obj-c++.dg/property/synthesize-9.mm | 80 ++++++++++ gcc/testsuite/objc.dg/property/at-property-16.m | 16 +- gcc/testsuite/objc.dg/property/at-property-18.m | 16 +- gcc/testsuite/objc.dg/property/at-property-21.m | 23 +++ gcc/testsuite/objc.dg/property/at-property-22.m | 172 +++++++++++++++++++++ gcc/testsuite/objc.dg/property/at-property-23.m | 17 ++ gcc/testsuite/objc.dg/property/at-property-4.m | 2 +- gcc/testsuite/objc.dg/property/property-neg-5.m | 2 +- gcc/testsuite/objc.dg/property/synthesize-10.m | 53 +++++++ gcc/testsuite/objc.dg/property/synthesize-11.m | 31 ++++ gcc/testsuite/objc.dg/property/synthesize-9.m | 80 ++++++++++ 28 files changed, 979 insertions(+), 112 deletions(-) create mode 100644 gcc/testsuite/obj-c++.dg/property/at-property-21.mm create mode 100644 gcc/testsuite/obj-c++.dg/property/at-property-22.mm create mode 100644 gcc/testsuite/obj-c++.dg/property/at-property-23.mm create mode 100644 gcc/testsuite/obj-c++.dg/property/synthesize-10.mm create mode 100644 gcc/testsuite/obj-c++.dg/property/synthesize-11.mm create mode 100644 gcc/testsuite/obj-c++.dg/property/synthesize-9.mm create mode 100644 gcc/testsuite/objc.dg/property/at-property-21.m create mode 100644 gcc/testsuite/objc.dg/property/at-property-22.m create mode 100644 gcc/testsuite/objc.dg/property/at-property-23.m create mode 100644 gcc/testsuite/objc.dg/property/synthesize-10.m create mode 100644 gcc/testsuite/objc.dg/property/synthesize-11.m create mode 100644 gcc/testsuite/objc.dg/property/synthesize-9.m diff --git a/gcc/objc/ChangeLog b/gcc/objc/ChangeLog index 41bc7969a03..9dfc4f95721 100644 --- a/gcc/objc/ChangeLog +++ b/gcc/objc/ChangeLog @@ -1,3 +1,22 @@ +2010-11-14 Nicola Pero + + * objc-act.c (objc_add_property_declaration): Check that the decl + we received from the parser is a FIELD_DECL; reject array and + bitfield properties. Convert the warning when a property is + readonly and a setter is specified into an error. Convert errors + when a property declaration does not match a property declaration + in a superclass into warnings. + (objc_add_synthesize_declaration_for_property): Use + DECL_BIT_FIELD_TYPE to determine the type of an instance variable + if it is a bitfield. Throw an error if we are asked to synthesize + setters/getters for a bitfield instance variable but the property + is not appropriate - it must be assign and nonatomic. If the + property is readonly, allow the instance variable type to be a + specialization of the property type. + (objc_type_valid_for_messaging): Fixed returning 'false' for a + Class qualified with a protocol when the 'accept_classes' argument + is 'false'. + 2010-11-13 Nicola Pero * objc-act.c (objc_get_protocol_qualified_type): detect cases diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c index 48b04ac9ef4..da97e14ced2 100644 --- a/gcc/objc/objc-act.c +++ b/gcc/objc/objc-act.c @@ -948,8 +948,7 @@ objc_add_property_declaration (location_t location, tree decl, if (parsed_property_readonly && parsed_property_setter_ident) { - /* Maybe this should be an error ? The Apple documentation says it is a warning. */ - warning_at (location, 0, "% attribute conflicts with % attribute"); + error_at (location, "% attribute conflicts with % attribute"); property_readonly = false; } @@ -989,16 +988,43 @@ objc_add_property_declaration (location_t location, tree decl, /* At this point we know that we are either in an interface, a category, or a protocol. */ - /* Check that the property does not have an initial value specified. - This should never happen as the parser doesn't allow this, but - it's just in case. */ - if (DECL_INITIAL (decl)) + /* We expect a FIELD_DECL from the parser. Make sure we didn't get + something else, as that would confuse the checks below. */ + if (TREE_CODE (decl) != FIELD_DECL) + { + error_at (location, "invalid property declaration"); + return; + } + + /* Do some spot-checks for the most obvious invalid types. */ + + if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE) { - error_at (location, "property can not have an initial value"); + error_at (location, "property can not be an array"); return; } - /* TODO: Check that the property type is an Objective-C object or a "POD". */ + /* The C++/ObjC++ parser seems to reject the ':' for a bitfield when + parsing, while the C/ObjC parser accepts it and gives us a + FIELD_DECL with a DECL_INITIAL set. So we use the DECL_INITIAL + to check for a bitfield when doing ObjC. */ +#ifndef OBJCPLUS + if (DECL_INITIAL (decl)) + { + /* A @property is not an actual variable, but it is a way to + describe a pair of accessor methods, so its type (which is + the type of the return value of the getter and the first + argument of the setter) can't be a bitfield (as return values + and arguments of functions can not be bitfields). The + underlying instance variable could be a bitfield, but that is + a different matter. */ + error_at (location, "property can not be a bit-field"); + return; + } +#endif + + /* TODO: Check that the property type is an Objective-C object or a + "POD". */ /* Implement -Wproperty-assign-default (which is enabled by default). */ if (warn_property_assign_default @@ -1136,7 +1162,8 @@ objc_add_property_declaration (location_t location, tree decl, if (PROPERTY_NONATOMIC (x) != parsed_property_nonatomic) { - error_at (location, "'nonatomic' attribute of property %qD conflicts with previous declaration", decl); + warning_at (location, 0, + "'nonatomic' attribute of property %qD conflicts with previous declaration", decl); if (original_location != UNKNOWN_LOCATION) inform (original_location, "originally specified here"); @@ -1145,7 +1172,8 @@ objc_add_property_declaration (location_t location, tree decl, if (PROPERTY_GETTER_NAME (x) != parsed_property_getter_ident) { - error_at (location, "'getter' attribute of property %qD conflicts with previous declaration", decl); + warning_at (location, 0, + "'getter' attribute of property %qD conflicts with previous declaration", decl); if (original_location != UNKNOWN_LOCATION) inform (original_location, "originally specified here"); @@ -1157,7 +1185,8 @@ objc_add_property_declaration (location_t location, tree decl, { if (PROPERTY_SETTER_NAME (x) != parsed_property_setter_ident) { - error_at (location, "'setter' attribute of property %qD conflicts with previous declaration", decl); + warning_at (location, 0, + "'setter' attribute of property %qD conflicts with previous declaration", decl); if (original_location != UNKNOWN_LOCATION) inform (original_location, "originally specified here"); @@ -1167,7 +1196,8 @@ objc_add_property_declaration (location_t location, tree decl, if (PROPERTY_ASSIGN_SEMANTICS (x) != property_assign_semantics) { - error_at (location, "assign semantics attributes of property %qD conflict with previous declaration", decl); + warning_at (location, 0, + "assign semantics attributes of property %qD conflict with previous declaration", decl); if (original_location != UNKNOWN_LOCATION) inform (original_location, "originally specified here"); @@ -1177,7 +1207,8 @@ objc_add_property_declaration (location_t location, tree decl, /* It's ok to have a readonly property that becomes a readwrite, but not vice versa. */ if (PROPERTY_READONLY (x) == 0 && property_readonly == 1) { - error_at (location, "'readonly' attribute of property %qD conflicts with previous declaration", decl); + warning_at (location, 0, + "'readonly' attribute of property %qD conflicts with previous declaration", decl); if (original_location != UNKNOWN_LOCATION) inform (original_location, "originally specified here"); @@ -9854,6 +9885,7 @@ objc_add_synthesize_declaration_for_property (location_t location, tree interfac instance variable is only used in one synthesized property). */ { tree ivar = is_ivar (CLASS_IVARS (interface), ivar_name); + tree type_of_ivar; if (!ivar) { error_at (location, "ivar %qs used by %<@synthesize%> declaration must be an existing ivar", @@ -9861,8 +9893,19 @@ objc_add_synthesize_declaration_for_property (location_t location, tree interfac return; } - /* If the instance variable has a different C type, we warn. */ - if (!comptypes (TREE_TYPE (property), TREE_TYPE (ivar))) + if (DECL_BIT_FIELD_TYPE (ivar)) + type_of_ivar = DECL_BIT_FIELD_TYPE (ivar); + else + type_of_ivar = TREE_TYPE (ivar); + + /* If the instance variable has a different C type, we throw an error ... */ + if (!comptypes (TREE_TYPE (property), type_of_ivar) + /* ... unless the property is readonly, in which case we allow + the instance variable to be more specialized (this means we + can generate the getter all right and it works). */ + && (!PROPERTY_READONLY (property) + || !objc_compare_types (TREE_TYPE (property), + type_of_ivar, -5, NULL_TREE))) { location_t original_location = DECL_SOURCE_LOCATION (ivar); @@ -9873,6 +9916,43 @@ objc_add_synthesize_declaration_for_property (location_t location, tree interfac if (original_location != UNKNOWN_LOCATION) inform (original_location, "originally specified here"); } + + /* If the instance variable is a bitfield, the property must be + 'assign', 'nonatomic' because the runtime getter/setter helper + do not work with bitfield instance variables. */ + if (DECL_BIT_FIELD_TYPE (ivar)) + { + /* If there is an error, we return and not generate any + getter/setter because trying to set up the runtime + getter/setter helper calls with bitfields is at high risk + of ICE. */ + + if (PROPERTY_ASSIGN_SEMANTICS (property) != OBJC_PROPERTY_ASSIGN) + { + location_t original_location = DECL_SOURCE_LOCATION (ivar); + + error_at (location, "'assign' property %qs is using bit-field instance variable %qs", + IDENTIFIER_POINTER (property_name), + IDENTIFIER_POINTER (ivar_name)); + + if (original_location != UNKNOWN_LOCATION) + inform (original_location, "originally specified here"); + return; + } + + if (!PROPERTY_NONATOMIC (property)) + { + location_t original_location = DECL_SOURCE_LOCATION (ivar); + + error_at (location, "'atomic' property %qs is using bit-field instance variable %qs", + IDENTIFIER_POINTER (property_name), + IDENTIFIER_POINTER (ivar_name)); + + if (original_location != UNKNOWN_LOCATION) + inform (original_location, "originally specified here"); + return; + } + } } /* Check that no other property is using the same instance @@ -12566,8 +12646,8 @@ objc_type_valid_for_messaging (tree type, bool accept_classes) if (objc_is_object_id (type)) return true; - if (accept_classes && objc_is_class_id (type)) - return true; + if (objc_is_class_id (type)) + return accept_classes; if (TYPE_HAS_OBJC_INFO (type)) return true; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f5456a1e9f7..5e1989464ff 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,39 @@ +2010-11-14 Nicola Pero + + * objc.dg/property/at-property-21.m: New. + * objc.dg/property/at-property-22.m: New. + * objc.dg/property/at-property-23.m: New. + * objc.dg/property/synthesize-9.m: New. + * objc.dg/property/synthesize-10.m: New. + * objc.dg/property/synthesize-11.m: New. + * obj-c++.dg/property/at-property-21.mm: New. + * obj-c++.dg/property/at-property-22.mm: New. + * obj-c++.dg/property/at-property-23.mm: New. + * obj-c++.dg/property/synthesize-9.mm: New. + * obj-c++.dg/property/synthesize-10.mm: New. + * obj-c++.dg/property/synthesize-11.mm: New. + + * objc.dg/property/at-property-4.m: Updated to match new compiler + where some errors have been converted into warnings and vice versa. + * objc.dg/property/at-property-16.m: Same change. + * objc.dg/property/at-property-18.m: Same change. + * objc.dg/property/property-neg-5.m: Same change. + * obj-c++.dg/property/at-property-4.mm: Same change. + * obj-c++.dg/property/at-property-16.mm: Same change. + * obj-c++.dg/property/at-property-18.mm: Same change. + * obj-c++.dg/property/property-neg-5.mm: Same change. + + * obj-c++.dg/property/dynamic-2.mm: Enable tests that were + commented out because of testsuite problems; I found out that + using dg-warning instead of dg-message gets them to work. + * obj-c++.dg/property/property-neg-3.mm: Same change. + * obj-c++.dg/property/synthesize-6.mm: Same change. + * obj-c++.dg/property/at-property-5.mm: Same change. + * obj-c++.dg/property/at-property-14.mm: Same change. + * obj-c++.dg/property/at-property-18.mm: Same change. + * obj-c++.dg/property/at-property-16.mm: Same change (in this file, + some tests still do not work due to some other testsuite issue). + 2010-11-13 Jason Merrill * g++.dg/cpp0x/auto20.C: New. diff --git a/gcc/testsuite/obj-c++.dg/property/at-property-14.mm b/gcc/testsuite/obj-c++.dg/property/at-property-14.mm index af427387349..33744ebfa93 100644 --- a/gcc/testsuite/obj-c++.dg/property/at-property-14.mm +++ b/gcc/testsuite/obj-c++.dg/property/at-property-14.mm @@ -9,16 +9,12 @@ } /* Test the warnings on 'assign'. */ -/* FIXME - there is a problem with the testuite in running the following test. The compiler - generates the messages, but the testsuite still complains. */ -/*@property id property_a; */ /* dg-warning "object property .property.a. has no .assign., .retain. or .copy. attribute" */ - /* dg-message ".assign. can be unsafe for Objective-C objects" "" { target *-*-* } 12 */ +@property id property_a; /* { dg-warning "object property .property.a. has no .assign., .retain. or .copy. attribute" } */ + /* { dg-warning ".assign. can be unsafe for Objective-C objects" "" { target *-*-* } 12 } */ @property (readonly) id property_b; /* No 'assign' warning (assign semantics do not matter if the property is readonly). */ @property id *property_c; /* No 'assign' warning (the type is not an Objective-C object). */ @property Class property_d; /* No 'assign' warning (Classes are static objects so assign semantics do not matter for them). */ -/* FIXME - there is a problem with the testuite in running the following test. The compiler - generates the messages, but the testsuite still complains. */ -/*@property MyRootClass *property_e;*/ /* dg-warning "object property .property.e. has no .assign., .retain. or .copy. attribute" */ - /* dg-message ".assign. can be unsafe for Objective-C objects" "" { target *-*-* } 18 */ +@property MyRootClass *property_e; /* { dg-warning "object property .property.e. has no .assign., .retain. or .copy. attribute" } */ + /* { dg-warning ".assign. can be unsafe for Objective-C objects" "" { target *-*-* } 18 } */ @end diff --git a/gcc/testsuite/obj-c++.dg/property/at-property-16.mm b/gcc/testsuite/obj-c++.dg/property/at-property-16.mm index ca8a68c373d..8cab00a7a9a 100644 --- a/gcc/testsuite/obj-c++.dg/property/at-property-16.mm +++ b/gcc/testsuite/obj-c++.dg/property/at-property-16.mm @@ -10,15 +10,16 @@ { Class isa; } -@property (assign) id a; -@property (retain) id b; -@property int c; -@property (nonatomic) int d; -@property int e; -@property int f; -@property int g; -@property (readonly) int h; -@property (readonly,getter=getMe) int i; +@property (assign) id a; /* { dg-warning "originally specified here" } */ +@property (retain) id b; /* { dg-warning "originally specified here" } */ +@property int c; /* { dg-warning "originally specified here" } */ +@property (nonatomic) int d; /* { dg-warning "originally specified here" } */ +/* FIXME: The compiler generates these errors, but the testsuite still fails the tests. */ +@property int e; /* dg-warning "originally specified here" */ +@property int f; /* dg-warning "originally specified here" */ +@property int g; /* dg-warning "originally specified here" */ +@property (readonly) int h; /* Ok */ +@property (readonly,getter=getMe) int i; /* { dg-warning "originally specified here" } */ @end @interface MyClass : MyRootClass @@ -32,23 +33,16 @@ @property (readonly) int h; @property (readonly,getter=getMe) int i; @end -/* FIXME - there is a problem with the testuite in running the following test. The compiler generates the messages, but the testsuite still complains. */ + @interface MyClass2 : MyRootClass -/* @property (retain) id a; */ /* dg-error "assign semantics attributes of property .a. conflict with previous declaration" */ - /* dg-message "originally specified here" "" { target *-*-* } 13 */ -/* @property (assign) id b; */ /* dg-error "assign semantics attributes of property .b. conflict with previous declaration" */ - /* dg-message "originally specified here" "" { target *-*-* } 14 */ -/* @property (nonatomic) int c; */ /* dg-error ".nonatomic. attribute of property .c. conflicts with previous declaration" */ - /* dg-message "originally specified here" "" { target *-*-* } 15 */ -/* @property int d; */ /* dg-error ".nonatomic. attribute of property .d. conflicts with previous declaration" */ - /* dg-message "originally specified here" "" { target *-*-* } 16 */ -/* @property (setter=setX:) int e; */ /* dg-error ".setter. attribute of property .e. conflicts with previous declaration" */ - /* dg-message "originally specified here" "" { target *-*-* } 17 */ -/* @property (getter=x) int f; */ /* dg-error ".getter. attribute of property .f. conflicts with previous declaration" */ - /* dg-message "originally specified here" "" { target *-*-* } 18 */ -/* @property (readonly) int g; */ /* dg-error ".readonly. attribute of property .g. conflicts with previous declaration" */ - /* dg-message "originally specified here" "" { target *-*-* } 19 */ +@property (retain) id a; /* { dg-warning "assign semantics attributes of property .a. conflict with previous declaration" } */ +@property (assign) id b; /* { dg-warning "assign semantics attributes of property .b. conflict with previous declaration" } */ +@property (nonatomic) int c; /* { dg-warning ".nonatomic. attribute of property .c. conflicts with previous declaration" } */ +@property int d; /* { dg-warning ".nonatomic. attribute of property .d. conflicts with previous declaration" } */ +/* FIXME: The compiler generates these errors, but the testsuite still fails the tests. */ +/*@property (setter=setX:) int e;*/ /* dg-warning ".setter. attribute of property .e. conflicts with previous declaration" */ +/*@property (getter=x) int f;*/ /* dg-warning ".getter. attribute of property .f. conflicts with previous declaration" */ +/*@property (readonly) int g;*/ /* dg-warning ".readonly. attribute of property .g. conflicts with previous declaration" */ @property (readwrite) int h; /* Ok */ -/* @property (readonly) int i; */ /* dg-error ".getter. attribute of property .i. conflicts with previous declaration" */ - /* dg-message "originally specified here" "" { target *-*-* } 21 */ +@property (readonly) int i; /* { dg-warning ".getter. attribute of property .i. conflicts with previous declaration" } */ @end diff --git a/gcc/testsuite/obj-c++.dg/property/at-property-18.mm b/gcc/testsuite/obj-c++.dg/property/at-property-18.mm index 482e1ff759d..72abb6b76b5 100644 --- a/gcc/testsuite/obj-c++.dg/property/at-property-18.mm +++ b/gcc/testsuite/obj-c++.dg/property/at-property-18.mm @@ -24,24 +24,23 @@ @property (readonly,getter=getMe) int i; @property (nonatomic) float j; @end -/* FIXME - there is a problem with the testuite in running the following test. The compiler generates the messages, but the testsuite still complains. */ @interface MyRootClass (Category) -/*@property (retain) id a; */ /* dg-error "assign semantics attributes of property .a. conflict with previous declaration" */ - /* dg-message "originally specified here" "" { target *-*-* } 16 */ -/*@property (assign) id b; */ /* dg-error "assign semantics attributes of property .b. conflict with previous declaration" */ - /* dg-message "originally specified here" "" { target *-*-* } 17 */ -/*@property (nonatomic) int c; */ /* dg-error ".nonatomic. attribute of property .c. conflicts with previous declaration" */ - /* dg-message "originally specified here" "" { target *-*-* } 18 */ -/*@property int d; */ /* dg-error ".nonatomic. attribute of property .d. conflicts with previous declaration" */ - /* dg-message "originally specified here" "" { target *-*-* } 19 */ -/*@property (setter=setX:) int e; */ /* dg-error ".setter. attribute of property .e. conflicts with previous declaration" */ - /* dg-message "originally specified here" "" { target *-*-* } 20 */ -/*@property (getter=x) int f; */ /* dg-error ".getter. attribute of property .f. conflicts with previous declaration" */ - /* dg-message "originally specified here" "" { target *-*-* } 21 */ -/*@property (readonly) int g; */ /* dg-error ".readonly. attribute of property .g. conflicts with previous declaration" */ - /* dg-message "originally specified here" "" { target *-*-* } 22 */ -@property (readwrite) int h; /* Ok */ -/*@property (readonly) int i; */ /* dg-error ".getter. attribute of property .i. conflicts with previous declaration" */ - /* dg-message "originally specified here" "" { target *-*-* } 24 */ +@property (retain) id a; /* { dg-warning "assign semantics attributes of property .a. conflict with previous declaration" } */ + /* { dg-warning "originally specified here" "" { target *-*-* } 16 } */ +@property (assign) id b; /* { dg-warning "assign semantics attributes of property .b. conflict with previous declaration" } */ + /* { dg-warning "originally specified here" "" { target *-*-* } 17 } */ +@property (nonatomic) int c; /* { dg-warning ".nonatomic. attribute of property .c. conflicts with previous declaration" } */ + /* { dg-warning "originally specified here" "" { target *-*-* } 18 } */ +@property int d; /* { dg-warning ".nonatomic. attribute of property .d. conflicts with previous declaration" } */ + /* { dg-warning "originally specified here" "" { target *-*-* } 19 } */ +@property (setter=setX:) int e; /* { dg-warning ".setter. attribute of property .e. conflicts with previous declaration" } */ + /* { dg-warning "originally specified here" "" { target *-*-* } 20 } */ +@property (getter=x) int f; /* { dg-warning ".getter. attribute of property .f. conflicts with previous declaration" } */ + /* { dg-warning "originally specified here" "" { target *-*-* } 21 } */ +@property (readonly) int g; /* { dg-warning ".readonly. attribute of property .g. conflicts with previous declaration" } */ + /* { dg-warning "originally specified here" "" { target *-*-* } 22 } */ +@property (readwrite) int h; /* Ok */ +@property (readonly) int i; /* { dg-warning ".getter. attribute of property .i. conflicts with previous declaration" } */ + /* { dg-warning "originally specified here" "" { target *-*-* } 24 } */ @property (nonatomic) float j; /* Ok */ @end diff --git a/gcc/testsuite/obj-c++.dg/property/at-property-21.mm b/gcc/testsuite/obj-c++.dg/property/at-property-21.mm new file mode 100644 index 00000000000..6106b7ee2aa --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/property/at-property-21.mm @@ -0,0 +1,23 @@ +/* Contributed by Nicola Pero , November 2010. */ +/* { dg-do compile } */ + +#include + +@protocol MyProtocol +- (void) message; +@end + +@interface MyRootClass +{ + Class isa; +} + +/* Test the warnings on 'assign' with protocols. */ +@property id property_a; /* { dg-warning "object property .property.a. has no .assign., .retain. or .copy. attribute" } */ + /* { dg-warning ".assign. can be unsafe for Objective-C objects" "" { target *-*-* } 16 } */ + +@property MyRootClass *property_b; /* { dg-warning "object property .property.b. has no .assign., .retain. or .copy. attribute" } */ + /* { dg-warning ".assign. can be unsafe for Objective-C objects" "" { target *-*-* } 19 } */ + +@property Class property_c; /* No 'assign' warning (Classes are static objects so assign semantics do not matter for them). */ +@end diff --git a/gcc/testsuite/obj-c++.dg/property/at-property-22.mm b/gcc/testsuite/obj-c++.dg/property/at-property-22.mm new file mode 100644 index 00000000000..af7f3bc1b4e --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/property/at-property-22.mm @@ -0,0 +1,172 @@ +/* Contributed by Nicola Pero , November 2010. */ +/* { dg-do run } */ +/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */ + +/* Test properties of different types. */ + +#include +#include +#include + +enum colour { Red, Black }; + +@interface MyRootClass +{ + Class isa; +} ++ (id) initialize; ++ (id) alloc; +- (id) init; ++ (Class) class; +@end + +@implementation MyRootClass ++ (id) initialize { return self; } ++ (id) alloc { return class_createInstance (self, 0); } +- (id) init { return self; } ++ (Class) class { return self; } +@end + + +@interface MyClass : MyRootClass +{ + /* A bunch of C types. */ + char pchar; + short pshort; + int pint; + long plong; + float pfloat; + double pdouble; + enum colour penum; + + /* A bunch of pointers to C types. */ + char *pcharp; + short *pshortp; + int *pintp; + long *plongp; + float *pfloatp; + double *pdoublep; + enum colour *penump; + + /* A bunch of Objective-C types. */ + id pid; + Class pclass; + MyClass *pMyClassp; +} +@property (assign) char pchar; +@property (assign) short pshort; +@property (assign) int pint; +@property (assign) long plong; +@property (assign) float pfloat; +@property (assign) double pdouble; +@property (assign) enum colour penum; + +@property (assign) char *pcharp; +@property (assign) short *pshortp; +@property (assign) int *pintp; +@property (assign) long *plongp; +@property (assign) float *pfloatp; +@property (assign) double *pdoublep; +@property (assign) enum colour *penump; + +@property (assign) id pid; +@property (assign) Class pclass; +@property (assign) MyClass *pMyClassp; +@end + +@implementation MyClass +@synthesize pchar; +@synthesize pshort; +@synthesize pint; +@synthesize plong; +@synthesize pfloat; +@synthesize pdouble; +@synthesize penum; + +@synthesize pcharp; +@synthesize pshortp; +@synthesize pintp; +@synthesize plongp; +@synthesize pfloatp; +@synthesize pdoublep; +@synthesize penump; + +@synthesize pid; +@synthesize pclass; +@synthesize pMyClassp; +@end + +int main (void) +{ + MyClass *object = [[MyClass alloc] init]; + + object.pchar = 1; + if (object.pchar != 1) + abort (); + + object.pshort = 2; + if (object.pshort != 2) + abort (); + + object.pint = 3; + if (object.pint != 3) + abort (); + + object.plong = 4; + if (object.plong != 4) + abort (); + + object.pfloat = 0; + if (object.pfloat != 0) + abort (); + + object.pdouble = 0; + if (object.pdouble != 0) + abort (); + + object.penum = Black; + if (object.penum != Black) + abort (); + + object.pcharp = 0; + if (object.pcharp != 0) + abort (); + + object.pshortp = 0; + if (object.pshortp != 0) + abort (); + + object.pintp = 0; + if (object.pintp != 0) + abort (); + + object.plongp = 0; + if (object.plongp != 0) + abort (); + + object.pfloatp = 0; + if (object.pfloatp != 0) + abort (); + + object.pdoublep = 0; + if (object.pdoublep != 0) + abort (); + + object.penump = 0; + if (object.penump != 0) + abort (); + + object.pid = object; + if (object.pid != object) + abort (); + + object.pclass = [MyClass class]; + if (object.pclass != [MyClass class]) + abort (); + + object.pMyClassp = object; + if (object.pMyClassp != object) + abort (); + + return 0; +} diff --git a/gcc/testsuite/obj-c++.dg/property/at-property-23.mm b/gcc/testsuite/obj-c++.dg/property/at-property-23.mm new file mode 100644 index 00000000000..73138f64c4a --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/property/at-property-23.mm @@ -0,0 +1,18 @@ +/* Contributed by Nicola Pero , November 2010. */ +/* { dg-do compile } */ + +/* Test that properties of type arrays or bitfields are rejected. */ + +#include +#include +#include + +@interface MyRootClass +{ + Class isa; +} +@property int a[8]; /* { dg-error "property can not be an array" } */ +@property int b:8; /* { dg-error "expected" } */ +@property int c[]; /* { dg-error "property can not be an array" } */ + /* { dg-error "ISO C.. forbids zero-size array" "" { target *-*-* } 16 } */ +@end diff --git a/gcc/testsuite/obj-c++.dg/property/at-property-4.mm b/gcc/testsuite/obj-c++.dg/property/at-property-4.mm index e327930f87b..941aab8e33c 100644 --- a/gcc/testsuite/obj-c++.dg/property/at-property-4.mm +++ b/gcc/testsuite/obj-c++.dg/property/at-property-4.mm @@ -28,7 +28,7 @@ /* Now test various problems. */ @property (readonly, readwrite) int a; /* { dg-error ".readonly. attribute conflicts with .readwrite. attribute" } */ -@property (readonly, setter=mySetterB:) int b; /* { dg-warning ".readonly. attribute conflicts with .setter. attribute" } */ +@property (readonly, setter=mySetterB:) int b; /* { dg-error ".readonly. attribute conflicts with .setter. attribute" } */ @property (assign, retain) id c; /* { dg-error ".assign. attribute conflicts with .retain. attribute" } */ @property (assign, copy) id d; /* { dg-error ".assign. attribute conflicts with .copy. attribute" } */ diff --git a/gcc/testsuite/obj-c++.dg/property/at-property-5.mm b/gcc/testsuite/obj-c++.dg/property/at-property-5.mm index 7ccf4c974d2..92dd114c879 100644 --- a/gcc/testsuite/obj-c++.dg/property/at-property-5.mm +++ b/gcc/testsuite/obj-c++.dg/property/at-property-5.mm @@ -17,10 +17,8 @@ } /* Test various error messages. */ -/* FIXME - there is a problem with the testuite in running the following test. The compiler - generates the messages, but the testsuite still complains. */ -/*@property id property_a;*/ /* dg-warning "object property .property.a. has no .assign., .retain. or .copy. attribute" */ - /* dg-message ".assign. can be unsafe for Objective-C objects" "" { target *-*-* } 20 */ +@property id property_a; /* { dg-warning "object property .property.a. has no .assign., .retain. or .copy. attribute" } */ + /* { dg-warning ".assign. can be unsafe for Objective-C objects" "" { target *-*-* } 20 } */ @property int property_b = 4; /* { dg-error "expected" } */ @property (retain) int property_c; /* { dg-error ".retain. attribute is only valid for Objective-C objects" } */ @property (copy) int property_d; /* { dg-error ".copy. attribute is only valid for Objective-C objects" } */ @@ -29,10 +27,8 @@ @property (retain) id property_f; @property (retain) id property_g; @property (retain) id property_h; -/* FIXME - there is a problem with the testuite in running the following test. The compiler - generates the messages, but the testsuite still complains. */ -/*@property (retain) id property_e;*/ /* dg-error "redeclaration of property .property_e." */ - /* dg-message "originally specified here" "" { target *-*-* } 26 */ +@property (retain) id property_e; /* { dg-error "redeclaration of property .property_e." } */ + /* { dg-warning "originally specified here" "" { target *-*-* } 26 } */ @end @property id test; /* { dg-error "misplaced .@property. Objective-C.. construct" } */ diff --git a/gcc/testsuite/obj-c++.dg/property/dynamic-2.mm b/gcc/testsuite/obj-c++.dg/property/dynamic-2.mm index 631eeeecc50..39ef6b2b7d7 100644 --- a/gcc/testsuite/obj-c++.dg/property/dynamic-2.mm +++ b/gcc/testsuite/obj-c++.dg/property/dynamic-2.mm @@ -39,9 +39,7 @@ @implementation AnotherTest @dynamic one; -/* FIXME - there is a problem with the testuite in running the following test. The compiler - generates the messages, but the testsuite still complains. */ -/*@dynamic one;*/ /* dg-error "property .one. already specified in .@dynamic." */ - /* dg-message "originally specified here" "" { target *-*-* } 40 */ +@dynamic one; /* { dg-error "property .one. already specified in .@dynamic." } */ + /* { dg-warning "originally specified here" "" { target *-*-* } 41 } */ @dynamic three; /* { dg-error "no declaration of property .three. found in the interface" } */ @end diff --git a/gcc/testsuite/obj-c++.dg/property/property-neg-3.mm b/gcc/testsuite/obj-c++.dg/property/property-neg-3.mm index a749c28c69c..a298bf01572 100644 --- a/gcc/testsuite/obj-c++.dg/property/property-neg-3.mm +++ b/gcc/testsuite/obj-c++.dg/property/property-neg-3.mm @@ -9,8 +9,6 @@ @implementation Person @dynamic firstName; -/* FIXME - there is a problem with the testuite in running the following test. The compiler - generates the messages, but the testsuite still complains. */ -/*@synthesize firstName;*/ /* dg-error "property .firstName. already specified in .@dynamic." */ - /* dg-message "originally specified here" "" { target *-*-* } 11 */ +@synthesize firstName; /* { dg-error "property .firstName. already specified in .@dynamic." } */ + /* { dg-warning "originally specified here" "" { target *-*-* } 11 } */ @end diff --git a/gcc/testsuite/obj-c++.dg/property/property-neg-5.mm b/gcc/testsuite/obj-c++.dg/property/property-neg-5.mm index 403f6841c8d..464470cba7b 100644 --- a/gcc/testsuite/obj-c++.dg/property/property-neg-5.mm +++ b/gcc/testsuite/obj-c++.dg/property/property-neg-5.mm @@ -1,5 +1,5 @@ /* { dg-do compile } */ @interface Foo -@property ( readonly, getter = HELLO, setter = THERE : ) int value; /* { dg-warning ".readonly. attribute conflicts with .setter. attribute" } */ +@property ( readonly, getter = HELLO, setter = THERE : ) int value; /* { dg-error ".readonly. attribute conflicts with .setter. attribute" } */ @end diff --git a/gcc/testsuite/obj-c++.dg/property/synthesize-10.mm b/gcc/testsuite/obj-c++.dg/property/synthesize-10.mm new file mode 100644 index 00000000000..fc4683187df --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/property/synthesize-10.mm @@ -0,0 +1,53 @@ +/* Contributed by Nicola Pero , November 2010. */ +/* { dg-do run } */ +/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */ + +/* Test @synthesize with bitfield instance variables. */ + +#include +#include +#include + +@interface MyRootClass +{ + Class isa; + int countA : 2; + int countB : 3; + int countC : 4; +} ++ (id) initialize; ++ (id) alloc; +- (id) init; +@property (nonatomic) int countA; +@property (nonatomic) int countB; +@property (nonatomic) int countC; +@end + +@implementation MyRootClass ++ (id) initialize { return self; } ++ (id) alloc { return class_createInstance (self, 0); } +- (id) init { return self; } +@synthesize countA; +@synthesize countB; +@synthesize countC; +@end + +int main (void) +{ + MyRootClass *object = [[MyRootClass alloc] init]; + + object.countA = 1; + object.countB = 3; + object.countC = 4; + + if (object.countA != 1) + abort (); + + if (object.countB != 3) + abort (); + + if (object.countC != 4) + abort (); + + return 0; +} diff --git a/gcc/testsuite/obj-c++.dg/property/synthesize-11.mm b/gcc/testsuite/obj-c++.dg/property/synthesize-11.mm new file mode 100644 index 00000000000..5d808d038f6 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/property/synthesize-11.mm @@ -0,0 +1,31 @@ +/* Contributed by Nicola Pero , November 2010. */ +/* { dg-do compile } */ + +/* Test errors when @synthesize is used with bitfield instance variables in an incorrect way. */ + +#include +#include +#include + +@interface MyRootClass +{ + Class isa; + int countA : 2; /* { dg-warning "originally specified here" } */ + int countB : 3; /* { dg-warning "originally specified here" } */ +} ++ (id) initialize; ++ (id) alloc; +- (id) init; +@property int countA; +@property (nonatomic) short countB; +@end + +@implementation MyRootClass ++ (id) initialize { return self; } ++ (id) alloc { return class_createInstance (self, 0); } +- (id) init { return self; } +@synthesize countA; /* { dg-error ".atomic. property .countA. is using bit-field instance variable .countA." } */ +@synthesize countB; /* { dg-error "property .countB. is using instance variable .countB. of incompatible type" } */ +@end /* { dg-warning "incomplete implementation of class" } */ +/* { dg-warning "method definition for ..setCountA.. not found" "" { target *-*-* } 29 } */ +/* { dg-warning "method definition for ..countA. not found" "" { target *-*-* } 29 } */ diff --git a/gcc/testsuite/obj-c++.dg/property/synthesize-6.mm b/gcc/testsuite/obj-c++.dg/property/synthesize-6.mm index 2d039279430..f6f5293e41d 100644 --- a/gcc/testsuite/obj-c++.dg/property/synthesize-6.mm +++ b/gcc/testsuite/obj-c++.dg/property/synthesize-6.mm @@ -14,12 +14,10 @@ @property int v1; @property int v2; @end -#if 0 /* This is a problem in the testsuite; the compiler is fine, but the testsuite still barfs on the following. */ @implementation Test -@synthesize v1 = v; /* dg-message "originally specified here" */ -@synthesize v2 = v; /* dg-error "property .v2. is using the same instance variable as property .v1." */ +@synthesize v1 = v; /* { dg-warning "originally specified here" } */ +@synthesize v2 = v; /* { dg-error "property .v2. is using the same instance variable as property .v1." } */ @end -#endif @interface Test2 : Test @property int w1; @end @@ -27,6 +25,6 @@ @implementation Test2 @synthesize w1; /* { dg-error "ivar .w1. used by .@synthesize. declaration must be an existing ivar" } */ @end -/* { dg-warning "incomplete implementation" "" { target *-*-* } 29 } */ -/* { dg-warning "method definition for .-setW1:. not found" "" { target *-*-* } 29 } */ -/* { dg-warning "method definition for .-w1. not found" "" { target *-*-* } 29 } */ +/* { dg-warning "incomplete implementation" "" { target *-*-* } 27 } */ +/* { dg-warning "method definition for .-setW1:. not found" "" { target *-*-* } 27 } */ +/* { dg-warning "method definition for .-w1. not found" "" { target *-*-* } 27 } */ diff --git a/gcc/testsuite/obj-c++.dg/property/synthesize-9.mm b/gcc/testsuite/obj-c++.dg/property/synthesize-9.mm new file mode 100644 index 00000000000..bcf195f9015 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/property/synthesize-9.mm @@ -0,0 +1,80 @@ +/* Contributed by Nicola Pero , November 2010. */ +/* { dg-do compile } */ + +/* Test that when using @synthesize with a readonly property, the + instance variable can be a specialization of the property type. */ + +#include + +@protocol MyProtocol +- (void)aMethod; +@end + +@interface ClassA +@end + +@interface ClassB : ClassA +@end + + +/* This is all OK. */ +@interface Test +{ + int v; + float w; + id x; + Test *y; + id *z; + ClassA *a; + ClassB *b; + ClassA *c; +} +@property (assign, readonly) int v; +@property (assign, readonly) float w; +@property (assign, readonly) id x; +@property (assign, readonly) Test *y; +@property (assign, readonly) id *z; +@property (assign, readonly) ClassA *a; +@property (assign, readonly) ClassB *b; +@end + +@implementation Test +@synthesize v; +@synthesize w; +@synthesize x; +@synthesize y; +@synthesize z; +@synthesize a; +@synthesize b; +@end + + +/* This is sometimes OK, sometimes not OK. */ +@interface Test2 +{ + int v; /* { dg-warning "originally specified here" } */ + float w; /* { dg-warning "originally specified here" } */ + id x; /* { dg-warning "originally specified here" } */ + Test *y; + id *z; /* { dg-warning "originally specified here" } */ + ClassA *a; /* { dg-warning "originally specified here" } */ + ClassB *b; +} +@property (assign, readonly) float v; +@property (assign, readonly) id w; +@property (assign, readonly) int x; +@property (assign, readonly) id y; +@property (assign, readonly) Test *z; +@property (assign, readonly) ClassB *a; +@property (assign, readonly) ClassA *b; +@end + +@implementation Test2 +@synthesize v; /* { dg-error "property .v. is using instance variable .v. of incompatible type" } */ +@synthesize w; /* { dg-error "property .w. is using instance variable .w. of incompatible type" } */ +@synthesize x; /* { dg-error "property .x. is using instance variable .x. of incompatible type" } */ +@synthesize y; +@synthesize z; /* { dg-error "property .z. is using instance variable .z. of incompatible type" } */ +@synthesize a; /* { dg-error "property .a. is using instance variable .a. of incompatible type" } */ +@synthesize b; +@end diff --git a/gcc/testsuite/objc.dg/property/at-property-16.m b/gcc/testsuite/objc.dg/property/at-property-16.m index f40225dea67..95f82e41beb 100644 --- a/gcc/testsuite/objc.dg/property/at-property-16.m +++ b/gcc/testsuite/objc.dg/property/at-property-16.m @@ -34,22 +34,22 @@ @end @interface MyClass2 : MyRootClass -@property (retain) id a; /* { dg-error "assign semantics attributes of property .a. conflict with previous declaration" } */ +@property (retain) id a; /* { dg-warning "assign semantics attributes of property .a. conflict with previous declaration" } */ /* { dg-message "originally specified here" "" { target *-*-* } 13 } */ -@property (assign) id b; /* { dg-error "assign semantics attributes of property .b. conflict with previous declaration" } */ +@property (assign) id b; /* { dg-warning "assign semantics attributes of property .b. conflict with previous declaration" } */ /* { dg-message "originally specified here" "" { target *-*-* } 14 } */ -@property (nonatomic) int c; /* { dg-error ".nonatomic. attribute of property .c. conflicts with previous declaration" } */ +@property (nonatomic) int c; /* { dg-warning ".nonatomic. attribute of property .c. conflicts with previous declaration" } */ /* { dg-message "originally specified here" "" { target *-*-* } 15 } */ -@property int d; /* { dg-error ".nonatomic. attribute of property .d. conflicts with previous declaration" } */ +@property int d; /* { dg-warning ".nonatomic. attribute of property .d. conflicts with previous declaration" } */ /* { dg-message "originally specified here" "" { target *-*-* } 16 } */ -@property (setter=setX:) int e; /* { dg-error ".setter. attribute of property .e. conflicts with previous declaration" } */ +@property (setter=setX:) int e; /* { dg-warning ".setter. attribute of property .e. conflicts with previous declaration" } */ /* { dg-message "originally specified here" "" { target *-*-* } 17 } */ -@property (getter=x) int f; /* { dg-error ".getter. attribute of property .f. conflicts with previous declaration" } */ +@property (getter=x) int f; /* { dg-warning ".getter. attribute of property .f. conflicts with previous declaration" } */ /* { dg-message "originally specified here" "" { target *-*-* } 18 } */ -@property (readonly) int g; /* { dg-error ".readonly. attribute of property .g. conflicts with previous declaration" } */ +@property (readonly) int g; /* { dg-warning ".readonly. attribute of property .g. conflicts with previous declaration" } */ /* { dg-message "originally specified here" "" { target *-*-* } 19 } */ @property (readwrite) int h; /* Ok */ -@property (readonly) int i; /* { dg-error ".getter. attribute of property .i. conflicts with previous declaration" } */ +@property (readonly) int i; /* { dg-warning ".getter. attribute of property .i. conflicts with previous declaration" } */ /* { dg-message "originally specified here" "" { target *-*-* } 21 } */ @end diff --git a/gcc/testsuite/objc.dg/property/at-property-18.m b/gcc/testsuite/objc.dg/property/at-property-18.m index 58b1d6a07cc..e6ffb39cbd2 100644 --- a/gcc/testsuite/objc.dg/property/at-property-18.m +++ b/gcc/testsuite/objc.dg/property/at-property-18.m @@ -26,22 +26,22 @@ @end @interface MyRootClass (Category) -@property (retain) id a; /* { dg-error "assign semantics attributes of property .a. conflict with previous declaration" } */ +@property (retain) id a; /* { dg-warning "assign semantics attributes of property .a. conflict with previous declaration" } */ /* { dg-message "originally specified here" "" { target *-*-* } 16 } */ -@property (assign) id b; /* { dg-error "assign semantics attributes of property .b. conflict with previous declaration" } */ +@property (assign) id b; /* { dg-warning "assign semantics attributes of property .b. conflict with previous declaration" } */ /* { dg-message "originally specified here" "" { target *-*-* } 17 } */ -@property (nonatomic) int c; /* { dg-error ".nonatomic. attribute of property .c. conflicts with previous declaration" } */ +@property (nonatomic) int c; /* { dg-warning ".nonatomic. attribute of property .c. conflicts with previous declaration" } */ /* { dg-message "originally specified here" "" { target *-*-* } 18 } */ -@property int d; /* { dg-error ".nonatomic. attribute of property .d. conflicts with previous declaration" } */ +@property int d; /* { dg-warning ".nonatomic. attribute of property .d. conflicts with previous declaration" } */ /* { dg-message "originally specified here" "" { target *-*-* } 19 } */ -@property (setter=setX:) int e; /* { dg-error ".setter. attribute of property .e. conflicts with previous declaration" } */ +@property (setter=setX:) int e; /* { dg-warning ".setter. attribute of property .e. conflicts with previous declaration" } */ /* { dg-message "originally specified here" "" { target *-*-* } 20 } */ -@property (getter=x) int f; /* { dg-error ".getter. attribute of property .f. conflicts with previous declaration" } */ +@property (getter=x) int f; /* { dg-warning ".getter. attribute of property .f. conflicts with previous declaration" } */ /* { dg-message "originally specified here" "" { target *-*-* } 21 } */ -@property (readonly) int g; /* { dg-error ".readonly. attribute of property .g. conflicts with previous declaration" } */ +@property (readonly) int g; /* { dg-warning ".readonly. attribute of property .g. conflicts with previous declaration" } */ /* { dg-message "originally specified here" "" { target *-*-* } 22 } */ @property (readwrite) int h; /* Ok */ -@property (readonly) int i; /* { dg-error ".getter. attribute of property .i. conflicts with previous declaration" } */ +@property (readonly) int i; /* { dg-warning ".getter. attribute of property .i. conflicts with previous declaration" } */ /* { dg-message "originally specified here" "" { target *-*-* } 24 } */ @property (nonatomic) float j; /* Ok */ @end diff --git a/gcc/testsuite/objc.dg/property/at-property-21.m b/gcc/testsuite/objc.dg/property/at-property-21.m new file mode 100644 index 00000000000..d1f54b1cda8 --- /dev/null +++ b/gcc/testsuite/objc.dg/property/at-property-21.m @@ -0,0 +1,23 @@ +/* Contributed by Nicola Pero , November 2010. */ +/* { dg-do compile } */ + +#include + +@protocol MyProtocol +- (void) message; +@end + +@interface MyRootClass +{ + Class isa; +} + +/* Test the warnings on 'assign' with protocols. */ +@property id property_a; /* { dg-warning "object property .property.a. has no .assign., .retain. or .copy. attribute" } */ + /* { dg-message ".assign. can be unsafe for Objective-C objects" "" { target *-*-* } 16 } */ + +@property MyRootClass *property_b; /* { dg-warning "object property .property.b. has no .assign., .retain. or .copy. attribute" } */ + /* { dg-message ".assign. can be unsafe for Objective-C objects" "" { target *-*-* } 19 } */ + +@property Class property_c; /* No 'assign' warning (Classes are static objects so assign semantics do not matter for them). */ +@end diff --git a/gcc/testsuite/objc.dg/property/at-property-22.m b/gcc/testsuite/objc.dg/property/at-property-22.m new file mode 100644 index 00000000000..af7f3bc1b4e --- /dev/null +++ b/gcc/testsuite/objc.dg/property/at-property-22.m @@ -0,0 +1,172 @@ +/* Contributed by Nicola Pero , November 2010. */ +/* { dg-do run } */ +/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */ + +/* Test properties of different types. */ + +#include +#include +#include + +enum colour { Red, Black }; + +@interface MyRootClass +{ + Class isa; +} ++ (id) initialize; ++ (id) alloc; +- (id) init; ++ (Class) class; +@end + +@implementation MyRootClass ++ (id) initialize { return self; } ++ (id) alloc { return class_createInstance (self, 0); } +- (id) init { return self; } ++ (Class) class { return self; } +@end + + +@interface MyClass : MyRootClass +{ + /* A bunch of C types. */ + char pchar; + short pshort; + int pint; + long plong; + float pfloat; + double pdouble; + enum colour penum; + + /* A bunch of pointers to C types. */ + char *pcharp; + short *pshortp; + int *pintp; + long *plongp; + float *pfloatp; + double *pdoublep; + enum colour *penump; + + /* A bunch of Objective-C types. */ + id pid; + Class pclass; + MyClass *pMyClassp; +} +@property (assign) char pchar; +@property (assign) short pshort; +@property (assign) int pint; +@property (assign) long plong; +@property (assign) float pfloat; +@property (assign) double pdouble; +@property (assign) enum colour penum; + +@property (assign) char *pcharp; +@property (assign) short *pshortp; +@property (assign) int *pintp; +@property (assign) long *plongp; +@property (assign) float *pfloatp; +@property (assign) double *pdoublep; +@property (assign) enum colour *penump; + +@property (assign) id pid; +@property (assign) Class pclass; +@property (assign) MyClass *pMyClassp; +@end + +@implementation MyClass +@synthesize pchar; +@synthesize pshort; +@synthesize pint; +@synthesize plong; +@synthesize pfloat; +@synthesize pdouble; +@synthesize penum; + +@synthesize pcharp; +@synthesize pshortp; +@synthesize pintp; +@synthesize plongp; +@synthesize pfloatp; +@synthesize pdoublep; +@synthesize penump; + +@synthesize pid; +@synthesize pclass; +@synthesize pMyClassp; +@end + +int main (void) +{ + MyClass *object = [[MyClass alloc] init]; + + object.pchar = 1; + if (object.pchar != 1) + abort (); + + object.pshort = 2; + if (object.pshort != 2) + abort (); + + object.pint = 3; + if (object.pint != 3) + abort (); + + object.plong = 4; + if (object.plong != 4) + abort (); + + object.pfloat = 0; + if (object.pfloat != 0) + abort (); + + object.pdouble = 0; + if (object.pdouble != 0) + abort (); + + object.penum = Black; + if (object.penum != Black) + abort (); + + object.pcharp = 0; + if (object.pcharp != 0) + abort (); + + object.pshortp = 0; + if (object.pshortp != 0) + abort (); + + object.pintp = 0; + if (object.pintp != 0) + abort (); + + object.plongp = 0; + if (object.plongp != 0) + abort (); + + object.pfloatp = 0; + if (object.pfloatp != 0) + abort (); + + object.pdoublep = 0; + if (object.pdoublep != 0) + abort (); + + object.penump = 0; + if (object.penump != 0) + abort (); + + object.pid = object; + if (object.pid != object) + abort (); + + object.pclass = [MyClass class]; + if (object.pclass != [MyClass class]) + abort (); + + object.pMyClassp = object; + if (object.pMyClassp != object) + abort (); + + return 0; +} diff --git a/gcc/testsuite/objc.dg/property/at-property-23.m b/gcc/testsuite/objc.dg/property/at-property-23.m new file mode 100644 index 00000000000..c1fd29df4f3 --- /dev/null +++ b/gcc/testsuite/objc.dg/property/at-property-23.m @@ -0,0 +1,17 @@ +/* Contributed by Nicola Pero , November 2010. */ +/* { dg-do compile } */ + +/* Test that properties of type arrays or bitfields are rejected. */ + +#include +#include +#include + +@interface MyRootClass +{ + Class isa; +} +@property int a[8]; /* { dg-error "property can not be an array" } */ +@property int b:8; /* { dg-error "property can not be a bit-field" } */ +@property int c[]; /* { dg-error "property can not be an array" } */ +@end diff --git a/gcc/testsuite/objc.dg/property/at-property-4.m b/gcc/testsuite/objc.dg/property/at-property-4.m index e327930f87b..941aab8e33c 100644 --- a/gcc/testsuite/objc.dg/property/at-property-4.m +++ b/gcc/testsuite/objc.dg/property/at-property-4.m @@ -28,7 +28,7 @@ /* Now test various problems. */ @property (readonly, readwrite) int a; /* { dg-error ".readonly. attribute conflicts with .readwrite. attribute" } */ -@property (readonly, setter=mySetterB:) int b; /* { dg-warning ".readonly. attribute conflicts with .setter. attribute" } */ +@property (readonly, setter=mySetterB:) int b; /* { dg-error ".readonly. attribute conflicts with .setter. attribute" } */ @property (assign, retain) id c; /* { dg-error ".assign. attribute conflicts with .retain. attribute" } */ @property (assign, copy) id d; /* { dg-error ".assign. attribute conflicts with .copy. attribute" } */ diff --git a/gcc/testsuite/objc.dg/property/property-neg-5.m b/gcc/testsuite/objc.dg/property/property-neg-5.m index 403f6841c8d..464470cba7b 100644 --- a/gcc/testsuite/objc.dg/property/property-neg-5.m +++ b/gcc/testsuite/objc.dg/property/property-neg-5.m @@ -1,5 +1,5 @@ /* { dg-do compile } */ @interface Foo -@property ( readonly, getter = HELLO, setter = THERE : ) int value; /* { dg-warning ".readonly. attribute conflicts with .setter. attribute" } */ +@property ( readonly, getter = HELLO, setter = THERE : ) int value; /* { dg-error ".readonly. attribute conflicts with .setter. attribute" } */ @end diff --git a/gcc/testsuite/objc.dg/property/synthesize-10.m b/gcc/testsuite/objc.dg/property/synthesize-10.m new file mode 100644 index 00000000000..fc4683187df --- /dev/null +++ b/gcc/testsuite/objc.dg/property/synthesize-10.m @@ -0,0 +1,53 @@ +/* Contributed by Nicola Pero , November 2010. */ +/* { dg-do run } */ +/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */ + +/* Test @synthesize with bitfield instance variables. */ + +#include +#include +#include + +@interface MyRootClass +{ + Class isa; + int countA : 2; + int countB : 3; + int countC : 4; +} ++ (id) initialize; ++ (id) alloc; +- (id) init; +@property (nonatomic) int countA; +@property (nonatomic) int countB; +@property (nonatomic) int countC; +@end + +@implementation MyRootClass ++ (id) initialize { return self; } ++ (id) alloc { return class_createInstance (self, 0); } +- (id) init { return self; } +@synthesize countA; +@synthesize countB; +@synthesize countC; +@end + +int main (void) +{ + MyRootClass *object = [[MyRootClass alloc] init]; + + object.countA = 1; + object.countB = 3; + object.countC = 4; + + if (object.countA != 1) + abort (); + + if (object.countB != 3) + abort (); + + if (object.countC != 4) + abort (); + + return 0; +} diff --git a/gcc/testsuite/objc.dg/property/synthesize-11.m b/gcc/testsuite/objc.dg/property/synthesize-11.m new file mode 100644 index 00000000000..e49d23424b9 --- /dev/null +++ b/gcc/testsuite/objc.dg/property/synthesize-11.m @@ -0,0 +1,31 @@ +/* Contributed by Nicola Pero , November 2010. */ +/* { dg-do compile } */ + +/* Test errors when @synthesize is used with bitfield instance variables in an incorrect way. */ + +#include +#include +#include + +@interface MyRootClass +{ + Class isa; + int countA : 2; /* { dg-message "originally specified here" } */ + int countB : 3; /* { dg-message "originally specified here" } */ +} ++ (id) initialize; ++ (id) alloc; +- (id) init; +@property int countA; +@property (nonatomic) short countB; +@end + +@implementation MyRootClass ++ (id) initialize { return self; } ++ (id) alloc { return class_createInstance (self, 0); } +- (id) init { return self; } +@synthesize countA; /* { dg-error ".atomic. property .countA. is using bit-field instance variable .countA." } */ +@synthesize countB; /* { dg-error "property .countB. is using instance variable .countB. of incompatible type" } */ +@end /* { dg-warning "incomplete implementation of class" } */ +/* { dg-warning "method definition for ..setCountA.. not found" "" { target *-*-* } 29 } */ +/* { dg-warning "method definition for ..countA. not found" "" { target *-*-* } 29 } */ diff --git a/gcc/testsuite/objc.dg/property/synthesize-9.m b/gcc/testsuite/objc.dg/property/synthesize-9.m new file mode 100644 index 00000000000..7eae31d3f4d --- /dev/null +++ b/gcc/testsuite/objc.dg/property/synthesize-9.m @@ -0,0 +1,80 @@ +/* Contributed by Nicola Pero , November 2010. */ +/* { dg-do compile } */ + +/* Test that when using @synthesize with a readonly property, the + instance variable can be a specialization of the property type. */ + +#include + +@protocol MyProtocol +- (void)aMethod; +@end + +@interface ClassA +@end + +@interface ClassB : ClassA +@end + + +/* This is all OK. */ +@interface Test +{ + int v; + float w; + id x; + Test *y; + id *z; + ClassA *a; + ClassB *b; + ClassA *c; +} +@property (assign, readonly) int v; +@property (assign, readonly) float w; +@property (assign, readonly) id x; +@property (assign, readonly) Test *y; +@property (assign, readonly) id *z; +@property (assign, readonly) ClassA *a; +@property (assign, readonly) ClassB *b; +@end + +@implementation Test +@synthesize v; +@synthesize w; +@synthesize x; +@synthesize y; +@synthesize z; +@synthesize a; +@synthesize b; +@end + + +/* This is sometimes OK, sometimes not OK. */ +@interface Test2 +{ + int v; /* { dg-message "originally specified here" } */ + float w; /* { dg-message "originally specified here" } */ + id x; /* { dg-message "originally specified here" } */ + Test *y; + id *z; /* { dg-message "originally specified here" } */ + ClassA *a; /* { dg-message "originally specified here" } */ + ClassB *b; +} +@property (assign, readonly) float v; +@property (assign, readonly) id w; +@property (assign, readonly) int x; +@property (assign, readonly) id y; +@property (assign, readonly) Test *z; +@property (assign, readonly) ClassB *a; +@property (assign, readonly) ClassA *b; +@end + +@implementation Test2 +@synthesize v; /* { dg-error "property .v. is using instance variable .v. of incompatible type" } */ +@synthesize w; /* { dg-error "property .w. is using instance variable .w. of incompatible type" } */ +@synthesize x; /* { dg-error "property .x. is using instance variable .x. of incompatible type" } */ +@synthesize y; +@synthesize z; /* { dg-error "property .z. is using instance variable .z. of incompatible type" } */ +@synthesize a; /* { dg-error "property .a. is using instance variable .a. of incompatible type" } */ +@synthesize b; +@end -- 2.11.0