]> granicus.if.org Git - clang/commitdiff
ObjectiveC migrator. Introduce a new objcmt-atomic-property option
authorFariborz Jahanian <fjahanian@apple.com>
Wed, 9 Oct 2013 19:06:08 +0000 (19:06 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Wed, 9 Oct 2013 19:06:08 +0000 (19:06 +0000)
and use it to infer all properties as 'atomic'.
// rdar://14988132

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@192317 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Driver/Options.td
include/clang/Frontend/FrontendOptions.h
lib/ARCMigrate/ObjCMT.cpp
lib/Frontend/CompilerInvocation.cpp
test/ARCMT/objcmt-atomic-property.m [new file with mode: 0644]
test/ARCMT/objcmt-atomic-property.m.result [new file with mode: 0644]

index ea49a62f5220acff237c6b3f224934ad2e4fa079..a3f652f7f4e1d4a7cad2f9ada9e110ff5aebf0d1 100644 (file)
@@ -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<internal_Group>, Flags<[Unsupported]>;
 
index ebf1e3622e5ef6b677ad8665a899e722f78189a7..b77c90b6730ab9cd980ac4233ba7f0b14340fe31 100644 (file)
@@ -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),
index f1ab4fca32a389c8042ede755f8fca3a2627ef86..a1d7a97842609d425c0ff28ab529ca40f5b64dbf 100644 (file)
@@ -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;
   }
index c7915fd89b653e0937a3648f455fcb6e93aba2ca..38a4b9531a65cc5cf5cdb99abeb197a871869aa2 100644 (file)
@@ -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/test/ARCMT/objcmt-atomic-property.m b/test/ARCMT/objcmt-atomic-property.m
new file mode 100644 (file)
index 0000000..78ab3ec
--- /dev/null
@@ -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 <NSCopying>
+@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/test/ARCMT/objcmt-atomic-property.m.result b/test/ARCMT/objcmt-atomic-property.m.result
new file mode 100644 (file)
index 0000000..620ae39
--- /dev/null
@@ -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 <NSCopying>
+@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