summaryrefslogtreecommitdiffstats
path: root/clang/lib/ARCMigrate/ObjCMT.cpp
diff options
context:
space:
mode:
authorFariborz Jahanian <fjahanian@apple.com>2014-10-09 18:30:56 +0000
committerFariborz Jahanian <fjahanian@apple.com>2014-10-09 18:30:56 +0000
commited6de56c77e7e658066d6ea19f2340c3e3f102ff (patch)
tree2dad731fd3823dfc51313d947263950c793d01d9 /clang/lib/ARCMigrate/ObjCMT.cpp
parent538a88aac7b2d93a88a4b9b5a838360022cbbc37 (diff)
downloadbcm5719-llvm-ed6de56c77e7e658066d6ea19f2340c3e3f102ff.tar.gz
bcm5719-llvm-ed6de56c77e7e658066d6ea19f2340c3e3f102ff.zip
Objective-C SDK modernization. convert message expression
to Objective-C dot-syntax. rdar://18498572 llvm-svn: 219424
Diffstat (limited to 'clang/lib/ARCMigrate/ObjCMT.cpp')
-rw-r--r--clang/lib/ARCMigrate/ObjCMT.cpp105
1 files changed, 105 insertions, 0 deletions
diff --git a/clang/lib/ARCMigrate/ObjCMT.cpp b/clang/lib/ARCMigrate/ObjCMT.cpp
index c21e7324ebb..7eebdb78d89 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<ArraySubscriptExpr>(Expr) ||
+ isa<CallExpr>(Expr) ||
+ isa<DeclRefExpr>(Expr) ||
+ isa<CXXNamedCastExpr>(Expr) ||
+ isa<CXXConstructExpr>(Expr) ||
+ isa<CXXThisExpr>(Expr) ||
+ isa<CXXTypeidExpr>(Expr) ||
+ isa<CXXUnresolvedConstructExpr>(Expr) ||
+ isa<ObjCMessageExpr>(Expr) ||
+ isa<ObjCPropertyRefExpr>(Expr) ||
+ isa<ObjCProtocolExpr>(Expr) ||
+ isa<MemberExpr>(Expr) ||
+ isa<ObjCIvarRefExpr>(Expr) ||
+ isa<ParenExpr>(FullExpr) ||
+ isa<ParenListExpr>(Expr) ||
+ isa<SizeOfPackExpr>(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<ObjCMigrator> {
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;
}
OpenPOWER on IntegriCloud