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