diff --git a/clang/lib/Analysis/CFRefCount.cpp b/clang/lib/Analysis/CFRefCount.cpp index b965393601c3..1b7a746f2631 100644 --- a/clang/lib/Analysis/CFRefCount.cpp +++ b/clang/lib/Analysis/CFRefCount.cpp @@ -635,8 +635,8 @@ class VISIBILITY_HIDDEN RetainSummaryManager { /// objects. RetEffect ObjCAllocRetE; - /// ObjCInitRetE - Default return effect for init methods returning Objective-C - /// objects. + /// ObjCInitRetE - Default return effect for init methods returning + /// Objective-C objects. RetEffect ObjCInitRetE; RetainSummary DefaultSummary; @@ -1452,8 +1452,13 @@ void RetainSummaryManager::InitializeMethodSummaries() { // Create the "init" selector. It just acts as a pass-through for the // receiver. - addNSObjectMethSummary(GetNullarySelector("init", Ctx), - getPersistentSummary(ObjCInitRetE, DecRefMsg)); + RetainSummary *InitSumm = getPersistentSummary(ObjCInitRetE, DecRefMsg); + addNSObjectMethSummary(GetNullarySelector("init", Ctx), InitSumm); + + // awakeAfterUsingCoder: behaves basically like an 'init' method. It + // claims the receiver and returns a retained object. + addNSObjectMethSummary(GetUnarySelector("awakeAfterUsingCoder", Ctx), + InitSumm); // The next methods are allocators. RetainSummary *AllocSumm = getPersistentSummary(ObjCAllocRetE); diff --git a/clang/test/Analysis/retain-release.m b/clang/test/Analysis/retain-release.m index e39bae9126d3..a510f441174a 100644 --- a/clang/test/Analysis/retain-release.m +++ b/clang/test/Analysis/retain-release.m @@ -94,19 +94,24 @@ typedef unsigned long NSUInteger; extern void NSLog(NSString *format, ...) __attribute__((format(__NSString__, 1, 2))); typedef struct _NSZone NSZone; @class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; -@protocol NSObject - (BOOL)isEqual:(id)object; +@protocol NSObject +- (BOOL)isEqual:(id)object; - (id)retain; - (oneway void)release; - (id)autorelease; @end @protocol NSCopying - (id)copyWithZone:(NSZone *)zone; @end @protocol NSMutableCopying - (id)mutableCopyWithZone:(NSZone *)zone; @end @protocol NSCoding - (void)encodeWithCoder:(NSCoder *)aCoder; -@end @interface NSObject { -} +@end +@interface NSObject {} + (id)allocWithZone:(NSZone *)zone; + (id)alloc; - (void)dealloc; -@end extern id NSAllocateObject(Class aClass, NSUInteger extraBytes, NSZone *zone); +@end +@interface NSObject (NSCoderMethods) +- (id)awakeAfterUsingCoder:(NSCoder *)aDecoder; +@end +extern id NSAllocateObject(Class aClass, NSUInteger extraBytes, NSZone *zone); typedef struct { } NSFastEnumerationState; @@ -647,7 +652,8 @@ typedef CFTypeRef OtherRef; @end //===----------------------------------------------------------------------===// -// false positive - init method returns an object owned by caller +// false positive - init method returns an object +// owned by caller //===----------------------------------------------------------------------===// @interface RDar6320065 : NSObject { @@ -690,7 +696,21 @@ int RDar6320065_test() { } //===----------------------------------------------------------------------===// -// [NSData dataWithBytesNoCopy] does not return a retained object +// -awakeAfterUsingCoder: returns an owned object +// and claims the receiver +//===----------------------------------------------------------------------===// + +@interface RDar7129086 : NSObject {} @end +@implementation RDar7129086 +- (id)awakeAfterUsingCoder:(NSCoder *)aDecoder { + [self release]; // no-warning + return [NSString alloc]; // no-warning +} +@end + +//===----------------------------------------------------------------------===// +// [NSData dataWithBytesNoCopy] does not return a +// retained object //===----------------------------------------------------------------------===// @interface RDar6859457 : NSObject {}