summaryrefslogtreecommitdiffstats
path: root/clang/test
diff options
context:
space:
mode:
Diffstat (limited to 'clang/test')
-rw-r--r--clang/test/Analysis/properties.m81
-rw-r--r--clang/test/Analysis/properties.mm80
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}}
+}
OpenPOWER on IntegriCloud