From: Argyrios Kyrtzidis Date: Wed, 6 Jun 2012 22:23:12 +0000 (+0000) Subject: [objcmt] When in ARC mode, also convert "[[.. alloc] init]" messages to literals, X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6b4db9b329c6964955153292e21de0a342354437;p=clang [objcmt] When in ARC mode, also convert "[[.. alloc] init]" messages to literals, since the change from +1 to +0 will be handled fine by ARC. rdar://11606358 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@158114 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Edit/RewriteObjCFoundationAPI.cpp b/lib/Edit/RewriteObjCFoundationAPI.cpp index c36793ff06..465f18051a 100644 --- a/lib/Edit/RewriteObjCFoundationAPI.cpp +++ b/lib/Edit/RewriteObjCFoundationAPI.cpp @@ -22,7 +22,8 @@ using namespace clang; using namespace edit; static bool checkForLiteralCreation(const ObjCMessageExpr *Msg, - IdentifierInfo *&ClassId) { + IdentifierInfo *&ClassId, + const LangOptions &LangOpts) { if (!Msg || Msg->isImplicit() || !Msg->getMethodDecl()) return false; @@ -34,6 +35,18 @@ static bool checkForLiteralCreation(const ObjCMessageExpr *Msg, if (Msg->getReceiverKind() == ObjCMessageExpr::Class) return true; + // When in ARC mode we also convert "[[.. alloc] init]" messages to literals, + // since the change from +1 to +0 will be handled fine by ARC. + if (LangOpts.ObjCAutoRefCount) { + if (Msg->getReceiverKind() == ObjCMessageExpr::Instance) { + if (const ObjCMessageExpr *Rec = dyn_cast( + Msg->getInstanceReceiver()->IgnoreParenImpCasts())) { + if (Rec->getMethodFamily() == OMF_alloc) + return true; + } + } + } + return false; } @@ -44,7 +57,7 @@ static bool checkForLiteralCreation(const ObjCMessageExpr *Msg, bool edit::rewriteObjCRedundantCallWithLiteral(const ObjCMessageExpr *Msg, const NSAPI &NS, Commit &commit) { IdentifierInfo *II = 0; - if (!checkForLiteralCreation(Msg, II)) + if (!checkForLiteralCreation(Msg, II, NS.getASTContext().getLangOpts())) return false; if (Msg->getNumArgs() != 1) return false; @@ -54,16 +67,19 @@ bool edit::rewriteObjCRedundantCallWithLiteral(const ObjCMessageExpr *Msg, if ((isa(Arg) && NS.getNSClassId(NSAPI::ClassId_NSString) == II && - NS.getNSStringSelector(NSAPI::NSStr_stringWithString) == Sel) || + (NS.getNSStringSelector(NSAPI::NSStr_stringWithString) == Sel || + NS.getNSStringSelector(NSAPI::NSStr_initWithString) == Sel)) || (isa(Arg) && NS.getNSClassId(NSAPI::ClassId_NSArray) == II && - NS.getNSArraySelector(NSAPI::NSArr_arrayWithArray) == Sel) || + (NS.getNSArraySelector(NSAPI::NSArr_arrayWithArray) == Sel || + NS.getNSArraySelector(NSAPI::NSArr_initWithArray) == Sel)) || (isa(Arg) && NS.getNSClassId(NSAPI::ClassId_NSDictionary) == II && - NS.getNSDictionarySelector( - NSAPI::NSDict_dictionaryWithDictionary) == Sel)) { + (NS.getNSDictionarySelector( + NSAPI::NSDict_dictionaryWithDictionary) == Sel || + NS.getNSDictionarySelector(NSAPI::NSDict_initWithDictionary) == Sel))) { commit.replaceWithInner(Msg->getSourceRange(), Msg->getArg(0)->getSourceRange()); @@ -246,7 +262,7 @@ static bool rewriteToStringBoxedExpression(const ObjCMessageExpr *Msg, bool edit::rewriteToObjCLiteralSyntax(const ObjCMessageExpr *Msg, const NSAPI &NS, Commit &commit) { IdentifierInfo *II = 0; - if (!checkForLiteralCreation(Msg, II)) + if (!checkForLiteralCreation(Msg, II, NS.getASTContext().getLangOpts())) return false; if (II == NS.getNSClassId(NSAPI::ClassId_NSArray)) @@ -290,7 +306,8 @@ static bool rewriteToArrayLiteral(const ObjCMessageExpr *Msg, return true; } - if (Sel == NS.getNSArraySelector(NSAPI::NSArr_arrayWithObjects)) { + if (Sel == NS.getNSArraySelector(NSAPI::NSArr_arrayWithObjects) || + Sel == NS.getNSArraySelector(NSAPI::NSArr_initWithObjects)) { if (Msg->getNumArgs() == 0) return false; const Expr *SentinelExpr = Msg->getArg(Msg->getNumArgs() - 1); @@ -352,7 +369,8 @@ static bool rewriteToDictionaryLiteral(const ObjCMessageExpr *Msg, } if (Sel == NS.getNSDictionarySelector( - NSAPI::NSDict_dictionaryWithObjectsAndKeys)) { + NSAPI::NSDict_dictionaryWithObjectsAndKeys) || + Sel == NS.getNSDictionarySelector(NSAPI::NSDict_initWithObjectsAndKeys)) { if (Msg->getNumArgs() % 2 != 1) return false; unsigned SentinelIdx = Msg->getNumArgs() - 1; diff --git a/test/ARCMT/objcmt-subscripting-literals-in-arc.m b/test/ARCMT/objcmt-subscripting-literals-in-arc.m new file mode 100644 index 0000000000..fd100ca94d --- /dev/null +++ b/test/ARCMT/objcmt-subscripting-literals-in-arc.m @@ -0,0 +1,94 @@ +// RUN: rm -rf %t +// RUN: %clang_cc1 -fobjc-arc -objcmt-migrate-literals -objcmt-migrate-subscripting -mt-migrate-directory %t %s -x objective-c -triple x86_64-apple-darwin11 +// RUN: c-arcmt-test -mt-migrate-directory %t | arcmt-test -verify-transformed-files %s.result +// RUN: %clang_cc1 -fobjc-arc -triple x86_64-apple-darwin10 -fsyntax-only -x objective-c %s.result + +typedef signed char BOOL; +#define nil ((void*) 0) + +typedef const struct __CFString * CFStringRef; + +@interface NSObject ++ (id)alloc; +@end + +@interface NSString : NSObject ++ (id)stringWithString:(NSString *)string; +- (id)initWithString:(NSString *)aString; +@end + +@interface NSArray : NSObject +- (id)objectAtIndex:(unsigned long)index; +- (id)objectAtIndexedSubscript:(int)index; +@end + +@interface NSArray (NSArrayCreation) ++ (id)array; ++ (id)arrayWithObject:(id)anObject; ++ (id)arrayWithObjects:(const id [])objects count:(unsigned long)cnt; ++ (id)arrayWithObjects:(id)firstObj, ...; ++ (id)arrayWithArray:(NSArray *)array; + +- (id)initWithObjects:(const id [])objects count:(unsigned long)cnt; +- (id)initWithObjects:(id)firstObj, ...; +- (id)initWithArray:(NSArray *)array; + +- (id)objectAtIndex:(unsigned long)index; +@end + +@interface NSMutableArray : NSArray +- (void)replaceObjectAtIndex:(unsigned long)index withObject:(id)anObject; +- (void)setObject:(id)object atIndexedSubscript:(int)index; +@end + +@interface NSDictionary : NSObject +- (id)objectForKeyedSubscript:(id)key; +@end + +@interface NSDictionary (NSDictionaryCreation) ++ (id)dictionary; ++ (id)dictionaryWithObject:(id)object forKey:(id)key; ++ (id)dictionaryWithObjects:(const id [])objects forKeys:(const id [])keys count:(unsigned long)cnt; ++ (id)dictionaryWithObjectsAndKeys:(id)firstObject, ...; ++ (id)dictionaryWithDictionary:(NSDictionary *)dict; ++ (id)dictionaryWithObjects:(NSArray *)objects forKeys:(NSArray *)keys; + +- (id)initWithObjects:(const id [])objects forKeys:(const id [])keys count:(unsigned long)cnt; +- (id)initWithObjectsAndKeys:(id)firstObject, ...; +- (id)initWithDictionary:(NSDictionary *)otherDictionary; +- (id)initWithObjects:(NSArray *)objects forKeys:(NSArray *)keys; + +- (id)objectForKey:(id)aKey; +@end + +@interface NSMutableDictionary : NSDictionary +- (void)setObject:(id)anObject forKey:(id)aKey; +- (void)setObject:(id)object forKeyedSubscript:(id)key; +@end + +@interface NSNumber : NSObject +@end + +@interface NSNumber (NSNumberCreation) ++ (NSNumber *)numberWithInt:(int)value; +- (id)initWithInt:(int)value; +@end + +@interface I { + NSArray *ivarArr; +} +@end +@implementation I +-(void) foo { + NSString *str; + NSArray *arr; + NSDictionary *dict; + + arr = [NSArray arrayWithObjects:str, str, nil]; + arr = [[NSArray alloc] initWithObjects:str, str, nil]; + dict = [NSDictionary dictionaryWithObjectsAndKeys: @"value1", @"key1", @"value2", @"key2", nil]; + dict = [[NSDictionary alloc] initWithObjectsAndKeys: @"value1", @"key1", @"value2", @"key2", nil]; + + NSNumber *n = [[NSNumber alloc] initWithInt:2]; +} +@end diff --git a/test/ARCMT/objcmt-subscripting-literals-in-arc.m.result b/test/ARCMT/objcmt-subscripting-literals-in-arc.m.result new file mode 100644 index 0000000000..4a65a23442 --- /dev/null +++ b/test/ARCMT/objcmt-subscripting-literals-in-arc.m.result @@ -0,0 +1,94 @@ +// RUN: rm -rf %t +// RUN: %clang_cc1 -fobjc-arc -objcmt-migrate-literals -objcmt-migrate-subscripting -mt-migrate-directory %t %s -x objective-c -triple x86_64-apple-darwin11 +// RUN: c-arcmt-test -mt-migrate-directory %t | arcmt-test -verify-transformed-files %s.result +// RUN: %clang_cc1 -fobjc-arc -triple x86_64-apple-darwin10 -fsyntax-only -x objective-c %s.result + +typedef signed char BOOL; +#define nil ((void*) 0) + +typedef const struct __CFString * CFStringRef; + +@interface NSObject ++ (id)alloc; +@end + +@interface NSString : NSObject ++ (id)stringWithString:(NSString *)string; +- (id)initWithString:(NSString *)aString; +@end + +@interface NSArray : NSObject +- (id)objectAtIndex:(unsigned long)index; +- (id)objectAtIndexedSubscript:(int)index; +@end + +@interface NSArray (NSArrayCreation) ++ (id)array; ++ (id)arrayWithObject:(id)anObject; ++ (id)arrayWithObjects:(const id [])objects count:(unsigned long)cnt; ++ (id)arrayWithObjects:(id)firstObj, ...; ++ (id)arrayWithArray:(NSArray *)array; + +- (id)initWithObjects:(const id [])objects count:(unsigned long)cnt; +- (id)initWithObjects:(id)firstObj, ...; +- (id)initWithArray:(NSArray *)array; + +- (id)objectAtIndex:(unsigned long)index; +@end + +@interface NSMutableArray : NSArray +- (void)replaceObjectAtIndex:(unsigned long)index withObject:(id)anObject; +- (void)setObject:(id)object atIndexedSubscript:(int)index; +@end + +@interface NSDictionary : NSObject +- (id)objectForKeyedSubscript:(id)key; +@end + +@interface NSDictionary (NSDictionaryCreation) ++ (id)dictionary; ++ (id)dictionaryWithObject:(id)object forKey:(id)key; ++ (id)dictionaryWithObjects:(const id [])objects forKeys:(const id [])keys count:(unsigned long)cnt; ++ (id)dictionaryWithObjectsAndKeys:(id)firstObject, ...; ++ (id)dictionaryWithDictionary:(NSDictionary *)dict; ++ (id)dictionaryWithObjects:(NSArray *)objects forKeys:(NSArray *)keys; + +- (id)initWithObjects:(const id [])objects forKeys:(const id [])keys count:(unsigned long)cnt; +- (id)initWithObjectsAndKeys:(id)firstObject, ...; +- (id)initWithDictionary:(NSDictionary *)otherDictionary; +- (id)initWithObjects:(NSArray *)objects forKeys:(NSArray *)keys; + +- (id)objectForKey:(id)aKey; +@end + +@interface NSMutableDictionary : NSDictionary +- (void)setObject:(id)anObject forKey:(id)aKey; +- (void)setObject:(id)object forKeyedSubscript:(id)key; +@end + +@interface NSNumber : NSObject +@end + +@interface NSNumber (NSNumberCreation) ++ (NSNumber *)numberWithInt:(int)value; +- (id)initWithInt:(int)value; +@end + +@interface I { + NSArray *ivarArr; +} +@end +@implementation I +-(void) foo { + NSString *str; + NSArray *arr; + NSDictionary *dict; + + arr = @[str, str]; + arr = @[str, str]; + dict = @{@"key1": @"value1", @"key2": @"value2"}; + dict = @{@"key1": @"value1", @"key2": @"value2"}; + + NSNumber *n = @2; +} +@end