1 | // RUN: %clang_analyze_cc1 -w -fblocks -analyzer-checker=osx.ObjCProperty %s -verify |
2 | |
3 | #include "Inputs/system-header-simulator-objc.h" |
4 | |
5 | @interface I : NSObject { |
6 | NSMutableString *_mutableExplicitStr; |
7 | NSMutableString *_trulyMutableStr; |
8 | NSMutableString *_trulyMutableExplicitStr; |
9 | } |
10 | @property(copy) NSString *str; // no-warning |
11 | @property(copy) NSMutableString *mutableStr; // expected-warning{{Property of mutable type 'NSMutableString' has 'copy' attribute; an immutable object will be stored instead}} |
12 | @property(copy) NSMutableString *mutableExplicitStr; // expected-warning{{Property of mutable type 'NSMutableString' has 'copy' attribute; an immutable object will be stored instead}} |
13 | @property(copy, readonly) NSMutableString *mutableReadonlyStr; // no-warning |
14 | @property(copy, readonly) NSMutableString *mutableReadonlyStrOverriddenInChild; // no-warning |
15 | @property(copy, readonly) NSMutableString *mutableReadonlyStrOverriddenInCategory; // no-warning |
16 | @property(copy) NSMutableString *trulyMutableStr; // no-warning |
17 | @property(copy) NSMutableString *trulyMutableExplicitStr; // no-warning |
18 | @property(copy) NSMutableString *trulyMutableStrWithSynthesizedStorage; // no-warning |
19 | @end |
20 | |
21 | @interface I () {} |
22 | @property(copy) NSMutableString *mutableStrInCategory; // expected-warning{{Property of mutable type 'NSMutableString' has 'copy' attribute; an immutable object will be stored instead}} |
23 | @property (copy, readwrite) NSMutableString *mutableReadonlyStrOverriddenInCategory; // expected-warning{{Property of mutable type 'NSMutableString' has 'copy' attribute; an immutable object will be stored instead}} |
24 | @end |
25 | |
26 | @implementation I |
27 | @synthesize mutableExplicitStr = _mutableExplicitStr; |
28 | - (NSMutableString *)trulyMutableStr { |
29 | return _trulyMutableStr; |
30 | } |
31 | - (void)setTrulyMutableStr: (NSMutableString *) S { |
32 | _trulyMutableStr = [S mutableCopy]; |
33 | } |
34 | @dynamic trulyMutableExplicitStr; |
35 | - (NSMutableString *)trulyMutableExplicitStr { |
36 | return _trulyMutableExplicitStr; |
37 | } |
38 | - (void)setTrulyMutableExplicitStr: (NSMutableString *) S { |
39 | _trulyMutableExplicitStr = [S mutableCopy]; |
40 | } |
41 | @synthesize trulyMutableStrWithSynthesizedStorage; |
42 | - (NSMutableString *)trulyMutableStrWithSynthesizedStorage { |
43 | return trulyMutableStrWithSynthesizedStorage; |
44 | } |
45 | - (void)setTrulyMutableStrWithSynthesizedStorage: (NSMutableString *) S { |
46 | trulyMutableStrWithSynthesizedStorage = [S mutableCopy]; |
47 | } |
48 | @end |
49 | |
50 | @interface J : I {} |
51 | @property (copy, readwrite) NSMutableString *mutableReadonlyStrOverriddenInChild; // expected-warning{{Property of mutable type 'NSMutableString' has 'copy' attribute; an immutable object will be stored instead}} |
52 | @end |
53 | |
54 | @implementation J |
55 | @end |
56 | |
57 | // If we do not see the implementation then we do not want to warn, |
58 | // because we may miss a user-defined setter that works correctly. |
59 | @interface IWithoutImpl : NSObject {} |
60 | @property(copy) NSMutableString *mutableStr; // no-warning |
61 | @end |
62 | |
63 | @protocol SomeProtocol |
64 | // Don't warn on protocol properties because it is possible to |
65 | // conform to them correctly; it is only synthesized setters that |
66 | // that are definitely incorrect. |
67 | @property (copy) NSMutableString *myProp; // no-crash // no-warning |
68 | @end |
69 | |