[analyzer] Handle the M_ZERO and __GFP_ZERO flags in kernel mallocs.

Add M_ZERO awareness to malloc() static analysis in Clang for FreeBSD,
NetBSD, and OpenBSD in a similar fashion to O_CREAT for open(2).
These systems have a three-argument malloc() in the kernel where the
third argument contains flags; the M_ZERO flag will zero-initialize the
allocated buffer.

This should reduce the number of false positives when running static
analysis on BSD kernels.

Additionally, add kmalloc() (Linux kernel malloc()) and treat __GFP_ZERO
like M_ZERO on Linux.

Future work involves a better method of checking for named flags without
hardcoding values.

Patch by Conrad Meyer, with minor modifications by me.

llvm-svn: 204832
diff --git a/clang/test/Analysis/kmalloc-linux.c b/clang/test/Analysis/kmalloc-linux.c
new file mode 100644
index 0000000..87c1107
--- /dev/null
+++ b/clang/test/Analysis/kmalloc-linux.c
@@ -0,0 +1,58 @@
+// RUN: %clang -target x86_64-unknown-linux --analyze %s
+
+#include "Inputs/system-header-simulator.h"
+
+#define __GFP_ZERO 0x8000
+#define NULL ((void *)0)
+
+void *kmalloc(size_t, int);
+
+struct test {
+};
+
+void foo(struct test *);
+
+void test_zeroed() {
+  struct test **list, *t;
+  int i;
+
+  list = kmalloc(sizeof(*list) * 10, __GFP_ZERO);
+  if (list == NULL)
+    return;
+
+  for (i = 0; i < 10; i++) {
+    t = list[i];
+    foo(t);
+  }
+  free(list); // no-warning
+}
+
+void test_nonzero() {
+  struct test **list, *t;
+  int i;
+
+  list = kmalloc(sizeof(*list) * 10, 0);
+  if (list == NULL)
+    return;
+
+  for (i = 0; i < 10; i++) {
+    t = list[i]; // expected-warning{{undefined}}
+    foo(t);
+  }
+  free(list);
+}
+
+void test_indeterminate(int flags) {
+  struct test **list, *t;
+  int i;
+
+  list = kmalloc(sizeof(*list) * 10, flags);
+  if (list == NULL)
+    return;
+
+  for (i = 0; i < 10; i++) {
+    t = list[i]; // expected-warning{{undefined}}
+    foo(t);
+  }
+  free(list);
+}