diff options
Diffstat (limited to 'clang/test')
| -rw-r--r-- | clang/test/Analysis/properties.m | 81 | ||||
| -rw-r--r-- | clang/test/Analysis/properties.mm | 80 |
2 files changed, 160 insertions, 1 deletions
diff --git a/clang/test/Analysis/properties.m b/clang/test/Analysis/properties.m index ddd0068d369..b3e654f377a 100644 --- a/clang/test/Analysis/properties.m +++ b/clang/test/Analysis/properties.m @@ -1,4 +1,6 @@ -// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.RetainCount -analyzer-store=region -verify -Wno-objc-root-class %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.RetainCount,debug.ExprInspection -analyzer-store=region -verify -Wno-objc-root-class %s + +void clang_analyzer_eval(int); typedef signed char BOOL; typedef unsigned int NSUInteger; @@ -14,6 +16,7 @@ typedef struct _NSZone NSZone; -(id)autorelease; -(id)copy; -(id)retain; +-(oneway void)release; @end @interface NSString : NSObject <NSCopying, NSMutableCopying, NSCoding> - (NSUInteger)length; @@ -166,3 +169,79 @@ void rdar6611873() { @end +//------ +// Property accessor synthesis +//------ + +void testConsistency(Person *p) { + clang_analyzer_eval(p.name == p.name); // expected-warning{{TRUE}} + + extern void doSomethingWithPerson(Person *p); + id origName = p.name; + clang_analyzer_eval(p.name == origName); // expected-warning{{TRUE}} + doSomethingWithPerson(p); + clang_analyzer_eval(p.name == origName); // expected-warning{{UNKNOWN}} +} + +void testOverrelease(Person *p) { + [p.name release]; // expected-warning{{not owned}} +} + +@interface IntWrapper +@property int value; +@end + +@implementation IntWrapper +@synthesize value; +@end + +void testConsistencyInt(IntWrapper *w) { + clang_analyzer_eval(w.value == w.value); // expected-warning{{TRUE}} + + int origValue = w.value; + if (origValue != 42) + return; + + clang_analyzer_eval(w.value == 42); // expected-warning{{TRUE}} +} + +void testConsistencyInt2(IntWrapper *w) { + if (w.value != 42) + return; + + clang_analyzer_eval(w.value == 42); // expected-warning{{TRUE}} +} + +typedef struct { + int value; +} IntWrapperStruct; + +@interface StructWrapper +@property IntWrapperStruct inner; +@end + +@implementation StructWrapper +@synthesize inner; +@end + +void testConsistencyStruct(StructWrapper *w) { + clang_analyzer_eval(w.inner.value == w.inner.value); // expected-warning{{TRUE}} + + int origValue = w.inner.value; + if (origValue != 42) + return; + + clang_analyzer_eval(w.inner.value == 42); // expected-warning{{TRUE}} +} + + +@interface OpaqueIntWrapper +@property int value; +@end + +// For now, don't assume a property is implemented using an ivar unless we can +// actually see that it is. +void testOpaqueConsistency(OpaqueIntWrapper *w) { + clang_analyzer_eval(w.value == w.value); // expected-warning{{UNKNOWN}} +} + diff --git a/clang/test/Analysis/properties.mm b/clang/test/Analysis/properties.mm new file mode 100644 index 00000000000..dd44219856f --- /dev/null +++ b/clang/test/Analysis/properties.mm @@ -0,0 +1,80 @@ +// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.RetainCount,debug.ExprInspection -analyzer-store=region -verify -Wno-objc-root-class %s + +void clang_analyzer_eval(bool); +void clang_analyzer_checkInlined(bool); + +@interface IntWrapper +@property (readonly) int &value; +@end + +@implementation IntWrapper +@synthesize value; +@end + +void testReferenceConsistency(IntWrapper *w) { + clang_analyzer_eval(w.value == w.value); // expected-warning{{TRUE}} + clang_analyzer_eval(&w.value == &w.value); // expected-warning{{TRUE}} + + if (w.value != 42) + return; + + clang_analyzer_eval(w.value == 42); // expected-warning{{TRUE}} +} + +void testReferenceAssignment(IntWrapper *w) { + w.value = 42; + clang_analyzer_eval(w.value == 42); // expected-warning{{TRUE}} +} + + +// FIXME: Handle C++ structs, which need to go through the copy constructor. + +struct IntWrapperStruct { + int value; +}; + +@interface StructWrapper +@property IntWrapperStruct inner; +@end + +@implementation StructWrapper +@synthesize inner; +@end + +void testConsistencyStruct(StructWrapper *w) { + clang_analyzer_eval(w.inner.value == w.inner.value); // expected-warning{{UNKNOWN}} + + int origValue = w.inner.value; + if (origValue != 42) + return; + + clang_analyzer_eval(w.inner.value == 42); // expected-warning{{UNKNOWN}} +} + + +class CustomCopy { +public: + CustomCopy() : value(0) {} + CustomCopy(const CustomCopy &other) { + clang_analyzer_checkInlined(false); + } + int value; +}; + +@interface CustomCopyWrapper +@property CustomCopy inner; +@end + +@implementation CustomCopyWrapper +@synthesize inner; +@end + +void testConsistencyCustomCopy(CustomCopyWrapper *w) { + clang_analyzer_eval(w.inner.value == w.inner.value); // expected-warning{{UNKNOWN}} + + int origValue = w.inner.value; + if (origValue != 42) + return; + + clang_analyzer_eval(w.inner.value == 42); // expected-warning{{UNKNOWN}} +} |

