[analyzer]Revert part of r161511; suppresses leak false positives in C++
authorAnna Zaks <ganna@apple.com>
Wed, 6 Feb 2013 00:01:14 +0000 (00:01 +0000)
committerAnna Zaks <ganna@apple.com>
Wed, 6 Feb 2013 00:01:14 +0000 (00:01 +0000)
This is a "quick fix".

The underlining issue is that when a const pointer to a struct is passed
into a function, we do not invalidate the pointer fields. This results
in false positives that are common in C++ (since copy constructors are
prevalent). (Silences two llvm false positives.)

llvm-svn: 174468

clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
clang/test/Analysis/malloc-annotations.c
clang/test/Analysis/malloc.c
clang/test/Analysis/malloc.cpp

index 26a3f9b..636aa3b 100644 (file)
@@ -1627,6 +1627,12 @@ ProgramStateRef ExprEngine::processPointerEscapedOnBind(ProgramStateRef State,
       if (StoredVal != Val)
         escapes = (State == (State->bindLoc(*regionLoc, Val)));
     }
+    if (!escapes) {
+      // Case 4: We do not currently model what happens when a symbol is
+      // assigned to a struct field, so be conservative here and let the symbol
+      // go. TODO: This could definitely be improved upon.
+      escapes = !isa<VarRegion>(regionLoc->getRegion());
+    }
   }
 
   // If our store can represent the binding and we aren't storing to something
index 3a260c3..bdd50c6 100644 (file)
@@ -70,11 +70,6 @@ void af1_c() {
   myglobalpointer = my_malloc(12); // no-warning
 }
 
-void af1_d() {
-  struct stuff mystuff;
-  mystuff.somefield = my_malloc(12);
-} // expected-warning{{Memory is never released; potential leak}}
-
 // Test that we can pass out allocated memory via pointer-to-pointer.
 void af1_e(void **pp) {
   *pp = my_malloc(42); // no-warning
@@ -267,3 +262,14 @@ void testMultipleFreeAnnotations() {
   my_freeBoth(p, q);
 }
 
+// ----------------------------------------------------------------------------
+
+// False negatives.
+
+// Pending on removal of the escaping on assignment to struct fields.
+void af1_d() {
+  struct stuff mystuff;
+  mystuff.somefield = my_malloc(12);
+} // missing warning
+
+
index 3e5f914..ed2d8e9 100644 (file)
@@ -530,12 +530,6 @@ int *testMalloc3() {
   return y; // no-warning
 }
 
-void testStructLeak() {
-  StructWithPtr St;
-  St.memP = malloc(12);
-  return; // expected-warning {{Memory is never released; potential leak of memory pointed to by 'St.memP'}}
-}
-
 void testElemRegion1() {
   char *x = (void*)malloc(2);
   int *ix = (int*)x;
@@ -934,18 +928,6 @@ int cmpHeapAllocationToUnknown() {
   return 0;
 }
 
-void localArrayTest() {
-  char *p = (char*)malloc(12);
-  char *ArrayL[12];
-  ArrayL[0] = p;
-} // expected-warning {{leak}}
-
-void localStructTest() {
-  StructWithPtr St;
-  StructWithPtr *pSt = &St;
-  pSt->memP = malloc(12);
-} // expected-warning{{Memory is never released; potential leak}}
-
 #ifdef __INTPTR_TYPE__
 // Test double assignment through integers.
 typedef __INTPTR_TYPE__ intptr_t;
@@ -1053,3 +1035,25 @@ void testMallocWithParam(int **p) {
 void testMallocWithParam_2(int **p) {
   *p = (int*) malloc(sizeof(int));
 }
+
+// Pending on removal of the escaping on assignment to struct fields.
+void testStructLeak() {
+  StructWithPtr St;
+  St.memP = malloc(12);
+  return; // missing warning
+}
+
+void localArrayTest() {
+  char *p = (char*)malloc(12);
+  char *ArrayL[12];
+  ArrayL[0] = p;
+} // missing warning
+
+void localStructTest() {
+  StructWithPtr St;
+  StructWithPtr *pSt = &St;
+  pSt->memP = malloc(12);
+} // missing warning
+
+
+
index 58b94ea..a7c3652 100644 (file)
@@ -60,3 +60,10 @@ namespace PR13751 {
   }
 }
 
+struct X { void *a; };
+
+struct X get() {
+  struct X result;
+  result.a = malloc(4);
+  return result; // no-warning
+}