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