From 554fd8c5195424bdbcabf5de30fdc183aba391bd Mon Sep 17 00:00:00 2001 From: upstream source tree Date: Sun, 15 Mar 2015 20:14:05 -0400 Subject: obtained gcc-4.6.4.tar.bz2 from upstream website; verified gcc-4.6.4.tar.bz2.sig; imported gcc-4.6.4 source tree from verified upstream tarball. downloading a git-generated archive based on the 'upstream' tag should provide you with a source tree that is binary identical to the one extracted from the above tarball. if you have obtained the source via the command 'git clone', however, do note that line-endings of files in your working directory might differ from line-endings of the respective files in the upstream repository. --- gcc/testsuite/objc.dg/property/at-property-1.m | 21 +++ gcc/testsuite/objc.dg/property/at-property-10.m | 100 +++++++++++ gcc/testsuite/objc.dg/property/at-property-11.m | 47 ++++++ gcc/testsuite/objc.dg/property/at-property-12.m | 47 ++++++ gcc/testsuite/objc.dg/property/at-property-13.m | 72 ++++++++ gcc/testsuite/objc.dg/property/at-property-14.m | 20 +++ gcc/testsuite/objc.dg/property/at-property-15.m | 20 +++ gcc/testsuite/objc.dg/property/at-property-16.m | 55 +++++++ gcc/testsuite/objc.dg/property/at-property-17.m | 98 +++++++++++ gcc/testsuite/objc.dg/property/at-property-18.m | 47 ++++++ gcc/testsuite/objc.dg/property/at-property-19.m | 74 +++++++++ gcc/testsuite/objc.dg/property/at-property-2.m | 13 ++ gcc/testsuite/objc.dg/property/at-property-20.m | 81 +++++++++ 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-24.m | 118 +++++++++++++ gcc/testsuite/objc.dg/property/at-property-25.m | 87 ++++++++++ gcc/testsuite/objc.dg/property/at-property-26.m | 85 ++++++++++ gcc/testsuite/objc.dg/property/at-property-27.m | 66 ++++++++ gcc/testsuite/objc.dg/property/at-property-28.m | 29 ++++ gcc/testsuite/objc.dg/property/at-property-29.m | 14 ++ gcc/testsuite/objc.dg/property/at-property-3.m | 15 ++ gcc/testsuite/objc.dg/property/at-property-4.m | 40 +++++ gcc/testsuite/objc.dg/property/at-property-5.m | 34 ++++ gcc/testsuite/objc.dg/property/at-property-6.m | 61 +++++++ gcc/testsuite/objc.dg/property/at-property-7.m | 58 +++++++ gcc/testsuite/objc.dg/property/at-property-8.m | 58 +++++++ gcc/testsuite/objc.dg/property/at-property-9.m | 53 ++++++ .../objc.dg/property/at-property-deprecated-1.m | 37 +++++ .../objc.dg/property/at-property-deprecated-2.m | 25 +++ gcc/testsuite/objc.dg/property/dotsyntax-1.m | 63 +++++++ gcc/testsuite/objc.dg/property/dotsyntax-10.m | 86 ++++++++++ gcc/testsuite/objc.dg/property/dotsyntax-11.m | 61 +++++++ gcc/testsuite/objc.dg/property/dotsyntax-12.m | 105 ++++++++++++ gcc/testsuite/objc.dg/property/dotsyntax-13.m | 53 ++++++ gcc/testsuite/objc.dg/property/dotsyntax-14.m | 77 +++++++++ gcc/testsuite/objc.dg/property/dotsyntax-15.m | 80 +++++++++ gcc/testsuite/objc.dg/property/dotsyntax-16.m | 91 +++++++++++ gcc/testsuite/objc.dg/property/dotsyntax-17.m | 67 ++++++++ gcc/testsuite/objc.dg/property/dotsyntax-18.m | 90 ++++++++++ gcc/testsuite/objc.dg/property/dotsyntax-19.m | 113 +++++++++++++ gcc/testsuite/objc.dg/property/dotsyntax-2.m | 72 ++++++++ gcc/testsuite/objc.dg/property/dotsyntax-20.m | 67 ++++++++ gcc/testsuite/objc.dg/property/dotsyntax-21.m | 113 +++++++++++++ gcc/testsuite/objc.dg/property/dotsyntax-22.m | 19 +++ gcc/testsuite/objc.dg/property/dotsyntax-3.m | 64 ++++++++ gcc/testsuite/objc.dg/property/dotsyntax-4.m | 42 +++++ gcc/testsuite/objc.dg/property/dotsyntax-5.m | 78 +++++++++ gcc/testsuite/objc.dg/property/dotsyntax-6.m | 106 ++++++++++++ gcc/testsuite/objc.dg/property/dotsyntax-7.m | 48 ++++++ gcc/testsuite/objc.dg/property/dotsyntax-8.m | 62 +++++++ gcc/testsuite/objc.dg/property/dotsyntax-9.m | 77 +++++++++ .../objc.dg/property/dotsyntax-deprecated-1.m | 41 +++++ gcc/testsuite/objc.dg/property/dynamic-1.m | 34 ++++ gcc/testsuite/objc.dg/property/dynamic-2.m | 45 +++++ gcc/testsuite/objc.dg/property/dynamic-3.m | 49 ++++++ gcc/testsuite/objc.dg/property/dynamic-4.m | 45 +++++ gcc/testsuite/objc.dg/property/dynamic-5.m | 53 ++++++ gcc/testsuite/objc.dg/property/dynamic-6.m | 26 +++ .../objc.dg/property/fsf-property-basic.m | 62 +++++++ .../objc.dg/property/fsf-property-method-access.m | 67 ++++++++ .../objc.dg/property/fsf-property-named-ivar.m | 61 +++++++ gcc/testsuite/objc.dg/property/property-1.m | 32 ++++ .../objc.dg/property/property-encoding-1.m | 182 +++++++++++++++++++++ gcc/testsuite/objc.dg/property/property-neg-1.m | 13 ++ gcc/testsuite/objc.dg/property/property-neg-2.m | 8 + gcc/testsuite/objc.dg/property/property-neg-3.m | 14 ++ gcc/testsuite/objc.dg/property/property-neg-4.m | 17 ++ gcc/testsuite/objc.dg/property/property-neg-5.m | 5 + gcc/testsuite/objc.dg/property/property-neg-6.m | 9 + gcc/testsuite/objc.dg/property/property-neg-7.m | 20 +++ gcc/testsuite/objc.dg/property/property.exp | 43 +++++ gcc/testsuite/objc.dg/property/synthesize-1.m | 53 ++++++ gcc/testsuite/objc.dg/property/synthesize-10.m | 53 ++++++ gcc/testsuite/objc.dg/property/synthesize-11.m | 31 ++++ gcc/testsuite/objc.dg/property/synthesize-2.m | 51 ++++++ gcc/testsuite/objc.dg/property/synthesize-3.m | 66 ++++++++ gcc/testsuite/objc.dg/property/synthesize-4.m | 67 ++++++++ gcc/testsuite/objc.dg/property/synthesize-5.m | 18 ++ gcc/testsuite/objc.dg/property/synthesize-6.m | 32 ++++ gcc/testsuite/objc.dg/property/synthesize-7.m | 86 ++++++++++ gcc/testsuite/objc.dg/property/synthesize-8.m | 80 +++++++++ gcc/testsuite/objc.dg/property/synthesize-9.m | 80 +++++++++ 84 files changed, 4764 insertions(+) create mode 100644 gcc/testsuite/objc.dg/property/at-property-1.m create mode 100644 gcc/testsuite/objc.dg/property/at-property-10.m create mode 100644 gcc/testsuite/objc.dg/property/at-property-11.m create mode 100644 gcc/testsuite/objc.dg/property/at-property-12.m create mode 100644 gcc/testsuite/objc.dg/property/at-property-13.m create mode 100644 gcc/testsuite/objc.dg/property/at-property-14.m create mode 100644 gcc/testsuite/objc.dg/property/at-property-15.m create mode 100644 gcc/testsuite/objc.dg/property/at-property-16.m create mode 100644 gcc/testsuite/objc.dg/property/at-property-17.m create mode 100644 gcc/testsuite/objc.dg/property/at-property-18.m create mode 100644 gcc/testsuite/objc.dg/property/at-property-19.m create mode 100644 gcc/testsuite/objc.dg/property/at-property-2.m create mode 100644 gcc/testsuite/objc.dg/property/at-property-20.m 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/at-property-24.m create mode 100644 gcc/testsuite/objc.dg/property/at-property-25.m create mode 100644 gcc/testsuite/objc.dg/property/at-property-26.m create mode 100644 gcc/testsuite/objc.dg/property/at-property-27.m create mode 100644 gcc/testsuite/objc.dg/property/at-property-28.m create mode 100644 gcc/testsuite/objc.dg/property/at-property-29.m create mode 100644 gcc/testsuite/objc.dg/property/at-property-3.m create mode 100644 gcc/testsuite/objc.dg/property/at-property-4.m create mode 100644 gcc/testsuite/objc.dg/property/at-property-5.m create mode 100644 gcc/testsuite/objc.dg/property/at-property-6.m create mode 100644 gcc/testsuite/objc.dg/property/at-property-7.m create mode 100644 gcc/testsuite/objc.dg/property/at-property-8.m create mode 100644 gcc/testsuite/objc.dg/property/at-property-9.m create mode 100644 gcc/testsuite/objc.dg/property/at-property-deprecated-1.m create mode 100644 gcc/testsuite/objc.dg/property/at-property-deprecated-2.m create mode 100644 gcc/testsuite/objc.dg/property/dotsyntax-1.m create mode 100644 gcc/testsuite/objc.dg/property/dotsyntax-10.m create mode 100644 gcc/testsuite/objc.dg/property/dotsyntax-11.m create mode 100644 gcc/testsuite/objc.dg/property/dotsyntax-12.m create mode 100644 gcc/testsuite/objc.dg/property/dotsyntax-13.m create mode 100644 gcc/testsuite/objc.dg/property/dotsyntax-14.m create mode 100644 gcc/testsuite/objc.dg/property/dotsyntax-15.m create mode 100644 gcc/testsuite/objc.dg/property/dotsyntax-16.m create mode 100644 gcc/testsuite/objc.dg/property/dotsyntax-17.m create mode 100644 gcc/testsuite/objc.dg/property/dotsyntax-18.m create mode 100644 gcc/testsuite/objc.dg/property/dotsyntax-19.m create mode 100644 gcc/testsuite/objc.dg/property/dotsyntax-2.m create mode 100644 gcc/testsuite/objc.dg/property/dotsyntax-20.m create mode 100644 gcc/testsuite/objc.dg/property/dotsyntax-21.m create mode 100644 gcc/testsuite/objc.dg/property/dotsyntax-22.m create mode 100644 gcc/testsuite/objc.dg/property/dotsyntax-3.m create mode 100644 gcc/testsuite/objc.dg/property/dotsyntax-4.m create mode 100644 gcc/testsuite/objc.dg/property/dotsyntax-5.m create mode 100644 gcc/testsuite/objc.dg/property/dotsyntax-6.m create mode 100644 gcc/testsuite/objc.dg/property/dotsyntax-7.m create mode 100644 gcc/testsuite/objc.dg/property/dotsyntax-8.m create mode 100644 gcc/testsuite/objc.dg/property/dotsyntax-9.m create mode 100644 gcc/testsuite/objc.dg/property/dotsyntax-deprecated-1.m create mode 100644 gcc/testsuite/objc.dg/property/dynamic-1.m create mode 100644 gcc/testsuite/objc.dg/property/dynamic-2.m create mode 100644 gcc/testsuite/objc.dg/property/dynamic-3.m create mode 100644 gcc/testsuite/objc.dg/property/dynamic-4.m create mode 100644 gcc/testsuite/objc.dg/property/dynamic-5.m create mode 100644 gcc/testsuite/objc.dg/property/dynamic-6.m create mode 100644 gcc/testsuite/objc.dg/property/fsf-property-basic.m create mode 100644 gcc/testsuite/objc.dg/property/fsf-property-method-access.m create mode 100644 gcc/testsuite/objc.dg/property/fsf-property-named-ivar.m create mode 100644 gcc/testsuite/objc.dg/property/property-1.m create mode 100644 gcc/testsuite/objc.dg/property/property-encoding-1.m create mode 100644 gcc/testsuite/objc.dg/property/property-neg-1.m create mode 100644 gcc/testsuite/objc.dg/property/property-neg-2.m create mode 100644 gcc/testsuite/objc.dg/property/property-neg-3.m create mode 100644 gcc/testsuite/objc.dg/property/property-neg-4.m create mode 100644 gcc/testsuite/objc.dg/property/property-neg-5.m create mode 100644 gcc/testsuite/objc.dg/property/property-neg-6.m create mode 100644 gcc/testsuite/objc.dg/property/property-neg-7.m create mode 100644 gcc/testsuite/objc.dg/property/property.exp create mode 100644 gcc/testsuite/objc.dg/property/synthesize-1.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-2.m create mode 100644 gcc/testsuite/objc.dg/property/synthesize-3.m create mode 100644 gcc/testsuite/objc.dg/property/synthesize-4.m create mode 100644 gcc/testsuite/objc.dg/property/synthesize-5.m create mode 100644 gcc/testsuite/objc.dg/property/synthesize-6.m create mode 100644 gcc/testsuite/objc.dg/property/synthesize-7.m create mode 100644 gcc/testsuite/objc.dg/property/synthesize-8.m create mode 100644 gcc/testsuite/objc.dg/property/synthesize-9.m (limited to 'gcc/testsuite/objc.dg/property') diff --git a/gcc/testsuite/objc.dg/property/at-property-1.m b/gcc/testsuite/objc.dg/property/at-property-1.m new file mode 100644 index 000000000..4ff269d0f --- /dev/null +++ b/gcc/testsuite/objc.dg/property/at-property-1.m @@ -0,0 +1,21 @@ +/* { dg-do compile } */ + +#include + +@interface MyRootClass +{ + Class isa; +} +@property; /* { dg-error "expected" } */ +@property int; /* { dg-error "expected identifier" } */ + /* { dg-warning "declaration does not declare anything" "" { target *-*-* } 10 } */ +@property int a; +@property int b, c; +@property () int d; /* { dg-error "expected identifier" } */ +@property (readonly) int e; +@property (readonly,) int f; /* { dg-error "expected identifier" } */ +@property (xxx) int g; /* { dg-error "unknown property attribute" } */ +@property (readonly,xxx) int h; /* { dg-error "unknown property attribute" } */ +@property ( int i; /* { dg-error "unknown property attribute" } */ +/* Because the last syntax error opens a '(' and never closes it, we get to the end of input. */ +@end /* { dg-error "expected ..end. at end of input" } */ diff --git a/gcc/testsuite/objc.dg/property/at-property-10.m b/gcc/testsuite/objc.dg/property/at-property-10.m new file mode 100644 index 000000000..79d2ecdbb --- /dev/null +++ b/gcc/testsuite/objc.dg/property/at-property-10.m @@ -0,0 +1,100 @@ +/* Contributed by Nicola Pero , October 2010. */ +/* { dg-do run } */ +/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */ + +/* Test the property syntax in a number of expressions. */ + +#include +#include +#include + +@interface MyRootClass +{ + Class isa; + int a; +} +/* Use the simplest synthesized accessor (assign, nonatomic) as we are + not testing the synthesized accessors in this test, just the + property syntax. */ +@property (nonatomic) int a; ++ (id) initialize; ++ (id) alloc; +- (id) init; +@end + +@implementation MyRootClass ++ (id) initialize { return self; } ++ (id) alloc { return class_createInstance (self, 0); } +- (id) init { return self; } +@synthesize a; +@end + +int +test (int g) +{ + return g; +} + +int main (void) +{ + MyRootClass *object = [[MyRootClass alloc] init]; + MyRootClass *object2 = [[MyRootClass alloc] init]; + + object.a = 14; + object.a = object.a + object.a; + + if (object.a != 28) + abort (); + + object.a = 99; + object.a++; + + if (object.a != 100) + abort (); + + object.a = 99; + object.a *= 2; + + if (object.a != 198) + abort (); + + { + int f = object.a; + + if (f != 198) + abort (); + + if (f != object.a) + abort (); + + if (object.a != f) + abort (); + + object.a = object.a; + + if (object.a != 198) + abort (); + } + + if (test (object.a) != 198) + abort (); + + object.a = -object.a; + + if (object.a != -198) + abort (); + + for (object.a = 0; object.a < 99; object.a++) + object2.a = object.a; + + if (object2.a != object.a - 1) + abort (); + + if (object2.a != 98) + abort (); + + if (object.a != 99) + abort (); + + return 0; +} diff --git a/gcc/testsuite/objc.dg/property/at-property-11.m b/gcc/testsuite/objc.dg/property/at-property-11.m new file mode 100644 index 000000000..33baee9d6 --- /dev/null +++ b/gcc/testsuite/objc.dg/property/at-property-11.m @@ -0,0 +1,47 @@ +/* Contributed by Nicola Pero , October 2010. */ +/* { dg-do run } */ +/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */ + +/* Test that properties are found even if implemented in superclasses. */ + +#include +#include +#include + +@interface MyRootClass +{ + Class isa; + int a; +} +/* Use the simplest synthesized accessor (assign, nonatomic) as we are + not testing the synthesized accessors in this test, just the + property syntax. */ +@property (nonatomic) int a; ++ (id) initialize; ++ (id) alloc; +- (id) init; +@end + +@implementation MyRootClass ++ (id) initialize { return self; } ++ (id) alloc { return class_createInstance (self, 0); } +- (id) init { return self; } +@synthesize a; +@end + +@interface MySubClass : MyRootClass +@end + +@implementation MySubClass +@end + +int main (void) +{ + MySubClass *object = [[MySubClass alloc] init]; + + object.a = 40; + if (object.a != 40) + abort (); + + return 0; +} diff --git a/gcc/testsuite/objc.dg/property/at-property-12.m b/gcc/testsuite/objc.dg/property/at-property-12.m new file mode 100644 index 000000000..e36f57aaa --- /dev/null +++ b/gcc/testsuite/objc.dg/property/at-property-12.m @@ -0,0 +1,47 @@ +/* Contributed by Nicola Pero , October 2010. */ +/* { dg-do run } */ +/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */ + +/* Test atomic, assign synthesized methods. */ + +#include +#include +#include + +@interface MyRootClass +{ + Class isa; + int a; + id b; +} +@property int a; +@property (assign) id b; ++ (id) initialize; ++ (id) alloc; +- (id) init; +@end + +@implementation MyRootClass ++ (id) initialize { return self; } ++ (id) alloc { return class_createInstance (self, 0); } +- (id) init { return self; } +@synthesize a; +@synthesize b; +@end + +int main (void) +{ + MyRootClass *object = [[MyRootClass alloc] init]; + + object.a = 40; + if (object.a != 40) + abort (); + + object.b = object; + if (object.b != object) + abort (); + + return 0; +} + + diff --git a/gcc/testsuite/objc.dg/property/at-property-13.m b/gcc/testsuite/objc.dg/property/at-property-13.m new file mode 100644 index 000000000..89bf748a2 --- /dev/null +++ b/gcc/testsuite/objc.dg/property/at-property-13.m @@ -0,0 +1,72 @@ +/* Contributed by Nicola Pero , October 2010. */ +/* { dg-do run } */ +/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */ + +/* Test retain and copy synthesized methods. */ + +#include +#include +#include + +@interface MyRootClass +{ + Class isa; + int copy_count; + id a; + id b; +} +@property (copy) id a; +@property (retain) id b; ++ (id) initialize; ++ (id) alloc; +- (id) init; +- (id) copyWithZone: (void *)zone; +- (int) copyCount; +- (id) autorelease; +- (oneway void) release; +- (id) retain; +@end + +/* This class implements copyWithZone, which doesn't do anything other + than increasing a counter of how many copies were made. */ +@implementation MyRootClass ++ (id) initialize { return self; } ++ (id) alloc { return class_createInstance (self, 0); } +- (id) init { return self; } +- (id) copyWithZone: (void *)zone { copy_count++; return self; } +- (int) copyCount { return copy_count; } +- (id) autorelease { return self; } +- (oneway void) release { return; } +- (id) retain { return self; } +@synthesize a; +@synthesize b; +@end + +int main (void) +{ + MyRootClass *object = [[MyRootClass alloc] init]; + MyRootClass *argument = [[MyRootClass alloc] init]; + + /* This should copy argument. */ + object.a = argument; + if (object.a != argument) + abort (); + + /* Test that it was copied. */ + if ([object.a copyCount] != 1) + abort (); + + /* We just test that the retain accessors seem to work and that they + don't copy. We don't test that retain was actually called, + because if garbage collection is enabled, it may never be + called! */ + object.b = argument; + if (object.b != argument) + abort (); + + /* Test that it was not copied. */ + if ([object.b copyCount] != 1) + abort (); + + return 0; +} diff --git a/gcc/testsuite/objc.dg/property/at-property-14.m b/gcc/testsuite/objc.dg/property/at-property-14.m new file mode 100644 index 000000000..ccf842b7f --- /dev/null +++ b/gcc/testsuite/objc.dg/property/at-property-14.m @@ -0,0 +1,20 @@ +/* Contributed by Nicola Pero , November 2010. */ +/* { dg-do compile } */ + +#include + +@interface MyRootClass +{ + Class isa; +} + +/* Test the warnings on 'assign'. */ +@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 (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). */ +@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 } */ +@end diff --git a/gcc/testsuite/objc.dg/property/at-property-15.m b/gcc/testsuite/objc.dg/property/at-property-15.m new file mode 100644 index 000000000..ef5344246 --- /dev/null +++ b/gcc/testsuite/objc.dg/property/at-property-15.m @@ -0,0 +1,20 @@ +/* Contributed by Nicola Pero , November 2010. */ +/* { dg-do compile } */ +/* { dg-options "-Wno-property-assign-default" } */ + +#include + +/* Test that -Wno-property-assign-default turns off all "object + property xxx has no assign, return or copy attribute" warnings. */ + +@interface MyRootClass +{ + Class isa; +} + +@property id property_a; /* Would normally generate a warning. */ +@property (readonly) id property_b; +@property id *property_c; +@property Class property_d; +@property MyRootClass *property_e; /* Would normally generate a warning. */ +@end diff --git a/gcc/testsuite/objc.dg/property/at-property-16.m b/gcc/testsuite/objc.dg/property/at-property-16.m new file mode 100644 index 000000000..95f82e41b --- /dev/null +++ b/gcc/testsuite/objc.dg/property/at-property-16.m @@ -0,0 +1,55 @@ +/* Contributed by Nicola Pero , November 2010. */ +/* { dg-do compile } */ + +#include + +/* Test that if you have a property declared in a class and a + sub-class, the attributes match. */ + +@interface MyRootClass +{ + 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; +@end + +@interface MyClass : MyRootClass +@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; +@end + +@interface MyClass2 : MyRootClass +@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-warning "assign semantics attributes of property .b. conflict with previous declaration" } */ + /* { dg-message "originally specified here" "" { target *-*-* } 14 } */ +@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-warning ".nonatomic. attribute of property .d. conflicts with previous declaration" } */ + /* { dg-message "originally specified here" "" { target *-*-* } 16 } */ +@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-warning ".getter. attribute of property .f. conflicts with previous declaration" } */ + /* { dg-message "originally specified here" "" { target *-*-* } 18 } */ +@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-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-17.m b/gcc/testsuite/objc.dg/property/at-property-17.m new file mode 100644 index 000000000..efb62d6f7 --- /dev/null +++ b/gcc/testsuite/objc.dg/property/at-property-17.m @@ -0,0 +1,98 @@ +/* Contributed by Nicola Pero , November 2010. */ +/* { dg-do compile } */ + +#include + +/* Test that if you have a property declared in a class, with + getters/setters in the superclass, there are no warnings. */ + +@interface MyRootClass +{ + Class isa; + int myCount; + int myCount2; + int myCount3; +} +- (int)count; +- (void)setCount: (int)number; +- (int)count2; +- (void)setCount2: (int)number; +- (int)count3; +@end + +@implementation MyRootClass +- (int) count +{ + return myCount; +} +- (void) setCount: (int)number +{ + myCount = number; +} +- (int) count2 +{ + return myCount2; +} +- (void) setCount2: (int)number +{ + myCount2 = number; +} +- (int) count3 +{ + return myCount3; +} +@end + + + +/* Try with a subclass. */ +@interface MyClass : MyRootClass +@property int count; +@end + +@implementation MyClass +@end /* No warnings. */ + + + +/* Try with a category. */ +@interface MyRootClass (count) +@property int count; +@end + +@implementation MyRootClass (count) +@end /* No warnings. */ + + + +/* Try with a category of a subclass. */ +@interface MyClass2 : MyClass +@end + +@implementation MyClass2 +@end + +@interface MyClass2 (count2) +@property int count2; +@end + +@implementation MyClass2 (count2) +@end /* No warnings. */ + + + +/* Now, try with a category of a subclass, but with a missing setter, + which should generate a warning. */ +@interface MyClass3 : MyClass +@end + +@implementation MyClass3 +@end + +@interface MyClass3 (count3) +@property int count3; +@end + +@implementation MyClass3 (count3) +@end /* { dg-warning "incomplete implementation" } */ +/* { dg-warning "method definition for .-setCount3:. not found" "" { target *-*-* } 97 } */ diff --git a/gcc/testsuite/objc.dg/property/at-property-18.m b/gcc/testsuite/objc.dg/property/at-property-18.m new file mode 100644 index 000000000..e6ffb39cb --- /dev/null +++ b/gcc/testsuite/objc.dg/property/at-property-18.m @@ -0,0 +1,47 @@ +/* Contributed by Nicola Pero , November 2010. */ +/* { dg-do compile } */ + +#include + +/* Test that if you have a property declared in a class and a + category, the attributes match. This is almost the same as + at-property-16.m, but for a category. It is a separate file + because it is difficult to test multiple messages for the same + line. */ + +@interface MyRootClass +{ + 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 (nonatomic) float j; +@end + +@interface MyRootClass (Category) +@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-warning "assign semantics attributes of property .b. conflict with previous declaration" } */ + /* { dg-message "originally specified here" "" { target *-*-* } 17 } */ +@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-warning ".nonatomic. attribute of property .d. conflicts with previous declaration" } */ + /* { dg-message "originally specified here" "" { target *-*-* } 19 } */ +@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-warning ".getter. attribute of property .f. conflicts with previous declaration" } */ + /* { dg-message "originally specified here" "" { target *-*-* } 21 } */ +@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-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-19.m b/gcc/testsuite/objc.dg/property/at-property-19.m new file mode 100644 index 000000000..be898e218 --- /dev/null +++ b/gcc/testsuite/objc.dg/property/at-property-19.m @@ -0,0 +1,74 @@ +/* Contributed by Nicola Pero , October 2010. */ +/* { dg-do run } */ +/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */ + +/* Test looking up a @property in a protocol of a category of a superclass. */ + +#include +#include +#include + +@interface MyRootClass +{ + Class isa; + int a; +} ++ (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 getter/setter, so that the only way to compile + object.count is to find the actual @property. */ +@protocol count +@property (getter=number, setter=setNumber:) int count; +@end + +@interface MySubClass : MyRootClass +- (int) testMe; +@end + +@interface MySubClass (Category) +@end + +@implementation MySubClass (Category) +- (int) number +{ + return a; +} +- (void) setNumber: (int)count +{ + a = count; +} +@end + +@implementation MySubClass +- (int) testMe +{ + self.count = 400; + if (self.count != 400) + abort (); + + return self.count; +} +@end + +int main (void) +{ + MySubClass *object = [[MySubClass alloc] init]; + + object.count = 44; + if (object.count != 44) + abort (); + + if ([object testMe] != 400) + abort (); + + return 0; +} diff --git a/gcc/testsuite/objc.dg/property/at-property-2.m b/gcc/testsuite/objc.dg/property/at-property-2.m new file mode 100644 index 000000000..19d59fdaa --- /dev/null +++ b/gcc/testsuite/objc.dg/property/at-property-2.m @@ -0,0 +1,13 @@ +/* { dg-do compile } */ + +#include + +@interface MyRootClass +{ + Class isa; +} +@property int name __attribute__((deprecated)); +@property int table __attribute__((xxx)); /* { dg-warning ".xxx. attribute directive ignored" } */ +@property void function (void); /* { dg-error "declared as a function" } */ +@property typedef int j; /* { dg-error "expected" } */ +@end diff --git a/gcc/testsuite/objc.dg/property/at-property-20.m b/gcc/testsuite/objc.dg/property/at-property-20.m new file mode 100644 index 000000000..1bb49da2b --- /dev/null +++ b/gcc/testsuite/objc.dg/property/at-property-20.m @@ -0,0 +1,81 @@ +/* Contributed by Nicola Pero , November 2010. */ +/* { dg-do compile } */ + +#include + +/* Test that if you have a property declared in a class and a + sub-class, the types match (unless it's a readonly property, in + which case a "specialization" is enough). */ + +@protocol MyProtocolA +- (void) doNothingA; +@end + +@protocol MyProtocolB +- (void) doNothingB; +@end + +@interface MyRootClass +{ + Class isa; +} +@end + +@interface MySubClass1 : MyRootClass +@end + +@interface MySubClass2 : MyRootClass +@end + +@interface MySubClass3 : MyRootClass +@end + +@interface MySubClass4 : MySubClass1 +@end + +/* Now, the test. */ + +@interface MyClass : MyRootClass +{ } +@property (assign) id a; /* { dg-message "originally specified here" } */ +@property int b; /* { dg-message "originally specified here" } */ +@property float c; /* { dg-message "originally specified here" } */ +@property (assign) MyRootClass *d; /* { dg-message "originally specified here" } */ +@property (assign) MySubClass1 *e; /* { dg-message "originally specified here" } */ +@property (assign, readonly) MySubClass1 *f; /* { dg-message "originally specified here" } */ +@property (assign) MySubClass3 *g; /* { dg-message "originally specified here" } */ +@property (assign, readonly) MySubClass3 *h; /* { dg-message "originally specified here" } */ +@end + +/* The following are all OK because they are identical. */ +@interface MyClass2 : MyClass +{ } +@property (assign) id a; +@property int b; +@property float c; +@property (assign) MyRootClass *d; +@property (assign) MySubClass1 *e; +@property (assign, readonly) MySubClass1 *f; +@property (assign) MySubClass3 *g; +@property (assign, readonly) MySubClass3 *h; +@end + +/* The following are not OK. */ +@interface MyClass3 : MyClass +{ } +@property (assign) MySubClass1 *a; /* { dg-warning "type of property .a. conflicts with previous declaration" } */ +@property float b; /* { dg-warning "type of property .b. conflicts with previous declaration" } */ +@property int c; /* { dg-warning "type of property .c. conflicts with previous declaration" } */ +@property (assign) id d; /* { dg-warning "type of property .d. conflicts with previous declaration" } */ +@property (assign) MyRootClass *e; /* { dg-warning "type of property .e. conflicts with previous declaration" } */ +@property (assign, readonly) MyRootClass *f; /* { dg-warning "type of property .f. conflicts with previous declaration" } */ +@property (assign) MySubClass2 *g; /* { dg-warning "type of property .g. conflicts with previous declaration" } */ +@property (assign, readonly) MySubClass2 *h; /* { dg-warning "type of property .h. conflicts with previous declaration" } */ +@end + +/* The following are OK. */ +@interface MyClass4 : MyClass +{ } +@property (assign, readonly) MySubClass4 *f; +@property (assign, readonly) MySubClass3 *h; +@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 000000000..d1f54b1cd --- /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 000000000..03b3d0bb4 --- /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 = (char *)0; + if (object.pcharp != 0) + abort (); + + object.pshortp = (short *)0; + if (object.pshortp != 0) + abort (); + + object.pintp = (int *)0; + if (object.pintp != 0) + abort (); + + object.plongp = (long *)0; + if (object.plongp != 0) + abort (); + + object.pfloatp = (float *)0; + if (object.pfloatp != 0) + abort (); + + object.pdoublep = (double *)0; + if (object.pdoublep != 0) + abort (); + + object.penump = (enum colour *)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 000000000..c1fd29df4 --- /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-24.m b/gcc/testsuite/objc.dg/property/at-property-24.m new file mode 100644 index 000000000..b4a7699f6 --- /dev/null +++ b/gcc/testsuite/objc.dg/property/at-property-24.m @@ -0,0 +1,118 @@ +/* Contributed by Nicola Pero , November 2010. */ +/* { dg-do run } */ +/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */ + +/* Test @optional @properties. */ + +#include +#include +#include + +@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 +{ + 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; +} diff --git a/gcc/testsuite/objc.dg/property/at-property-25.m b/gcc/testsuite/objc.dg/property/at-property-25.m new file mode 100644 index 000000000..422a29e55 --- /dev/null +++ b/gcc/testsuite/objc.dg/property/at-property-25.m @@ -0,0 +1,87 @@ +/* Contributed by Nicola Pero , November 2010. */ +/* { dg-do compile } */ + +/* Test warnings and non-warnings with @optional @properties. */ + +#include +#include +#include + +@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 +{ + 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 +@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 +{ + 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 +@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 } */ diff --git a/gcc/testsuite/objc.dg/property/at-property-26.m b/gcc/testsuite/objc.dg/property/at-property-26.m new file mode 100644 index 000000000..c45757e23 --- /dev/null +++ b/gcc/testsuite/objc.dg/property/at-property-26.m @@ -0,0 +1,85 @@ +/* Contributed by Nicola Pero , December 2010. */ +/* { dg-do run } */ +/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */ + +/* Test @properties in class extensions. */ + +#include +#include +#include + +@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 () +@property (getter=number3, setter=setNumber3:) int count3; +@end + +@implementation MySubClass +@synthesize count1; +@synthesize count2; +- (int) number3 +{ + return count3; +} +- (void) setNumber3: (int)value +{ + count3 = value; +} +@synthesize count4; +@end + +int main (void) +{ + MySubClass *object = [[MySubClass alloc] init]; + + object.count1 = 20; + if (object.count1 != 20) + abort (); + + object.count2 = 11; + if (object.count2 != 11) + abort (); + + object.count3 = 19; + if (object.count3 != 19) + abort (); + + object.count4 = 74; + if (object.count4 != 74) + abort (); + + return 0; +} diff --git a/gcc/testsuite/objc.dg/property/at-property-27.m b/gcc/testsuite/objc.dg/property/at-property-27.m new file mode 100644 index 000000000..727834684 --- /dev/null +++ b/gcc/testsuite/objc.dg/property/at-property-27.m @@ -0,0 +1,66 @@ +/* Contributed by Nicola Pero , 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 +#include +#include + +@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 () +@property (readwrite, getter=number2, setter=setNumber2:) int count2; +@end + +@implementation MySubClass +@synthesize count1; +@synthesize count2; +@end + +int main (void) +{ + MySubClass *object = [[MySubClass alloc] init]; + + object.count1 = 20; + if (object.count1 != 20) + abort (); + + object.count2 = 11; + if (object.count2 != 11) + abort (); + + return 0; +} diff --git a/gcc/testsuite/objc.dg/property/at-property-28.m b/gcc/testsuite/objc.dg/property/at-property-28.m new file mode 100644 index 000000000..de5122443 --- /dev/null +++ b/gcc/testsuite/objc.dg/property/at-property-28.m @@ -0,0 +1,29 @@ +/* Contributed by Nicola Pero , December 2010. */ +/* { dg-do compile } */ + +/* Test errors when extending a property in a class extension. */ + +#include +#include + +@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 + + + diff --git a/gcc/testsuite/objc.dg/property/at-property-29.m b/gcc/testsuite/objc.dg/property/at-property-29.m new file mode 100644 index 000000000..0f31617f8 --- /dev/null +++ b/gcc/testsuite/objc.dg/property/at-property-29.m @@ -0,0 +1,14 @@ +/* Contributed by Nicola Pero , January 2011. */ +/* { dg-do compile } */ + +#include + +@interface MyRootClass +{ + Class isa; +} +/* Test missing '=' in setter/getter attributes. */ +@property (getter) int property_a; /* { dg-error "missing .=. .after .getter. attribute." } */ +@property (setter) int property_b; /* { dg-error "missing .=. .after .setter. attribute." } */ +@property (assign, getter) int property_c; /* { dg-error "missing .=. .after .getter. attribute." } */ +@end diff --git a/gcc/testsuite/objc.dg/property/at-property-3.m b/gcc/testsuite/objc.dg/property/at-property-3.m new file mode 100644 index 000000000..70b522cba --- /dev/null +++ b/gcc/testsuite/objc.dg/property/at-property-3.m @@ -0,0 +1,15 @@ +/* { dg-do compile } */ + +#include + +@interface MyRootClass +{ + Class isa; +} +@property volatile int a; /* This is allowed */ +@property extern int b; /* { dg-error "expected" } */ +@property static int c; /* { dg-error "expected" } */ +@property inline int d; /* { dg-error "expected" } */ +@property typedef int e; /* { dg-error "expected" } */ +@property __thread int f; /* { dg-error "expected" } */ +@end diff --git a/gcc/testsuite/objc.dg/property/at-property-4.m b/gcc/testsuite/objc.dg/property/at-property-4.m new file mode 100644 index 000000000..941aab8e3 --- /dev/null +++ b/gcc/testsuite/objc.dg/property/at-property-4.m @@ -0,0 +1,40 @@ +/* { dg-do compile } */ + +#include + +@interface MyRootClass +{ + Class isa; +} +- (int) myGetter; +- (int) myGetterB; +- (int) myGetter2; +- (void) mySetter: (int)property; +- (void) mySetterB: (int)property; +- (void) mySetter2: (int)property; + +/* Test that all the new property attributes can be parsed. */ +@property (assign) id property_a; +@property (copy) id property_b; +@property (nonatomic) int property_c; +@property (readonly) int property_d; +@property (readwrite) int property_e; +@property (retain) id property_f; +@property (release) int property_g; /* { dg-error "unknown property attribute" } */ + +@property (getter=myGetter) int property_h; +@property (setter=mySetter:) int property_i; + +/* Now test various problems. */ + +@property (readonly, readwrite) int a; /* { dg-error ".readonly. attribute conflicts with .readwrite. 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" } */ +@property (copy, retain) id e; /* { dg-error ".retain. attribute conflicts with .copy. attribute" } */ + +@property (setter=mySetter:,setter=mySetter2:) int f; /* { dg-error ".setter. attribute may only be specified once" } */ +@property (getter=myGetter, getter=myGetter2 ) int g; /* { dg-error ".getter. attribute may only be specified once" } */ + +@end diff --git a/gcc/testsuite/objc.dg/property/at-property-5.m b/gcc/testsuite/objc.dg/property/at-property-5.m new file mode 100644 index 000000000..bd8949b7f --- /dev/null +++ b/gcc/testsuite/objc.dg/property/at-property-5.m @@ -0,0 +1,34 @@ +/* Contributed by Nicola Pero , October 2010. */ +/* { dg-do compile } */ + +#include + +@interface MyRootClass +{ + Class isa; + id property_a; + int property_b; + int property_c; + int property_d; + id property_e; + id property_f; + id property_g; + id property_h; +} + +/* Test various error messages. */ +@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 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" } */ + +@property (retain) id property_e; +@property (retain) id property_f; +@property (retain) id property_g; +@property (retain) id property_h; +@property (retain) id property_e; /* { dg-error "redeclaration of property .property_e." } */ + /* { dg-message "originally specified here" "" { target *-*-* } 26 } */ +@end + +@property id test; /* { dg-error "property declaration not in .interface or .protocol context" } */ diff --git a/gcc/testsuite/objc.dg/property/at-property-6.m b/gcc/testsuite/objc.dg/property/at-property-6.m new file mode 100644 index 000000000..b3584cc40 --- /dev/null +++ b/gcc/testsuite/objc.dg/property/at-property-6.m @@ -0,0 +1,61 @@ +/* Contributed by Nicola Pero , October 2010. */ +/* { dg-do run } */ +/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */ + +/* Test the property syntax with non-synthesized setter/getter + and with standard names. */ + +#include +#include +#include + +@interface MyRootClass +{ + Class isa; + int a; +} +@property (nonatomic) int a; ++ (id) initialize; ++ (id) alloc; +- (id) init; +@end + +@implementation MyRootClass ++ (id) initialize { return self; } ++ (id) alloc { return class_createInstance (self, 0); } +- (id) init { return self; } + +- (int) a +{ + return a; +} +- (void) setA: (int)value +{ + a = value; +} +@end + +int main (void) +{ + MyRootClass *object = [[MyRootClass alloc] init]; + + if (object.a != 0) + abort (); + + object.a = 14; + + if (object.a != 14) + abort (); + + object.a = 23; + + if (object.a != 23) + abort (); + + object.a = 78; + + if (object.a != 78) + abort (); + + return 0; +} diff --git a/gcc/testsuite/objc.dg/property/at-property-7.m b/gcc/testsuite/objc.dg/property/at-property-7.m new file mode 100644 index 000000000..6f5cedaac --- /dev/null +++ b/gcc/testsuite/objc.dg/property/at-property-7.m @@ -0,0 +1,58 @@ +/* Contributed by Nicola Pero , October 2010. */ +/* { dg-do run } */ +/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */ + +/* Test the property syntax with non-synthesized setter/getter + and with a non-standard name for the getter. */ + +#include +#include +#include + +@interface MyRootClass +{ + Class isa; + int a; +} +@property (getter = getA, nonatomic) int a; ++ (id) initialize; ++ (id) alloc; +- (id) init; +@end + +@implementation MyRootClass ++ (id) initialize { return self; } ++ (id) alloc { return class_createInstance (self, 0); } +- (id) init { return self; } + +- (int) getA +{ + return a; +} +- (void) setA: (int)value +{ + a = value; +} +@end + +int main (void) +{ + MyRootClass *object = [[MyRootClass alloc] init]; + + object.a = 14; + + if (object.a != 14) + abort (); + + object.a = 23; + + if (object.a != 23) + abort (); + + object.a = 78; + + if (object.a != 78) + abort (); + + return 0; +} diff --git a/gcc/testsuite/objc.dg/property/at-property-8.m b/gcc/testsuite/objc.dg/property/at-property-8.m new file mode 100644 index 000000000..497dedca7 --- /dev/null +++ b/gcc/testsuite/objc.dg/property/at-property-8.m @@ -0,0 +1,58 @@ +/* Contributed by Nicola Pero , October 2010. */ +/* { dg-do run } */ +/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */ + +/* Test the property syntax with non-synthesized setter/getter + and with a non-standard name for the setter. */ + +#include +#include +#include + +@interface MyRootClass +{ + Class isa; + int a; +} +@property (setter = writeA:, nonatomic) int a; ++ (id) initialize; ++ (id) alloc; +- (id) init; +@end + +@implementation MyRootClass ++ (id) initialize { return self; } ++ (id) alloc { return class_createInstance (self, 0); } +- (id) init { return self; } + +- (int) a +{ + return a; +} +- (void) writeA: (int)value +{ + a = value; +} +@end + +int main (void) +{ + MyRootClass *object = [[MyRootClass alloc] init]; + + object.a = 14; + + if (object.a != 14) + abort (); + + object.a = 23; + + if (object.a != 23) + abort (); + + object.a = 78; + + if (object.a != 78) + abort (); + + return 0; +} diff --git a/gcc/testsuite/objc.dg/property/at-property-9.m b/gcc/testsuite/objc.dg/property/at-property-9.m new file mode 100644 index 000000000..0f144fad2 --- /dev/null +++ b/gcc/testsuite/objc.dg/property/at-property-9.m @@ -0,0 +1,53 @@ +/* Contributed by Nicola Pero , October 2010. */ +/* { dg-do run } */ +/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */ + +/* Test the property syntax with synthesized setter/getter + and with a non-standard name for the getter and setter. */ + +#include +#include +#include + +@interface MyRootClass +{ + Class isa; + int a; +} +/* Use the simplest synthesized accessor (assign, nonatomic) as we are + not testing the synthesized accessors in this test, just the + property syntax. */ +@property (getter = giveMeA, setter = writeA:, nonatomic) int a; ++ (id) initialize; ++ (id) alloc; +- (id) init; +@end + +@implementation MyRootClass ++ (id) initialize { return self; } ++ (id) alloc { return class_createInstance (self, 0); } +- (id) init { return self; } +@synthesize a; +@end + +int main (void) +{ + MyRootClass *object = [[MyRootClass alloc] init]; + + object.a = 14; + + if (object.a != 14) + abort (); + + object.a = 23; + + if (object.a != 23) + abort (); + + object.a = 78; + + if (object.a != 78) + abort (); + + return 0; +} diff --git a/gcc/testsuite/objc.dg/property/at-property-deprecated-1.m b/gcc/testsuite/objc.dg/property/at-property-deprecated-1.m new file mode 100644 index 000000000..e52047771 --- /dev/null +++ b/gcc/testsuite/objc.dg/property/at-property-deprecated-1.m @@ -0,0 +1,37 @@ +/* Contributed by Nicola Pero , October 2010. */ +/* { dg-do compile } */ + +/* Test that properties can be deprecated. */ + +#include +#include +#include + +@interface MyRootClass +{ + Class isa; + int a; +} +@property int a __attribute__((deprecated)); ++ (id) initialize; ++ (id) alloc; +- (id) init; +@end + +@implementation MyRootClass ++ (id) initialize { return self; } ++ (id) alloc { return class_createInstance (self, 0); } +- (id) init { return self; } +@synthesize a; +@end + +int main (void) +{ + MyRootClass *object = [[MyRootClass alloc] init]; + + object.a = 40; /* { dg-warning "is deprecated" } */ + if (object.a != 40) /* { dg-warning "is deprecated" } */ + abort (); + + return 0; +} diff --git a/gcc/testsuite/objc.dg/property/at-property-deprecated-2.m b/gcc/testsuite/objc.dg/property/at-property-deprecated-2.m new file mode 100644 index 000000000..d2901a55b --- /dev/null +++ b/gcc/testsuite/objc.dg/property/at-property-deprecated-2.m @@ -0,0 +1,25 @@ +/* Contributed by Nicola Pero , October 2010. */ +/* { dg-do compile } */ + +/* Test that deprecation warnings are produced when a setter/getter of + a @property is used directly. */ + +#include + +@interface MyClass +{ + Class isa; + int variable; +} +@property (assign, nonatomic) int property __attribute__ ((deprecated)); +@end + +void foo (void) +{ + MyClass *object = nil; + + if ([object property] > 0) /* { dg-warning "is deprecated" } */ + { + [object setProperty: 43]; /* { dg-warning "is deprecated" } */ + } +} diff --git a/gcc/testsuite/objc.dg/property/dotsyntax-1.m b/gcc/testsuite/objc.dg/property/dotsyntax-1.m new file mode 100644 index 000000000..8922f5f03 --- /dev/null +++ b/gcc/testsuite/objc.dg/property/dotsyntax-1.m @@ -0,0 +1,63 @@ +/* Contributed by Nicola Pero , November 2010. */ +/* { dg-do run } */ +/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */ + +/* Test the 'dot syntax' without a declarated property. */ + +#include +#include +#include + +@interface MyRootClass +{ + Class isa; + int a; + id b; +} ++ (id) initialize; ++ (id) alloc; +- (id) init; +- (int) count; +- (void) setCount: (int)value; +- (id) next; +- (void) setNext: (id)value; +@end + +@implementation MyRootClass ++ (id) initialize { return self; } ++ (id) alloc { return class_createInstance (self, 0); } +- (id) init { return self; } +- (int) count +{ + return a; +} +- (void) setCount: (int)value +{ + a = value; +} +- (id) next +{ + return b; +} +- (void) setNext: (id)value +{ + b = value; +} +@end + +int main (void) +{ + MyRootClass *object = [[MyRootClass alloc] init]; + + object.count = 40; + if (object.count != 40) + abort (); + + object.next = object; + if (object.next != object) + abort (); + + return 0; +} + + diff --git a/gcc/testsuite/objc.dg/property/dotsyntax-10.m b/gcc/testsuite/objc.dg/property/dotsyntax-10.m new file mode 100644 index 000000000..433595f3d --- /dev/null +++ b/gcc/testsuite/objc.dg/property/dotsyntax-10.m @@ -0,0 +1,86 @@ +/* Contributed by Nicola Pero , November 2010. */ +/* { dg-do run } */ +/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */ + +/* Test dot-syntax with 'super'. */ + +#include +#include +#include + +static int c; + +@interface MyRootClass +{ + Class isa; + int a; +} ++ (id) initialize; ++ (id) alloc; +- (id) init; +- (int) count; +- (void) setCount: (int)count; ++ (int) classCount; ++ (void) setClassCount: (int)count; +@end + +@implementation MyRootClass ++ (id) initialize { return self; } ++ (id) alloc { return class_createInstance (self, 0); } +- (id) init { return self; } +- (int) count +{ + return a; +} +- (void) setCount: (int)count +{ + a = count; +} ++ (int) classCount +{ + return c; +} ++ (void) setClassCount: (int)count +{ + c = count; +} +@end + +@interface MySubClass : MyRootClass ++ (int) testMe; +- (int) testMe; +@end + +@implementation MySubClass +- (int) testMe +{ + super.count = 400; + if (super.count != 400) + abort (); + + return super.count; +} ++ (int) testMe +{ + super.classCount = 4000; + if (super.classCount != 4000) + abort (); + + return super.classCount; +} +@end + +int main (void) +{ + MySubClass *object = [[MySubClass alloc] init]; + + if ([object testMe] != 400) + abort (); + + if ([MySubClass testMe] != 4000) + abort (); + + return 0; +} + + diff --git a/gcc/testsuite/objc.dg/property/dotsyntax-11.m b/gcc/testsuite/objc.dg/property/dotsyntax-11.m new file mode 100644 index 000000000..6c9d924ca --- /dev/null +++ b/gcc/testsuite/objc.dg/property/dotsyntax-11.m @@ -0,0 +1,61 @@ +/* Contributed by Nicola Pero , November 2010. */ +/* { dg-do compile } */ + +/* Test the error reporting for the dot-syntax in the scenario where + we have a setter, but not a getter, yet a getter is requested. */ + +#include +#include +#include + +static int c; + +@interface MyRootClass +{ + Class isa; + int a; +} ++ (id) initialize; ++ (id) alloc; +- (id) init; +- (void) setCount: (int)count; ++ (void) setClassCount: (int)count; +@end + +@implementation MyRootClass ++ (id) initialize { return self; } ++ (id) alloc { return class_createInstance (self, 0); } +- (id) init { return self; } +- (void) setCount: (int)count +{ + a = count; +} ++ (void) setClassCount: (int)count +{ + c = count; +} +@end + +@interface MySubClass : MyRootClass ++ (int) testMe; +- (int) testMe; +@end + +@implementation MySubClass +- (int) testMe +{ + super.count = 400; + if (super.count != 400) /* { dg-error "no .count. getter found" } */ + abort (); + + return super.count; /* { dg-error "no .count. getter found" } */ +} ++ (int) testMe +{ + super.classCount = 4000; + if (super.classCount != 4000) /* { dg-error "no .classCount. getter found" } */ + abort (); + + return super.classCount; /* { dg-error "no .classCount. getter found" } */ +} +@end diff --git a/gcc/testsuite/objc.dg/property/dotsyntax-12.m b/gcc/testsuite/objc.dg/property/dotsyntax-12.m new file mode 100644 index 000000000..20882f909 --- /dev/null +++ b/gcc/testsuite/objc.dg/property/dotsyntax-12.m @@ -0,0 +1,105 @@ +/* Contributed by Nicola Pero , November 2010. */ +/* { dg-do run } */ +/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */ + +/* Test looking up a setter or getter which are in a protocol attached + to a category of a superclass. */ + +#include +#include +#include + +static int c; + +@interface MyRootClass +{ + Class isa; + int a; +} ++ (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 +- (int) count; +- (void) setCount: (int)count; +@end + +@protocol classCount ++ (int) classCount; ++ (void) setClassCount: (int)count; +@end + +@interface MyRootClass (Category) +@end + +@implementation MyRootClass (Category) +- (int) count +{ + return a; +} +- (void) setCount: (int)count +{ + a = count; +} ++ (int) classCount +{ + return c; +} ++ (void) setClassCount: (int)count +{ + c = count; +} +@end + +@interface MySubClass : MyRootClass ++ (int) testMe; +- (int) testMe; +@end + +@implementation MySubClass +- (int) testMe +{ + self.count = 400; + if (self.count != 400) + abort (); + + return self.count; +} ++ (int) testMe +{ + self.classCount = 4000; + if (self.classCount != 4000) + abort (); + + return self.classCount; +} +@end + +int main (void) +{ + MySubClass *object = [[MySubClass alloc] init]; + + object.count = 44; + if (object.count != 44) + abort (); + + MySubClass.classCount = 40; + if (MySubClass.classCount != 40) + abort (); + + if ([object testMe] != 400) + abort (); + + if ([MySubClass testMe] != 4000) + abort (); + + return 0; +} diff --git a/gcc/testsuite/objc.dg/property/dotsyntax-13.m b/gcc/testsuite/objc.dg/property/dotsyntax-13.m new file mode 100644 index 000000000..c5a4b3301 --- /dev/null +++ b/gcc/testsuite/objc.dg/property/dotsyntax-13.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 dot-syntax with a local variable. */ + +#include +#include +#include + +@interface MyRootClass +{ + Class isa; + int a; +} ++ (id) initialize; ++ (id) alloc; +- (id) init; +- (int) count; +- (void) setCount: (int)count; +@end + +@implementation MyRootClass ++ (id) initialize { return self; } ++ (id) alloc { return class_createInstance (self, 0); } +- (id) init { return self; } +- (int) count +{ + return a; +} +- (void) setCount: (int)count +{ + a = count; +} +@end + +int main (void) +{ + MyRootClass *object = [[MyRootClass alloc] init]; + int i; + + for (i = 0; i < 10; i++) + { + object.count = i; + + if (object.count != i) + abort (); + } + + return 0; +} + + diff --git a/gcc/testsuite/objc.dg/property/dotsyntax-14.m b/gcc/testsuite/objc.dg/property/dotsyntax-14.m new file mode 100644 index 000000000..0606ec4a2 --- /dev/null +++ b/gcc/testsuite/objc.dg/property/dotsyntax-14.m @@ -0,0 +1,77 @@ +/* Contributed by Nicola Pero , November 2010. */ +/* { dg-do compile } */ + +/* Test dot-syntax with accessors to be looked up in protocol @properties. */ + +#include +#include +#include + +@protocol ProtocolA +@property int countA; +@end + +@protocol ProtocolB +@property int countB; +@end + +@protocol ProtocolC +@property int countC; +@end + +@interface MyRootClass +{ + Class isa; +} ++ (id) initialize; ++ (id) alloc; +- (id) init; +@end + +@interface MySubClass +@end + +int function (MySubClass *object, int x) +{ + object.countA = x; + object.countB = x; + object.countC = object.countB; + + return object.countC; +} + +int function2 (MyRootClass *object, int x) +{ + object.countA = x; + object.countB = x; + object.countC = object.countB; + + return object.countC; +} + +int function3 (MyRootClass *object, int x) +{ + object.countA = x; + object.countB = x; + object.countC = object.countB; /* { dg-error "request for member .countC. in something not a structure or union" } */ + + return object.countC; /* { dg-error "request for member .countC. in something not a structure or union" } */ +} + +int function4 (id object, int x) +{ + object.countA = x; + object.countB = x; + object.countC = object.countB; + + return object.countC; +} + +int function5 (id object, int x) +{ + object.countA = x; + object.countB = x; + object.countC = object.countB; /* { dg-error "request for member .countC. in something not a structure or union" } */ + + return object.countC; /* { dg-error "request for member .countC. in something not a structure or union" } */ +} diff --git a/gcc/testsuite/objc.dg/property/dotsyntax-15.m b/gcc/testsuite/objc.dg/property/dotsyntax-15.m new file mode 100644 index 000000000..767f6a2b8 --- /dev/null +++ b/gcc/testsuite/objc.dg/property/dotsyntax-15.m @@ -0,0 +1,80 @@ +/* Contributed by Nicola Pero , November 2010. */ +/* { dg-do compile } */ + +/* Test dot-syntax with accessors to be looked up in protocols. */ + +#include +#include +#include + +@protocol ProtocolA +- (int) countA; +- (void) setCountA: (int)aNumber; +@end + +@protocol ProtocolB +- (int) countB; +- (void) setCountB: (int)aNumber; +@end + +@protocol ProtocolC +- (int) countC; +- (void) setCountC: (int)aNumber; +@end + +@interface MyRootClass +{ + Class isa; +} ++ (id) initialize; ++ (id) alloc; +- (id) init; +@end + +@interface MySubClass +@end + +int function (MySubClass *object, int x) +{ + object.countA = x; + object.countB = x; + object.countC = object.countB; + + return object.countC; +} + +int function2 (MyRootClass *object, int x) +{ + object.countA = x; + object.countB = x; + object.countC = object.countB; + + return object.countC; +} + +int function3 (MyRootClass *object, int x) +{ + object.countA = x; + object.countB = x; + object.countC = object.countB; /* { dg-error "request for member .countC. in something not a structure or union" } */ + + return object.countC; /* { dg-error "request for member .countC. in something not a structure or union" } */ +} + +int function4 (id object, int x) +{ + object.countA = x; + object.countB = x; + object.countC = object.countB; + + return object.countC; +} + +int function5 (id object, int x) +{ + object.countA = x; + object.countB = x; + object.countC = object.countB; /* { dg-error "request for member .countC. in something not a structure or union" } */ + + return object.countC; /* { dg-error "request for member .countC. in something not a structure or union" } */ +} diff --git a/gcc/testsuite/objc.dg/property/dotsyntax-16.m b/gcc/testsuite/objc.dg/property/dotsyntax-16.m new file mode 100644 index 000000000..893db69d9 --- /dev/null +++ b/gcc/testsuite/objc.dg/property/dotsyntax-16.m @@ -0,0 +1,91 @@ +/* Contributed by Nicola Pero , November 2010. */ +/* { dg-do run } */ +/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */ + +/* Test dot-syntax with pre/post increment and decrement. */ + +#include +#include +#include + +@interface MyRootClass +{ + Class isa; + int a; +} ++ (id) initialize; ++ (id) alloc; +- (id) init; +- (int) count; +- (void) setCount: (int)count; +@end + +@implementation MyRootClass ++ (id) initialize { return self; } ++ (id) alloc { return class_createInstance (self, 0); } +- (id) init { return self; } +- (int) count +{ + return a; +} +- (void) setCount: (int)count +{ + a = count; +} +@end + +int main (void) +{ + MyRootClass *object = [[MyRootClass alloc] init]; + + object.count = 10; + if (object.count != 10) + abort (); + + /* First, test that they increment/decrement as expected. */ + object.count++; + if (object.count != 11) + abort (); + + ++object.count; + if (object.count != 12) + abort (); + + object.count--; + if (object.count != 11) + abort (); + + --object.count; + if (object.count != 10) + abort (); + + /* Now, test that they are pre/post increment/decrement, as + expected. */ + if (object.count++ != 10) + abort (); + + if (object.count != 11) + abort (); + + if (++object.count != 12) + abort (); + + if (object.count != 12) + abort (); + + if (object.count-- != 12) + abort (); + + if (object.count != 11) + abort (); + + if (--object.count != 10) + abort (); + + if (object.count != 10) + abort (); + + return 0; +} + + diff --git a/gcc/testsuite/objc.dg/property/dotsyntax-17.m b/gcc/testsuite/objc.dg/property/dotsyntax-17.m new file mode 100644 index 000000000..c28e11f48 --- /dev/null +++ b/gcc/testsuite/objc.dg/property/dotsyntax-17.m @@ -0,0 +1,67 @@ +/* Contributed by Nicola Pero , November 2010. */ +/* { dg-do compile } */ + +/* Test errors with the dot-syntax with pre/post increment and decrement. */ + +#include +#include +#include + +@interface MyRootClass +{ + Class isa; + int count; + int a; +} ++ (id) initialize; ++ (id) alloc; +- (id) init; +@property (assign, readonly) int count; +- (void) setWriteOnlyCount: (int)value; +@end + +@implementation MyRootClass ++ (id) initialize { return self; } ++ (id) alloc { return class_createInstance (self, 0); } +- (id) init { return self; } +@synthesize count; +- (void) setWriteOnlyCount: (int)value +{ + a = value; +} +@end + +int main (void) +{ + MyRootClass *object = [[MyRootClass alloc] init]; + + object.count = 10; /* { dg-error "readonly property can not be set" } */ + if (object.count != 10) /* Ok */ + abort (); + + /* Test errors when trying to change a readonly property using + pre/post increment/decrement operators. */ + object.count++; /* { dg-error "readonly property can not be set" } */ + + ++object.count; /* { dg-error "readonly property can not be set" } */ + + object.count--; /* { dg-error "readonly property can not be set" } */ + + --object.count; /* { dg-error "readonly property can not be set" } */ + + /* Test errors when trying to change something using Objective-C 2.0 + dot-syntax but there is a setter but no getter. */ + object.writeOnlyCount = 10; /* Ok */ + + object.writeOnlyCount++; /* { dg-error "no .writeOnlyCount. getter found" } */ + + ++object.writeOnlyCount; /* { dg-error "no .writeOnlyCount. getter found" } */ + + object.writeOnlyCount--; /* { dg-error "no .writeOnlyCount. getter found" } */ + + --object.writeOnlyCount; /* { dg-error "no .writeOnlyCount. getter found" } */ + + return 0; +} + + diff --git a/gcc/testsuite/objc.dg/property/dotsyntax-18.m b/gcc/testsuite/objc.dg/property/dotsyntax-18.m new file mode 100644 index 000000000..5697d311d --- /dev/null +++ b/gcc/testsuite/objc.dg/property/dotsyntax-18.m @@ -0,0 +1,90 @@ +/* Contributed by Nicola Pero , November 2010. */ +/* { dg-do run } */ +/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */ + +/* Test dot-syntax with tricky assignments. */ + +#include +#include +#include + +@interface MyRootClass +{ + Class isa; + int a; +} ++ (id) initialize; ++ (id) alloc; +- (id) init; +- (int) count; +- (void) setCount: (int)count; +- (int) somethingToExecuteOnlyOnce; +@end + +@implementation MyRootClass ++ (id) initialize { return self; } ++ (id) alloc { return class_createInstance (self, 0); } +- (id) init { return self; } +- (int) count +{ + return a; +} +- (void) setCount: (int)count +{ + a = count; +} +- (int) somethingToExecuteOnlyOnce +{ + a++; + return 10; +} +@end + +int main (void) +{ + MyRootClass *object1 = [[MyRootClass alloc] init]; + MyRootClass *object2 = [[MyRootClass alloc] init]; + MyRootClass *object3 = [[MyRootClass alloc] init]; + int i; + + object1.count = 10; + if (object1.count != 10) + abort (); + + object2.count = 10; + if (object2.count != 10) + abort (); + + /* Test multiple assignments to a constant. */ + object1.count = object2.count = 20; + + if (object1.count != 20 || object2.count != 20) + abort (); + + i = object1.count = 30; + + if (i != 30 || object1.count != 30) + abort (); + + i = object2.count = 30; + + if (i != 30 || object2.count != 30) + abort (); + + /* Test a simple assignment to something with a side-effect; the + 'rhs' should be evaluated only once. */ + object1.count = ([object2 somethingToExecuteOnlyOnce] > 0 ? 30 : 45); + + if (object1.count != 30 || object2.count != 31) + abort (); + + /* Test multiple assignments with side effects. */ + object3.count = object1.count = ([object2 somethingToExecuteOnlyOnce] > 0 ? 30 : 45); + + if (object1.count != 30 || object2.count != 32 || object3.count != 30) + abort (); + + return 0; +} + + diff --git a/gcc/testsuite/objc.dg/property/dotsyntax-19.m b/gcc/testsuite/objc.dg/property/dotsyntax-19.m new file mode 100644 index 000000000..df4867b0a --- /dev/null +++ b/gcc/testsuite/objc.dg/property/dotsyntax-19.m @@ -0,0 +1,113 @@ +/* Contributed by Nicola Pero , November 2010. */ +/* { dg-do run } */ +/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */ + +/* Test dot-syntax with more tricky assignments. */ + +#include +#include +#include + +@interface MyRootClass +{ + Class isa; + id a; + id b; + int p1; + float p2; +} ++ (id) initialize; ++ (id) alloc; +- (id) init; + +@property (assign) id object1; +@property (assign) id object2; +- (id) test; +- (id) myself; +- (id) nilObject; + +@property int p1; +@property float p2; +@end + +@implementation MyRootClass ++ (id) initialize { return self; } ++ (id) alloc { return class_createInstance (self, 0); } +- (id) init { return self; } +@synthesize object1 = a; +@synthesize object2 = b; +- (id) test +{ + /* Test multiple assignments with 'self'. */ + self.object1 = self.object2 = self; + + if (self.object1 != self || self.object2 != self) + abort (); + + /* Test multiple assignments with a conditional and method calls. */ + self.object1 = self.object2 = (self ? [self myself] : [self nilObject]); + + if (self.object1 != self || self.object2 != self) + abort (); + + self.object1 = self.object2 = (self ? [self nilObject] : [self myself]); + + if (self.object1 != nil || self.object2 != nil) + abort (); + + return self.object1; +} +- (id) myself +{ + return self; +} +- (id) nilObject +{ + return nil; +} + +@synthesize p1; +@synthesize p2; +@end + +int main (void) +{ + MyRootClass *object = [[MyRootClass alloc] init]; + MyRootClass *object1 = [[MyRootClass alloc] init]; + + [object test]; + + /* Now, test multiple assignments with different types. Use + int/float as they seem to happily crash the compiler in gimplify + if proper conversions are not being generated by the + frontend. ;-) */ + object.p1 = object.p2 = 12; + + if (object.p1 != 12 || object.p2 != 12) + abort (); + + object.p1 = object.p2 = 2.7; + + if (object.p1 != 2) + abort (); + + /* Just try a different loop, mixing in a few different standard C + constructs to cover a few other cases. */ + object.p1 = 10; + object1.p1 = 0; + while (object.p1) + { + object1.p1 += ((object.p2 = 4.56) ? 0 : object.p1); + object.p1--; + } + + if (object.p1 != 0 || object1.p1 != 0) + abort (); + + if ((object.p1 = 0)) + abort (); + + return 0; +} + + diff --git a/gcc/testsuite/objc.dg/property/dotsyntax-2.m b/gcc/testsuite/objc.dg/property/dotsyntax-2.m new file mode 100644 index 000000000..03e49aebc --- /dev/null +++ b/gcc/testsuite/objc.dg/property/dotsyntax-2.m @@ -0,0 +1,72 @@ +/* Contributed by Nicola Pero , November 2010. */ +/* { dg-do run } */ +/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */ + +/* Test the 'dot syntax' without a declarated property. This tests the case where + only the setter (or only the getter) exists. */ + +#include +#include +#include + +@interface MyRootClass +{ + Class isa; + int a; + id b; +} ++ (id) initialize; ++ (id) alloc; +- (id) init; +- (int) a; +- (void) setCount: (int)value; +- (id) b; +- (void) setNext: (id)value; +@end + +@implementation MyRootClass ++ (id) initialize { return self; } ++ (id) alloc { return class_createInstance (self, 0); } +- (id) init { return self; } +- (int) a +{ + return a; +} +- (void) setCount: (int)value +{ + a = value; +} +- (id) b +{ + return b; +} +- (void) setNext: (id)value +{ + b = value; +} +@end + +int main (void) +{ + MyRootClass *object = [[MyRootClass alloc] init]; + + /* This should work because -setCount: exists (even if -count does + not). */ + object.count = 40; + + /* This should work because -a exists (even if -setA: does not). */ + if (object.a != 40) + abort (); + + /* This should work because -setNext: exists (even if -next does + not). */ + object.next = object; + + /* This should work because -b exists (even if -setB: does not). */ + if (object.b != object) + abort (); + + return 0; +} + + diff --git a/gcc/testsuite/objc.dg/property/dotsyntax-20.m b/gcc/testsuite/objc.dg/property/dotsyntax-20.m new file mode 100644 index 000000000..f1dd48e61 --- /dev/null +++ b/gcc/testsuite/objc.dg/property/dotsyntax-20.m @@ -0,0 +1,67 @@ +/* Contributed by Nicola Pero , November 2010. */ +/* { dg-do compile } */ +/* { dg-options "-Wall" } */ + +/* Test warnings with the dot-syntax. */ + +#include +#include +#include + +@interface MyRootClass +{ + Class isa; + id a; + id b; + int p1; + int p2; +} ++ (id) initialize; ++ (id) alloc; +- (id) init; + +@property int p1; +@property int p2; +@end + +@implementation MyRootClass ++ (id) initialize { return self; } ++ (id) alloc { return class_createInstance (self, 0); } +- (id) init { return self; } +@synthesize p1; +@synthesize p2; +@end + +int main (void) +{ + MyRootClass *object = [[MyRootClass alloc] init]; + + /* First, test that the artificial code generated by dot-syntax does + not generate unexpected warnings. */ + + /* All of the following should generate no warnings. */ + object.p1 = 0; + object.p2 = 0; + object.p1 = object.p2 = 0; + if (object.p1 > 0) + object.p2 = 0; + + object.p1++; + ++object.p1; + object.p1--; + --object.p1; + + while (object.p1) + object.p1--; + + /* Now test some warnings. */ + object.p1; /* { dg-warning "value computed is not used" } */ + + /* TODO: It would be good to get the following to warn. */ + if (object.p1 = 0) /* dg-warning "suggest parentheses around assignment used as truth value" */ + abort (); + + return 0; +} + + diff --git a/gcc/testsuite/objc.dg/property/dotsyntax-21.m b/gcc/testsuite/objc.dg/property/dotsyntax-21.m new file mode 100644 index 000000000..4b8945ed6 --- /dev/null +++ b/gcc/testsuite/objc.dg/property/dotsyntax-21.m @@ -0,0 +1,113 @@ +/* Contributed by Nicola Pero , November 2010. */ +/* { dg-do run } */ +/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */ + +/* Test dot-syntax with super in a category. */ + +#include +#include +#include + +@interface MyRootClass +{ + Class isa; + int a; +} ++ (id) initialize; ++ (id) alloc; +- (id) init; +- (int) count; +- (void) setCount: (int)count; +@end + +@implementation MyRootClass ++ (id) initialize { return self; } ++ (id) alloc { return class_createInstance (self, 0); } +- (id) init { return self; } +- (int) count +{ + return a; +} +- (void) setCount: (int)count +{ + a = count; +} +@end + +/* First, test 'super' in the main implementation of a subclass. */ +@interface MySubClass : MyRootClass +- (int) superCount; +- (void) setSuperCount: (int)count; +@end + +@implementation MySubClass +- (int) superCount +{ + return super.count; +} +- (void) setSuperCount: (int)count +{ + super.count = count; +} +@end + +/* Now, test 'super' in a category of a subclass. */ +@interface MySubClass (Category) +- (int) superCount2; +- (void) setSuperCount2: (int)count; +- (int) test: (int)x; +@end + +@implementation MySubClass (Category) +- (int) superCount2 +{ + return super.count; +} +- (void) setSuperCount2: (int)count +{ + super.count = count; +} +- (int) test: (int)x +{ + /* For positive x, the following will leave super.count + unchanged. */ + super.count++; + --super.count; + + super.count = (x < 0 ? x : super.count); + + if ((x = super.count)) + super.count += 1; + + if ((x = super.count)) + super.count -= 1; + + /* Finally, also put a bit of self.count in the mix. */ + self.count++; + super.count--; + + return super.count; +} +@end + +int main (void) +{ + MySubClass *object = [[MySubClass alloc] init]; + + object.count = 10; + if (object.count != 10) + abort (); + + object.superCount = 11; + if (object.superCount != 11) + abort (); + + object.superCount2 = 12; + if (object.superCount2 != 12) + abort (); + + if ([object test: 45] != 12) + abort (); + + return 0; +} diff --git a/gcc/testsuite/objc.dg/property/dotsyntax-22.m b/gcc/testsuite/objc.dg/property/dotsyntax-22.m new file mode 100644 index 000000000..cc5834822 --- /dev/null +++ b/gcc/testsuite/objc.dg/property/dotsyntax-22.m @@ -0,0 +1,19 @@ +/* PR objc/47784. This testcase used to crash the compiler. */ + +typedef struct { + float x; +} SomeType; + +@interface MyClass + +@property(assign,readwrite) SomeType position; + +@end + +void example (MyClass *x) +{ + const SomeType SomeTypeZero = {0.0f}; + + x.position= SomeTypeZero; +} + diff --git a/gcc/testsuite/objc.dg/property/dotsyntax-3.m b/gcc/testsuite/objc.dg/property/dotsyntax-3.m new file mode 100644 index 000000000..d34780628 --- /dev/null +++ b/gcc/testsuite/objc.dg/property/dotsyntax-3.m @@ -0,0 +1,64 @@ +/* Contributed by Nicola Pero , November 2010. */ +/* { dg-do run } */ +/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */ + +/* Test the 'dot syntax' without a declarated property. This tests the case where + the object is a Class. */ + + +#include +#include +#include + +static int a; +static id b; + +@interface MyRootClass +{ + Class isa; +} ++ (id) initialize; ++ (id) alloc; +- (id) init; ++ (int) count; ++ (void) setCount: (int)value; ++ (id) next; ++ (void) setNext: (id)value; +@end + +@implementation MyRootClass ++ (id) initialize { return self; } ++ (id) alloc { return class_createInstance (self, 0); } +- (id) init { return self; } ++ (int) count +{ + return a; +} ++ (void) setCount: (int)value +{ + a = value; +} ++ (id) next +{ + return b; +} ++ (void) setNext: (id)value +{ + b = value; +} +@end + +int main (void) +{ + MyRootClass *object = [[MyRootClass alloc] init]; + + MyRootClass.count = 40; + if (MyRootClass.count != 40) + abort (); + + MyRootClass.next = object; + if (MyRootClass.next != object) + abort (); + + return 0; +} diff --git a/gcc/testsuite/objc.dg/property/dotsyntax-4.m b/gcc/testsuite/objc.dg/property/dotsyntax-4.m new file mode 100644 index 000000000..2db067f1f --- /dev/null +++ b/gcc/testsuite/objc.dg/property/dotsyntax-4.m @@ -0,0 +1,42 @@ +/* Contributed by Nicola Pero , November 2010. */ +/* { dg-do compile } */ + +/* Test the 'dot syntax' without a declarated property. This tests + syntax errors in the case where the object is a Class. */ + + +#include +#include +#include + +@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 + +int main (void) +{ + MyRootClass.invalid = 40; /* { dg-error "could not find setter.getter" } */ + if (MyRootClass.invalid != 40) /* { dg-error "could not find setter.getter" } */ + abort (); + + MyRootClass.; /* { dg-error "expected identifier" } */ + if (MyRootClass.) /* { dg-error "expected identifier" } */ + abort (); + + MyRootClass.int; /* { dg-error "expected identifier" } */ + if (MyRootClass.int) /* { dg-error "expected identifier" } */ + abort (); + + return 0; +} diff --git a/gcc/testsuite/objc.dg/property/dotsyntax-5.m b/gcc/testsuite/objc.dg/property/dotsyntax-5.m new file mode 100644 index 000000000..06e113032 --- /dev/null +++ b/gcc/testsuite/objc.dg/property/dotsyntax-5.m @@ -0,0 +1,78 @@ +/* Contributed by Nicola Pero , November 2010. */ +/* { dg-do run } */ +/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */ + +/* Test the 'dot syntax' with self, both in instance and class methods. */ + +#include +#include +#include + +static int c; + +@interface MyRootClass +{ + Class isa; + int a; +} ++ (id) initialize; ++ (id) alloc; +- (id) init; +- (int) count; +- (void) setCount: (int)count; ++ (int) classCount; ++ (void) setClassCount: (int)count; +@end + +@implementation MyRootClass ++ (id) initialize { return self; } ++ (id) alloc { return class_createInstance (self, 0); } +- (id) init { return self; } +- (int) count +{ + return a; +} +- (void) setCount: (int)count +{ + a = count; +} ++ (int) classCount +{ + return c; +} ++ (void) setClassCount: (int)count +{ + c = count; +} +- (int) testMe +{ + self.count = 400; + if (self.count != 400) + abort (); + + return self.count; +} ++ (int) testMe +{ + self.classCount = 4000; + if (self.classCount != 4000) + abort (); + + return self.classCount; +} +@end + +int main (void) +{ + MyRootClass *object = [[MyRootClass alloc] init]; + + if ([object testMe] != 400) + abort (); + + if ([MyRootClass testMe] != 4000) + abort (); + + return 0; +} + + diff --git a/gcc/testsuite/objc.dg/property/dotsyntax-6.m b/gcc/testsuite/objc.dg/property/dotsyntax-6.m new file mode 100644 index 000000000..7ecd34e3d --- /dev/null +++ b/gcc/testsuite/objc.dg/property/dotsyntax-6.m @@ -0,0 +1,106 @@ +/* Contributed by Nicola Pero , November 2010. */ +/* { dg-do run } */ +/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */ + +/* Test nested 'dot syntax' (xxx.yyy.zzz or [xxx yyy].zzz). */ + +#include +#include +#include + +@class MyRootClass; + +static MyRootClass *shared_root = nil; + +@interface MyRootClass +{ + Class isa; + int a; + int b; + MyRootClass *next; +} +@property int b; +@property (assign) MyRootClass *next; ++ (id) initialize; ++ (MyRootClass *)sharedInstance; ++ (id) alloc; +- (id) init; +- (MyRootClass *)same; +- (int) count; +- (void) setCount: (int)count; +@end + +@implementation MyRootClass +@synthesize b; +@synthesize next; ++ (id) initialize { return self; } ++ (id) alloc { return class_createInstance (self, 0); } +- (id) init { return self; } ++ (MyRootClass *)sharedInstance +{ + if (!shared_root) + shared_root = [[self alloc] init]; + + return shared_root; +} +- (MyRootClass *)same +{ + return self; +} +- (int) count +{ + return a; +} +- (void) setCount: (int)count +{ + a = count; +} +@end + +int main (void) +{ + MyRootClass *object = [[MyRootClass alloc] init]; + + /* Test ClassName.accessor.accessor. */ + MyRootClass.sharedInstance.count = 500; + if (MyRootClass.sharedInstance.count != 500) + abort (); + + /* Test object.accessor.accessor. */ + object.same.count = 1000; + if (object.same.count != 1000) + abort (); + + /* Test object.accessor.property. */ + object.same.next = object; + if (object.same.next != object) + abort (); + + /* Test lots of nesting. */ + if (object.next.next.same.same.next.next.same != object) + abort (); + + /* Test more nesting. */ + MyRootClass.sharedInstance.next = object; + MyRootClass.sharedInstance.next.next.next.next.next.count = 2000; + if (MyRootClass.sharedInstance.next.next.next.next.next.count != 2000) + abort (); + + /* Test more nesting. */ + MyRootClass.sharedInstance.same.same.same.same.same.count = 3000; + if (MyRootClass.sharedInstance.same.same.same.same.same.count != 3000) + abort (); + + /* Test [object method].property. */ + [MyRootClass sharedInstance].count = 5000; + if ([MyRootClass sharedInstance].count != 5000) + abort (); + + /* Just a final check. */ + if (shared_root.count != 5000) + abort (); + + return 0; +} + + diff --git a/gcc/testsuite/objc.dg/property/dotsyntax-7.m b/gcc/testsuite/objc.dg/property/dotsyntax-7.m new file mode 100644 index 000000000..15c1725d8 --- /dev/null +++ b/gcc/testsuite/objc.dg/property/dotsyntax-7.m @@ -0,0 +1,48 @@ +/* Contributed by Nicola Pero , November 2010. */ +/* { dg-do run } */ +/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */ + +/* Test dot syntax of a casted expression. */ + +#include +#include +#include + +@interface MyRootClass +{ + Class isa; + int a; +} ++ (id) initialize; ++ (id) alloc; +- (id) init; +- (int) count; +- (void) setCount: (int)count; +@end + +@implementation MyRootClass ++ (id) initialize { return self; } ++ (id) alloc { return class_createInstance (self, 0); } +- (id) init { return self; } +- (int) count +{ + return a; +} +- (void) setCount: (int)count +{ + a = count; +} +@end + +int main (void) +{ + id object = [[MyRootClass alloc] init]; + + ((MyRootClass *)object).count = 200; + if (((MyRootClass *)object).count != 200) + abort (); + + return 0; +} + + diff --git a/gcc/testsuite/objc.dg/property/dotsyntax-8.m b/gcc/testsuite/objc.dg/property/dotsyntax-8.m new file mode 100644 index 000000000..35dfda40c --- /dev/null +++ b/gcc/testsuite/objc.dg/property/dotsyntax-8.m @@ -0,0 +1,62 @@ +/* Contributed by Nicola Pero , November 2010. */ +/* { dg-do run } */ +/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */ + +/* Test the 'dot syntax' with typedefs. */ + +#include +#include +#include + +static int c; + +@interface MyRootClass +{ + Class isa; + int a; +} ++ (id) initialize; ++ (id) alloc; +- (id) init; +- (int) count; +- (void) setCount: (int)count; ++ (int) classCount; ++ (void) setClassCount: (int)count; +@end + +@implementation MyRootClass ++ (id) initialize { return self; } ++ (id) alloc { return class_createInstance (self, 0); } +- (id) init { return self; } +- (int) count +{ + return a; +} +- (void) setCount: (int)count +{ + a = count; +} ++ (int) classCount +{ + return c; +} ++ (void) setClassCount: (int)count +{ + c = count; +} +@end + +typedef MyRootClass MyType; + +int main (void) +{ + MyType *object = [[MyRootClass alloc] init]; + + object.count = 1974; + if (object.count != 1974) + abort (); + + return 0; +} + + diff --git a/gcc/testsuite/objc.dg/property/dotsyntax-9.m b/gcc/testsuite/objc.dg/property/dotsyntax-9.m new file mode 100644 index 000000000..61a5c0eb8 --- /dev/null +++ b/gcc/testsuite/objc.dg/property/dotsyntax-9.m @@ -0,0 +1,77 @@ +/* Contributed by Nicola Pero , November 2010. */ +/* { dg-do run } */ +/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */ + +/* Test that setter/getters for dot-syntax are properly found even if + not declared in the @interface, but available in the local + @implementation before the current line (ie, [object name] can be + compiled in that case, so object.name should be compiled too). */ + +#include +#include +#include + +static int c; + +@interface MyRootClass +{ + Class isa; + int a; +} ++ (id) initialize; ++ (id) alloc; +- (id) init; +@end + +@implementation MyRootClass ++ (id) initialize { return self; } ++ (id) alloc { return class_createInstance (self, 0); } +- (id) init { return self; } +- (int) count +{ + return a; +} +- (void) setCount: (int)count +{ + a = count; +} ++ (int) classCount +{ + return c; +} ++ (void) setClassCount: (int)count +{ + c = count; +} +- (int) testMe +{ + self.count = 400; + if (self.count != 400) + abort (); + + return self.count; +} ++ (int) testMe +{ + self.classCount = 4000; + if (self.classCount != 4000) + abort (); + + return self.classCount; +} +@end + +int main (void) +{ + MyRootClass *object = [[MyRootClass alloc] init]; + + if ([object testMe] != 400) + abort (); + + if ([MyRootClass testMe] != 4000) + abort (); + + return 0; +} + + diff --git a/gcc/testsuite/objc.dg/property/dotsyntax-deprecated-1.m b/gcc/testsuite/objc.dg/property/dotsyntax-deprecated-1.m new file mode 100644 index 000000000..ad627a8c1 --- /dev/null +++ b/gcc/testsuite/objc.dg/property/dotsyntax-deprecated-1.m @@ -0,0 +1,41 @@ +/* Contributed by Nicola Pero , October 2010. */ +/* { dg-do compile } */ + +/* Test the 'dot syntax' with deprecated methods. */ + +#include + +@interface MyClass +{ + Class isa; +} ++ (int) classCount __attribute__ ((deprecated)); ++ (void) setClassCount: (int)value __attribute__ ((deprecated)); + +- (int) count __attribute__ ((deprecated)); +- (void) setCount: (int)value __attribute__ ((deprecated)); + +- (int) classCount2; +- (void) setClassCount2: (int)value; + +- (int) count2; +- (void) setCount2: (int)value; +@end + +void foo (void) +{ + MyClass *object = nil; + + + if (object.count > 0) /* { dg-warning "is deprecated" } */ + object.count = 20; /* { dg-warning "is deprecated" } */ + + if (MyClass.classCount < -7) /* { dg-warning "is deprecated" } */ + MyClass.classCount = 11; /* { dg-warning "is deprecated" } */ + + if (object.classCount2 > 0) + object.classCount2 = 19; + + if (object.count2 < -7) + object.count2 = 74; +} diff --git a/gcc/testsuite/objc.dg/property/dynamic-1.m b/gcc/testsuite/objc.dg/property/dynamic-1.m new file mode 100644 index 000000000..8f9737139 --- /dev/null +++ b/gcc/testsuite/objc.dg/property/dynamic-1.m @@ -0,0 +1,34 @@ +/* { dg-do compile } */ + +#include + +@interface MyRootClass +{ + Class isa; +} +@end + +@implementation MyRootClass +@end + +@dynamic isa; /* { dg-error ".@dynamic. not in @implementation context" } */ + +@interface Test : MyRootClass +{ + int v1; + int v2; + int v3; + int v4; +} +@property int v1; +@property int v2; +@property int v3; +@property int v4; +@end + +@implementation Test +@dynamic; /* { dg-error "expected identifier" } */ +@dynamic v1, ; /* { dg-error "expected identifier" } */ +@dynamic v1, v2, v3; +@dynamic v4; +@end diff --git a/gcc/testsuite/objc.dg/property/dynamic-2.m b/gcc/testsuite/objc.dg/property/dynamic-2.m new file mode 100644 index 000000000..203ba34a1 --- /dev/null +++ b/gcc/testsuite/objc.dg/property/dynamic-2.m @@ -0,0 +1,45 @@ +/* Contributed by Nicola Pero , October 2010. */ +/* { dg-do compile } */ + +#include + +@interface MyRootClass +{ + Class isa; +} +@end + +@implementation MyRootClass +@end + +@dynamic isa; /* { dg-error ".@dynamic. not in @implementation context" } */ + +@interface Test : MyRootClass +{ + int v1; +} +@end +@implementation Test +@end + + +@interface Test (Category) +@property int v1; +@end +@implementation Test (Category) +@dynamic v1; +@end + + +@interface AnotherTest : MyRootClass +{ +} +@property int one; +@end + +@implementation AnotherTest +@dynamic one; +@dynamic one; /* { dg-error "property .one. already specified in .@dynamic." } */ + /* { dg-message "originally specified here" "" { target *-*-* } 41 } */ +@dynamic three; /* { dg-error "no declaration of property .three. found in the interface" } */ +@end diff --git a/gcc/testsuite/objc.dg/property/dynamic-3.m b/gcc/testsuite/objc.dg/property/dynamic-3.m new file mode 100644 index 000000000..e8a6693b0 --- /dev/null +++ b/gcc/testsuite/objc.dg/property/dynamic-3.m @@ -0,0 +1,49 @@ +/* Contributed by Nicola Pero , November 2010. */ +/* { dg-do compile } */ + +#include + +@interface MyRootClass +{ + Class isa; +} +@end + +@implementation MyRootClass +@end + +/* Test @property/@dynamic in a category. First, a case where + @dynamic should turn off all warnings. */ + +@interface MyRootClass (Category) +@property int a; +- (int) test; +@end +@implementation MyRootClass (Category) +@dynamic a; +- (int) test +{ + return self.a; /* This should compile into [self a] with no warnings. */ +} +@end + + + +/* Test @property/@dynamic in a category. Second, a case with a + missing setter and no @dynamic. A warning should be generated. */ + +@interface MyRootClass (Category2) +@property int b; +- (int) test; +@end +@implementation MyRootClass (Category2) +- (int) b +{ + return 0; +} +- (int) test +{ + return self.b; +} +@end /* { dg-warning "incomplete implementation" } */ +/* { dg-warning "method definition for .-setB:. not found" "" { target *-*-* } 48 } */ diff --git a/gcc/testsuite/objc.dg/property/dynamic-4.m b/gcc/testsuite/objc.dg/property/dynamic-4.m new file mode 100644 index 000000000..84998d6b4 --- /dev/null +++ b/gcc/testsuite/objc.dg/property/dynamic-4.m @@ -0,0 +1,45 @@ +/* Contributed by Nicola Pero , November 2010. */ +/* { dg-do compile } */ + +#include + +@interface MyRootClass +{ + Class isa; +} +@end + +@implementation MyRootClass +@end + +/* Test @property/@dynamic with protocols. */ + +@protocol MyProtocol +@property int a; +@end + + +/* This class is declared to conform to the protocol, but because of + @dynamic, no warnings are issued even if the getter/setter for the + @property are missing. */ +@interface MyClass1 : MyRootClass +@end + +@implementation MyClass1 +@dynamic a; +@end + + +/* This class is declared to conform to the protocol and warnings are + issued because the setter for the @property is missing. */ +@interface MyClass2 : MyRootClass +@end + +@implementation MyClass2 +- (int) a +{ + return 0; +} +@end /* { dg-warning "incomplete implementation" } */ +/* { dg-warning "method definition for .-setA:. not found" "" { target *-*-* } 43 } */ +/* { dg-warning "class .MyClass2. does not fully implement the .MyProtocol. protocol" "" { target *-*-* } 43 } */ diff --git a/gcc/testsuite/objc.dg/property/dynamic-5.m b/gcc/testsuite/objc.dg/property/dynamic-5.m new file mode 100644 index 000000000..77e81411a --- /dev/null +++ b/gcc/testsuite/objc.dg/property/dynamic-5.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 @dynamic in the real scenario where a class declares a + @property, uses @dynamic to avoid implementing it, then subclasses + implement it. */ + +#include +#include +#include + +@interface MyRootClass +{ + Class isa; +} +@property int a; ++ (id) initialize; ++ (id) alloc; +- (id) init; +@end + +@implementation MyRootClass ++ (id) initialize { return self; } ++ (id) alloc { return class_createInstance (self, 0); } +- (id) init { return self; } +@dynamic a; +@end + +@interface Test : MyRootClass +{ + int v1; +} +@end + +@implementation Test +@synthesize a = v1; +@end + +int main (void) +{ + /* Note how 'object' is declared to be of class 'MyRootClass', but + actually is of the subclass which implements the property for + real. */ + MyRootClass *object = [[Test alloc] init]; + + object.a = 40; + + if (object.a != 40) + abort (); + + return 0; +} diff --git a/gcc/testsuite/objc.dg/property/dynamic-6.m b/gcc/testsuite/objc.dg/property/dynamic-6.m new file mode 100644 index 000000000..23a7a8905 --- /dev/null +++ b/gcc/testsuite/objc.dg/property/dynamic-6.m @@ -0,0 +1,26 @@ +/* Contributed by Nicola Pero , November 2010. */ +/* { dg-do compile } */ + +/* Test case when an accessor from a @property matches a method + required by a protocol. If the @property is @dynamic, then no + warning should be generated. */ + +#include +#include +#include + +@protocol Count +- (int) count; +@end + +@interface MyRootClass +{ + Class isa; +} +@property int count; +@end + +@implementation MyRootClass +/* This @dynamic turns off any warnings for -count and -setCount:. */ +@dynamic count; +@end diff --git a/gcc/testsuite/objc.dg/property/fsf-property-basic.m b/gcc/testsuite/objc.dg/property/fsf-property-basic.m new file mode 100644 index 000000000..ddc0589e0 --- /dev/null +++ b/gcc/testsuite/objc.dg/property/fsf-property-basic.m @@ -0,0 +1,62 @@ +/* Basic test, auto-generated getter/setter based on property name. */ +/* { dg-do run } */ +/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */ + +extern int printf (char *fmt,...) ; +extern void abort (void); + +#include +#include + +@interface Bar +{ +@public + Class isa; + int FooBar; +} ++ (id) initialize; ++ (id) alloc ; +- (id) init; +- (int) whatIsFooBar; +@property int FooBar; +@end + +@implementation Bar + ++initialize { return self;} ++ (id) alloc { return class_createInstance (self, 0); } + +- (id) init {return self;} + +- (int) whatIsFooBar { return self->FooBar; } +@synthesize FooBar; +@end + +int main(int argc, char *argv[]) { + int res; + Bar *f = [[Bar alloc] init]; + + /* First, establish that the property getter & setter have been synthesized + and operate correctly. */ + [f setFooBar:1]; + + if ([f whatIsFooBar] != 1) + { printf ("setFooBar did not set FooBar\n"); abort ();} + + res = [f FooBar]; + + if (res != 1 ) + { printf ("[f FooBar] = %d\n", res); abort ();} + + /* Now check the short-cut object.property syntax. */ + /* Read... */ + res = f.FooBar; + if (res != 1 ) + { printf ("f.FooBar = %d\n", res); abort ();} + + /* .... write. */ + f.FooBar = 0; + /* printf ("seems OK\n", res); */ + return f.FooBar; +} + diff --git a/gcc/testsuite/objc.dg/property/fsf-property-method-access.m b/gcc/testsuite/objc.dg/property/fsf-property-method-access.m new file mode 100644 index 000000000..01eea5bf7 --- /dev/null +++ b/gcc/testsuite/objc.dg/property/fsf-property-method-access.m @@ -0,0 +1,67 @@ +/* test access in methods, auto-generated getter/setter based on property name. */ +/* { dg-do run } */ +/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */ + +extern int printf (char *fmt,...) ; +extern void abort (void); + +#include +#include + +@interface Bar +{ +@public + Class isa; + int FooBar; +} ++ (id) initialize; ++ (id) alloc ; +- (id) init; + +- (int) lookAtProperty; +- (void) setProperty: (int) v; + +@property int FooBar; +@end + +@implementation Bar + ++initialize { return self;} ++ (id) alloc { return class_createInstance(self, 0);} + +- (id) init {return self;} + +@synthesize FooBar; + +- (int) lookAtProperty { return FooBar; } +- (void) setProperty: (int) v { FooBar = v; } + +@end + +int main(int argc, char *argv[]) { + int res; + Bar *f = [[Bar alloc] init]; + + /* First, establish that the property getter & setter have been synthesized + and operate correctly. */ + [f setProperty:11]; + + if (f.FooBar != 11) + { printf ("setProperty did not set FooBar\n"); abort ();} + + res = [f lookAtProperty]; + if (res != 11 ) + { printf ("[f lookAtProperty] = %d\n", res); abort ();} + + /* Make sure we haven't messed up the shortcut form. */ + /* read ... */ + res = f.FooBar; + if (res != 11 ) + { printf ("f.FooBar = %d\n", res); abort ();} + + /* ... write. */ + f.FooBar = 0; + /* printf ("seems OK\n", res); */ + return f.FooBar; +} + diff --git a/gcc/testsuite/objc.dg/property/fsf-property-named-ivar.m b/gcc/testsuite/objc.dg/property/fsf-property-named-ivar.m new file mode 100644 index 000000000..545856850 --- /dev/null +++ b/gcc/testsuite/objc.dg/property/fsf-property-named-ivar.m @@ -0,0 +1,61 @@ +/* Basic test, auto-generated getter/setter based on named ivar */ +/* { dg-do run } */ +/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */ + +extern int printf (char *fmt,...) ; +extern void abort (void); + +#include +#include + +@interface Bar +{ +@public + Class isa; + int var; +} ++ (id) initialize; ++ (id) alloc ; +- (id) init; + +@property int FooBar; +@end + +@implementation Bar + ++initialize { return self;} ++ (id) alloc { return class_createInstance (self, 0); } + +- (id) init {return self;} + +@synthesize FooBar = var; +@end + +int main(int argc, char *argv[]) { + int res; + Bar *f = [[Bar alloc] init]; + + /* First, establish that the property getter & setter have been synthesized + and operate correctly. */ + [f setFooBar:1234]; + + if (f->var != 1234) + { printf ("setFooBar did not set var correctly\n"); abort ();} + + res = [f FooBar]; + + if (res != 1234 ) + { printf ("[f FooBar] = %d\n", res); abort ();} + + /* Now check the short-cut object.property syntax. */ + /* Read .... */ + res = f.FooBar; + if (res != 1234 ) + { printf ("f.FooBar = %d\n", res); abort ();} + + /* ... and write. */ + f.FooBar = 0; + /* printf ("seems OK\n", res); */ + return f.FooBar; +} + diff --git a/gcc/testsuite/objc.dg/property/property-1.m b/gcc/testsuite/objc.dg/property/property-1.m new file mode 100644 index 000000000..147f007b9 --- /dev/null +++ b/gcc/testsuite/objc.dg/property/property-1.m @@ -0,0 +1,32 @@ +/* This program tests use of property provided setter/getter functions. */ +/* { dg-options "-std=c99" } */ +/* { dg-do run } */ +/* { dg-additional-sources "../../objc-obj-c++-shared/Object1.m" } */ +/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */ + +#import "../../objc-obj-c++-shared/Object1.h" + +@interface Bar : Object +{ + int iVar; +} +@property (setter=MySetter:) int FooBar; +@end + +@implementation Bar +@synthesize FooBar=iVar; + +- (void) MySetter : (int) value { iVar = value; } + +@end + +int main(int argc, char *argv[]) { + Bar *f = [Bar new]; + f.FooBar = 1; + + f.FooBar += 3; + + f.FooBar -= 4; + return f.FooBar; +} + diff --git a/gcc/testsuite/objc.dg/property/property-encoding-1.m b/gcc/testsuite/objc.dg/property/property-encoding-1.m new file mode 100644 index 000000000..dc12c3137 --- /dev/null +++ b/gcc/testsuite/objc.dg/property/property-encoding-1.m @@ -0,0 +1,182 @@ +/* Contributed by Nicola Pero , March 2011. */ +/* Test encoding properties. */ +/* { dg-do run } */ +/* { dg-skip-if "No API#2 pre-Darwin9" { *-*-darwin[5-8]* } { "-fnext-runtime" } { "" } } */ + +#include +#include +#include +#include + +@interface MyRootClass +{ Class isa; } ++ alloc; +- init; ++ initialize; +@end + +@implementation MyRootClass ++ alloc { return class_createInstance (self, 0); } +- init { return self; } ++ initialize { return self; } +@end + +@interface MySubClass : MyRootClass +{ + char char_property; + short short_property; + int int_property; + long long_property; + float float_property; + double double_property; + int *int_pointer_property; + + id propertyA; + id propertyB; + id propertyC; + id propertyD; + int propertyE; + id propertyF; + + id other_variable; +} +@property char char_property; +@property short short_property; +@property int int_property; +@property long long_property; +@property float float_property; +@property double double_property; +@property int *int_pointer_property; + +@property (assign, getter=getP, setter=setP:) id propertyA; +@property (assign) id propertyB; +@property (copy) id propertyC; +@property (retain) id propertyD; +@property (nonatomic) int propertyE; +@property (nonatomic, readonly, copy) id propertyF; + +@property (assign) id propertyG; +@property (assign, readonly, getter=X) id propertyH; +@end + +@implementation MySubClass +@synthesize char_property; +@synthesize short_property; +@synthesize int_property; +@synthesize long_property; +@synthesize float_property; +@synthesize double_property; +@synthesize int_pointer_property; + +@synthesize propertyA; +@synthesize propertyB; +@synthesize propertyC; +@synthesize propertyD; +@synthesize propertyE; +@synthesize propertyF; + +@synthesize propertyG = other_variable; +@dynamic propertyH; +@end + +#ifdef __OBJC2__ +void error (objc_property_t p) +{ + printf ("Error - property_getAttributes (\"%s\") returns \"%s\"\n", + property_getName (p), + property_getAttributes (p)); + abort (); +} + +/* Concatenate 3 strings and return the result. */ +char *concat (const char *a, const char *b, const char *c) +{ + /* We happily leak memory here. This is a test. */ + char *x = (char *)malloc (sizeof (char) * 128); + snprintf (x, 128, "%s%s%s", a, b, c); + return x; +} + +#endif + +int main (void) +{ +#ifdef __OBJC2__ + Class c = objc_getClass ("MySubClass"); + objc_property_t p; + + p = class_getProperty (c, "char_property"); + /* Usually we expect "Tc,Vchar_property", but if a char is of + different size, it may be encoded differently than "c". */ + if (strcmp (concat ("T", @encode (char), ",Vchar_property"), + property_getAttributes (p)) != 0) + error (p); + + p = class_getProperty (c, "short_property"); + if (strcmp (concat ("T", @encode (short), ",Vshort_property"), + property_getAttributes (p)) != 0) + error (p); + + p = class_getProperty (c, "int_property"); + if (strcmp (concat ("T", @encode (int), ",Vint_property"), + property_getAttributes (p)) != 0) + error (p); + + p = class_getProperty (c, "long_property"); + if (strcmp (concat ("T", @encode (long), ",Vlong_property"), + property_getAttributes (p)) != 0) + error (p); + + p = class_getProperty (c, "float_property"); + if (strcmp (concat ("T", @encode (float), ",Vfloat_property"), + property_getAttributes (p)) != 0) + error (p); + + p = class_getProperty (c, "double_property"); + if (strcmp (concat ("T", @encode (double), ",Vdouble_property"), + property_getAttributes (p)) != 0) + error (p); + + p = class_getProperty (c, "int_pointer_property"); + if (strcmp (concat ("T", @encode (int *), ",Vint_pointer_property"), + property_getAttributes (p)) != 0) + error (p); + + /* Objects are always encoded as '@' hence the string does not + depend on the architecture. */ + p = class_getProperty (c, "propertyA"); + if (strcmp ("T@,GgetP,SsetP:,VpropertyA", property_getAttributes (p)) != 0) + error (p); + + p = class_getProperty (c, "propertyB"); + if (strcmp ("T@,VpropertyB", property_getAttributes (p)) != 0) + error (p); + + p = class_getProperty (c, "propertyC"); + if (strcmp ("T@,C,VpropertyC", property_getAttributes (p)) != 0) + error (p); + + p = class_getProperty (c, "propertyD"); + if (strcmp ("T@,&,VpropertyD", property_getAttributes (p)) != 0) + error (p); + + p = class_getProperty (c, "propertyE"); + if (strcmp (concat ("T", @encode (int), ",N,VpropertyE"), + property_getAttributes (p)) != 0) + error (p); + + p = class_getProperty (c, "propertyF"); + if (strcmp ("T@,R,C,N,VpropertyF", property_getAttributes (p)) != 0) + error (p); + + p = class_getProperty (c, "propertyG"); + if (strcmp ("T@,Vother_variable", property_getAttributes (p)) != 0) + error (p); + + p = class_getProperty (c, "propertyH"); + if (strcmp ("T@,R,D,GX", property_getAttributes (p)) != 0) + error (p); +#endif + + return 0; +} diff --git a/gcc/testsuite/objc.dg/property/property-neg-1.m b/gcc/testsuite/objc.dg/property/property-neg-1.m new file mode 100644 index 000000000..cae1a5615 --- /dev/null +++ b/gcc/testsuite/objc.dg/property/property-neg-1.m @@ -0,0 +1,13 @@ +/* { dg-do compile } */ + +@interface Bar +{ + int iVar; +} +@property int fooBar; +@end + +@implementation Bar +@end /* { dg-warning "incomplete implementation of class .Bar." } */ + /* { dg-warning "method definition for .-setFooBar:. not found" "" { target *-*-* } 11 } */ + /* { dg-warning "method definition for .-fooBar. not found" "" { target *-*-* } 11 } */ diff --git a/gcc/testsuite/objc.dg/property/property-neg-2.m b/gcc/testsuite/objc.dg/property/property-neg-2.m new file mode 100644 index 000000000..f730fe846 --- /dev/null +++ b/gcc/testsuite/objc.dg/property/property-neg-2.m @@ -0,0 +1,8 @@ +/* { dg-do compile } */ + +@interface Bar +@end + +@implementation Bar +@property int FooBar; /* { dg-error "property declaration not in @interface or @protocol context" } */ +@end diff --git a/gcc/testsuite/objc.dg/property/property-neg-3.m b/gcc/testsuite/objc.dg/property/property-neg-3.m new file mode 100644 index 000000000..0b30931a8 --- /dev/null +++ b/gcc/testsuite/objc.dg/property/property-neg-3.m @@ -0,0 +1,14 @@ +/* { dg-do compile } */ + +@interface Person +{ + char *firstName; +} +@property char *firstName; +@end + +@implementation Person +@dynamic firstName; +@synthesize firstName; /* { dg-error "property .firstName. already specified in .@dynamic." } */ + /* { dg-message "originally specified here" "" { target *-*-* } 11 } */ +@end diff --git a/gcc/testsuite/objc.dg/property/property-neg-4.m b/gcc/testsuite/objc.dg/property/property-neg-4.m new file mode 100644 index 000000000..cc25d84af --- /dev/null +++ b/gcc/testsuite/objc.dg/property/property-neg-4.m @@ -0,0 +1,17 @@ +/* { dg-do compile } */ + +@interface Person +{ + char *fullName; +} +@property char *fullName; ++ (void) testClass; +@end + + +@implementation Person +@synthesize fullName; ++ (void) testClass { + self.fullName = "MyName"; /* { dg-error "request for member .fullName." } */ +} +@end diff --git a/gcc/testsuite/objc.dg/property/property-neg-5.m b/gcc/testsuite/objc.dg/property/property-neg-5.m new file mode 100644 index 000000000..464470cba --- /dev/null +++ b/gcc/testsuite/objc.dg/property/property-neg-5.m @@ -0,0 +1,5 @@ +/* { dg-do compile } */ + +@interface Foo +@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/property-neg-6.m b/gcc/testsuite/objc.dg/property/property-neg-6.m new file mode 100644 index 000000000..7059a56f0 --- /dev/null +++ b/gcc/testsuite/objc.dg/property/property-neg-6.m @@ -0,0 +1,9 @@ +/* Check for proper declaration of @property. */ +/* { dg-do compile } */ + +@interface Bar +{ + int iVar; +} +@property int FooBar /* { dg-error "expected ':', ',', ';', '\}' or '__attribute__' at end of input" } */ +/* { dg-error "expected ..end. at end of input" "" { target *-*-* } 8 } */ diff --git a/gcc/testsuite/objc.dg/property/property-neg-7.m b/gcc/testsuite/objc.dg/property/property-neg-7.m new file mode 100644 index 000000000..4c3d5d7d3 --- /dev/null +++ b/gcc/testsuite/objc.dg/property/property-neg-7.m @@ -0,0 +1,20 @@ +/* { dg-do compile } */ + +@interface NSArray +{ + int count; +} +@property(readonly) int count; +@end + +@implementation NSArray +@synthesize count; +@end + +void foo (NSArray *ans[], id pid, id apid[], int i) { + NSArray *test; + test.count = 1; /* { dg-error "readonly property can not be set" } */ + ((NSArray *)pid).count = 1; /* { dg-error "readonly property can not be set" } */ + ((NSArray *)apid[i]).count = 1; /* { dg-error "readonly property can not be set" } */ + ans[i].count = 3; /* { dg-error "readonly property can not be set" } */ +} diff --git a/gcc/testsuite/objc.dg/property/property.exp b/gcc/testsuite/objc.dg/property/property.exp new file mode 100644 index 000000000..e87730188 --- /dev/null +++ b/gcc/testsuite/objc.dg/property/property.exp @@ -0,0 +1,43 @@ +# GCC Objective-C testsuite that uses the `dg.exp' driver. +# Copyright (C) 1997, 2001, 2007, 2010 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GCC; see the file COPYING3. If not see +# . + +# Load support procs. +load_lib objc-dg.exp + +# If a testcase doesn't have special options, use these. +global DEFAULT_CFLAGS +if ![info exists DEFAULT_CFLAGS] then { + set DEFAULT_CFLAGS "" +} + +# Initialize `dg'. +dg-init + +# Gather a list of all tests. +set tests [lsort [glob -nocomplain $srcdir/$subdir/*.m]] + +# Main loop. +dg-runtest $tests "-fgnu-runtime" $DEFAULT_CFLAGS + +# Darwin targets can also run code with the NeXT runtime. +# but Properties are not supported by the runtime lib before Darwin 9. +if [istarget "*-*-darwin\[9123\]*" ] { + dg-runtest $tests "-fnext-runtime" $DEFAULT_CFLAGS +} + +# All done. +dg-finish diff --git a/gcc/testsuite/objc.dg/property/synthesize-1.m b/gcc/testsuite/objc.dg/property/synthesize-1.m new file mode 100644 index 000000000..fbc8e03ee --- /dev/null +++ b/gcc/testsuite/objc.dg/property/synthesize-1.m @@ -0,0 +1,53 @@ +/* { dg-do compile } */ + +#include + +@interface MyRootClass +{ + Class isa; +} +@end + +@implementation MyRootClass +@end + +@synthesize isa; /* { dg-error ".@synthesize. not in @implementation context" } */ + +@interface Test : MyRootClass +{ + int v1; + int v2; + int v3; + int v4; + int v5; + int v6; + int v7; + int v8; +} +@property int v1; +@property int v2; +@property int v3; +@property int v4; +@property int v5; +@property int v6; +@property int v7; +@property int v8; +@end + +@implementation Test +@synthesize; /* { dg-error "expected identifier" } */ +@synthesize v1, ; /* { dg-error "expected identifier" } */ +@synthesize v2, v3 = ; /* { dg-error "expected identifier" } */ +@synthesize v4, v5=v6, v6 = v5,v7; +@synthesize v8; +/* Some of the @synthesize above will fail due to syntax errors. The + compiler will then complain that the methods implementing the + properties are missing. That is correct, but we are not + interested. The following ones shut up the compiler. */ +- (int) v1 { return v1; } +- (void) setV1: (int)a { v1 = a; } +- (int) v2 { return v2; } +- (void) setV2: (int)a { v2 = a; } +- (int) v3 { return v3; } +- (void) setV3: (int)a { v3 = a; } +@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 000000000..fc4683187 --- /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 000000000..e49d23424 --- /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-2.m b/gcc/testsuite/objc.dg/property/synthesize-2.m new file mode 100644 index 000000000..92170678f --- /dev/null +++ b/gcc/testsuite/objc.dg/property/synthesize-2.m @@ -0,0 +1,51 @@ +/* Contributed by Nicola Pero , October 2010. */ +/* { dg-do run } */ +/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */ + +#include +#include +#include + +@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 + +@interface Test : MyRootClass +{ + int v1; +} +@property int v1; +/* TODO: Test more types of properties with different semantics + (retain, copy, atomic, nonatomic, and test various C and + Objective-C types). */ +@end + +@implementation Test +@synthesize v1; +@end + +int main (void) +{ + Test *object = [[Test alloc] init]; + + /* Check that the synthesized methods exist and work. Do not invoke + them via property syntax - that is another test. Here we just + want to test the synthesis of the methods. */ + [object setV1: 400]; + + if ([object v1] != 400) + abort (); + + return 0; +} diff --git a/gcc/testsuite/objc.dg/property/synthesize-3.m b/gcc/testsuite/objc.dg/property/synthesize-3.m new file mode 100644 index 000000000..866990531 --- /dev/null +++ b/gcc/testsuite/objc.dg/property/synthesize-3.m @@ -0,0 +1,66 @@ +/* Contributed by Nicola Pero , November 2010. */ +/* { dg-do run } */ +/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */ + +/* Test @synthesize for a @property which is not declared directly in + the @interface, but in a @protocol that the @interface conforms + to. */ + +#include +#include +#include + +@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 MyProtocol +@property int v1; +@end + +@protocol MyProtocol2 +@property int v2; +@end + +@interface Test : MyRootClass +{ + int v1; + int _v2; +} +@end + +@implementation Test +@synthesize v1; +@synthesize v2 = _v2; +@end + +int main (void) +{ + Test *object = [[Test alloc] init]; + + /* Check that the synthesized methods exist and work. Do not invoke + them via property syntax - that is another test. Here we just + want to test the synthesis of the methods. */ + [object setV1: 400]; + + if ([object v1] != 400) + abort (); + + [object setV2: 31]; + + if ([object v2] != 31) + abort (); + + return 0; +} diff --git a/gcc/testsuite/objc.dg/property/synthesize-4.m b/gcc/testsuite/objc.dg/property/synthesize-4.m new file mode 100644 index 000000000..602dc68b4 --- /dev/null +++ b/gcc/testsuite/objc.dg/property/synthesize-4.m @@ -0,0 +1,67 @@ +/* Contributed by Nicola Pero , November 2010. */ +/* { dg-do run } */ +/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */ + +/* Test @synthesize for a @property where the setter/getter are also + declared by the user. This is fine. */ + +#include +#include +#include + +@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 MyProtocol +@property int v1; +@end + +@protocol MyProtocol2 +@property int v2; +@end + +@interface Test : MyRootClass +{ + int v1; + int _v2; +} +- (int)v1; +- (void)setV1: (int)aNumber; +- (int)v2; +@end + +@implementation Test +@synthesize v1; +@synthesize v2 = _v2; +@end + +int main (void) +{ + Test *object = [[Test alloc] init]; + + /* We use dot-syntax here as this is just a general test that + user-declared setters/getters don't cause confusion. */ + object.v1 = 400; + + if (object.v1 != 400) + abort (); + + object.v2 = 31; + + if (object.v2 != 31) + abort (); + + return 0; +} diff --git a/gcc/testsuite/objc.dg/property/synthesize-5.m b/gcc/testsuite/objc.dg/property/synthesize-5.m new file mode 100644 index 000000000..0871b63ee --- /dev/null +++ b/gcc/testsuite/objc.dg/property/synthesize-5.m @@ -0,0 +1,18 @@ +/* Contributed by Nicola Pero , November 2010. */ +/* { dg-do compile } */ + +/* Test that @synthesize does not ICE if asked to use a non-existing + ivar. */ + +#include + +@interface Test +@property int v1; +@end + +@implementation Test +@synthesize v1; /* { dg-error "must be an existing ivar" } */ +@end +/* { dg-warning "incomplete implementation" "" { target *-*-* } 15 } */ +/* { dg-warning "method definition for .-setV1:. not found" "" { target *-*-* } 15 } */ +/* { dg-warning "method definition for .-v1. not found" "" { target *-*-* } 15 } */ diff --git a/gcc/testsuite/objc.dg/property/synthesize-6.m b/gcc/testsuite/objc.dg/property/synthesize-6.m new file mode 100644 index 000000000..19f7c9534 --- /dev/null +++ b/gcc/testsuite/objc.dg/property/synthesize-6.m @@ -0,0 +1,32 @@ +/* Contributed by Nicola Pero , November 2010. */ +/* { dg-do compile } */ + +/* Test that each @synthesize is using a different instance variable, + and that it must belong to the class (not to a superclass). */ + +#include + +@interface Test +{ + int v; + int w; +} +@property int v1; +@property int v2; +@end + +@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." } */ +@end + +@interface Test2 : Test +@property int w1; +@end + +@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 } */ diff --git a/gcc/testsuite/objc.dg/property/synthesize-7.m b/gcc/testsuite/objc.dg/property/synthesize-7.m new file mode 100644 index 000000000..929e3803b --- /dev/null +++ b/gcc/testsuite/objc.dg/property/synthesize-7.m @@ -0,0 +1,86 @@ +/* Contributed by Nicola Pero , November 2010. */ +/* { dg-do run } */ +/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */ + +/* Test @synthesize with protocols of protocols. */ + +#include +#include +#include + +@protocol ProtocolA +@property int countA; +@end + +@protocol ProtocolB +@property int countB; +@end + +@protocol ProtocolC +@property int countC; +@end + +@protocol ProtocolD +@property int countD; +@end + +@interface MyRootClass +{ + Class isa; + int countA; + int countB; + int countC; +} ++ (id) initialize; ++ (id) alloc; +- (id) init; +@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 + +@interface MySubClass : MyRootClass +{ + int countD; +} +@end + +@implementation MySubClass +@synthesize countD; +@end + +int main (void) +{ + MySubClass *object = [[MySubClass alloc] init]; + int i; + + for (i = 0; i < 10; i++) + { + object.countA += i; + object.countB += i + 1; + object.countC += i + 2; + object.countD += i + 3; + } + + if (object.countA != 45) + abort (); + + if (object.countB != 55) + abort (); + + if (object.countC != 65) + abort (); + + if (object.countD != 75) + abort (); + + return 0; +} + + diff --git a/gcc/testsuite/objc.dg/property/synthesize-8.m b/gcc/testsuite/objc.dg/property/synthesize-8.m new file mode 100644 index 000000000..4af3ecc74 --- /dev/null +++ b/gcc/testsuite/objc.dg/property/synthesize-8.m @@ -0,0 +1,80 @@ +/* Contributed by Nicola Pero , November 2010. */ +/* { dg-do compile } */ + +/* Test that when using @synthesize the instance variable and the + property have exactly the same 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) int v; +@property (assign) float w; +@property (assign) id x; +@property (assign) Test *y; +@property (assign) id *z; +@property (assign) ClassA *a; +@property (assign) ClassB *b; +@end + +@implementation Test +@synthesize v; +@synthesize w; +@synthesize x; +@synthesize y; +@synthesize z; +@synthesize a; +@synthesize b; +@end + + +/* This is 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; /* { dg-message "originally specified here" } */ + id *z; /* { dg-message "originally specified here" } */ + ClassA *a; /* { dg-message "originally specified here" } */ + ClassB *b; /* { dg-message "originally specified here" } */ +} +@property (assign) float v; +@property (assign) id w; +@property (assign) int x; +@property (assign) id y; +@property (assign) Test *z; +@property (assign) ClassB *a; +@property (assign) 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; /* { dg-error "property .y. is using instance variable .y. of incompatible type" } */ +@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; /* { dg-error "property .b. is using instance variable .b. of incompatible type" } */ +@end 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 000000000..7eae31d3f --- /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 -- cgit v1.2.3