|  | // 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 <typename T> | 
|  | 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<int> 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; | 
|  | } | 
|  | }; | 
|  | } | 
|  |  |