diff options
author | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2012-05-14 22:01:53 +0000 |
---|---|---|
committer | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2012-05-14 22:01:53 +0000 |
commit | 055b395294d190a432e9d87bb665634636a1418a (patch) | |
tree | 774bfb5403aaab78b904e4455a9a05060c656a6a /lib/Edit/RewriteObjCFoundationAPI.cpp | |
parent | 13ec9100ca6bc03b5ce8832e4a0fcb724d47bcb1 (diff) |
[objcmt] When rewriting to array/dictionary literals, add an explicit
cast to 'id' for any argument that requires it.
Part of rdar://11438360.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@156782 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Edit/RewriteObjCFoundationAPI.cpp')
-rw-r--r-- | lib/Edit/RewriteObjCFoundationAPI.cpp | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/lib/Edit/RewriteObjCFoundationAPI.cpp b/lib/Edit/RewriteObjCFoundationAPI.cpp index 24a0db1875..8c3c7a5bf3 100644 --- a/lib/Edit/RewriteObjCFoundationAPI.cpp +++ b/lib/Edit/RewriteObjCFoundationAPI.cpp @@ -229,6 +229,9 @@ bool edit::rewriteToObjCLiteralSyntax(const ObjCMessageExpr *Msg, // rewriteToArrayLiteral. //===----------------------------------------------------------------------===// +/// \brief Adds an explicit cast to 'id' if the type is not objc object. +static void objectifyExpr(const Expr *E, Commit &commit); + static bool rewriteToArrayLiteral(const ObjCMessageExpr *Msg, const NSAPI &NS, Commit &commit) { Selector Sel = Msg->getSelector(); @@ -244,6 +247,7 @@ static bool rewriteToArrayLiteral(const ObjCMessageExpr *Msg, if (Sel == NS.getNSArraySelector(NSAPI::NSArr_arrayWithObject)) { if (Msg->getNumArgs() != 1) return false; + objectifyExpr(Msg->getArg(0), commit); SourceRange ArgRange = Msg->getArg(0)->getSourceRange(); commit.replaceWithInner(MsgRange, ArgRange); commit.insertWrap("@[", ArgRange, "]"); @@ -257,6 +261,9 @@ static bool rewriteToArrayLiteral(const ObjCMessageExpr *Msg, if (!NS.getASTContext().isSentinelNullExpr(SentinelExpr)) return false; + for (unsigned i = 0, e = Msg->getNumArgs() - 1; i != e; ++i) + objectifyExpr(Msg->getArg(i), commit); + if (Msg->getNumArgs() == 1) { commit.replace(MsgRange, "@[]"); return true; @@ -291,6 +298,10 @@ static bool rewriteToDictionaryLiteral(const ObjCMessageExpr *Msg, NSAPI::NSDict_dictionaryWithObjectForKey)) { if (Msg->getNumArgs() != 2) return false; + + objectifyExpr(Msg->getArg(0), commit); + objectifyExpr(Msg->getArg(1), commit); + SourceRange ValRange = Msg->getArg(0)->getSourceRange(); SourceRange KeyRange = Msg->getArg(1)->getSourceRange(); // Insert key before the value. @@ -319,6 +330,9 @@ static bool rewriteToDictionaryLiteral(const ObjCMessageExpr *Msg, } for (unsigned i = 0; i < SentinelIdx; i += 2) { + objectifyExpr(Msg->getArg(i), commit); + objectifyExpr(Msg->getArg(i+1), commit); + SourceRange ValRange = Msg->getArg(i)->getSourceRange(); SourceRange KeyRange = Msg->getArg(i+1)->getSourceRange(); // Insert value after key. @@ -585,3 +599,52 @@ static bool rewriteToNumberLiteral(const ObjCMessageExpr *Msg, } return true; } + +static bool castOperatorNeedsParens(const Expr *FullExpr) { + const Expr* Expr = FullExpr->IgnoreImpCasts(); + if (isa<ArraySubscriptExpr>(Expr) || + isa<CallExpr>(Expr) || + isa<DeclRefExpr>(Expr) || + isa<CastExpr>(Expr) || + isa<CXXNewExpr>(Expr) || + isa<CXXConstructExpr>(Expr) || + isa<CXXDeleteExpr>(Expr) || + isa<CXXNoexceptExpr>(Expr) || + isa<CXXPseudoDestructorExpr>(Expr) || + isa<CXXScalarValueInitExpr>(Expr) || + isa<CXXThisExpr>(Expr) || + isa<CXXTypeidExpr>(Expr) || + isa<CXXUnresolvedConstructExpr>(Expr) || + isa<ObjCMessageExpr>(Expr) || + isa<ObjCPropertyRefExpr>(Expr) || + isa<ObjCProtocolExpr>(Expr) || + isa<MemberExpr>(Expr) || + isa<ParenExpr>(FullExpr) || + isa<ParenListExpr>(Expr) || + isa<SizeOfPackExpr>(Expr) || + isa<UnaryOperator>(Expr)) + return false; + + return true; +} + +static void objectifyExpr(const Expr *E, Commit &commit) { + if (!E) return; + + QualType T = E->getType(); + if (T->isObjCObjectPointerType()) { + if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) { + if (ICE->getCastKind() != CK_CPointerToObjCPointerCast) + return; + } else { + return; + } + } else if (!T->isPointerType()) { + return; + } + + SourceRange Range = E->getSourceRange(); + if (castOperatorNeedsParens(E)) + commit.insertWrap("(", Range, ")"); + commit.insertBefore(Range.getBegin(), "(id)"); +} |