ObjectiveC migrator. 'atomic' is the default attribute.
Don't add it to inferred property. // rdar://14988132



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@192834 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/ARCMigrate/ObjCMT.cpp b/lib/ARCMigrate/ObjCMT.cpp
index 65825ce..0f7b4c2 100644
--- a/lib/ARCMigrate/ObjCMT.cpp
+++ b/lib/ARCMigrate/ObjCMT.cpp
@@ -229,8 +229,14 @@
   BodyMigrator(*this).TraverseDecl(D);
 }
 
-static void append_attr(std::string &PropertyString, const char *attr) {
-  PropertyString += ", ";
+static void append_attr(std::string &PropertyString, const char *attr,
+                        bool &LParenAdded) {
+  if (!LParenAdded) {
+    PropertyString += "(";
+    LParenAdded = true;
+  }
+  else
+    PropertyString += ", ";
   PropertyString += attr;
 }
 
@@ -273,24 +279,40 @@
                                   unsigned LengthOfPrefix,
                                   bool Atomic) {
   ASTContext &Context = NS.getASTContext();
-  std::string PropertyString = "@property (";
-  PropertyString += (Atomic ? "atomic" : "nonatomic");
+  bool LParenAdded = false;
+  std::string PropertyString = "@property ";
+  if (!Atomic) {
+    PropertyString += "(nonatomic";
+    LParenAdded = true;
+  }
+  
   std::string PropertyNameString = Getter->getNameAsString();
   StringRef PropertyName(PropertyNameString);
   if (LengthOfPrefix > 0) {
-    PropertyString += ", getter=";
+    if (!LParenAdded) {
+      PropertyString += "(getter=";
+      LParenAdded = true;
+    }
+    else
+      PropertyString += ", getter=";
     PropertyString += PropertyNameString;
   }
   // Property with no setter may be suggested as a 'readonly' property.
-  if (!Setter)
-    append_attr(PropertyString, "readonly");
+  if (!Setter) {
+    if (!LParenAdded) {
+      PropertyString += "(readonly";
+      LParenAdded = true;
+    }
+    else
+      append_attr(PropertyString, "readonly", LParenAdded);
+  }
   
   // Short circuit 'delegate' properties that contain the name "delegate" or
   // "dataSource", or have exact name "target" to have 'assign' attribute.
   if (PropertyName.equals("target") ||
       (PropertyName.find("delegate") != StringRef::npos) ||
       (PropertyName.find("dataSource") != StringRef::npos))
-    append_attr(PropertyString, "assign");
+    append_attr(PropertyString, "assign", LParenAdded);
   else if (Setter) {
     const ParmVarDecl *argDecl = *Setter->param_begin();
     QualType ArgType = Context.getCanonicalType(argDecl->getType());
@@ -302,21 +324,22 @@
         ObjCInterfaceDecl *IDecl = ObjPtrTy->getObjectType()->getInterface();
         if (IDecl &&
             IDecl->lookupNestedProtocol(&Context.Idents.get("NSCopying")))
-          append_attr(PropertyString, "copy");
+          append_attr(PropertyString, "copy", LParenAdded);
         else
-          append_attr(PropertyString, "retain");
+          append_attr(PropertyString, "retain", LParenAdded);
       }
       else if (ArgType->isBlockPointerType())
-        append_attr(PropertyString, "copy");
+        append_attr(PropertyString, "copy", LParenAdded);
     } else if (propertyLifetime == Qualifiers::OCL_Weak)
       // TODO. More precise determination of 'weak' attribute requires
       // looking into setter's implementation for backing weak ivar.
-      append_attr(PropertyString, "weak");
+      append_attr(PropertyString, "weak", LParenAdded);
     else if (RetainableObject)
       append_attr(PropertyString,
-                  ArgType->isBlockPointerType() ? "copy" : "retain");
+                  ArgType->isBlockPointerType() ? "copy" : "retain", LParenAdded);
   }
-  PropertyString += ')';
+  if (LParenAdded)
+    PropertyString += ')';
   QualType RT = Getter->getResultType();
   if (!isa<TypedefType>(RT)) {
     // strip off any ARC lifetime qualifier.
diff --git a/test/ARCMT/objcmt-atomic-property.m.result b/test/ARCMT/objcmt-atomic-property.m.result
index 2bebf4a..f764488 100644
--- a/test/ARCMT/objcmt-atomic-property.m.result
+++ b/test/ARCMT/objcmt-atomic-property.m.result
@@ -22,21 +22,21 @@
   int ivarVal;
 }
 
-@property (atomic, weak) NSString *WeakProp;
+@property (weak) NSString *WeakProp;
 
-@property (atomic, retain) NSString *StrongProp;
+@property (retain) NSString *StrongProp;
 
 
 - (NSString *) UnavailProp  __attribute__((unavailable));
 - (void) setUnavailProp  : (NSString *)Val;
 
-@property (atomic, retain) NSString *UnavailProp1  __attribute__((unavailable));
+@property (retain) NSString *UnavailProp1  __attribute__((unavailable));
 
 
 - (NSString *) UnavailProp2;
 - (void) setUnavailProp2  : (NSString *)Val  __attribute__((unavailable));
 
-@property (atomic, copy) NSDictionary *undoAction;
+@property (copy) NSDictionary *undoAction;
 
 @end
 
@@ -56,108 +56,108 @@
 
 
 
-@property (atomic, retain) NSArray *names2;
-@property (atomic, retain) NSArray *names3;
-@property (atomic, retain) NSArray *names4;
-@property (atomic, retain) NSArray *names1;
+@property (retain) NSArray *names2;
+@property (retain) NSArray *names3;
+@property (retain) NSArray *names4;
+@property (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, assign) id target;
+@property (assign) id target;
 
 
-@property (atomic, assign) id dataSource;
+@property (assign) id dataSource;
 
-@property (atomic, assign) id xxxdelegateYYY;
+@property (assign) id xxxdelegateYYY;
 
 
 
 
-@property (atomic, retain) id MYtarget;
+@property (retain) id MYtarget;
 
 
-@property (atomic, retain) id targetX;
+@property (retain) id targetX;
 
  
-@property (atomic) int value;
+@property  int value;
 
 
-@property (atomic, getter=isContinuous) BOOL continuous;
+@property (getter=isContinuous) BOOL continuous;
 
 
 - (id) isAnObject;
 - (void)setAnObject : (id) object;
 
-@property (atomic, getter=isinValid, readonly) BOOL inValid;
+@property (getter=isinValid, readonly) BOOL inValid;
 - (void) setInValid : (BOOL) arg;
 
 - (void) Nothing;
-@property (atomic, readonly) int Length;
-@property (atomic, readonly) id object;
+@property (readonly) int Length;
+@property (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 (readonly) void *JSObject WEBKIT_OBJC_METHOD_ANNOTATION(AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER);
+@property (getter=isIgnoringInteractionEvents, readonly) BOOL ignoringInteractionEvents;
 
-@property (atomic, getter=getStringValue, retain) NSString *stringValue;
-@property (atomic, getter=getCounterValue, readonly) BOOL counterValue;
+@property (getter=getStringValue, retain) NSString *stringValue;
+@property (getter=getCounterValue, readonly) BOOL counterValue;
 
-@property (atomic, getter=getns_dixtionary, readonly) NSDictionary *ns_dixtionary;
+@property (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;
+@property (getter=getM, readonly) BOOL m;
+@property (getter=getMA, readonly) BOOL MA;
+@property (getter=getALL, readonly) BOOL ALL;
+@property (getter=getMANY, readonly) BOOL MANY;
+@property (getter=getSome, readonly) BOOL some;
 @end
 
 
 @interface NSInvocation(CAT)
-@property (atomic, assign) id target;
+@property (assign) id target;
 
 
-@property (atomic, assign) id dataSource;
+@property (assign) id dataSource;
 
-@property (atomic, assign) id xxxdelegateYYY;
+@property (assign) id xxxdelegateYYY;
 
 
 
 
-@property (atomic, retain) id MYtarget;
+@property (retain) id MYtarget;
 
 
-@property (atomic, retain) id targetX;
+@property (retain) id targetX;
 
 
-@property (atomic) int value;
+@property  int value;
 
 
-@property (atomic, getter=isContinuous) BOOL continuous;
+@property (getter=isContinuous) BOOL continuous;
 
 
 - (id) isAnObject;
 - (void)setAnObject : (id) object;
 
-@property (atomic, getter=isinValid, readonly) BOOL inValid;
+@property (getter=isinValid, readonly) BOOL inValid;
 - (void) setInValid : (BOOL) arg;
 
 - (void) Nothing;
-@property (atomic, readonly) int Length;
-@property (atomic, readonly) id object;
+@property (readonly) int Length;
+@property (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;
+@property (getter=getM, readonly) BOOL m;
+@property (getter=getMA, readonly) BOOL MA;
+@property (getter=getALL, readonly) BOOL ALL;
+@property (getter=getMANY, readonly) BOOL MANY;
+@property (getter=getSome, readonly) BOOL some;
 @end
 
 DEPRECATED
@@ -187,14 +187,14 @@
 - (NSURL *)appStoreReceiptURL NS_AVAILABLE;
 - (void) setAppStoreReceiptURL : (NSURL *)object;
 
-@property (atomic, retain) NSURL *appStoreReceiptURLX NS_AVAILABLE;
+@property (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;
+@property (readonly) id OkToInfer NS_AVAILABLE;
 
 // Do not infer a property.
 - (NSURL *)appStoreReceiptURLZ ;
@@ -204,14 +204,14 @@
 - (id) t1 NORETURN NS_AVAILABLE;
 - (void) setT1 : (id) arg NS_AVAILABLE;
 
-@property (atomic, retain) id method1 ALIGNED NS_AVAILABLE;
+@property (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
+@property (getter=isClass, readonly) BOOL class;    // This is a valid property 'class' is not a keyword in ObjC
 - (BOOL)isDouble; // Not a valid property
 
 @end
@@ -220,10 +220,10 @@
 @class NSMutableDictionary;
 
 @interface NSArray
-@property (atomic, readonly) id (^expressionBlock)(id, NSArray *, NSMutableDictionary *);
-@property (atomic, copy) id (^MyBlock)(id, NSArray *, NSMutableDictionary *);
+@property (readonly) id (^expressionBlock)(id, NSArray *, NSMutableDictionary *);
+@property (copy) id (^MyBlock)(id, NSArray *, NSMutableDictionary *);
 
-@property (atomic, readonly) id (*expressionFuncptr)(id, NSArray *, NSMutableDictionary *);
-@property (atomic) id (*MyFuncptr)(id, NSArray *, NSMutableDictionary *);
+@property (readonly) id (*expressionFuncptr)(id, NSArray *, NSMutableDictionary *);
+@property  id (*MyFuncptr)(id, NSArray *, NSMutableDictionary *);
 
 @end