From 215f96c084a2456ba9cc8717cb5758b5f04eef15 Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Fri, 6 Sep 2013 23:45:20 +0000 Subject: [PATCH] ObjectiveC migrator: When inferring a property, preserve getter's attribute. Also, do not attach an inferred NS_RETURNS_INNER_POINTER to the inferred property (it is illegal). llvm-svn: 190223 --- clang/lib/ARCMigrate/ObjCMT.cpp | 135 ++++++++++++---------- clang/test/ARCMT/objcmt-property.m | 7 ++ clang/test/ARCMT/objcmt-property.m.result | 7 ++ 3 files changed, 89 insertions(+), 60 deletions(-) diff --git a/clang/lib/ARCMigrate/ObjCMT.cpp b/clang/lib/ARCMigrate/ObjCMT.cpp index 8490d00e1262..702149e018ee 100644 --- a/clang/lib/ARCMigrate/ObjCMT.cpp +++ b/clang/lib/ARCMigrate/ObjCMT.cpp @@ -51,6 +51,7 @@ class ObjCMigrateASTConsumer : public ASTConsumer { void migrateMethods(ASTContext &Ctx, ObjCContainerDecl *CDecl); void migrateMethodInstanceType(ASTContext &Ctx, ObjCContainerDecl *CDecl, ObjCMethodDecl *OM); + bool migrateProperty(ASTContext &Ctx, ObjCInterfaceDecl *D, ObjCMethodDecl *OM); void migrateNsReturnsInnerPointer(ASTContext &Ctx, ObjCMethodDecl *OM); void migrateFactoryMethod(ASTContext &Ctx, ObjCContainerDecl *CDecl, ObjCMethodDecl *OM, @@ -316,8 +317,13 @@ static bool rewriteToObjCProperty(const ObjCMethodDecl *Getter, } else PropertyString += PropertyNameString; + SourceLocation StartGetterSelectorLoc = Getter->getSelectorStartLoc(); + Selector GetterSelector = Getter->getSelector(); + + SourceLocation EndGetterSelectorLoc = + StartGetterSelectorLoc.getLocWithOffset(GetterSelector.getNameForSlot(0).size()); commit.replace(CharSourceRange::getCharRange(Getter->getLocStart(), - Getter->getDeclaratorEndLoc()), + EndGetterSelectorLoc), PropertyString); if (Setter) { SourceLocation EndLoc = Setter->getDeclaratorEndLoc(); @@ -333,64 +339,8 @@ void ObjCMigrateASTConsumer::migrateObjCInterfaceDecl(ASTContext &Ctx, for (ObjCContainerDecl::method_iterator M = D->meth_begin(), MEnd = D->meth_end(); M != MEnd; ++M) { ObjCMethodDecl *Method = (*M); - if (Method->isPropertyAccessor() || !Method->isInstanceMethod() || - Method->param_size() != 0) - continue; - // Is this method candidate to be a getter? - QualType GRT = Method->getResultType(); - if (GRT->isVoidType()) - continue; - // FIXME. Don't know what todo with attributes, skip for now. - if (Method->hasAttrs()) - continue; - - Selector GetterSelector = Method->getSelector(); - IdentifierInfo *getterName = GetterSelector.getIdentifierInfoForSlot(0); - Selector SetterSelector = - SelectorTable::constructSetterSelector(PP.getIdentifierTable(), - PP.getSelectorTable(), - getterName); - ObjCMethodDecl *SetterMethod = D->lookupMethod(SetterSelector, true); - bool GetterHasIsPrefix = false; - if (!SetterMethod) { - // try a different naming convention for getter: isXxxxx - StringRef getterNameString = getterName->getName(); - if (getterNameString.startswith("is") && !GRT->isObjCRetainableType()) { - GetterHasIsPrefix = true; - const char *CGetterName = getterNameString.data() + 2; - if (CGetterName[0] && isUppercase(CGetterName[0])) { - getterName = &Ctx.Idents.get(CGetterName); - SetterSelector = - SelectorTable::constructSetterSelector(PP.getIdentifierTable(), - PP.getSelectorTable(), - getterName); - SetterMethod = D->lookupMethod(SetterSelector, true); - } - } - } - if (SetterMethod) { - // Is this a valid setter, matching the target getter? - QualType SRT = SetterMethod->getResultType(); - if (!SRT->isVoidType()) - continue; - const ParmVarDecl *argDecl = *SetterMethod->param_begin(); - QualType ArgType = argDecl->getType(); - if (!Ctx.hasSameUnqualifiedType(ArgType, GRT) || - SetterMethod->hasAttrs()) - continue; - edit::Commit commit(*Editor); - rewriteToObjCProperty(Method, SetterMethod, *NSAPIObj, commit, - GetterHasIsPrefix); - Editor->commit(commit); - } - else if (MigrateReadonlyProperty) { - // Try a non-void method with no argument (and no setter or property of same name - // as a 'readonly' property. - edit::Commit commit(*Editor); - rewriteToObjCProperty(Method, 0 /*SetterMethod*/, *NSAPIObj, commit, - false /*GetterHasIsPrefix*/); - Editor->commit(commit); - } + if (!migrateProperty(Ctx, D, Method)) + migrateNsReturnsInnerPointer(Ctx, Method); } } @@ -747,6 +697,72 @@ static bool TypeIsInnerPointer(QualType T) { return true; } +bool ObjCMigrateASTConsumer::migrateProperty(ASTContext &Ctx, + ObjCInterfaceDecl *D, + ObjCMethodDecl *Method) { + if (Method->isPropertyAccessor() || !Method->isInstanceMethod() || + Method->param_size() != 0) + return false; + // Is this method candidate to be a getter? + QualType GRT = Method->getResultType(); + if (GRT->isVoidType()) + return false; + // FIXME. Don't know what todo with attributes, skip for now. + if (Method->hasAttrs()) + return false; + + Selector GetterSelector = Method->getSelector(); + IdentifierInfo *getterName = GetterSelector.getIdentifierInfoForSlot(0); + Selector SetterSelector = + SelectorTable::constructSetterSelector(PP.getIdentifierTable(), + PP.getSelectorTable(), + getterName); + ObjCMethodDecl *SetterMethod = D->lookupMethod(SetterSelector, true); + bool GetterHasIsPrefix = false; + if (!SetterMethod) { + // try a different naming convention for getter: isXxxxx + StringRef getterNameString = getterName->getName(); + if (getterNameString.startswith("is") && !GRT->isObjCRetainableType()) { + GetterHasIsPrefix = true; + const char *CGetterName = getterNameString.data() + 2; + if (CGetterName[0] && isUppercase(CGetterName[0])) { + getterName = &Ctx.Idents.get(CGetterName); + SetterSelector = + SelectorTable::constructSetterSelector(PP.getIdentifierTable(), + PP.getSelectorTable(), + getterName); + SetterMethod = D->lookupMethod(SetterSelector, true); + } + } + } + if (SetterMethod) { + // Is this a valid setter, matching the target getter? + QualType SRT = SetterMethod->getResultType(); + if (!SRT->isVoidType()) + return false; + const ParmVarDecl *argDecl = *SetterMethod->param_begin(); + QualType ArgType = argDecl->getType(); + if (!Ctx.hasSameUnqualifiedType(ArgType, GRT) || + SetterMethod->hasAttrs()) + return false; + edit::Commit commit(*Editor); + rewriteToObjCProperty(Method, SetterMethod, *NSAPIObj, commit, + GetterHasIsPrefix); + Editor->commit(commit); + return true; + } + else if (MigrateReadonlyProperty) { + // Try a non-void method with no argument (and no setter or property of same name + // as a 'readonly' property. + edit::Commit commit(*Editor); + rewriteToObjCProperty(Method, 0 /*SetterMethod*/, *NSAPIObj, commit, + false /*GetterHasIsPrefix*/); + Editor->commit(commit); + return true; + } + return false; +} + void ObjCMigrateASTConsumer::migrateNsReturnsInnerPointer(ASTContext &Ctx, ObjCMethodDecl *OM) { if (OM->hasAttr()) @@ -770,7 +786,6 @@ void ObjCMigrateASTConsumer::migrateMethods(ASTContext &Ctx, M != MEnd; ++M) { ObjCMethodDecl *Method = (*M); migrateMethodInstanceType(Ctx, CDecl, Method); - migrateNsReturnsInnerPointer(Ctx, Method); } } diff --git a/clang/test/ARCMT/objcmt-property.m b/clang/test/ARCMT/objcmt-property.m index 6d66da780395..2f655b9a2a3b 100644 --- a/clang/test/ARCMT/objcmt-property.m +++ b/clang/test/ARCMT/objcmt-property.m @@ -3,6 +3,10 @@ // 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 -fobjc-default-synthesize-properties %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 + typedef char BOOL; @class NSString; @protocol NSCopying @end @@ -92,4 +96,7 @@ typedef char BOOL; - (int) Length; - (id) object; + (double) D; +- (void *)JSObject WEBKIT_OBJC_METHOD_ANNOTATION(AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER); @end + + diff --git a/clang/test/ARCMT/objcmt-property.m.result b/clang/test/ARCMT/objcmt-property.m.result index 2a633367c53a..751b85e3db62 100644 --- a/clang/test/ARCMT/objcmt-property.m.result +++ b/clang/test/ARCMT/objcmt-property.m.result @@ -3,6 +3,10 @@ // 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 -fobjc-default-synthesize-properties %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 + typedef char BOOL; @class NSString; @protocol NSCopying @end @@ -92,4 +96,7 @@ typedef char BOOL; @property(nonatomic, readonly) int Length; @property(nonatomic, readonly) id object; + (double) D; +@property(nonatomic, readonly) void * JSObject WEBKIT_OBJC_METHOD_ANNOTATION(AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER); @end + +