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);
}
}
}