diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2015-06-21 14:00:56 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2015-06-21 14:00:56 +0000 |
| commit | 2e645aa5697838f16ec570eb07c2bee7e13d0e0b (patch) | |
| tree | a764184c2fc9486979b074250b013a0937ee64e5 /test/Analysis | |
| parent | 798321d8eb5630cd4a8f490a4f25e32ef195fb07 (diff) | |
Notes
Diffstat (limited to 'test/Analysis')
| -rw-r--r-- | test/Analysis/CFContainers.mm | 22 | ||||
| -rw-r--r-- | test/Analysis/designated-initializer.c | 41 | ||||
| -rw-r--r-- | test/Analysis/retain-release.m | 34 |
3 files changed, 97 insertions, 0 deletions
diff --git a/test/Analysis/CFContainers.mm b/test/Analysis/CFContainers.mm index b01942310f7b2..f315bc9f045cb 100644 --- a/test/Analysis/CFContainers.mm +++ b/test/Analysis/CFContainers.mm @@ -19,6 +19,7 @@ typedef struct { } CFArrayCallBacks; typedef const struct __CFArray * CFArrayRef; CFArrayRef CFArrayCreate(CFAllocatorRef allocator, const void **values, CFIndex numValues, const CFArrayCallBacks *callBacks); +typedef struct __CFArray * CFMutableArrayRef; typedef const struct __CFString * CFStringRef; enum { kCFNumberSInt8Type = 1, @@ -202,3 +203,24 @@ void TestConst(CFArrayRef A, CFIndex sIndex, void* x[]) { void TestNullArray() { CFArrayGetValueAtIndex(0, 0); } + +void ArrayRefMutableEscape(CFMutableArrayRef a); +void ArrayRefEscape(CFArrayRef a); + +void TestCFMutableArrayRefEscapeViaMutableArgument(CFMutableArrayRef a) { + CFIndex aLen = CFArrayGetCount(a); + ArrayRefMutableEscape(a); + + // ArrayRefMutableEscape could mutate a to make it have + // at least aLen + 1 elements, so do not report an error here. + CFArrayGetValueAtIndex(a, aLen); +} + +void TestCFMutableArrayRefEscapeViaImmutableArgument(CFMutableArrayRef a) { + CFIndex aLen = CFArrayGetCount(a); + ArrayRefEscape(a); + + // ArrayRefEscape is declared to take a CFArrayRef (i.e, an immutable array) + // so we assume it does not change the length of a. + CFArrayGetValueAtIndex(a, aLen); // expected-warning {{Index is out of bounds}} +} diff --git a/test/Analysis/designated-initializer.c b/test/Analysis/designated-initializer.c new file mode 100644 index 0000000000000..b601f872571f0 --- /dev/null +++ b/test/Analysis/designated-initializer.c @@ -0,0 +1,41 @@ +// RUN: %clang_cc1 -analyze -analyzer-checker=debug.DumpCFG %s 2>&1 \ +// RUN: | FileCheck %s + +struct Q { int a, b, c; }; +union UQ { struct Q q; }; +union UQ getUQ() { + union UQ u = { { 1, 2, 3 } }; + return u; +} + +void test() { + struct LUQ { union UQ uq; } var = { getUQ(), .uq.q.a = 100 }; + struct Q s[] = { + [0] = (struct Q){1, 2}, + [0].c = 3 + }; +} + +// CHECK: void test() +// CHECK: [B1] +// CHECK: 1: getUQ +// CHECK: 2: [B1.1] (ImplicitCastExpr, FunctionToPointerDecay, union UQ (*)()) +// CHECK: 3: [B1.2]() +// CHECK: 4: 100 +// CHECK: 5: /*no init*/ +// CHECK: 6: /*no init*/ +// CHECK: 7: {[B1.4], [B1.5], [B1.6]} +// CHECK: 8: {[B1.7]} +// CHECK: 9: {/*base*/[B1.3], /*updater*/[B1.8]} +// CHECK: 10: {[B1.3], .uq.q.a = [B1.4]} +// CHECK: 11: struct LUQ var = {getUQ(), .uq.q.a = 100}; +// CHECK: 12: 1 +// CHECK: 13: 2 +// CHECK: 14: /*implicit*/(int)0 +// CHECK: 15: {[B1.12], [B1.13]} +// CHECK: 18: /*no init*/ +// CHECK: 19: /*no init*/ +// CHECK: 20: 3 +// CHECK: 21: {[B1.18], [B1.19], [B1.20]} +// CHECK: 22: {/*base*/[B1.17], /*updater*/[B1.21]} +// CHECK: 24: struct Q s[] = {[0] = (struct Q){1, 2}, [0].c = 3}; diff --git a/test/Analysis/retain-release.m b/test/Analysis/retain-release.m index 6973f9bcd67df..1dbcda507c174 100644 --- a/test/Analysis/retain-release.m +++ b/test/Analysis/retain-release.m @@ -2153,6 +2153,40 @@ id returnNSNull() { return [NSNull null]; // no-warning } +//===----------------------------------------------------------------------===// +// cf_returns_[not_]retained on parameters +//===----------------------------------------------------------------------===// + +void testCFReturnsNotRetained() { + extern void getViaParam(CFTypeRef * CF_RETURNS_NOT_RETAINED outObj); + CFTypeRef obj; + getViaParam(&obj); + CFRelease(obj); // // expected-warning {{Incorrect decrement of the reference count of an object that is not owned at this point by the caller}} +} + +void testCFReturnsNotRetainedAnnotated() { + extern void getViaParam2(CFTypeRef * __nonnull CF_RETURNS_NOT_RETAINED outObj); + CFTypeRef obj; + getViaParam2(&obj); + CFRelease(obj); // // expected-warning {{Incorrect decrement of the reference count of an object that is not owned at this point by the caller}} +} + +void testCFReturnsRetained() { + extern int copyViaParam(CFTypeRef * CF_RETURNS_RETAINED outObj); + CFTypeRef obj; + copyViaParam(&obj); + CFRelease(obj); + CFRelease(obj); // // FIXME-warning {{Incorrect decrement of the reference count of an object that is not owned at this point by the caller}} +} + +void testCFReturnsRetainedError() { + extern int copyViaParam(CFTypeRef * CF_RETURNS_RETAINED outObj); + CFTypeRef obj; + if (copyViaParam(&obj) == -42) + return; // no-warning + CFRelease(obj); +} + // CHECK: <key>diagnostics</key> // CHECK-NEXT: <array> // CHECK-NEXT: <dict> |
