From c1dfed6572b58515747d59fce045cfdacf8a6b1c Mon Sep 17 00:00:00 2001 From: Argyrios Kyrtzidis Date: Mon, 14 May 2012 22:01:53 +0000 Subject: [objcmt] When rewriting to array/dictionary literals, add an explicit cast to 'id' for any argument that requires it. Part of rdar://11438360. llvm-svn: 156782 --- clang/lib/Edit/RewriteObjCFoundationAPI.cpp | 63 +++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) (limited to 'clang/lib/Edit/RewriteObjCFoundationAPI.cpp') diff --git a/clang/lib/Edit/RewriteObjCFoundationAPI.cpp b/clang/lib/Edit/RewriteObjCFoundationAPI.cpp index 24a0db18755..8c3c7a5bf3a 100644 --- a/clang/lib/Edit/RewriteObjCFoundationAPI.cpp +++ b/clang/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(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(Expr) || + isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(FullExpr) || + isa(Expr) || + isa(Expr) || + isa(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(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)"); +} -- cgit v1.2.3