From 20a1124ce58bd1d8c6b88cd19cea68f2e020f6ad Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Wed, 9 Oct 2013 19:06:08 +0000 Subject: [PATCH] ObjectiveC migrator. Introduce a new objcmt-atomic-property option and use it to infer all properties as 'atomic'. // rdar://14988132 llvm-svn: 192317 --- clang/include/clang/Driver/Options.td | 3 + .../include/clang/Frontend/FrontendOptions.h | 2 + clang/lib/ARCMigrate/ObjCMT.cpp | 14 +- clang/lib/Frontend/CompilerInvocation.cpp | 2 + clang/test/ARCMT/objcmt-atomic-property.m | 229 ++++++++++++++++++ .../ARCMT/objcmt-atomic-property.m.result | 229 ++++++++++++++++++ 6 files changed, 475 insertions(+), 4 deletions(-) create mode 100644 clang/test/ARCMT/objcmt-atomic-property.m create mode 100644 clang/test/ARCMT/objcmt-atomic-property.m.result diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index ea49a62f5220..a3f652f7f4e1 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -177,6 +177,9 @@ def objcmt_migrate_nsmacros : Flag<["-"], "objcmt-migrate-ns-macros">, Flags<[CC HelpText<"Enable migration to NS_ENUM/NS_OPTIONS macros">; def objcmt_migrate_protocol_conformance : Flag<["-"], "objcmt-migrate-protocol-conformance">, Flags<[CC1Option]>, HelpText<"Enable migration to add protocol conformance on classes">; +def objcmt_atomic_property : Flag<["-"], "objcmt-atomic-property">, + Flags<[CC1Option]>, + HelpText<"Make migration to 'atomic' properties">; // Make sure all other -ccc- options are rejected. def ccc_ : Joined<["-"], "ccc-">, Group, Flags<[Unsupported]>; diff --git a/clang/include/clang/Frontend/FrontendOptions.h b/clang/include/clang/Frontend/FrontendOptions.h index ebf1e3622e5e..b77c90b6730a 100644 --- a/clang/include/clang/Frontend/FrontendOptions.h +++ b/clang/include/clang/Frontend/FrontendOptions.h @@ -173,6 +173,8 @@ public: ObjCMT_NsMacros = 0x40, /// \brief Enable migration to add conforming protocols. ObjCMT_ProtocolConformance = 0x80, + /// \brief prefer 'atomic' property over 'nonatomic'. + ObjCMT_AtomicProperty = 0x100, ObjCMT_MigrateDecls = (ObjCMT_ReadonlyProperty | ObjCMT_ReadwriteProperty | ObjCMT_Annotation | ObjCMT_Instancetype | ObjCMT_NsMacros | ObjCMT_ProtocolConformance), diff --git a/clang/lib/ARCMigrate/ObjCMT.cpp b/clang/lib/ARCMigrate/ObjCMT.cpp index f1ab4fca32a3..a1d7a9784260 100644 --- a/clang/lib/ARCMigrate/ObjCMT.cpp +++ b/clang/lib/ARCMigrate/ObjCMT.cpp @@ -266,9 +266,11 @@ void MigrateBlockOrFunctionPointerTypeVariable(std::string & PropertyString, static bool rewriteToObjCProperty(const ObjCMethodDecl *Getter, const ObjCMethodDecl *Setter, const NSAPI &NS, edit::Commit &commit, - unsigned LengthOfPrefix) { + unsigned LengthOfPrefix, + bool Atomic) { ASTContext &Context = NS.getASTContext(); - std::string PropertyString = "@property (nonatomic"; + std::string PropertyString = "@property ("; + PropertyString += (Atomic ? "atomic" : "nonatomic"); std::string PropertyNameString = Getter->getNameAsString(); StringRef PropertyName(PropertyNameString); if (LengthOfPrefix > 0) { @@ -866,7 +868,9 @@ bool ObjCMigrateASTConsumer::migrateProperty(ASTContext &Ctx, return false; edit::Commit commit(*Editor); rewriteToObjCProperty(Method, SetterMethod, *NSAPIObj, commit, - LengthOfPrefix); + LengthOfPrefix, + (ASTMigrateActions & + FrontendOptions::ObjCMT_AtomicProperty) != 0); Editor->commit(commit); return true; } @@ -875,7 +879,9 @@ bool ObjCMigrateASTConsumer::migrateProperty(ASTContext &Ctx, // as a 'readonly' property. edit::Commit commit(*Editor); rewriteToObjCProperty(Method, 0 /*SetterMethod*/, *NSAPIObj, commit, - LengthOfPrefix); + LengthOfPrefix, + (ASTMigrateActions & + FrontendOptions::ObjCMT_AtomicProperty) != 0); Editor->commit(commit); return true; } diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index c7915fd89b65..38a4b9531a65 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -809,6 +809,8 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, Opts.ObjCMTAction |= FrontendOptions::ObjCMT_NsMacros; if (Args.hasArg(OPT_objcmt_migrate_protocol_conformance)) Opts.ObjCMTAction |= FrontendOptions::ObjCMT_ProtocolConformance; + if (Args.hasArg(OPT_objcmt_atomic_property)) + Opts.ObjCMTAction |= FrontendOptions::ObjCMT_AtomicProperty; if (Args.hasArg(OPT_objcmt_migrate_all)) Opts.ObjCMTAction |= FrontendOptions::ObjCMT_MigrateDecls; diff --git a/clang/test/ARCMT/objcmt-atomic-property.m b/clang/test/ARCMT/objcmt-atomic-property.m new file mode 100644 index 000000000000..78ab3ec71596 --- /dev/null +++ b/clang/test/ARCMT/objcmt-atomic-property.m @@ -0,0 +1,229 @@ +// RUN: rm -rf %t +// RUN: %clang_cc1 -fblocks -objcmt-migrate-readwrite-property -objcmt-migrate-readonly-property -objcmt-atomic-property -mt-migrate-directory %t %s -x objective-c -fobjc-runtime-has-weak -fobjc-arc -triple x86_64-apple-darwin11 +// RUN: c-arcmt-test -mt-migrate-directory %t | arcmt-test -verify-transformed-files %s.result +// RUN: %clang_cc1 -fblocks -triple x86_64-apple-darwin10 -fsyntax-only -x objective-c -fobjc-runtime-has-weak -fobjc-arc %s.result + +#define WEBKIT_OBJC_METHOD_ANNOTATION(ANNOTATION) ANNOTATION +#define WEAK_IMPORT_ATTRIBUTE __attribute__((objc_arc_weak_reference_unavailable)) +#define AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER +#define DEPRECATED __attribute__((deprecated)) + +typedef char BOOL; +@class NSString; +@protocol NSCopying @end + +@interface NSObject +@end + +@interface NSDictionary : NSObject +@end + +@interface I : NSObject { + int ivarVal; +} +- (void) setWeakProp : (NSString *__weak)Val; +- (NSString *__weak) WeakProp; + +- (NSString *) StrongProp; +- (void) setStrongProp : (NSString *)Val; + +- (NSString *) UnavailProp __attribute__((unavailable)); +- (void) setUnavailProp : (NSString *)Val; + +- (NSString *) UnavailProp1 __attribute__((unavailable)); +- (void) setUnavailProp1 : (NSString *)Val __attribute__((unavailable)); + +- (NSString *) UnavailProp2; +- (void) setUnavailProp2 : (NSString *)Val __attribute__((unavailable)); + +- (NSDictionary*) undoAction; +- (void) setUndoAction: (NSDictionary*)Arg; +@end + +@implementation I +@end + +@class NSArray; + +@interface MyClass2 { +@private + NSArray *_names1; + NSArray *_names2; + NSArray *_names3; + NSArray *_names4; +} +- (void)setNames1:(NSArray *)names; +- (void)setNames4:(__strong NSArray *)names; +- (void)setNames3:(__strong NSArray *)names; +- (void)setNames2:(NSArray *)names; +- (NSArray *) names2; +- (NSArray *)names3; +- (__strong NSArray *)names4; +- (NSArray *) names1; +@end + +// Properties that contain the name "delegate" or "dataSource", +// or have exact name "target" have unsafe_unretained attribute. +@interface NSInvocation +- (id)target; +- (void)setTarget:(id)target; + +- (id) dataSource; + +- (id)xxxdelegateYYY; +- (void)setXxxdelegateYYY:(id)delegate; + +- (void)setDataSource:(id)source; + +- (id)MYtarget; +- (void)setMYtarget: (id)target; + +- (id)targetX; +- (void)setTargetX: (id)t; + +- (int)value; +- (void)setValue: (int)val; + +-(BOOL) isContinuous; +-(void) setContinuous:(BOOL)value; + +- (id) isAnObject; +- (void)setAnObject : (id) object; + +- (BOOL) isinValid; +- (void) setInValid : (BOOL) arg; + +- (void) Nothing; +- (int) Length; +- (id) object; ++ (double) D; +- (void *)JSObject WEBKIT_OBJC_METHOD_ANNOTATION(AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER); +- (BOOL)isIgnoringInteractionEvents; + +- (NSString *)getStringValue; +- (BOOL)getCounterValue; +- (void)setStringValue:(NSString *)stringValue AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER; +- (NSDictionary *)getns_dixtionary; + +- (BOOL)is3bar; // watch out +- (NSString *)get3foo; // watch out + +- (BOOL) getM; +- (BOOL) getMA; +- (BOOL) getALL; +- (BOOL) getMANY; +- (BOOL) getSome; +@end + + +@interface NSInvocation(CAT) +- (id)target; +- (void)setTarget:(id)target; + +- (id) dataSource; + +- (id)xxxdelegateYYY; +- (void)setXxxdelegateYYY:(id)delegate; + +- (void)setDataSource:(id)source; + +- (id)MYtarget; +- (void)setMYtarget: (id)target; + +- (id)targetX; +- (void)setTargetX: (id)t; + +- (int)value; +- (void)setValue: (int)val; + +-(BOOL) isContinuous; +-(void) setContinuous:(BOOL)value; + +- (id) isAnObject; +- (void)setAnObject : (id) object; + +- (BOOL) isinValid; +- (void) setInValid : (BOOL) arg; + +- (void) Nothing; +- (int) Length; +- (id) object; ++ (double) D; + +- (BOOL)is3bar; // watch out +- (NSString *)get3foo; // watch out + +- (BOOL) getM; +- (BOOL) getMA; +- (BOOL) getALL; +- (BOOL) getMANY; +- (BOOL) getSome; +@end + +DEPRECATED +@interface I_DEP +- (BOOL) isinValid; +- (void) setInValid : (BOOL) arg; +@end + +@interface AnotherOne +- (BOOL) isinValid DEPRECATED; +- (void) setInValid : (BOOL) arg; +- (id)MYtarget; +- (void)setMYtarget: (id)target DEPRECATED; +- (BOOL) getM DEPRECATED; + +- (id)xxxdelegateYYY DEPRECATED; +- (void)setXxxdelegateYYY:(id)delegate DEPRECATED; +@end + +// rdar://14987909 +#define NS_AVAILABLE __attribute__((availability(macosx,introduced=10.0))) +#define NORETURN __attribute__((noreturn)) +#define ALIGNED __attribute__((aligned(16))) + +@interface NSURL +// Do not infer a property. +- (NSURL *)appStoreReceiptURL NS_AVAILABLE; +- (void) setAppStoreReceiptURL : (NSURL *)object; + +- (NSURL *)appStoreReceiptURLX NS_AVAILABLE; +- (void) setAppStoreReceiptURLX : (NSURL *)object NS_AVAILABLE; + +// Do not infer a property. +- (NSURL *)appStoreReceiptURLY ; +- (void) setAppStoreReceiptURLY : (NSURL *)object NS_AVAILABLE; + +- (id)OkToInfer NS_AVAILABLE; + +// Do not infer a property. +- (NSURL *)appStoreReceiptURLZ ; +- (void) setAppStoreReceiptURLZ : (NSURL *)object NS_AVAILABLE; + +// Do not infer a property. +- (id) t1 NORETURN NS_AVAILABLE; +- (void) setT1 : (id) arg NS_AVAILABLE; + +- (id)method1 ALIGNED NS_AVAILABLE; +- (void) setMethod1 : (id) object NS_AVAILABLE ALIGNED; + +- (NSURL *)init; // No Change ++ (id)alloc; // No Change + +- (BOOL)is1stClass; // Not a valid property +- (BOOL)isClass; // This is a valid property 'class' is not a keyword in ObjC +- (BOOL)isDouble; // Not a valid property + +@end + +// rdar://15082818 +@class NSMutableDictionary; + +@interface NSArray +- (id (^)(id, NSArray *, NSMutableDictionary *)) expressionBlock; +- (id (^)(id, NSArray *, NSMutableDictionary *)) MyBlock; +- (void) setMyBlock : (id (^)(id, NSArray *, NSMutableDictionary *)) bl; +- (id (*)(id, NSArray *, NSMutableDictionary *)) expressionFuncptr; +- (id (*)(id, NSArray *, NSMutableDictionary *)) MyFuncptr; +- (void) setMyFuncptr : (id (*)(id, NSArray *, NSMutableDictionary *)) bl; +@end diff --git a/clang/test/ARCMT/objcmt-atomic-property.m.result b/clang/test/ARCMT/objcmt-atomic-property.m.result new file mode 100644 index 000000000000..620ae39a00dd --- /dev/null +++ b/clang/test/ARCMT/objcmt-atomic-property.m.result @@ -0,0 +1,229 @@ +// RUN: rm -rf %t +// RUN: %clang_cc1 -fblocks -objcmt-migrate-readwrite-property -objcmt-migrate-readonly-property -objcmt-atomic-property -mt-migrate-directory %t %s -x objective-c -fobjc-runtime-has-weak -fobjc-arc -triple x86_64-apple-darwin11 +// RUN: c-arcmt-test -mt-migrate-directory %t | arcmt-test -verify-transformed-files %s.result +// RUN: %clang_cc1 -fblocks -triple x86_64-apple-darwin10 -fsyntax-only -x objective-c -fobjc-runtime-has-weak -fobjc-arc %s.result + +#define WEBKIT_OBJC_METHOD_ANNOTATION(ANNOTATION) ANNOTATION +#define WEAK_IMPORT_ATTRIBUTE __attribute__((objc_arc_weak_reference_unavailable)) +#define AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER +#define DEPRECATED __attribute__((deprecated)) + +typedef char BOOL; +@class NSString; +@protocol NSCopying @end + +@interface NSObject +@end + +@interface NSDictionary : NSObject +@end + +@interface I : NSObject { + int ivarVal; +} + +@property (atomic, weak) NSString *WeakProp; + +@property (atomic, retain) NSString *StrongProp; + + +- (NSString *) UnavailProp __attribute__((unavailable)); +- (void) setUnavailProp : (NSString *)Val; + +@property (atomic, retain) NSString *UnavailProp1 __attribute__((unavailable)); + + +- (NSString *) UnavailProp2; +- (void) setUnavailProp2 : (NSString *)Val __attribute__((unavailable)); + +@property (atomic, copy) NSDictionary *undoAction; + +@end + +@implementation I +@end + +@class NSArray; + +@interface MyClass2 { +@private + NSArray *_names1; + NSArray *_names2; + NSArray *_names3; + NSArray *_names4; +} + + + + +@property (atomic, retain) NSArray *names2; +@property (atomic, retain) NSArray *names3; +@property (atomic, retain) NSArray *names4; +@property (atomic, retain) NSArray *names1; +@end + +// Properties that contain the name "delegate" or "dataSource", +// or have exact name "target" have unsafe_unretained attribute. +@interface NSInvocation +@property (atomic, unsafe_unretained) id target; + + +@property (atomic, unsafe_unretained) id dataSource; + +@property (atomic, unsafe_unretained) id xxxdelegateYYY; + + + + +@property (atomic, retain) id MYtarget; + + +@property (atomic, retain) id targetX; + + +@property (atomic) int value; + + +@property (atomic, getter=isContinuous) BOOL continuous; + + +- (id) isAnObject; +- (void)setAnObject : (id) object; + +@property (atomic, getter=isinValid, readonly) BOOL inValid; +- (void) setInValid : (BOOL) arg; + +- (void) Nothing; +@property (atomic, readonly) int Length; +@property (atomic, readonly) id object; ++ (double) D; +@property (atomic, readonly) void *JSObject WEBKIT_OBJC_METHOD_ANNOTATION(AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER); +@property (atomic, getter=isIgnoringInteractionEvents, readonly) BOOL ignoringInteractionEvents; + +@property (atomic, getter=getStringValue, retain) NSString *stringValue; +@property (atomic, getter=getCounterValue, readonly) BOOL counterValue; + +@property (atomic, getter=getns_dixtionary, readonly) NSDictionary *ns_dixtionary; + +- (BOOL)is3bar; // watch out +- (NSString *)get3foo; // watch out + +@property (atomic, getter=getM, readonly) BOOL m; +@property (atomic, getter=getMA, readonly) BOOL MA; +@property (atomic, getter=getALL, readonly) BOOL ALL; +@property (atomic, getter=getMANY, readonly) BOOL MANY; +@property (atomic, getter=getSome, readonly) BOOL some; +@end + + +@interface NSInvocation(CAT) +@property (atomic, unsafe_unretained) id target; + + +@property (atomic, unsafe_unretained) id dataSource; + +@property (atomic, unsafe_unretained) id xxxdelegateYYY; + + + + +@property (atomic, retain) id MYtarget; + + +@property (atomic, retain) id targetX; + + +@property (atomic) int value; + + +@property (atomic, getter=isContinuous) BOOL continuous; + + +- (id) isAnObject; +- (void)setAnObject : (id) object; + +@property (atomic, getter=isinValid, readonly) BOOL inValid; +- (void) setInValid : (BOOL) arg; + +- (void) Nothing; +@property (atomic, readonly) int Length; +@property (atomic, readonly) id object; ++ (double) D; + +- (BOOL)is3bar; // watch out +- (NSString *)get3foo; // watch out + +@property (atomic, getter=getM, readonly) BOOL m; +@property (atomic, getter=getMA, readonly) BOOL MA; +@property (atomic, getter=getALL, readonly) BOOL ALL; +@property (atomic, getter=getMANY, readonly) BOOL MANY; +@property (atomic, getter=getSome, readonly) BOOL some; +@end + +DEPRECATED +@interface I_DEP +- (BOOL) isinValid; +- (void) setInValid : (BOOL) arg; +@end + +@interface AnotherOne +- (BOOL) isinValid DEPRECATED; +- (void) setInValid : (BOOL) arg; +- (id)MYtarget; +- (void)setMYtarget: (id)target DEPRECATED; +- (BOOL) getM DEPRECATED; + +- (id)xxxdelegateYYY DEPRECATED; +- (void)setXxxdelegateYYY:(id)delegate DEPRECATED; +@end + +// rdar://14987909 +#define NS_AVAILABLE __attribute__((availability(macosx,introduced=10.0))) +#define NORETURN __attribute__((noreturn)) +#define ALIGNED __attribute__((aligned(16))) + +@interface NSURL +// Do not infer a property. +- (NSURL *)appStoreReceiptURL NS_AVAILABLE; +- (void) setAppStoreReceiptURL : (NSURL *)object; + +@property (atomic, retain) NSURL *appStoreReceiptURLX NS_AVAILABLE; + + +// Do not infer a property. +- (NSURL *)appStoreReceiptURLY ; +- (void) setAppStoreReceiptURLY : (NSURL *)object NS_AVAILABLE; + +@property (atomic, readonly) id OkToInfer NS_AVAILABLE; + +// Do not infer a property. +- (NSURL *)appStoreReceiptURLZ ; +- (void) setAppStoreReceiptURLZ : (NSURL *)object NS_AVAILABLE; + +// Do not infer a property. +- (id) t1 NORETURN NS_AVAILABLE; +- (void) setT1 : (id) arg NS_AVAILABLE; + +@property (atomic, retain) id method1 ALIGNED NS_AVAILABLE; + + +- (NSURL *)init; // No Change ++ (id)alloc; // No Change + +- (BOOL)is1stClass; // Not a valid property +@property (atomic, getter=isClass, readonly) BOOL class; // This is a valid property 'class' is not a keyword in ObjC +- (BOOL)isDouble; // Not a valid property + +@end + +// rdar://15082818 +@class NSMutableDictionary; + +@interface NSArray +@property (atomic, readonly) id (^expressionBlock)(id, NSArray *, NSMutableDictionary *); +@property (atomic, copy) id (^MyBlock)(id, NSArray *, NSMutableDictionary *); + +@property (atomic, readonly) id (*expressionFuncptr)(id, NSArray *, NSMutableDictionary *); +@property (atomic) id (*MyFuncptr)(id, NSArray *, NSMutableDictionary *); + +@end