From 07b1bbe648a21b8cdbc073fb6a409422c49921bb Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Wed, 10 Jul 2013 21:30:22 +0000 Subject: [PATCH] ObjC migrator: Improve on hueristics. migrate to 'copy attribute if Object class implements NSCopying otherwise assume implied 'strong'. Remove lifetime qualifier on property as it has moved to property's attribute. Added TODO comment for future work by poking into setter implementation. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@186037 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/DeclObjC.h | 2 ++ lib/AST/DeclObjC.cpp | 11 +++++++++++ lib/Edit/RewriteObjCFoundationAPI.cpp | 25 ++++++++++++++++++++----- test/ARCMT/objcmt-property.m | 10 +++++++++- test/ARCMT/objcmt-property.m.result | 22 +++++++++++++++------- 5 files changed, 57 insertions(+), 13 deletions(-) diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index e4ca61a5c0..1e7a0d7a9a 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -1136,6 +1136,8 @@ public: return lookupInstanceVariable(IVarName, ClassDeclared); } + ObjCProtocolDecl *lookupNestedProtocol(IdentifierInfo *Name); + // Lookup a method. First, we search locally. If a method isn't // found, we search referenced protocols and class categories. ObjCMethodDecl *lookupMethod(Selector Sel, bool isInstance, diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp index 3895a52085..c15f01deba 100644 --- a/lib/AST/DeclObjC.cpp +++ b/lib/AST/DeclObjC.cpp @@ -441,6 +441,17 @@ ObjCInterfaceDecl *ObjCInterfaceDecl::lookupInheritedClass( return NULL; } +ObjCProtocolDecl * +ObjCInterfaceDecl::lookupNestedProtocol(IdentifierInfo *Name) { + for (ObjCInterfaceDecl::all_protocol_iterator P = + all_referenced_protocol_begin(), PE = all_referenced_protocol_end(); + P != PE; ++P) + if ((*P)->lookupProtocolNamed(Name)) + return (*P); + ObjCInterfaceDecl *SuperClass = getSuperClass(); + return SuperClass ? SuperClass->lookupNestedProtocol(Name) : NULL; +} + /// lookupMethod - This method returns an instance/class method by looking in /// the class, its categories, and its super classes (using a linear search). /// When argument category "C" is specified, any implicit method found diff --git a/lib/Edit/RewriteObjCFoundationAPI.cpp b/lib/Edit/RewriteObjCFoundationAPI.cpp index e257a0b6f1..8d24003d94 100644 --- a/lib/Edit/RewriteObjCFoundationAPI.cpp +++ b/lib/Edit/RewriteObjCFoundationAPI.cpp @@ -358,23 +358,38 @@ bool edit::rewriteToObjCLiteralSyntax(const ObjCMessageExpr *Msg, bool edit::rewriteToObjCProperty(const ObjCMethodDecl *Getter, const ObjCMethodDecl *Setter, const NSAPI &NS, Commit &commit) { + ASTContext &Context = NS.getASTContext(); std::string PropertyString = "@property"; const ParmVarDecl *argDecl = *Setter->param_begin(); - QualType ArgType = argDecl->getType(); + QualType ArgType = Context.getCanonicalType(argDecl->getType()); Qualifiers::ObjCLifetime propertyLifetime = ArgType.getObjCLifetime(); if (ArgType->isObjCRetainableType() && propertyLifetime == Qualifiers::OCL_Strong) { - PropertyString += "(copy)"; + if (const ObjCObjectPointerType *ObjPtrTy = + ArgType->getAs()) { + ObjCInterfaceDecl *IDecl = ObjPtrTy->getObjectType()->getInterface(); + if (IDecl && + IDecl->lookupNestedProtocol(&Context.Idents.get("NSCopying"))) + PropertyString += "(copy)"; + } } else if (propertyLifetime == Qualifiers::OCL_Weak) + // TODO. More precise determination of 'weak' attribute requires + // looking into setter's implementation for backing weak ivar. PropertyString += "(weak)"; else PropertyString += "(unsafe_unretained)"; - - QualType PropQT = Getter->getResultType(); + + // strip off any ARC lifetime qualifier. + QualType CanResultTy = Context.getCanonicalType(Getter->getResultType()); + if (CanResultTy.getQualifiers().hasObjCLifetime()) { + Qualifiers Qs = CanResultTy.getQualifiers(); + Qs.removeObjCLifetime(); + CanResultTy = Context.getQualifiedType(CanResultTy.getUnqualifiedType(), Qs); + } PropertyString += " "; - PropertyString += PropQT.getAsString(NS.getASTContext().getPrintingPolicy()); + PropertyString += CanResultTy.getAsString(Context.getPrintingPolicy()); PropertyString += " "; PropertyString += Getter->getNameAsString(); commit.replace(CharSourceRange::getCharRange(Getter->getLocStart(), diff --git a/test/ARCMT/objcmt-property.m b/test/ARCMT/objcmt-property.m index 1f0bcdd735..ca1b504dcb 100644 --- a/test/ARCMT/objcmt-property.m +++ b/test/ARCMT/objcmt-property.m @@ -4,7 +4,13 @@ // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -x objective-c -fobjc-runtime-has-weak -fobjc-arc -fobjc-default-synthesize-properties %s.result @class NSString; -@interface NSObject @end +@protocol NSCopying @end + +@interface NSObject +@end + +@interface NSDictionary : NSObject +@end @interface I : NSObject { int ivarVal; @@ -24,6 +30,8 @@ - (NSString *) UnavailProp2; - (void) setUnavailProp2 : (NSString *)Val __attribute__((unavailable)); +- (NSDictionary*) undoAction; +- (void) setUndoAction: (NSDictionary*)Arg; @end @implementation I diff --git a/test/ARCMT/objcmt-property.m.result b/test/ARCMT/objcmt-property.m.result index 11912d950a..2bcae864a0 100644 --- a/test/ARCMT/objcmt-property.m.result +++ b/test/ARCMT/objcmt-property.m.result @@ -4,15 +4,21 @@ // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -x objective-c -fobjc-runtime-has-weak -fobjc-arc -fobjc-default-synthesize-properties %s.result @class NSString; -@interface NSObject @end +@protocol NSCopying @end + +@interface NSObject +@end + +@interface NSDictionary : NSObject +@end @interface I : NSObject { int ivarVal; } -@property(weak) NSString *__weak WeakProp; +@property(weak) NSString * WeakProp; -@property(copy) NSString * StrongProp; +@property NSString * StrongProp; - (NSString *) UnavailProp __attribute__((unavailable)); @@ -24,6 +30,8 @@ - (NSString *) UnavailProp2; - (void) setUnavailProp2 : (NSString *)Val __attribute__((unavailable)); +@property(copy) NSDictionary * undoAction; + @end @implementation I @@ -42,8 +50,8 @@ -@property(copy) NSArray * names2; -@property(copy) NSArray * names3; -@property(copy) NSArray *__strong names4; -@property(copy) NSArray * names1; +@property NSArray * names2; +@property NSArray * names3; +@property NSArray * names4; +@property NSArray * names1; @end -- 2.40.0