summaryrefslogtreecommitdiffstats
path: root/clang/test/Analysis/weak-functions.c
diff options
context:
space:
mode:
authorJordan Rose <jordan_rose@apple.com>2013-08-28 17:07:04 +0000
committerJordan Rose <jordan_rose@apple.com>2013-08-28 17:07:04 +0000
commitacd080b956d8a0007a36ca6727977cdfd5c284db (patch)
treecd54e2f9f8083ac8a10fb1400d0044383b72b897 /clang/test/Analysis/weak-functions.c
parent5c6235968f50a90f4c68012efbeb006903279fde (diff)
downloadbcm5719-llvm-acd080b956d8a0007a36ca6727977cdfd5c284db.tar.gz
bcm5719-llvm-acd080b956d8a0007a36ca6727977cdfd5c284db.zip
[analyzer] Add support for testing the presence of weak functions.
When casting the address of a FunctionTextRegion to bool, or when adding constraints to such an address, use a stand-in symbol to represent the presence or absence of the function if the function is weakly linked. This is groundwork for possible simple availability testing checks, and can already catch mistakes involving inverted null checks for weakly-linked functions. Currently, the implementation reuses the "extent" symbols, originally created for tracking the size of a malloc region. Since FunctionTextRegions cannot be dereferenced, the extent symbol will never be used for anything else. Still, this probably deserves a refactoring in the future. This patch does not attempt to support testing the presence of weak /variables/ (global variables), which would likely require much more of a change and a generalization of "region structure metadata", like the current "extents", vs. "region contents metadata", like CStringChecker's "string length". Patch by Richard <tarka.t.otter@googlemail.com>! llvm-svn: 189492
Diffstat (limited to 'clang/test/Analysis/weak-functions.c')
-rw-r--r--clang/test/Analysis/weak-functions.c117
1 files changed, 117 insertions, 0 deletions
diff --git a/clang/test/Analysis/weak-functions.c b/clang/test/Analysis/weak-functions.c
new file mode 100644
index 00000000000..96e3b44d03b
--- /dev/null
+++ b/clang/test/Analysis/weak-functions.c
@@ -0,0 +1,117 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core,debug.ExprInspection,unix.Malloc,unix.cstring,alpha.unix.cstring,unix.API,osx.API,osx.cocoa.RetainCount -Wno-null-dereference -analyzer-store=region -fblocks -verify %s
+#define NULL 0
+void clang_analyzer_eval(int);
+void myFunc();
+void myWeakFunc() __attribute__((weak_import));
+
+void testWeakFuncIsNull()
+{
+ clang_analyzer_eval(myFunc == NULL); // expected-warning{{FALSE}}
+ clang_analyzer_eval(myWeakFunc == NULL); // expected-warning{{UNKNOWN}}
+ if (myWeakFunc == NULL) {
+ clang_analyzer_eval(myWeakFunc == NULL); // expected-warning{{TRUE}}
+ } else {
+ clang_analyzer_eval(myWeakFunc == NULL); // expected-warning{{FALSE}}
+ }
+}
+
+void testWeakFuncIsNot()
+{
+ clang_analyzer_eval(myWeakFunc == NULL); // expected-warning{{UNKNOWN}}
+ if (!myWeakFunc) {
+ clang_analyzer_eval(myWeakFunc == NULL); // expected-warning{{TRUE}}
+ } else {
+ clang_analyzer_eval(myWeakFunc == NULL); // expected-warning{{FALSE}}
+ }
+}
+
+void testWeakFuncIsTrue()
+{
+ clang_analyzer_eval(myWeakFunc == NULL); // expected-warning{{UNKNOWN}}
+ if (myWeakFunc) {
+ clang_analyzer_eval(myWeakFunc == NULL); // expected-warning{{FALSE}}
+ } else {
+ clang_analyzer_eval(myWeakFunc == NULL); // expected-warning{{TRUE}}
+ }
+}
+
+//===----------------------------------------------------------------------===
+// func.c
+//===----------------------------------------------------------------------===
+void f(void) __attribute__((weak_import));
+void g(void (*fp)(void)) __attribute__((weak_import));
+
+void f(void) {
+ void (*p)(void);
+ p = f;
+ p = &f;
+ p();
+ (*p)();
+}
+
+void g(void (*fp)(void));
+
+void f2() {
+ g(f);
+}
+
+void f3(void (*f)(void), void (*g)(void)) {
+ clang_analyzer_eval(!f); // expected-warning{{UNKNOWN}}
+ f();
+ clang_analyzer_eval(!f); // expected-warning{{FALSE}}
+
+ clang_analyzer_eval(!g); // expected-warning{{UNKNOWN}}
+ (*g)();
+ clang_analyzer_eval(!g); // expected-warning{{FALSE}}
+}
+
+//===----------------------------------------------------------------------===
+// free.c
+//===----------------------------------------------------------------------===
+void free(void *) __attribute__((weak_import));
+
+void t10 () {
+ free((void*)&t10); // expected-warning {{Argument to free() is the address of the function 't10', which is not memory allocated by malloc()}}
+}
+
+//===----------------------------------------------------------------------===
+// string.c : strnlen()
+//===----------------------------------------------------------------------===
+typedef typeof(sizeof(int)) size_t;
+size_t strlen(const char *s) __attribute__((weak_import));
+
+size_t strlen_fn() {
+ return strlen((char*)&strlen_fn); // expected-warning{{Argument to string length function is the address of the function 'strlen_fn', which is not a null-terminated string}}
+}
+
+//===----------------------------------------------------------------------===
+// unix-fns.c : dispatch_once
+//===----------------------------------------------------------------------===
+typedef void (^dispatch_block_t)(void);
+typedef long dispatch_once_t;
+void dispatch_once(dispatch_once_t *predicate, dispatch_block_t block) __attribute__((weak_import));
+
+void test_dispatch_once() {
+ dispatch_once_t pred = 0;
+ do { if (__builtin_expect(*(&pred), ~0l) != ~0l) dispatch_once((&pred), (^() {})); } while (0); // expected-warning{{Call to 'dispatch_once' uses the local variable 'pred' for the predicate value}}
+}
+void test_dispatch_once_neg() {
+ static dispatch_once_t pred = 0;
+ do { if (__builtin_expect(*(&pred), ~0l) != ~0l) dispatch_once((&pred), (^() {})); } while (0); // no-warning
+}
+
+//===----------------------------------------------------------------------===
+// retain-release-path-notes.m
+//===----------------------------------------------------------------------===
+typedef struct CFType *CFTypeRef;
+CFTypeRef CFCreateSomething() __attribute__((weak_import));
+CFTypeRef CFGetSomething() __attribute__((weak_import));
+
+CFTypeRef CFCopyRuleViolation () {
+ CFTypeRef object = CFGetSomething();
+ return object; // expected-warning{{Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected}}
+}
+
+CFTypeRef CFGetRuleViolation () {
+ CFTypeRef object = CFCreateSomething(); // expected-warning{{Potential leak of an object stored into 'object'}}
+ return object; }
OpenPOWER on IntegriCloud