r193837 - ObjectiveC migrator. When inferring readwrite property,

Fariborz Jahanian fjahanian at apple.com
Thu Oct 31 17:26:48 PDT 2013


Author: fjahanian
Date: Thu Oct 31 19:26:48 2013
New Revision: 193837

URL: http://llvm.org/viewvc/llvm-project?rev=193837&view=rev
Log:
ObjectiveC migrator. When inferring readwrite property,
do not remove the setter if its availability differs
from availability of the getter (which is now turned into
a property). Otherwise, synthesized setter will
inherit availability of the property (which is incorrect).
// rdar://15300059

Added:
    cfe/trunk/test/ARCMT/objcmt-property-availability.m
    cfe/trunk/test/ARCMT/objcmt-property-availability.m.result
Modified:
    cfe/trunk/lib/ARCMigrate/ObjCMT.cpp
    cfe/trunk/test/ARCMT/objcmt-atomic-property.m.result
    cfe/trunk/test/ARCMT/objcmt-property.m.result

Modified: cfe/trunk/lib/ARCMigrate/ObjCMT.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ARCMigrate/ObjCMT.cpp?rev=193837&r1=193836&r2=193837&view=diff
==============================================================================
--- cfe/trunk/lib/ARCMigrate/ObjCMT.cpp (original)
+++ cfe/trunk/lib/ARCMigrate/ObjCMT.cpp Thu Oct 31 19:26:48 2013
@@ -278,7 +278,7 @@ static void rewriteToObjCProperty(const
                                   const ObjCMethodDecl *Setter,
                                   const NSAPI &NS, edit::Commit &commit,
                                   unsigned LengthOfPrefix,
-                                  bool Atomic) {
+                                  bool Atomic, bool AvailabilityArgsMatch) {
   ASTContext &Context = NS.getASTContext();
   bool LParenAdded = false;
   std::string PropertyString = "@property ";
@@ -390,7 +390,7 @@ static void rewriteToObjCProperty(const
   commit.replace(CharSourceRange::getCharRange(Getter->getLocStart(),
                                                EndGetterSelectorLoc),
                  PropertyString);
-  if (Setter) {
+  if (Setter && AvailabilityArgsMatch) {
     SourceLocation EndLoc = Setter->getDeclaratorEndLoc();
     // Get location past ';'
     EndLoc = EndLoc.getLocWithOffset(1);
@@ -910,23 +910,49 @@ static bool TypeIsInnerPointer(QualType
   return true;
 }
 
-static bool AttributesMatch(const Decl *Decl1, const Decl *Decl2) {
-  if (Decl1->hasAttrs() != Decl2->hasAttrs())
-    return false;
-  
-  if (!Decl1->hasAttrs())
+/// \brief Check whether the two versions match.
+static bool versionsMatch(const VersionTuple &X, const VersionTuple &Y) {
+  return (X == Y);
+}
+
+/// AvailabilityAttrsMatch - This routine checks that if comparing two
+/// availability attributes, all their components match. It returns
+/// true, if not dealing with availability or when all components of
+/// availability attributes match. This routine is only called when
+/// the attributes are of the same kind.
+static bool AvailabilityAttrsMatch(Attr *At1, Attr *At2) {
+  const AvailabilityAttr *AA1 = dyn_cast<AvailabilityAttr>(At1);
+  if (!AA1)
     return true;
+  const AvailabilityAttr *AA2 = dyn_cast<AvailabilityAttr>(At2);
   
-  const AttrVec &Attrs1 = Decl1->getAttrs();
-  const AttrVec &Attrs2 = Decl2->getAttrs();
+  VersionTuple Introduced1 = AA1->getIntroduced();
+  VersionTuple Deprecated1 = AA1->getDeprecated();
+  VersionTuple Obsoleted1 = AA1->getObsoleted();
+  bool IsUnavailable1 = AA1->getUnavailable();
+  VersionTuple Introduced2 = AA2->getIntroduced();
+  VersionTuple Deprecated2 = AA2->getDeprecated();
+  VersionTuple Obsoleted2 = AA2->getObsoleted();
+  bool IsUnavailable2 = AA2->getUnavailable();
+  return (versionsMatch(Introduced1, Introduced2) &&
+          versionsMatch(Deprecated1, Deprecated2) &&
+          versionsMatch(Obsoleted1, Obsoleted2) &&
+          IsUnavailable1 == IsUnavailable2);
+  
+}
+
+static bool MatchTwoAttributeLists(const AttrVec &Attrs1, const AttrVec &Attrs2,
+                                   bool &AvailabilityArgsMatch) {
   // This list is very small, so this need not be optimized.
   for (unsigned i = 0, e = Attrs1.size(); i != e; i++) {
     bool match = false;
     for (unsigned j = 0, f = Attrs2.size(); j != f; j++) {
-      // Matching attribute kind only. We are not getting into
-      // details of the attributes. For all practical purposes
+      // Matching attribute kind only. Except for Availabilty attributes,
+      // we are not getting into details of the attributes. For all practical purposes
       // this is sufficient.
       if (Attrs1[i]->getKind() == Attrs2[j]->getKind()) {
+        if (AvailabilityArgsMatch)
+          AvailabilityArgsMatch = AvailabilityAttrsMatch(Attrs1[i], Attrs2[j]);
         match = true;
         break;
       }
@@ -937,6 +963,28 @@ static bool AttributesMatch(const Decl *
   return true;
 }
 
+/// AttributesMatch - This routine checks list of attributes for two
+/// decls. It returns false, if there is a mismatch in kind of
+/// attributes seen in the decls. It returns true if the two decls
+/// have list of same kind of attributes. Furthermore, when there
+/// are availability attributes in the two decls, it sets the
+/// AvailabilityArgsMatch to false if availability attributes have
+/// different versions, etc.
+static bool AttributesMatch(const Decl *Decl1, const Decl *Decl2,
+                            bool &AvailabilityArgsMatch) {
+  if (!Decl1->hasAttrs() || !Decl2->hasAttrs()) {
+    AvailabilityArgsMatch = (Decl1->hasAttrs() == Decl2->hasAttrs());
+    return true;
+  }
+  AvailabilityArgsMatch = true;
+  const AttrVec &Attrs1 = Decl1->getAttrs();
+  const AttrVec &Attrs2 = Decl2->getAttrs();
+  bool match = MatchTwoAttributeLists(Attrs1, Attrs2, AvailabilityArgsMatch);
+  if (match && (Attrs2.size() > Attrs1.size()))
+    return MatchTwoAttributeLists(Attrs2, Attrs1, AvailabilityArgsMatch);
+  return match;
+}
+
 static bool IsValidIdentifier(ASTContext &Ctx,
                               const char *Name) {
   if (!isIdentifierHead(Name[0]))
@@ -1001,8 +1049,9 @@ bool ObjCMigrateASTConsumer::migrateProp
   if (SetterMethod) {
     if ((ASTMigrateActions & FrontendOptions::ObjCMT_ReadwriteProperty) == 0)
       return false;
+    bool AvailabilityArgsMatch;
     if (SetterMethod->isDeprecated() ||
-        !AttributesMatch(Method, SetterMethod))
+        !AttributesMatch(Method, SetterMethod, AvailabilityArgsMatch))
       return false;
     
     // Is this a valid setter, matching the target getter?
@@ -1017,7 +1066,8 @@ bool ObjCMigrateASTConsumer::migrateProp
     rewriteToObjCProperty(Method, SetterMethod, *NSAPIObj, commit,
                           LengthOfPrefix,
                           (ASTMigrateActions &
-                           FrontendOptions::ObjCMT_AtomicProperty) != 0);
+                           FrontendOptions::ObjCMT_AtomicProperty) != 0,
+                          AvailabilityArgsMatch);
     Editor->commit(commit);
     return true;
   }
@@ -1028,7 +1078,8 @@ bool ObjCMigrateASTConsumer::migrateProp
     rewriteToObjCProperty(Method, 0 /*SetterMethod*/, *NSAPIObj, commit,
                           LengthOfPrefix,
                           (ASTMigrateActions &
-                           FrontendOptions::ObjCMT_AtomicProperty) != 0);
+                           FrontendOptions::ObjCMT_AtomicProperty) != 0,
+                          /*AvailabilityArgsMatch*/false);
     Editor->commit(commit);
     return true;
   }

Modified: cfe/trunk/test/ARCMT/objcmt-atomic-property.m.result
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ARCMT/objcmt-atomic-property.m.result?rev=193837&r1=193836&r2=193837&view=diff
==============================================================================
--- cfe/trunk/test/ARCMT/objcmt-atomic-property.m.result (original)
+++ cfe/trunk/test/ARCMT/objcmt-atomic-property.m.result Thu Oct 31 19:26:48 2013
@@ -25,12 +25,12 @@ typedef char BOOL;
 
 @property (retain) NSString *StrongProp;
 
-- (NSString *) UnavailProp  __attribute__((unavailable));
+ at property (retain) NSString *UnavailProp  __attribute__((unavailable));
 - (void) setUnavailProp  : (NSString *)Val;
 
 @property (retain) NSString *UnavailProp1  __attribute__((unavailable));
 
-- (NSString *) UnavailProp2;
+ at property (retain) NSString *UnavailProp2;
 - (void) setUnavailProp2  : (NSString *)Val  __attribute__((unavailable));
 
 @property (copy) NSDictionary *undoAction;
@@ -161,19 +161,19 @@ DEPRECATED
 
 @interface NSURL
 // Do not infer a property.
-- (NSURL *)appStoreReceiptURL NS_AVAILABLE;
+ at property (retain) NSURL *appStoreReceiptURL NS_AVAILABLE;
 - (void) setAppStoreReceiptURL : (NSURL *)object;
 
 @property (retain) NSURL *appStoreReceiptURLX NS_AVAILABLE;
 
 // Do not infer a property.
-- (NSURL *)appStoreReceiptURLY ;
+ at property (retain) NSURL *appStoreReceiptURLY ;
 - (void) setAppStoreReceiptURLY : (NSURL *)object NS_AVAILABLE;
 
 @property (readonly) id OkToInfer NS_AVAILABLE;
 
 // Do not infer a property.
-- (NSURL *)appStoreReceiptURLZ ;
+ at property (retain) NSURL *appStoreReceiptURLZ ;
 - (void) setAppStoreReceiptURLZ : (NSURL *)object NS_AVAILABLE;
 
 // Do not infer a property.

Added: cfe/trunk/test/ARCMT/objcmt-property-availability.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ARCMT/objcmt-property-availability.m?rev=193837&view=auto
==============================================================================
--- cfe/trunk/test/ARCMT/objcmt-property-availability.m (added)
+++ cfe/trunk/test/ARCMT/objcmt-property-availability.m Thu Oct 31 19:26:48 2013
@@ -0,0 +1,46 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1  -objcmt-migrate-readwrite-property -objcmt-migrate-readonly-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 -triple x86_64-apple-darwin10 -fsyntax-only -x objective-c -fobjc-runtime-has-weak -fobjc-arc %s.result
+// rdar://15300059
+
+
+#define __NSi_7_0 introduced=7.0
+#define __NSi_6_0 introduced=6.0
+
+#define CF_AVAILABLE(_mac, _ios) __attribute__((availability(ios,__NSi_##_ios)))
+#define CF_AVAILABLE_MAC(_mac) __attribute__((availability(macosx,__NSi_##_mac)))
+#define CF_AVAILABLE_IOS(_ios) __attribute__((availability(macosx,unavailable)))
+
+#define NS_AVAILABLE(_mac, _ios) CF_AVAILABLE(_mac, _ios)
+#define NS_AVAILABLE_MAC(_mac) CF_AVAILABLE_MAC(_mac)
+#define NS_AVAILABLE_IOS(_ios) CF_AVAILABLE_IOS(_ios)
+
+#define UNAVAILABLE __attribute__((unavailable("not available in automatic reference counting mode")))
+
+ at interface MKMapItem
+- (MKMapItem *)source NS_AVAILABLE(10_9, 6_0);
+- (void)setSource:(MKMapItem *)source NS_AVAILABLE(10_9, 7_0);
+
+- (void)setDest:(MKMapItem *)source NS_AVAILABLE(10_9, 6_0);
+- (MKMapItem *)dest NS_AVAILABLE(10_9, 6_0);
+
+- (MKMapItem *)final;
+- (void)setFinal:(MKMapItem *)source;
+
+- (MKMapItem *)total NS_AVAILABLE(10_9, 6_0);
+- (void)setTotal:(MKMapItem *)source;
+
+- (MKMapItem *)comp NS_AVAILABLE(10_9, 6_0);
+- (void)setComp:(MKMapItem *)source UNAVAILABLE;
+
+- (MKMapItem *)tally  UNAVAILABLE NS_AVAILABLE(10_9, 6_0);
+- (void)setTally:(MKMapItem *)source UNAVAILABLE NS_AVAILABLE(10_9, 6_0);
+
+- (MKMapItem *)itally  NS_AVAILABLE(10_9, 6_0);
+- (void)setItally:(MKMapItem *)source UNAVAILABLE NS_AVAILABLE(10_9, 6_0);
+
+- (MKMapItem *)normal  UNAVAILABLE;
+- (void)setNormal:(MKMapItem *)source UNAVAILABLE NS_AVAILABLE(10_9, 6_0);
+ at end
+

Added: cfe/trunk/test/ARCMT/objcmt-property-availability.m.result
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ARCMT/objcmt-property-availability.m.result?rev=193837&view=auto
==============================================================================
--- cfe/trunk/test/ARCMT/objcmt-property-availability.m.result (added)
+++ cfe/trunk/test/ARCMT/objcmt-property-availability.m.result Thu Oct 31 19:26:48 2013
@@ -0,0 +1,43 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1  -objcmt-migrate-readwrite-property -objcmt-migrate-readonly-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 -triple x86_64-apple-darwin10 -fsyntax-only -x objective-c -fobjc-runtime-has-weak -fobjc-arc %s.result
+// rdar://15300059
+
+
+#define __NSi_7_0 introduced=7.0
+#define __NSi_6_0 introduced=6.0
+
+#define CF_AVAILABLE(_mac, _ios) __attribute__((availability(ios,__NSi_##_ios)))
+#define CF_AVAILABLE_MAC(_mac) __attribute__((availability(macosx,__NSi_##_mac)))
+#define CF_AVAILABLE_IOS(_ios) __attribute__((availability(macosx,unavailable)))
+
+#define NS_AVAILABLE(_mac, _ios) CF_AVAILABLE(_mac, _ios)
+#define NS_AVAILABLE_MAC(_mac) CF_AVAILABLE_MAC(_mac)
+#define NS_AVAILABLE_IOS(_ios) CF_AVAILABLE_IOS(_ios)
+
+#define UNAVAILABLE __attribute__((unavailable("not available in automatic reference counting mode")))
+
+ at interface MKMapItem
+ at property (nonatomic, retain) MKMapItem *source NS_AVAILABLE(10_9, 6_0);
+- (void)setSource:(MKMapItem *)source NS_AVAILABLE(10_9, 7_0);
+
+ at property (nonatomic, retain) MKMapItem *dest NS_AVAILABLE(10_9, 6_0);
+
+ at property (nonatomic, retain) MKMapItem *final;
+
+ at property (nonatomic, retain) MKMapItem *total NS_AVAILABLE(10_9, 6_0);
+- (void)setTotal:(MKMapItem *)source;
+
+- (MKMapItem *)comp NS_AVAILABLE(10_9, 6_0);
+- (void)setComp:(MKMapItem *)source UNAVAILABLE;
+
+ at property (nonatomic, retain) MKMapItem *tally  UNAVAILABLE NS_AVAILABLE(10_9, 6_0);
+
+- (MKMapItem *)itally  NS_AVAILABLE(10_9, 6_0);
+- (void)setItally:(MKMapItem *)source UNAVAILABLE NS_AVAILABLE(10_9, 6_0);
+
+- (MKMapItem *)normal  UNAVAILABLE;
+- (void)setNormal:(MKMapItem *)source UNAVAILABLE NS_AVAILABLE(10_9, 6_0);
+ at end
+

Modified: cfe/trunk/test/ARCMT/objcmt-property.m.result
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ARCMT/objcmt-property.m.result?rev=193837&r1=193836&r2=193837&view=diff
==============================================================================
--- cfe/trunk/test/ARCMT/objcmt-property.m.result (original)
+++ cfe/trunk/test/ARCMT/objcmt-property.m.result Thu Oct 31 19:26:48 2013
@@ -25,12 +25,12 @@ typedef char BOOL;
 
 @property (nonatomic, retain) NSString *StrongProp;
 
-- (NSString *) UnavailProp  __attribute__((unavailable));
+ at property (nonatomic, retain) NSString *UnavailProp  __attribute__((unavailable));
 - (void) setUnavailProp  : (NSString *)Val;
 
 @property (nonatomic, retain) NSString *UnavailProp1  __attribute__((unavailable));
 
-- (NSString *) UnavailProp2;
+ at property (nonatomic, retain) NSString *UnavailProp2;
 - (void) setUnavailProp2  : (NSString *)Val  __attribute__((unavailable));
 
 @property (nonatomic, copy) NSDictionary *undoAction;
@@ -161,19 +161,19 @@ DEPRECATED
 
 @interface NSURL
 // Do not infer a property.
-- (NSURL *)appStoreReceiptURL NS_AVAILABLE;
+ at property (nonatomic, retain) NSURL *appStoreReceiptURL NS_AVAILABLE;
 - (void) setAppStoreReceiptURL : (NSURL *)object;
 
 @property (nonatomic, retain) NSURL *appStoreReceiptURLX NS_AVAILABLE;
 
 // Do not infer a property.
-- (NSURL *)appStoreReceiptURLY ;
+ at property (nonatomic, retain) NSURL *appStoreReceiptURLY ;
 - (void) setAppStoreReceiptURLY : (NSURL *)object NS_AVAILABLE;
 
 @property (nonatomic, readonly) id OkToInfer NS_AVAILABLE;
 
 // Do not infer a property.
-- (NSURL *)appStoreReceiptURLZ ;
+ at property (nonatomic, retain) NSURL *appStoreReceiptURLZ ;
 - (void) setAppStoreReceiptURLZ : (NSURL *)object NS_AVAILABLE;
 
 // Do not infer a property.





More information about the cfe-commits mailing list