diff options
Diffstat (limited to 'test/Analysis/alloc-match-dealloc.mm')
-rw-r--r-- | test/Analysis/alloc-match-dealloc.mm | 221 |
1 files changed, 221 insertions, 0 deletions
diff --git a/test/Analysis/alloc-match-dealloc.mm b/test/Analysis/alloc-match-dealloc.mm new file mode 100644 index 0000000..56d46d9 --- /dev/null +++ b/test/Analysis/alloc-match-dealloc.mm @@ -0,0 +1,221 @@ +// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.MismatchedDeallocator -fblocks -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 *); + +//--------------------------------------------------------------- +// 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[]}} +} + +//--------------- 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()}} +} + +void testNew7() { + int *p = new int; + 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[]'}} +} + +void testNew9() { + int *p = new int[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{{Memory allocated by 'new' should be deallocated by 'delete', not +dataWithBytesNoCopy:length:freeWhenDone:}} + // FIXME: should be "+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)); + } +} |