| 1 | // RUN: %clang_cc1 -triple x86_64-apple-darwin11 -fobjc-runtime-has-weak -fsyntax-only -fobjc-arc -verify %s |
| 2 | // rdar://9340606 |
| 3 | |
| 4 | @interface Foo { |
| 5 | @public |
| 6 | id __unsafe_unretained x; |
| 7 | id __weak y; |
| 8 | id __autoreleasing z; // expected-error {{instance variables cannot have __autoreleasing ownership}} |
| 9 | } |
| 10 | @property(strong) id x; |
| 11 | @property(strong) id y; |
| 12 | @property(strong) id z; |
| 13 | @end |
| 14 | |
| 15 | @interface Bar { |
| 16 | @public |
| 17 | id __unsafe_unretained x; |
| 18 | id __weak y; |
| 19 | id __autoreleasing z; // expected-error {{instance variables cannot have __autoreleasing ownership}} |
| 20 | } |
| 21 | @property(retain) id x; |
| 22 | @property(retain) id y; |
| 23 | @property(retain) id z; |
| 24 | @end |
| 25 | |
| 26 | @interface Bas { |
| 27 | @public |
| 28 | id __unsafe_unretained x; |
| 29 | id __weak y; |
| 30 | id __autoreleasing z; // expected-error {{instance variables cannot have __autoreleasing ownership}} |
| 31 | } |
| 32 | @property(copy) id x; |
| 33 | @property(copy) id y; |
| 34 | @property(copy) id z; |
| 35 | @end |
| 36 | |
| 37 | // Errors should start about here :-) |
| 38 | |
| 39 | @interface Bat |
| 40 | @property(strong) __unsafe_unretained id x; // expected-error {{strong property 'x' may not also be declared __unsafe_unretained}} |
| 41 | @property(strong) __weak id y; // expected-error {{strong property 'y' may not also be declared __weak}} |
| 42 | @property(strong) __autoreleasing id z; // expected-error {{strong property 'z' may not also be declared __autoreleasing}} |
| 43 | @end |
| 44 | |
| 45 | @interface Bau |
| 46 | @property(retain) __unsafe_unretained id x; // expected-error {{strong property 'x' may not also be declared __unsafe_unretained}} |
| 47 | @property(retain) __weak id y; // expected-error {{strong property 'y' may not also be declared __weak}} |
| 48 | @property(retain) __autoreleasing id z; // expected-error {{strong property 'z' may not also be declared __autoreleasing}} |
| 49 | @end |
| 50 | |
| 51 | @interface Bav |
| 52 | @property(copy) __unsafe_unretained id x; // expected-error {{strong property 'x' may not also be declared __unsafe_unretained}} |
| 53 | @property(copy) __weak id y; // expected-error {{strong property 'y' may not also be declared __weak}} |
| 54 | @property(copy) __autoreleasing id z; // expected-error {{strong property 'z' may not also be declared __autoreleasing}} |
| 55 | @end |
| 56 | |
| 57 | @interface Bingo |
| 58 | @property(assign) __unsafe_unretained id x; |
| 59 | @property(assign) __weak id y; // expected-error {{unsafe_unretained property 'y' may not also be declared __weak}} |
| 60 | @property(assign) __autoreleasing id z; // expected-error {{unsafe_unretained property 'z' may not also be declared __autoreleasing}} |
| 61 | @end |
| 62 | |
| 63 | @interface Batman |
| 64 | @property(unsafe_unretained) __unsafe_unretained id x; |
| 65 | @property(unsafe_unretained) __weak id y; // expected-error {{unsafe_unretained property 'y' may not also be declared __weak}} |
| 66 | @property(unsafe_unretained) __autoreleasing id z; // expected-error {{unsafe_unretained property 'z' may not also be declared __autoreleasing}} |
| 67 | @end |
| 68 | |
| 69 | // rdar://9396329 |
| 70 | @interface Super |
| 71 | @property (readonly, retain) id foo; |
| 72 | @property (readonly, weak) id fee; |
| 73 | @property (readonly, strong) id frr; |
| 74 | @end |
| 75 | |
| 76 | @interface Bugg : Super |
| 77 | @property (readwrite) id foo; |
| 78 | @property (readwrite) id fee; |
| 79 | @property (readwrite) id frr; |
| 80 | @end |
| 81 | |
| 82 | // rdar://20152386 |
| 83 | // rdar://20383235 |
| 84 | |
| 85 | @interface NSObject @end |
| 86 | |
| 87 | #pragma clang assume_nonnull begin |
| 88 | @interface I: NSObject |
| 89 | @property(nonatomic, weak) id delegate; // Do not warn, nullable is inferred. |
| 90 | @property(nonatomic, weak, readonly) id ROdelegate; // Do not warn, nullable is inferred. |
| 91 | @property(nonatomic, weak, nonnull) id NonNulldelete; // expected-error {{property attributes 'nonnull' and 'weak' are mutually exclusive}} |
| 92 | @property(nonatomic, weak, nullable) id Nullabledelete; // do not warn |
| 93 | |
| 94 | // strong cases. |
| 95 | @property(nonatomic, strong) id stdelegate; // Do not warn |
| 96 | @property(nonatomic, readonly) id stROdelegate; // Do not warn |
| 97 | @property(nonatomic, strong, nonnull) id stNonNulldelete; // Do not warn |
| 98 | @property(nonatomic, nullable) id stNullabledelete; // do not warn |
| 99 | @end |
| 100 | #pragma clang assume_nonnull end |
| 101 | |
| 102 | @interface J: NSObject |
| 103 | @property(nonatomic, weak) id ddd; // Do not warn, nullable is inferred. |
| 104 | @property(nonatomic, weak, nonnull) id delegate; // expected-error {{property attributes 'nonnull' and 'weak' are mutually exclusive}} |
| 105 | @property(nonatomic, weak, nonnull, readonly) id ROdelegate; // expected-error {{property attributes 'nonnull' and 'weak' are mutually exclusive}} |
| 106 | @end |
| 107 | |
| 108 | // rdar://problem/23931441 |
| 109 | @protocol P |
| 110 | @property(readonly, retain) id prop; |
| 111 | @end |
| 112 | |
| 113 | __attribute__((objc_root_class)) |
| 114 | @interface I2<P> |
| 115 | @end |
| 116 | |
| 117 | @interface I2() |
| 118 | @property (readwrite) id prop; |
| 119 | @end |
| 120 | |
| 121 | @implementation I2 |
| 122 | @synthesize prop; |
| 123 | @end |
| 124 | |
| 125 | // rdar://31579994 |
| 126 | // Verify that the all of the property declarations in inherited protocols are |
| 127 | // compatible when synthesing a property from a protocol. |
| 128 | |
| 129 | @protocol CopyVsAssign1 |
| 130 | @property (copy, nonatomic, readonly) id prop; // expected-error {{property with attribute 'copy' was selected for synthesis}} |
| 131 | @end |
| 132 | @protocol CopyVsAssign2 |
| 133 | @property (assign, nonatomic, readonly) id prop; // expected-note {{it could also be property without attribute 'copy' declared here}} |
| 134 | @end |
| 135 | |
| 136 | @interface CopyVsAssign: Foo <CopyVsAssign1, CopyVsAssign2> |
| 137 | @end |
| 138 | @implementation CopyVsAssign |
| 139 | @synthesize prop; // expected-note {{property synthesized here}} |
| 140 | @end |
| 141 | |
| 142 | @protocol RetainVsNonRetain1 |
| 143 | @property (readonly) id prop; // expected-error {{property without attribute 'retain (or strong)' was selected for synthesis}} |
| 144 | @end |
| 145 | @protocol RetainVsNonRetain2 |
| 146 | @property (retain, readonly) id prop; // expected-note {{it could also be property with attribute 'retain (or strong)' declared here}} |
| 147 | @end |
| 148 | |
| 149 | @interface RetainVsNonRetain: Foo <RetainVsNonRetain1, RetainVsNonRetain2> |
| 150 | @end |
| 151 | @implementation RetainVsNonRetain |
| 152 | @synthesize prop; // expected-note {{property synthesized here}} |
| 153 | @end |
| 154 | |
| 155 | @protocol AtomicVsNonatomic1 |
| 156 | @property (copy, nonatomic, readonly) id prop; // expected-error {{property without attribute 'atomic' was selected for synthesis}} |
| 157 | @end |
| 158 | @protocol AtomicVsNonatomic2 |
| 159 | @property (copy, atomic, readonly) id prop; // expected-note {{it could also be property with attribute 'atomic' declared here}} |
| 160 | @end |
| 161 | |
| 162 | @interface AtomicVsNonAtomic: Foo <AtomicVsNonatomic1, AtomicVsNonatomic2> |
| 163 | @end |
| 164 | @implementation AtomicVsNonAtomic |
| 165 | @synthesize prop; // expected-note {{property synthesized here}} |
| 166 | @end |
| 167 | |
| 168 | @protocol Getter1 |
| 169 | @property (copy, readonly) id prop; // expected-error {{property with getter 'prop' was selected for synthesis}} |
| 170 | @end |
| 171 | @protocol Getter2 |
| 172 | @property (copy, getter=x, readonly) id prop; // expected-note {{it could also be property with getter 'x' declared here}} |
| 173 | @end |
| 174 | |
| 175 | @interface GetterVsGetter: Foo <Getter1, Getter2> |
| 176 | @end |
| 177 | @implementation GetterVsGetter |
| 178 | @synthesize prop; // expected-note {{property synthesized here}} |
| 179 | @end |
| 180 | |
| 181 | @protocol Setter1 |
| 182 | @property (copy, readonly) id prop; |
| 183 | @end |
| 184 | @protocol Setter2 |
| 185 | @property (copy, setter=setp:, readwrite) id prop; // expected-error {{property with setter 'setp:' was selected for synthesis}} |
| 186 | @end |
| 187 | @protocol Setter3 |
| 188 | @property (copy, readwrite) id prop; // expected-note {{it could also be property with setter 'setProp:' declared here}} |
| 189 | @end |
| 190 | |
| 191 | @interface SetterVsSetter: Foo <Setter1, Setter2, Setter3> |
| 192 | @end |
| 193 | @implementation SetterVsSetter |
| 194 | @synthesize prop; // expected-note {{property synthesized here}} |
| 195 | @end |
| 196 | |
| 197 | @protocol TypeVsAttribute1 |
| 198 | @property (assign, atomic, readonly) int prop; // expected-error {{property of type 'int' was selected for synthesis}} |
| 199 | @end |
| 200 | @protocol TypeVsAttribute2 |
| 201 | @property (assign, atomic, readonly) id prop; // expected-note {{it could also be property of type 'id' declared here}} |
| 202 | @end |
| 203 | @protocol TypeVsAttribute3 |
| 204 | @property (copy, readonly) id prop; // expected-note {{it could also be property with attribute 'copy' declared here}} |
| 205 | @end |
| 206 | |
| 207 | @interface TypeVsAttribute: Foo <TypeVsAttribute1, TypeVsAttribute2, TypeVsAttribute3> |
| 208 | @end |
| 209 | @implementation TypeVsAttribute |
| 210 | @synthesize prop; // expected-note {{property synthesized here}} |
| 211 | @end |
| 212 | |
| 213 | @protocol TypeVsSetter1 |
| 214 | @property (assign, nonatomic, readonly) int prop; // expected-note {{it could also be property of type 'int' declared here}} |
| 215 | @end |
| 216 | @protocol TypeVsSetter2 |
| 217 | @property (assign, nonatomic, readonly) id prop; // ok |
| 218 | @end |
| 219 | @protocol TypeVsSetter3 |
| 220 | @property (assign, nonatomic, readwrite) id prop; // expected-error {{property of type 'id' was selected for synthesis}} |
| 221 | @end |
| 222 | |
| 223 | @interface TypeVsSetter: Foo <TypeVsSetter1, TypeVsSetter2, TypeVsSetter3> |
| 224 | @end |
| 225 | @implementation TypeVsSetter |
| 226 | @synthesize prop; // expected-note {{property synthesized here}} |
| 227 | @end |
| 228 | |
| 229 | @protocol AutoStrongProp |
| 230 | |
| 231 | @property (nonatomic, readonly) NSObject *prop; |
| 232 | |
| 233 | @end |
| 234 | |
| 235 | @protocol AutoStrongProp_Internal <AutoStrongProp> |
| 236 | |
| 237 | // This property gets the 'strong' attribute automatically. |
| 238 | @property (nonatomic, readwrite) NSObject *prop; |
| 239 | |
| 240 | @end |
| 241 | |
| 242 | @interface SynthesizeWithImplicitStrongNoError : NSObject <AutoStrongProp> |
| 243 | @end |
| 244 | |
| 245 | @interface SynthesizeWithImplicitStrongNoError () <AutoStrongProp_Internal> |
| 246 | |
| 247 | @end |
| 248 | |
| 249 | @implementation SynthesizeWithImplicitStrongNoError |
| 250 | |
| 251 | // no error, 'strong' is implicit in the 'readwrite' property. |
| 252 | @synthesize prop = _prop; |
| 253 | |
| 254 | @end |
| 255 | |
| 256 | // rdar://39024725 |
| 257 | // Allow strong readwrite property and a readonly one. |
| 258 | @protocol StrongCollision |
| 259 | |
| 260 | @property(strong) NSObject *p; |
| 261 | @property(copy) NSObject *p2; |
| 262 | |
| 263 | // expected-error@+1 {{property with attribute 'retain (or strong)' was selected for synthesis}} |
| 264 | @property(strong, readwrite) NSObject *collision; |
| 265 | |
| 266 | @end |
| 267 | |
| 268 | @protocol ReadonlyCollision |
| 269 | |
| 270 | @property(readonly) NSObject *p; |
| 271 | @property(readonly) NSObject *p2; |
| 272 | |
| 273 | // expected-note@+1 {{it could also be property without attribute 'retain (or strong)' declared here}} |
| 274 | @property(readonly, weak) NSObject *collision; |
| 275 | |
| 276 | @end |
| 277 | |
| 278 | @interface StrongReadonlyCollision : NSObject <StrongCollision, ReadonlyCollision> |
| 279 | @end |
| 280 | |
| 281 | @implementation StrongReadonlyCollision |
| 282 | |
| 283 | // no error |
| 284 | @synthesize p = _p; |
| 285 | @synthesize p2 = _p2; |
| 286 | |
| 287 | @synthesize collision = _collision; // expected-note {{property synthesized here}} |
| 288 | |
| 289 | @end |
| 290 | |