@@ -301,8 +301,9 @@ const RetainSummary *RetainSummaryManager::getSummaryForObjCOrCFObject(
301
301
302
302
std::string RetTyName = RetTy.getAsString ();
303
303
if (FName == " pthread_create" || FName == " pthread_setspecific" ) {
304
- // Part of: <rdar://problem/7299394> and <rdar://problem/11282706>.
305
- // This will be addressed better with IPA.
304
+ // It's not uncommon to pass a tracked object into the thread
305
+ // as 'void *arg', and then release it inside the thread.
306
+ // FIXME: We could build a much more precise model for these functions.
306
307
return getPersistentStopSummary ();
307
308
} else if (FName == " NSMakeCollectable" ) {
308
309
// Handle: id NSMakeCollectable(CFTypeRef)
@@ -311,7 +312,8 @@ const RetainSummary *RetainSummaryManager::getSummaryForObjCOrCFObject(
311
312
: getPersistentStopSummary ();
312
313
} else if (FName == " CMBufferQueueDequeueAndRetain" ||
313
314
FName == " CMBufferQueueDequeueIfDataReadyAndRetain" ) {
314
- // Part of: <rdar://problem/39390714>.
315
+ // These API functions are known to NOT act as a CFRetain wrapper.
316
+ // They simply make a new object owned by the caller.
315
317
return getPersistentSummary (RetEffect::MakeOwned (ObjKind::CF),
316
318
ScratchArgs,
317
319
ArgEffect (DoNothing),
@@ -324,52 +326,47 @@ const RetainSummary *RetainSummaryManager::getSummaryForObjCOrCFObject(
324
326
FName == " IOServiceNameMatching" ||
325
327
FName == " IORegistryEntryIDMatching" ||
326
328
FName == " IOOpenFirmwarePathMatching" ))) {
327
- // Part of <rdar://problem/6961230>. ( IOKit)
328
- // This should be addressed using a API table .
329
+ // Yes, these IOKit functions return CF objects.
330
+ // They also violate the CF naming convention .
329
331
return getPersistentSummary (RetEffect::MakeOwned (ObjKind::CF), ScratchArgs,
330
332
ArgEffect (DoNothing), ArgEffect (DoNothing));
331
333
} else if (FName == " IOServiceGetMatchingService" ||
332
334
FName == " IOServiceGetMatchingServices" ) {
333
- // FIXES: <rdar://problem/6326900>
334
- // This should be addressed using a API table. This strcmp is also
335
- // a little gross, but there is no need to super optimize here.
335
+ // These IOKit functions accept CF objects as arguments.
336
+ // They also consume them without an appropriate annotation.
336
337
ScratchArgs = AF.add (ScratchArgs, 1 , ArgEffect (DecRef, ObjKind::CF));
337
338
return getPersistentSummary (RetEffect::MakeNoRet (),
338
339
ScratchArgs,
339
340
ArgEffect (DoNothing), ArgEffect (DoNothing));
340
341
} else if (FName == " IOServiceAddNotification" ||
341
342
FName == " IOServiceAddMatchingNotification" ) {
342
- // Part of <rdar://problem/6961230>. (IOKit)
343
- // This should be addressed using a API table .
343
+ // More IOKit functions suddenly accepting (and even more suddenly,
344
+ // consuming) CF objects .
344
345
ScratchArgs = AF.add (ScratchArgs, 2 , ArgEffect (DecRef, ObjKind::CF));
345
346
return getPersistentSummary (RetEffect::MakeNoRet (),
346
347
ScratchArgs,
347
348
ArgEffect (DoNothing), ArgEffect (DoNothing));
348
349
} else if (FName == " CVPixelBufferCreateWithBytes" ) {
349
- // FIXES: <rdar://problem/7283567>
350
350
// Eventually this can be improved by recognizing that the pixel
351
351
// buffer passed to CVPixelBufferCreateWithBytes is released via
352
352
// a callback and doing full IPA to make sure this is done correctly.
353
- // FIXME: This function has an out parameter that returns an
353
+ // Note that it's passed as a 'void *', so it's hard to annotate.
354
+ // FIXME: This function also has an out parameter that returns an
354
355
// allocated object.
355
356
ScratchArgs = AF.add (ScratchArgs, 7 , ArgEffect (StopTracking));
356
357
return getPersistentSummary (RetEffect::MakeNoRet (),
357
358
ScratchArgs,
358
359
ArgEffect (DoNothing), ArgEffect (DoNothing));
359
360
} else if (FName == " CGBitmapContextCreateWithData" ) {
360
- // FIXES: <rdar://problem/7358899>
361
+ // This is similar to the CVPixelBufferCreateWithBytes situation above.
361
362
// Eventually this can be improved by recognizing that 'releaseInfo'
362
363
// passed to CGBitmapContextCreateWithData is released via
363
364
// a callback and doing full IPA to make sure this is done correctly.
364
365
ScratchArgs = AF.add (ScratchArgs, 8 , ArgEffect (ArgEffect (StopTracking)));
365
366
return getPersistentSummary (RetEffect::MakeOwned (ObjKind::CF), ScratchArgs,
366
367
ArgEffect (DoNothing), ArgEffect (DoNothing));
367
368
} else if (FName == " CVPixelBufferCreateWithPlanarBytes" ) {
368
- // FIXES: <rdar://problem/7283567>
369
- // Eventually this can be improved by recognizing that the pixel
370
- // buffer passed to CVPixelBufferCreateWithPlanarBytes is released
371
- // via a callback and doing full IPA to make sure this is done
372
- // correctly.
369
+ // Same as CVPixelBufferCreateWithBytes, just more arguments.
373
370
ScratchArgs = AF.add (ScratchArgs, 12 , ArgEffect (StopTracking));
374
371
return getPersistentSummary (RetEffect::MakeNoRet (),
375
372
ScratchArgs,
@@ -386,12 +383,10 @@ const RetainSummary *RetainSummaryManager::getSummaryForObjCOrCFObject(
386
383
ArgEffect (DoNothing), ArgEffect (DoNothing));
387
384
} else if (FName == " dispatch_set_context" ||
388
385
FName == " xpc_connection_set_context" ) {
389
- // <rdar://problem/11059275> - The analyzer currently doesn't have
390
- // a good way to reason about the finalizer function for libdispatch .
386
+ // The analyzer currently doesn't have a good way to reason about
387
+ // dispatch_set_finalizer_f() which typically cleans up the context .
391
388
// If we pass a context object that is memory managed, stop tracking it.
392
- // <rdar://problem/13783514> - Same problem, but for XPC.
393
- // FIXME: this hack should possibly go away once we can handle
394
- // libdispatch and XPC finalizers.
389
+ // Same with xpc_connection_set_finalizer_f().
395
390
ScratchArgs = AF.add (ScratchArgs, 1 , ArgEffect (StopTracking));
396
391
return getPersistentSummary (RetEffect::MakeNoRet (),
397
392
ScratchArgs,
@@ -740,8 +735,8 @@ RetainSummaryManager::canEval(const CallExpr *CE, const FunctionDecl *FD,
740
735
// It's okay to be a little sloppy here.
741
736
if (FName == " CMBufferQueueDequeueAndRetain" ||
742
737
FName == " CMBufferQueueDequeueIfDataReadyAndRetain" ) {
743
- // Part of: <rdar://problem/39390714> .
744
- // These are not retain. They just return something and retain it .
738
+ // These API functions are known to NOT act as a CFRetain wrapper .
739
+ // They simply make a new object owned by the caller .
745
740
return std::nullopt;
746
741
}
747
742
if (CE->getNumArgs () == 1 &&
@@ -1243,8 +1238,6 @@ void RetainSummaryManager::InitializeMethodSummaries() {
1243
1238
// FIXME: For now we opt for false negatives with NSWindow, as these objects
1244
1239
// self-own themselves. However, they only do this once they are displayed.
1245
1240
// Thus, we need to track an NSWindow's display status.
1246
- // This is tracked in <rdar://problem/6062711>.
1247
- // See also http://llvm.org/bugs/show_bug.cgi?id=3714.
1248
1241
const RetainSummary *NoTrackYet =
1249
1242
getPersistentSummary (RetEffect::MakeNoRet (), ScratchArgs,
1250
1243
ArgEffect (StopTracking), ArgEffect (StopTracking));
@@ -1259,7 +1252,6 @@ void RetainSummaryManager::InitializeMethodSummaries() {
1259
1252
1260
1253
// For NSNull, objects returned by +null are singletons that ignore
1261
1254
// retain/release semantics. Just don't track them.
1262
- // <rdar://problem/12858915>
1263
1255
addClassMethSummary (" NSNull" , " null" , NoTrackYet);
1264
1256
1265
1257
// Don't track allocated autorelease pools, as it is okay to prematurely
0 commit comments