| // RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.MismatchedDeallocator -fblocks -verify %s | 
 | // RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.MismatchedDeallocator -fblocks -DTEST_INLINABLE_ALLOCATORS -verify %s | 
 |  | 
 | #include "Inputs/system-header-simulator-objc.h" | 
 | #include "Inputs/system-header-simulator-cxx.h" | 
 |  | 
 | typedef __typeof__(sizeof(int)) size_t; | 
 | void *malloc(size_t); | 
 | void *realloc(void *ptr, size_t size); | 
 | void *calloc(size_t nmemb, size_t size); | 
 | char *strdup(const char *s); | 
 | void __attribute((ownership_returns(malloc))) *my_malloc(size_t); | 
 |  | 
 | void free(void *); | 
 | void __attribute((ownership_takes(malloc, 1))) my_free(void *); | 
 |  | 
 | void __attribute((ownership_returns(malloc1))) *my_malloc1(size_t); | 
 | void __attribute((ownership_takes(malloc1, 1))) my_free1(void *); | 
 |  | 
 | void __attribute((ownership_returns(malloc2))) *my_malloc2(size_t); | 
 |  | 
 | // The order of these declarations are important to verify that analisys still works even | 
 | // if there are less specific declarations of the same functions | 
 | void __attribute((ownership_returns(malloc3))) *my_malloc3(size_t); | 
 | void *my_malloc3(size_t); | 
 |  | 
 | void *my_malloc4(size_t); | 
 | void __attribute((ownership_returns(malloc4))) *my_malloc4(size_t); | 
 |  | 
 | //--------------------------------------------------------------- | 
 | // Test if an allocation function matches deallocation function | 
 | //--------------------------------------------------------------- | 
 |  | 
 | //--------------- test malloc family | 
 | void testMalloc1() { | 
 |   int *p = (int *)malloc(sizeof(int)); | 
 |   delete p; // expected-warning{{Memory allocated by 'malloc()' should be deallocated by 'free()', not 'delete'}} | 
 | } | 
 |  | 
 | void testMalloc2() { | 
 |   int *p = (int *)malloc(8); | 
 |   int *q = (int *)realloc(p, 16); | 
 |   delete q; // expected-warning{{Memory allocated by 'realloc()' should be deallocated by 'free()', not 'delete'}} | 
 | } | 
 |  | 
 | void testMalloc3() { | 
 |   int *p = (int *)calloc(1, sizeof(int)); | 
 |   delete p; // expected-warning{{Memory allocated by 'calloc()' should be deallocated by 'free()', not 'delete'}} | 
 | } | 
 |  | 
 | void testMalloc4(const char *s) { | 
 |   char *p = strdup(s); | 
 |   delete p; // expected-warning{{Memory allocated by 'strdup()' should be deallocated by 'free()', not 'delete'}} | 
 | } | 
 |  | 
 | void testMalloc5() { | 
 |   int *p = (int *)my_malloc(sizeof(int)); | 
 |   delete p; // expected-warning{{Memory allocated by 'my_malloc()' should be deallocated by 'free()', not 'delete'}} | 
 | } | 
 |  | 
 | void testMalloc6() { | 
 |   int *p = (int *)malloc(sizeof(int)); | 
 |   operator delete(p); // expected-warning{{Memory allocated by 'malloc()' should be deallocated by 'free()', not 'operator delete'}} | 
 | } | 
 |  | 
 | void testMalloc7() { | 
 |   int *p = (int *)malloc(sizeof(int)); | 
 |   delete[] p; // expected-warning{{Memory allocated by 'malloc()' should be deallocated by 'free()', not 'delete[]'}} | 
 | } | 
 |  | 
 | void testMalloc8() { | 
 |   int *p = (int *)malloc(sizeof(int)); | 
 |   operator delete[](p); // expected-warning{{Memory allocated by 'malloc()' should be deallocated by 'free()', not 'operator delete[]'}} | 
 | } | 
 |  | 
 | void testMalloc9() { | 
 |   int *p = (int *)my_malloc(sizeof(int)); | 
 |   my_free(p); // no warning | 
 | } | 
 |  | 
 | void testMalloc10() { | 
 |   int *p = (int *)my_malloc1(sizeof(int)); | 
 |   my_free1(p); // no warning | 
 | } | 
 |  | 
 | void testMalloc11() { | 
 |   int *p = (int *)my_malloc1(sizeof(int)); | 
 |   my_free(p); // expected-warning{{Memory allocated by 'my_malloc1()' should be deallocated by function that takes ownership of 'malloc1', not 'my_free()', which takes ownership of 'malloc'}} | 
 | } | 
 |  | 
 | void testMalloc12() { | 
 |   int *p = (int *)my_malloc2(sizeof(int)); | 
 |   my_free1(p); // expected-warning{{Memory allocated by 'my_malloc2()' should be deallocated by function that takes ownership of 'malloc2', not 'my_free1()', which takes ownership of 'malloc1'}} | 
 | } | 
 |  | 
 | void testMalloc13() { | 
 |   int *p = (int *)my_malloc1(sizeof(int)); | 
 |   free(p); // expected-warning{{Memory allocated by 'my_malloc1()' should be deallocated by function that takes ownership of 'malloc1', not 'free()'}} | 
 | } | 
 |  | 
 | void testMalloc14() { | 
 |   int *p = (int *)my_malloc3(sizeof(int)); | 
 |   free(p); // expected-warning{{Memory allocated by 'my_malloc3()' should be deallocated by function that takes ownership of 'malloc3', not 'free()'}} | 
 | } | 
 |  | 
 | void testMalloc15() { | 
 |   int *p = (int *)my_malloc4(sizeof(int)); | 
 |   free(p); // expected-warning{{Memory allocated by 'my_malloc4()' should be deallocated by function that takes ownership of 'malloc4', not 'free()'}} | 
 | } | 
 |  | 
 | void testAlloca() { | 
 |   int *p = (int *)__builtin_alloca(sizeof(int)); | 
 |   delete p; // expected-warning{{Memory allocated by 'alloca()' should not be deallocated}} | 
 | } | 
 |  | 
 | //--------------- test new family | 
 | void testNew1() { | 
 |   int *p = new int; | 
 |   free(p); // expected-warning{{Memory allocated by 'new' should be deallocated by 'delete', not 'free()'}} | 
 | } | 
 |  | 
 | void testNew2() { | 
 |   int *p = (int *)operator new(0); | 
 |   free(p); // expected-warning{{Memory allocated by 'operator new' should be deallocated by 'delete', not 'free()'}} | 
 | } | 
 |  | 
 | void testNew3() { | 
 |   int *p = new int[1]; | 
 |   free(p); // expected-warning{{Memory allocated by 'new[]' should be deallocated by 'delete[]', not 'free()'}} | 
 | } | 
 |  | 
 | void testNew4() { | 
 |   int *p = new int; | 
 |   realloc(p, sizeof(long)); // expected-warning{{Memory allocated by 'new' should be deallocated by 'delete', not 'realloc()'}} | 
 | } | 
 |  | 
 | void testNew5() { | 
 |   int *p = (int *)operator new(0); | 
 |   realloc(p, sizeof(long)); // expected-warning{{Memory allocated by 'operator new' should be deallocated by 'delete', not 'realloc()'}} | 
 | } | 
 |  | 
 | void testNew6() { | 
 |   int *p = new int[1]; | 
 |   realloc(p, sizeof(long)); // expected-warning{{Memory allocated by 'new[]' should be deallocated by 'delete[]', not 'realloc()'}} | 
 | } | 
 |  | 
 | int *allocInt() { | 
 |   return new int; | 
 | } | 
 | void testNew7() { | 
 |   int *p = allocInt(); | 
 |   delete[] p; // expected-warning{{Memory allocated by 'new' should be deallocated by 'delete', not 'delete[]'}} | 
 | } | 
 |  | 
 | void testNew8() { | 
 |   int *p = (int *)operator new(0); | 
 |   delete[] p; // expected-warning{{Memory allocated by 'operator new' should be deallocated by 'delete', not 'delete[]'}} | 
 | } | 
 |  | 
 | int *allocIntArray(unsigned c) { | 
 |   return new int[c]; | 
 | } | 
 |  | 
 | void testNew9() { | 
 |   int *p = allocIntArray(1); | 
 |   delete p; // expected-warning{{Memory allocated by 'new[]' should be deallocated by 'delete[]', not 'delete'}} | 
 | } | 
 |  | 
 | void testNew10() { | 
 |   int *p = (int *)operator new[](0); | 
 |   delete p; // expected-warning{{Memory allocated by 'operator new[]' should be deallocated by 'delete[]', not 'delete'}} | 
 | } | 
 |  | 
 | void testNew11(NSUInteger dataLength) { | 
 |   int *p = new int; | 
 |   NSData *d = [NSData dataWithBytesNoCopy:p length:sizeof(int) freeWhenDone:1]; // expected-warning{{+dataWithBytesNoCopy:length:freeWhenDone: cannot take ownership of memory allocated by 'new'}} | 
 | } | 
 |  | 
 | //------------------------------------------------------- | 
 | // Check for intersection with unix.Malloc bounded with  | 
 | // unix.MismatchedDeallocator | 
 | //------------------------------------------------------- | 
 |  | 
 | // new/delete oparators are subjects of cplusplus.NewDelete. | 
 | void testNewDeleteNoWarn() { | 
 |   int i; | 
 |   delete &i; // no-warning | 
 |  | 
 |   int *p1 = new int; | 
 |   delete ++p1; // no-warning | 
 |  | 
 |   int *p2 = new int; | 
 |   delete p2; | 
 |   delete p2; // no-warning | 
 |  | 
 |   int *p3 = new int; // no-warning | 
 | } | 
 |  | 
 | void testDeleteOpAfterFree() { | 
 |   int *p = (int *)malloc(sizeof(int)); | 
 |   free(p); | 
 |   operator delete(p); // no-warning | 
 | } | 
 |  | 
 | void testDeleteAfterFree() { | 
 |   int *p = (int *)malloc(sizeof(int)); | 
 |   free(p); | 
 |   delete p; // no-warning | 
 | } | 
 |  | 
 | void testStandardPlacementNewAfterFree() { | 
 |   int *p = (int *)malloc(sizeof(int)); | 
 |   free(p); | 
 |   p = new(p) int; // no-warning | 
 | } | 
 |  | 
 | //--------------------------------------------------------------- | 
 | // Check for intersection with cplusplus.NewDelete bounded with  | 
 | // unix.MismatchedDeallocator | 
 | //--------------------------------------------------------------- | 
 |  | 
 | // malloc()/free() are subjects of unix.Malloc and unix.MallocWithAnnotations | 
 | void testMallocFreeNoWarn() { | 
 |   int i; | 
 |   free(&i); // no-warning | 
 |  | 
 |   int *p1 = (int *)malloc(sizeof(int)); | 
 |   free(++p1); // no-warning | 
 |  | 
 |   int *p2 = (int *)malloc(sizeof(int)); | 
 |   free(p2); | 
 |   free(p2); // no-warning | 
 |  | 
 |   int *p3 = (int *)malloc(sizeof(int)); // no-warning | 
 | } | 
 |  | 
 | void testFreeAfterDelete() { | 
 |   int *p = new int;   | 
 |   delete p; | 
 |   free(p); // no-warning | 
 | } | 
 |  | 
 | void testStandardPlacementNewAfterDelete() { | 
 |   int *p = new int;   | 
 |   delete p; | 
 |   p = new(p) int; // no-warning | 
 | } | 
 |  | 
 |  | 
 | // Smart pointer example | 
 | template <typename T> | 
 | struct SimpleSmartPointer { | 
 |   T *ptr; | 
 |  | 
 |   explicit SimpleSmartPointer(T *p = 0) : ptr(p) {} | 
 |   ~SimpleSmartPointer() { | 
 |     delete ptr; | 
 |     // expected-warning@-1 {{Memory allocated by 'new[]' should be deallocated by 'delete[]', not 'delete'}} | 
 |     // expected-warning@-2 {{Memory allocated by 'malloc()' should be deallocated by 'free()', not 'delete'}} | 
 |   } | 
 | }; | 
 |  | 
 | void testSimpleSmartPointerArrayNew() { | 
 |   { | 
 |     SimpleSmartPointer<int> a(new int); | 
 |   } // no-warning | 
 |  | 
 |   { | 
 |     SimpleSmartPointer<int> a(new int[4]); | 
 |   } | 
 | } | 
 |  | 
 | void testSimpleSmartPointerMalloc() { | 
 |   { | 
 |     SimpleSmartPointer<int> a(new int); | 
 |   } // no-warning | 
 |  | 
 |   { | 
 |     SimpleSmartPointer<int> a((int *)malloc(4)); | 
 |   } | 
 | } |