|  | // RUN: %clang_analyze_cc1 -w -fblocks -analyzer-checker=osx.ObjCProperty %s -verify | 
|  |  | 
|  | #include "Inputs/system-header-simulator-objc.h" | 
|  |  | 
|  | @interface I : NSObject { | 
|  | NSMutableString *_mutableExplicitStr; | 
|  | NSMutableString *_trulyMutableStr; | 
|  | NSMutableString *_trulyMutableExplicitStr; | 
|  | } | 
|  | @property(copy) NSString *str; // no-warning | 
|  | @property(copy) NSMutableString *mutableStr; // expected-warning{{Property of mutable type 'NSMutableString' has 'copy' attribute; an immutable object will be stored instead}} | 
|  | @property(copy) NSMutableString *mutableExplicitStr; // expected-warning{{Property of mutable type 'NSMutableString' has 'copy' attribute; an immutable object will be stored instead}} | 
|  | @property(copy, readonly) NSMutableString *mutableReadonlyStr; // no-warning | 
|  | @property(copy, readonly) NSMutableString *mutableReadonlyStrOverriddenInChild; // no-warning | 
|  | @property(copy, readonly) NSMutableString *mutableReadonlyStrOverriddenInCategory; // no-warning | 
|  | @property(copy) NSMutableString *trulyMutableStr; // no-warning | 
|  | @property(copy) NSMutableString *trulyMutableExplicitStr; // no-warning | 
|  | @property(copy) NSMutableString *trulyMutableStrWithSynthesizedStorage; // no-warning | 
|  | @end | 
|  |  | 
|  | @interface I () {} | 
|  | @property(copy) NSMutableString *mutableStrInCategory; // expected-warning{{Property of mutable type 'NSMutableString' has 'copy' attribute; an immutable object will be stored instead}} | 
|  | @property (copy, readwrite) NSMutableString *mutableReadonlyStrOverriddenInCategory; // expected-warning{{Property of mutable type 'NSMutableString' has 'copy' attribute; an immutable object will be stored instead}} | 
|  | @end | 
|  |  | 
|  | @implementation I | 
|  | @synthesize mutableExplicitStr = _mutableExplicitStr; | 
|  | - (NSMutableString *)trulyMutableStr { | 
|  | return _trulyMutableStr; | 
|  | } | 
|  | - (void)setTrulyMutableStr: (NSMutableString *) S { | 
|  | _trulyMutableStr = [S mutableCopy]; | 
|  | } | 
|  | @dynamic trulyMutableExplicitStr; | 
|  | - (NSMutableString *)trulyMutableExplicitStr { | 
|  | return _trulyMutableExplicitStr; | 
|  | } | 
|  | - (void)setTrulyMutableExplicitStr: (NSMutableString *) S { | 
|  | _trulyMutableExplicitStr = [S mutableCopy]; | 
|  | } | 
|  | @synthesize trulyMutableStrWithSynthesizedStorage; | 
|  | - (NSMutableString *)trulyMutableStrWithSynthesizedStorage { | 
|  | return trulyMutableStrWithSynthesizedStorage; | 
|  | } | 
|  | - (void)setTrulyMutableStrWithSynthesizedStorage: (NSMutableString *) S { | 
|  | trulyMutableStrWithSynthesizedStorage = [S mutableCopy]; | 
|  | } | 
|  | @end | 
|  |  | 
|  | @interface J : I {} | 
|  | @property (copy, readwrite) NSMutableString *mutableReadonlyStrOverriddenInChild; // expected-warning{{Property of mutable type 'NSMutableString' has 'copy' attribute; an immutable object will be stored instead}} | 
|  | @end | 
|  |  | 
|  | @implementation J | 
|  | @end | 
|  |  | 
|  | // If we do not see the implementation then we do not want to warn, | 
|  | // because we may miss a user-defined setter that works correctly. | 
|  | @interface IWithoutImpl : NSObject {} | 
|  | @property(copy) NSMutableString *mutableStr; // no-warning | 
|  | @end | 
|  |  | 
|  | @protocol SomeProtocol | 
|  | // Don't warn on protocol properties because it is possible to | 
|  | // conform to them correctly; it is only synthesized setters that | 
|  | // that are definitely incorrect. | 
|  | @property (copy) NSMutableString *myProp; // no-crash // no-warning | 
|  | @end |