retain/release checker: When generating summaries for CF/CG functions, allow arguments to "escape" if they are passed to a function containing the terms "InsertValue", "SetValue", or "AddValue".  This fixes <rdar://problem/6539791>.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@63341 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Analysis/CFRefCount.cpp b/lib/Analysis/CFRefCount.cpp
index 35b7ee7..ab9d409 100644
--- a/lib/Analysis/CFRefCount.cpp
+++ b/lib/Analysis/CFRefCount.cpp
@@ -809,12 +809,27 @@
       if (isRelease(FD, FName+2))
         S = getUnarySummary(FT, cfrelease);
       else {
-        // For CoreFoundation and CoreGraphics functions we assume they
-        // follow the ownership idiom strictly and thus do not cause
-        // ownership to "escape".
-        assert (ScratchArgs.empty());  
-        S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, 
-                                 DoNothing);
+        assert (ScratchArgs.empty());
+        // Remaining CoreFoundation and CoreGraphics functions.
+        // We use to assume that they all strictly followed the ownership idiom
+        // and that ownership cannot be transferred.  While this is technically
+        // correct, many methods allow a tracked object to escape.  For example:
+        //
+        //   CFMutableDictionaryRef x = CFDictionaryCreateMutable(...);        
+        //   CFDictionaryAddValue(y, key, x);
+        //   CFRelease(x); 
+        //   ... it is okay to use 'x' since 'y' has a reference to it
+        //
+        // We handle this and similar cases with the follow heuristic.  If the
+        // function name contains "InsertValue", "SetValue" or "AddValue" then
+        // we assume that arguments may "escape."
+        //
+        ArgEffect E = (CStrInCStrNoCase(FName, "InsertValue") ||
+                       CStrInCStrNoCase(FName, "AddValue") ||
+                       CStrInCStrNoCase(FName, "SetValue"))
+                      ? MayEscape : DoNothing;
+        
+        S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, E);
       }
     }
   }