[analyzer] Allow pointers escape through calls containing callback args.

(Since we don't have a generic pointer escape callback, modify
ExprEngineCallAndReturn as well as the malloc checker.)

llvm-svn: 156134
diff --git a/clang/test/Analysis/malloc.c b/clang/test/Analysis/malloc.c
index 9c09051..f5bff4f 100644
--- a/clang/test/Analysis/malloc.c
+++ b/clang/test/Analysis/malloc.c
@@ -798,6 +798,27 @@
   ptr = ptr; // expected-warning {{leak}}
 }
 
+// Assume that functions which take a function pointer can free memory even if
+// they are defined in system headers and take the const pointer to the
+// allocated memory. (radar://11160612)
+int const_ptr_and_callback(int, const char*, int n, void(*)(void*));
+void r11160612_1() {
+  char *x = malloc(12);
+  const_ptr_and_callback(0, x, 12, free); // no - warning
+}
+
+// Null is passed as callback.
+void r11160612_2() {
+  char *x = malloc(12);
+  const_ptr_and_callback(0, x, 12, 0); // expected-warning {{leak}}
+}
+
+// Callback is passed to a function defined in a system header.
+void r11160612_4() {
+  char *x = malloc(12);
+  sqlite3_bind_text_my(0, x, 12, free); // no - warning
+}
+
 // ----------------------------------------------------------------------------
 // Below are the known false positives.
 
diff --git a/clang/test/Analysis/malloc.cpp b/clang/test/Analysis/malloc.cpp
index 8f80b2b..f36d8fc 100644
--- a/clang/test/Analysis/malloc.cpp
+++ b/clang/test/Analysis/malloc.cpp
@@ -14,3 +14,13 @@
 Foo aFunction() {
     return malloc(10);
 }
+
+// Assume that functions which take a function pointer can free memory even if
+// they are defined in system headers and take the const pointer to the
+// allocated memory. (radar://11160612)
+// Test default parameter.
+int const_ptr_and_callback_def_param(int, const char*, int n, void(*)(void*) = 0);
+void r11160612_3() {
+  char *x = (char*)malloc(12);
+  const_ptr_and_callback_def_param(0, x, 12);
+}
diff --git a/clang/test/Analysis/malloc.m b/clang/test/Analysis/malloc.m
index 6c94118..08206f3 100644
--- a/clang/test/Analysis/malloc.m
+++ b/clang/test/Analysis/malloc.m
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc -analyzer-store=region -verify -Wno-objc-root-class %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc -analyzer-store=region -verify -Wno-objc-root-class -fblocks %s
 #include "system-header-simulator-objc.h"
 
 @class NSString;
diff --git a/clang/test/Analysis/malloc.mm b/clang/test/Analysis/malloc.mm
index 3515a4f..ef1adda 100644
--- a/clang/test/Analysis/malloc.mm
+++ b/clang/test/Analysis/malloc.mm
@@ -153,4 +153,29 @@
 void testCGDataProviderCreateWithData() { 
   void* b = calloc(8, 8);
   CGDataProviderRef p = CGDataProviderCreateWithData(0, b, 8*8, releaseDataCallback);
+}
+
+// Assume that functions which take a function pointer can free memory even if
+// they are defined in system headers and take the const pointer to the
+// allocated memory. (radar://11160612)
+extern CGDataProviderRef UnknownFunWithCallback(void *info,
+    const void *data, size_t size,
+    CGDataProviderReleaseDataCallback releaseData)
+    __attribute__((visibility("default")));
+void testUnknownFunWithCallBack() { 
+  void* b = calloc(8, 8);
+  CGDataProviderRef p = UnknownFunWithCallback(0, b, 8*8, releaseDataCallback);
+}
+
+// Test blocks.
+void acceptBlockParam(void *, void (^block)(void *), unsigned);
+void testCallWithBlockCallback() {
+  void *l = malloc(12);
+  acceptBlockParam(l, ^(void *i) { free(i); }, sizeof(char *));
+}
+
+// Test blocks in system headers.
+void testCallWithBlockCallbackInSystem() {
+  void *l = malloc(12);
+  SystemHeaderFunctionWithBlockParam(l, ^(void *i) { free(i); }, sizeof(char *));
 }
\ No newline at end of file
diff --git a/clang/test/Analysis/system-header-simulator-objc.h b/clang/test/Analysis/system-header-simulator-objc.h
index 92d5899..4626a4e 100644
--- a/clang/test/Analysis/system-header-simulator-objc.h
+++ b/clang/test/Analysis/system-header-simulator-objc.h
@@ -112,3 +112,5 @@
 extern CFMutableStringRef CFStringCreateMutableWithExternalCharactersNoCopy(CFAllocatorRef alloc, UniChar *chars, CFIndex numChars, CFIndex capacity, CFAllocatorRef externalCharactersAllocator);
 extern CFStringRef CFStringCreateWithCStringNoCopy(CFAllocatorRef alloc, const char *cStr, CFStringEncoding encoding, CFAllocatorRef contentsDeallocator);
 extern void CFStringAppend(CFMutableStringRef theString, CFStringRef appendedString);
+
+void SystemHeaderFunctionWithBlockParam(void *, void (^block)(void *), unsigned);
diff --git a/clang/test/Analysis/system-header-simulator.h b/clang/test/Analysis/system-header-simulator.h
index 6212131..c910ad9 100644
--- a/clang/test/Analysis/system-header-simulator.h
+++ b/clang/test/Analysis/system-header-simulator.h
@@ -36,3 +36,4 @@
                  fpos_t (*)(void *, fpos_t, int),
                  int (*)(void *));
 
+int sqlite3_bind_text_my(int, const char*, int n, void(*)(void*));