1 // RUN: %clang_cc1 -fsyntax-only -verify %s 2 3 @interface I0 4 @property(readonly) int x; 5 @property(readonly) int y; 6 @property(readonly) int z; 7 -(void) setY: (int) y0; 8 @end 9 10 @interface I0 (Cat0) 11 -(void) setX: (int) a0; 12 @end 13 14 @implementation I0 15 @dynamic x; 16 @dynamic y; 17 @dynamic z; 18 -(void) setY: (int) y0{} 19 20 -(void) im0 { 21 self.x = 0; 22 self.y = 2; 23 self.z = 2; // expected-error {{assigning to property with 'readonly' attribute not allowed}} 24 } 25 @end 26 27 // Test when property is 'readonly' but it has a setter in 28 // its implementation only. 29 @interface I1 { 30 } 31 @property(readonly) int identifier; 32 @end 33 34 35 @implementation I1 36 @dynamic identifier; 37 - (void)setIdentifier:(int)ident {} 38 39 - (id)initWithIdentifier:(int)Arg { 40 self.identifier = 0; 41 } 42 43 @end 44 45 46 // Also in a category implementation 47 @interface I1(CAT) 48 @property(readonly) int rprop; 49 @end 50 51 52 @implementation I1(CAT) 53 @dynamic rprop; 54 - (void)setRprop:(int)ident {} 55 56 - (id)initWithIdentifier:(int)Arg { 57 self.rprop = 0; 58 } 59 60 @end 61 62 static int g_val; 63 64 @interface Root 65 + alloc; 66 - init; 67 @end 68 69 @interface Subclass : Root 70 { 71 int setterOnly; 72 } 73 - (void) setSetterOnly:(int)value; 74 @end 75 76 @implementation Subclass 77 - (void) setSetterOnly:(int)value { 78 setterOnly = value; 79 g_val = setterOnly; 80 } 81 @end 82 83 @interface C {} 84 // - (int)Foo; 85 - (void)setFoo:(int)value; 86 @end 87 88 void g(int); 89 90 void f(C *c) { 91 c.Foo = 17; // OK 92 g(c.Foo); // expected-error {{expected getter method not found on object of type 'C *'}} 93 } 94 95 96 void abort(void); 97 int main (void) { 98 Subclass *x = [[Subclass alloc] init]; 99 100 x.setterOnly = 4; // OK 101 if (g_val != 4) 102 abort (); 103 return 0; 104 } 105