forked from OSchip/llvm-project
Objective-C SDK modernization. convert message expression
to Objective-C dot-syntax. rdar://18498572 llvm-svn: 219424
This commit is contained in:
parent
538a88aac7
commit
ed6de56c77
|
@ -211,6 +211,104 @@ bool ObjCMigrateAction::BeginInvocation(CompilerInstance &CI) {
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
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> {
|
class ObjCMigrator : public RecursiveASTVisitor<ObjCMigrator> {
|
||||||
ObjCMigrateASTConsumer &Consumer;
|
ObjCMigrateASTConsumer &Consumer;
|
||||||
ParentMap &PMap;
|
ParentMap &PMap;
|
||||||
|
@ -235,6 +333,13 @@ public:
|
||||||
Consumer.Editor->commit(commit);
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
@ -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
|
Loading…
Reference in New Issue