// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,deadcode.DeadStores,osx.cocoa.RetainCount,unix.Malloc,unix.MismatchedDeallocator -analyzer-output=plist -analyzer-config deadcode.DeadStores:ShowFixIts=true -o %t -w %s // RUN: %normalize_plist <%t | diff -ub %S/Inputs/expected-plists/edges-new.mm.plist - //===----------------------------------------------------------------------===// // Forward declarations (from headers). //===----------------------------------------------------------------------===// typedef const struct __CFNumber * CFNumberRef; typedef const struct __CFAllocator * CFAllocatorRef; extern const CFAllocatorRef kCFAllocatorDefault; typedef signed long CFIndex; enum { kCFNumberSInt8Type = 1, kCFNumberSInt16Type = 2, kCFNumberSInt32Type = 3, kCFNumberSInt64Type = 4, kCFNumberFloat32Type = 5, kCFNumberFloat64Type = 6, kCFNumberCharType = 7, kCFNumberShortType = 8, kCFNumberIntType = 9, kCFNumberLongType = 10, kCFNumberLongLongType = 11, kCFNumberFloatType = 12, kCFNumberDoubleType = 13, kCFNumberCFIndexType = 14, kCFNumberNSIntegerType = 15, kCFNumberCGFloatType = 16, kCFNumberMaxType = 16 }; typedef CFIndex CFNumberType; CFNumberRef CFNumberCreate(CFAllocatorRef allocator, CFNumberType theType, const void *valuePtr); #define nil ((id)0) __attribute__((objc_root_class)) @interface NSObject + (instancetype) alloc; - (instancetype) init; - (instancetype)retain; - (void)release; @end @interface NSArray : NSObject @end //===----------------------------------------------------------------------===// // Basic tracking of null and tests for null. //===----------------------------------------------------------------------===// void test_null_init(void) { int *p = 0; *p = 0xDEADBEEF; } void test_null_assign(void) { int *p; p = 0; *p = 0xDEADBEEF; } void test_null_assign_transitive(void) { int *p; p = 0; int *q = p; *q = 0xDEADBEEF; } void test_null_cond(int *p) { if (!p) { *p = 0xDEADBEEF; } } void test_null_cond_transitive(int *q) { if (!q) { int *p = q; *p = 0xDEADBEEF; } } void test_null_field(void) { struct s { int *p; } x; x.p = 0; *(x.p) = 0xDEADBEEF; } void test_assumptions(int a, int b) { if (a == 0) { return; } if (b != 0) { return; } int *p = 0; *p = 0xDEADBEEF; } int *bar_cond_assign(); int test_cond_assign() { int *p; if ((p = bar_cond_assign())) return 1; return *p; } //===----------------------------------------------------------------------===// // Diagnostics for leaks and "noreturn" paths. //===----------------------------------------------------------------------===// // leak reports should not show paths that end with exit() (but ones that don't end with exit()) void stop() __attribute__((noreturn)); void rdar8331641(int x) { signed z = 1; CFNumberRef value = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &z); // expected-warning{{leak}} if (x) stop(); (void) value; } //===----------------------------------------------------------------------===// // Test loops and control-flow. //===----------------------------------------------------------------------===// void test_objc_fast_enumeration(NSArray *x) { id obj; for (obj in x) *(volatile int *)0 = 0; } void test_objc_fast_enumeration_2(id arr) { int x; for (id obj in arr) { x = 1; } x += 1; } // Test that loops are documented in the path. void rdar12280665() { for (unsigned i = 0; i < 2; ++i) { if (i == 1) { int *p = 0; *p = 0xDEADBEEF; // expected-warning {{dereference}} } } } // Test for a "loop executed 0 times" diagnostic. int *radar12322528_bar(); void radar12322528_for(int x) { int z; int *p = 0; for (unsigned i = 0; i < x; ++i) { p = radar12322528_bar(); } *p = 0xDEADBEEF; } void radar12322528_while(int x) { int *p = 0; unsigned i = 0; for ( ; i < x ; ) { ++i; p = radar12322528_bar(); } *p = 0xDEADBEEF; } void radar12322528_foo_2() { int *p = 0; for (unsigned i = 0; i < 2; ++i) { if (i == 0) continue; if (i == 1) { break; } } *p = 0xDEADBEEF; } void test_loop_diagnostics() { int *p = 0; for (int i = 0; i < 2; ++i) { p = 0; } *p = 1; } void test_loop_diagnostics_2() { int *p = 0; for (int i = 0; i < 2; ) { ++i; p = 0; } *p = 1; } void test_loop_diagnostics_3() { int z; int y; int k; int *p = 0; int i = 0; while (i < 2) { ++i; p = 0; } * p = 1; } void test_do_while() { unsigned i = 0; int *p; do { ++i; p = 0; } while (i< 2); *p = 0xDEADBEEF; } void test_logical_and() { int *p = 0; if (1 && 2) { *p = 0xDEADBEEF; } } void test_logical_or() { int *p = 0; if (0 || 2) { *p = 0xDEADBEEF; } } void test_logical_or_call() { extern int call(int); int *p = 0; if (call(0 || 2)) { *p = 0xDEADBEEF; } } void test_nested_logicals(int coin) { int *p = 0; if ((0 || 0) || coin) { *p = 0xDEADBEEF; } if (0 || (0 || !coin)) { *p = 0xDEADBEEF; } } void test_deeply_nested_logicals() { extern int call(int); int *p = 0; if ((0 || (5 && 0)) ? 0 : ((0 || 4) ? call(1 && 5) : 0)) { *p = 0xDEADBEEF; } } void test_ternary(int x, int *y) { int z = x ? 0 : 1; int *p = z ? y : 0; *p = 0xDEADBEEF; } void testUseless(int *y) { if (y) { } if (y) { } int *p = 0; *p = 0xDEADBEEF; } //===----------------------------------------------------------------------===// // Interprocedural tests. //===----------------------------------------------------------------------===// @interface IPA_Foo - (int *) returnsPointer; @end int testFoo(IPA_Foo *x) { if (x) return 1; return *[x returnsPointer]; } @interface IPA_X : NSObject - (int *)getPointer; @end void test1_IPA_X() { IPA_X *x = nil; *[x getPointer] = 1; // here } @interface IPA_Y : NSObject - (IPA_Y *)opaque; - (IPA_X *)getX; @end @implementation IPA_Y - (IPA_X *)getX { return nil; } @end void test_IPA_Y(IPA_Y *y) { if (y) return; IPA_X *x = [[y opaque] getX]; // here *[x getPointer] = 1; } // From diagnostics/report-issues-within-main-file.cpp: void causeDivByZeroInMain(int in) { int m = 0; m = in/m; m++; } void mainPlusMain() { int i = 0; i++; causeDivByZeroInMain(i); i++; } // From inlining/path-notes.c: int *getZero() { int *p = 0; return p; } void usePointer(int *p) { *p = 1; } void testUseOfNullPointer() { // Test the case where an argument expression is itself a call. usePointer(getZero()); } //===----------------------------------------------------------------------===// // Misc. tests. //===----------------------------------------------------------------------===// // Test for tracking null state of ivars. @interface RDar12114812 : NSObject { char *p; } @end @implementation RDar12114812 - (void)test { p = 0; *p = 1; } @end // Test diagnostics for initialization of structs. void RDar13295437_f(void *i) __attribute__((__nonnull__)); struct RDar13295437_S { int *i; }; int RDar13295437() { struct RDar13295437_S s = {0}; struct RDar13295437_S *sp = &s; RDar13295437_f(sp->i); return 0; } void testCast(int coin) { if (coin) { (void)(1+2); (void)(2+3); (void)(3+4); *(volatile int *)0 = 1; } } // The following previously crashed when generating extensive diagnostics. // @interface RDar10797980_help @property (readonly) int x; @end @interface RDar10797980 : NSObject { RDar10797980_help *y; } - (void) test; @end @implementation RDar10797980 - (void) test { if (y.x == 1) { int *p = 0; *p = 0xDEADBEEF; // expected-warning {{deference}} } } // The original source for the above Radar contains another problem: // if the end-of-path node is an implicit statement, it may not have a valid // source location. - (void)test2 { if (bar_cond_assign()) { id foo = [[RDar10797980 alloc] init]; // leak } (void)y; // first statement after the 'if' is an implicit 'self' DeclRefExpr } @end void variousLoops(id input) { extern int a(); extern int b(); extern int c(); extern int work(); while (a()) { work(); work(); work(); *(volatile int *)0 = 1; } int first = 1; do { work(); work(); work(); if (!first) *(volatile int *)0 = 1; first = 0; } while (a()); for (int i = 0; i != b(); ++i) { work(); *(volatile int *)0 = 1; } for (id x in input) { work(); work(); work(); (void)x; *(volatile int *)0 = 1; } int z[] = {1,2}; for (int y : z) { work(); work(); work(); (void)y; } int empty[] = {}; for (int y : empty) { work(); work(); work(); (void)y; } for (int i = 0; ; ++i) { work(); if (i == b()) break; } int i; for (i = 0; i != b(); ++i) { work(); *(volatile int *)0 = 1; } for (; i != b(); ++i) { work(); *(volatile int *)0 = 1; } for (; i != b(); ) { work(); if (i == b()) break; *(volatile int *)0 = 1; } for (;;) { work(); if (i == b()) break; } *(volatile int *)0 = 1; } void *malloc(unsigned long); void *realloc(void *, unsigned long); void free(void *); void reallocDiagnostics() { char * buf = (char*)malloc(100); char * tmp; tmp = (char*)realloc(buf, 0x1000000); if (!tmp) { return;// expected-warning {{leak}} } buf = tmp; free(buf); } template class unique_ptr { T *ptr; public: explicit unique_ptr(T *p) : ptr(p) {} ~unique_ptr() { delete ptr; } }; void test() { int i = 0; ++i; unique_ptr p(new int[4]); { ++i; } } void longLines() { id foo = [[NSObject alloc] init]; // leak id bar = [foo retain]; [bar release]; id baz = [foo retain]; [baz release]; // This next line is intentionally longer than 80 characters. id garply = [foo retain]; [garply release]; } #define POINTER(T) T* POINTER(void) testMacroInFunctionDecl(void *q) { int *p = 0; *p = 1; return q; } namespace rdar14960554 { class Foo { int a = 1; int b = 2; int c = 3; Foo() : a(0), c(3) { // Check that we don't have an edge to the in-class initializer for 'b'. if (b == 2) *(volatile int *)0 = 1; } }; }