From ed6de56c77e7e658066d6ea19f2340c3e3f102ff Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Thu, 9 Oct 2014 18:30:56 +0000 Subject: [PATCH] Objective-C SDK modernization. convert message expression to Objective-C dot-syntax. rdar://18498572 llvm-svn: 219424 --- clang/lib/ARCMigrate/ObjCMT.cpp | 105 ++++++++++++++++++ clang/test/ARCMT/objcmt-property-dot-syntax.m | 39 +++++++ .../ARCMT/objcmt-property-dot-syntax.m.result | 39 +++++++ 3 files changed, 183 insertions(+) create mode 100644 clang/test/ARCMT/objcmt-property-dot-syntax.m create mode 100644 clang/test/ARCMT/objcmt-property-dot-syntax.m.result diff --git a/clang/lib/ARCMigrate/ObjCMT.cpp b/clang/lib/ARCMigrate/ObjCMT.cpp index c21e7324ebbf..7eebdb78d898 100644 --- a/clang/lib/ARCMigrate/ObjCMT.cpp +++ b/clang/lib/ARCMigrate/ObjCMT.cpp @@ -211,6 +211,104 @@ bool ObjCMigrateAction::BeginInvocation(CompilerInstance &CI) { } namespace { + // FIXME. This duplicates one in RewriteObjCFoundationAPI.cpp + bool subscriptOperatorNeedsParens(const Expr *FullExpr) { + const Expr* Expr = FullExpr->IgnoreImpCasts(); + if (isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(FullExpr) || + isa(Expr) || + isa(Expr)) + return false; + + return true; + } + + /// \brief - Rewrite message expression for Objective-C setter and getters into + /// property-dot syntax. + bool rewriteToPropertyDotSyntax(const ObjCMessageExpr *Msg, + Preprocessor &PP, + const NSAPI &NS, edit::Commit &commit, + const ParentMap *PMap) { + if (!Msg || Msg->isImplicit() || + Msg->getReceiverKind() != ObjCMessageExpr::Instance) + return false; + const ObjCMethodDecl *Method = Msg->getMethodDecl(); + if (!Method) + return false; + if (!Method->isPropertyAccessor()) + return false; + + const ObjCInterfaceDecl *IFace = + NS.getASTContext().getObjContainingInterface(Method); + if (!IFace) + return false; + + const ObjCPropertyDecl *Prop = Method->findPropertyDecl(); + if (!Prop) + return false; + + SourceRange MsgRange = Msg->getSourceRange(); + const Expr *receiver = Msg->getInstanceReceiver(); + bool NeedsParen = subscriptOperatorNeedsParens(receiver); + bool IsGetter = (Msg->getNumArgs() == 0); + if (IsGetter) { + // Find space location range between receiver expression and getter method. + SourceLocation BegLoc = receiver->getLocEnd(); + BegLoc = PP.getLocForEndOfToken(BegLoc); + SourceLocation EndLoc = Msg->getSelectorLoc(0); + SourceRange SpaceRange(BegLoc, EndLoc); + std::string PropertyDotString; + // rewrite getter method expression into: receiver.property or + // (receiver).property + if (NeedsParen) { + commit.insertBefore(receiver->getLocStart(), "("); + PropertyDotString = ")."; + } + else + PropertyDotString = "."; + PropertyDotString += Prop->getName(); + commit.replace(SpaceRange, PropertyDotString); + + // remove '[' ']' + commit.replace(SourceRange(MsgRange.getBegin(), MsgRange.getBegin()), ""); + commit.replace(SourceRange(MsgRange.getEnd(), MsgRange.getEnd()), ""); + } else { + SourceRange ReceiverRange = receiver->getSourceRange(); + if (NeedsParen) + commit.insertWrap("(", ReceiverRange, ")"); + std::string PropertyDotString = "."; + PropertyDotString += Prop->getName(); + PropertyDotString += " ="; + const Expr*const* Args = Msg->getArgs(); + const Expr *RHS = Args[0]; + if (!RHS) + return false; + SourceLocation BegLoc = ReceiverRange.getEnd(); + BegLoc = PP.getLocForEndOfToken(BegLoc); + SourceLocation EndLoc = RHS->getLocStart(); + EndLoc = EndLoc.getLocWithOffset(-1); + SourceRange Range(BegLoc, EndLoc); + commit.replace(Range, PropertyDotString); + // remove '[' ']' + commit.replace(SourceRange(MsgRange.getBegin(), MsgRange.getBegin()), ""); + commit.replace(SourceRange(MsgRange.getEnd(), MsgRange.getEnd()), ""); + } + return true; + } + + class ObjCMigrator : public RecursiveASTVisitor { ObjCMigrateASTConsumer &Consumer; ParentMap &PMap; @@ -235,6 +333,13 @@ public: Consumer.Editor->commit(commit); } + if (Consumer.ASTMigrateActions & FrontendOptions::ObjCMT_Property) { + edit::Commit commit(*Consumer.Editor); + rewriteToPropertyDotSyntax(E, Consumer.PP, *Consumer.NSAPIObj, + commit, &PMap); + Consumer.Editor->commit(commit); + } + return true; } diff --git a/clang/test/ARCMT/objcmt-property-dot-syntax.m b/clang/test/ARCMT/objcmt-property-dot-syntax.m new file mode 100644 index 000000000000..ce6dc162ea15 --- /dev/null +++ b/clang/test/ARCMT/objcmt-property-dot-syntax.m @@ -0,0 +1,39 @@ +// RUN: rm -rf %t +// RUN: %clang_cc1 -objcmt-migrate-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 -fblocks -triple x86_64-apple-darwin10 -fsyntax-only -x objective-c -fobjc-runtime-has-weak -fobjc-arc %s.result + +// rdar://18498572 +@interface NSObject @end + +@interface P : NSObject +{ + P* obj; + int i1, i2, i3; +} +@property int count; +@property (copy) P* PropertyReturnsPObj; +- (P*) MethodReturnsPObj; +@end + +P* fun(); + +@implementation P +- (int) Meth : (P*)array { + [obj setCount : 100]; + + [(P*)0 setCount : [array count]]; + + [[obj PropertyReturnsPObj] setCount : [array count]]; + + [obj setCount : (i1+i2*i3 - 100)]; + + return [obj count] - + [(P*)0 count] + [array count] + + [fun() count] - + [[obj PropertyReturnsPObj] count] + + [self->obj count]; +} + +- (P*) MethodReturnsPObj { return 0; } +@end diff --git a/clang/test/ARCMT/objcmt-property-dot-syntax.m.result b/clang/test/ARCMT/objcmt-property-dot-syntax.m.result new file mode 100644 index 000000000000..0532c6f67cf3 --- /dev/null +++ b/clang/test/ARCMT/objcmt-property-dot-syntax.m.result @@ -0,0 +1,39 @@ +// RUN: rm -rf %t +// RUN: %clang_cc1 -objcmt-migrate-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 -fblocks -triple x86_64-apple-darwin10 -fsyntax-only -x objective-c -fobjc-runtime-has-weak -fobjc-arc %s.result + +// rdar://18498572 +@interface NSObject @end + +@interface P : NSObject +{ + P* obj; + int i1, i2, i3; +} +@property int count; +@property (copy) P* PropertyReturnsPObj; +@property (nonatomic, readonly, strong) P *MethodReturnsPObj; +@end + +P* fun(); + +@implementation P +- (int) Meth : (P*)array { + obj.count = 100; + + ((P*)0).count = array.count; + + obj.PropertyReturnsPObj.count = array.count; + + obj.count = (i1+i2*i3 - 100); + + return obj.count - + ((P*)0).count + array.count + + fun().count - + obj.PropertyReturnsPObj.count + + self->obj.count; +} + +- (P*) MethodReturnsPObj { return 0; } +@end