// RUN: %clang_cc1 -Wfree-nonheap-object -std=c++11 -x c++ -fsyntax-only -verify %s extern "C" void free(void *) {} namespace std { using size_t = decltype(sizeof(0)); void *malloc(size_t); void free(void *p); } // namespace std int GI; void free_reference(char &x) { ::free(&x); } void free_reference(char &&x) { ::free(&x); } void std_free_reference(char &x) { std::free(&x); } void std_free_reference(char &&x) { std::free(&x); } struct S { operator char *() { return ptr1; } void CFree() { ::free(&ptr1); // expected-warning {{attempt to call free on non-heap object 'ptr1'}} ::free(&I); // expected-warning {{attempt to call free on non-heap object 'I'}} ::free(ptr1); free_reference(*ptr2); free_reference(static_cast(*ptr3)); } void CXXFree() { std::free(&ptr1); // expected-warning {{attempt to call std::free on non-heap object 'ptr1'}} std::free(&I); // expected-warning {{attempt to call std::free on non-heap object 'I'}} std::free(ptr1); std_free_reference(*ptr2); std_free_reference(static_cast(*ptr3)); } private: char *ptr1 = (char *)std::malloc(10); char *ptr2 = (char *)std::malloc(10); char *ptr3 = (char *)std::malloc(10); static int I; }; int S::I = 0; void test1() { { free(&GI); // expected-warning {{attempt to call free on non-heap object 'GI'}} } { static int SI = 0; free(&SI); // expected-warning {{attempt to call free on non-heap object 'SI'}} } { int I = 0; free(&I); // expected-warning {{attempt to call free on non-heap object 'I'}} } { int I = 0; int *P = &I; free(P); } { void *P = std::malloc(8); free(P); // FIXME diagnosing this would require control flow analysis. } { int A[] = {0, 1, 2, 3}; free(A); // expected-warning {{attempt to call free on non-heap object 'A'}} } { int A[] = {0, 1, 2, 3}; free(&A); // expected-warning {{attempt to call free on non-heap object 'A'}} } { S s; free(s); free(&s); // expected-warning {{attempt to call free on non-heap object 's'}} } { S s; s.CFree(); } } void test2() { { std::free(&GI); // expected-warning {{attempt to call std::free on non-heap object 'GI'}} } { static int SI = 0; std::free(&SI); // expected-warning {{attempt to call std::free on non-heap object 'SI'}} } { int I = 0; std::free(&I); // expected-warning {{attempt to call std::free on non-heap object 'I'}} } { int I = 0; int *P = &I; std::free(P); // FIXME diagnosing this would require control flow analysis. } { void *P = std::malloc(8); std::free(P); } { char* P = (char *)std::malloc(2); std_free_reference(*P); } { char* P = (char *)std::malloc(2); std_free_reference(static_cast(*P)); } { int A[] = {0, 1, 2, 3}; std::free(A); // expected-warning {{attempt to call std::free on non-heap object 'A'}} } { int A[] = {0, 1, 2, 3}; std::free(&A); // expected-warning {{attempt to call std::free on non-heap object 'A'}} } { S s; std::free(s); std::free(&s); // expected-warning {{attempt to call std::free on non-heap object 's'}} } { S s; s.CXXFree(); } }