diff --git a/clang/lib/Analysis/CFRefCount.cpp b/clang/lib/Analysis/CFRefCount.cpp index bd5e3b4d5372..625eda4fb196 100644 --- a/clang/lib/Analysis/CFRefCount.cpp +++ b/clang/lib/Analysis/CFRefCount.cpp @@ -2356,8 +2356,15 @@ PathDiagnosticPiece* CFRefReport::VisitNode(const ExplodedNode* N, os << " returns an Objective-C object with a "; } - if (CurrV.isOwned()) - os << "+1 retain count (owning reference)."; + if (CurrV.isOwned()) { + os << "+1 retain count (owning reference)."; + + if (static_cast(getBugType()).getTF().isGCEnabled()) { + assert(CurrV.getObjKind() == RetEffect::CF); + os << " " + "Core Foundation objects are not automatically garbage collected."; + } + } else { assert (CurrV.isNotOwned()); os << "+0 retain count (non-owning reference)."; diff --git a/clang/test/Analysis/CFDateGC.m b/clang/test/Analysis/CFDateGC.m index 5ed8ae960937..c405fe24e590 100644 --- a/clang/test/Analysis/CFDateGC.m +++ b/clang/test/Analysis/CFDateGC.m @@ -26,6 +26,7 @@ typedef signed char BOOL; static __inline__ __attribute__((always_inline)) id NSMakeCollectable(CFTypeRef cf) {} @protocol NSObject - (BOOL)isEqual:(id)object; - (oneway void)release; +- (id)retain; @end @class NSArray; @@ -46,7 +47,7 @@ CFAbsoluteTime f1_use_after_release() { // The following two test cases verifies that CFMakeCollectable is a no-op // in non-GC mode and a "release" in GC mode. -CFAbsoluteTime f2_leak() { +CFAbsoluteTime f2_use_after_release() { CFAbsoluteTime t = CFAbsoluteTimeGetCurrent(); CFDateRef date = CFDateCreate(0, t); CFRetain(date); @@ -68,6 +69,11 @@ CFAbsoluteTime f2_noleak() { return t; } +void f3_leak_with_gc() { + CFDateRef date = CFDateCreate(0, CFAbsoluteTimeGetCurrent()); + [[(id) date retain] release]; // expected-warning{{leak}} +} + // The following test case verifies that we "stop tracking" a retained object // when it is passed as an argument to an implicitly defined function. CFAbsoluteTime f4() {