summaryrefslogtreecommitdiffstats
path: root/test/Analysis/malloc.c
diff options
context:
space:
mode:
authordim <dim@FreeBSD.org>2010-09-17 15:54:40 +0000
committerdim <dim@FreeBSD.org>2010-09-17 15:54:40 +0000
commit36c49e3f258dced101949edabd72e9bc3f1dedc4 (patch)
tree0bbe07708f7571f8b5291f6d7b96c102b7c99dee /test/Analysis/malloc.c
parentfc84956ac8b7cd244ef30e7a4d4d38a58dec5904 (diff)
downloadFreeBSD-src-36c49e3f258dced101949edabd72e9bc3f1dedc4.zip
FreeBSD-src-36c49e3f258dced101949edabd72e9bc3f1dedc4.tar.gz
Vendor import of clang r114020 (from the release_28 branch):
http://llvm.org/svn/llvm-project/cfe/branches/release_28@114020 Approved by: rpaulo (mentor)
Diffstat (limited to 'test/Analysis/malloc.c')
-rw-r--r--test/Analysis/malloc.c124
1 files changed, 119 insertions, 5 deletions
diff --git a/test/Analysis/malloc.c b/test/Analysis/malloc.c
index b4c1314..e443150 100644
--- a/test/Analysis/malloc.c
+++ b/test/Analysis/malloc.c
@@ -4,22 +4,136 @@ void *malloc(size_t);
void free(void *);
void *realloc(void *ptr, size_t size);
void *calloc(size_t nmemb, size_t size);
+void __attribute((ownership_returns(malloc))) *my_malloc(size_t);
+void __attribute((ownership_takes(malloc, 1))) my_free(void *);
+void __attribute((ownership_returns(malloc, 1))) *my_malloc2(size_t);
+void __attribute((ownership_holds(malloc, 1))) my_hold(void *);
+
+// Duplicate attributes are silly, but not an error.
+// Duplicate attribute has no extra effect.
+// If two are of different kinds, that is an error and reported as such.
+void __attribute((ownership_holds(malloc, 1)))
+__attribute((ownership_holds(malloc, 1)))
+__attribute((ownership_holds(malloc, 3))) my_hold2(void *, void *, void *);
+void *my_malloc3(size_t);
+void *myglobalpointer;
+struct stuff {
+ void *somefield;
+};
+struct stuff myglobalstuff;
void f1() {
int *p = malloc(12);
return; // expected-warning{{Allocated memory never released. Potential memory leak.}}
}
-void f1_b() {
- int *p = malloc(12); // expected-warning{{Allocated memory never released. Potential memory leak.}}
-}
-
void f2() {
int *p = malloc(12);
free(p);
free(p); // expected-warning{{Try to free a memory block that has been released}}
}
+// ownership attributes tests
+void naf1() {
+ int *p = my_malloc3(12);
+ return; // no-warning
+}
+
+void n2af1() {
+ int *p = my_malloc2(12);
+ return; // expected-warning{{Allocated memory never released. Potential memory leak.}}
+}
+
+void af1() {
+ int *p = my_malloc(12);
+ return; // expected-warning{{Allocated memory never released. Potential memory leak.}}
+}
+
+void af1_b() {
+ int *p = my_malloc(12); // expected-warning{{Allocated memory never released. Potential memory leak.}}
+}
+
+void af1_c() {
+ myglobalpointer = my_malloc(12); // no-warning
+}
+
+void af1_d() {
+ struct stuff mystuff;
+ mystuff.somefield = my_malloc(12); // expected-warning{{Allocated memory never released. Potential memory leak.}}
+}
+
+// Test that we can pass out allocated memory via pointer-to-pointer.
+void af1_e(void **pp) {
+ *pp = my_malloc(42); // no-warning
+}
+
+void af1_f(struct stuff *somestuff) {
+ somestuff->somefield = my_malloc(12); // no-warning
+}
+
+// Allocating memory for a field via multiple indirections to our arguments is OK.
+void af1_g(struct stuff **pps) {
+ *pps = my_malloc(sizeof(struct stuff)); // no-warning
+ (*pps)->somefield = my_malloc(42); // no-warning
+}
+
+void af2() {
+ int *p = my_malloc(12);
+ my_free(p);
+ free(p); // expected-warning{{Try to free a memory block that has been released}}
+}
+
+void af2b() {
+ int *p = my_malloc(12);
+ free(p);
+ my_free(p); // expected-warning{{Try to free a memory block that has been released}}
+}
+
+void af2c() {
+ int *p = my_malloc(12);
+ free(p);
+ my_hold(p); // expected-warning{{Try to free a memory block that has been released}}
+}
+
+void af2d() {
+ int *p = my_malloc(12);
+ free(p);
+ my_hold2(0, 0, p); // expected-warning{{Try to free a memory block that has been released}}
+}
+
+// No leak if malloc returns null.
+void af2e() {
+ int *p = my_malloc(12);
+ if (!p)
+ return; // no-warning
+ free(p); // no-warning
+}
+
+// This case would inflict a double-free elsewhere.
+// However, this case is considered an analyzer bug since it causes false-positives.
+void af3() {
+ int *p = my_malloc(12);
+ my_hold(p);
+ free(p); // no-warning
+}
+
+// This case would inflict a double-free elsewhere.
+// However, this case is considered an analyzer bug since it causes false-positives.
+int * af4() {
+ int *p = my_malloc(12);
+ my_free(p);
+ return p; // no-warning
+}
+
+// This case is (possibly) ok, be conservative
+int * af5() {
+ int *p = my_malloc(12);
+ my_hold(p);
+ return p; // no-warning
+}
+
+
+
// This case tests that storing malloc'ed memory to a static variable which is
// then returned is not leaked. In the absence of known contracts for functions
// or inter-procedural analysis, this is a conservative answer.
@@ -117,7 +231,7 @@ char callocZeroesBad () {
char *buf = calloc(2,2);
char result = buf[3]; // no-warning
if (buf[1] != 0) {
- free(buf);
+ free(buf); // expected-warning{{never executed}}
}
return result; // expected-warning{{never released}}
}
OpenPOWER on IntegriCloud