130660a898545416f0fea2d717f16f75640001e38Ted Kremenek//===--- RewriteObjCFoundationAPI.cpp - Foundation API Rewriter -----------===//
230660a898545416f0fea2d717f16f75640001e38Ted Kremenek//
330660a898545416f0fea2d717f16f75640001e38Ted Kremenek//                     The LLVM Compiler Infrastructure
430660a898545416f0fea2d717f16f75640001e38Ted Kremenek//
530660a898545416f0fea2d717f16f75640001e38Ted Kremenek// This file is distributed under the University of Illinois Open Source
630660a898545416f0fea2d717f16f75640001e38Ted Kremenek// License. See LICENSE.TXT for details.
730660a898545416f0fea2d717f16f75640001e38Ted Kremenek//
830660a898545416f0fea2d717f16f75640001e38Ted Kremenek//===----------------------------------------------------------------------===//
930660a898545416f0fea2d717f16f75640001e38Ted Kremenek//
1030660a898545416f0fea2d717f16f75640001e38Ted Kremenek// Rewrites legacy method calls to modern syntax.
1130660a898545416f0fea2d717f16f75640001e38Ted Kremenek//
1230660a898545416f0fea2d717f16f75640001e38Ted Kremenek//===----------------------------------------------------------------------===//
1330660a898545416f0fea2d717f16f75640001e38Ted Kremenek
1430660a898545416f0fea2d717f16f75640001e38Ted Kremenek#include "clang/Edit/Rewriters.h"
15478851c3ed6bd784e7377dffd8e57b200c1b9ba9Benjamin Kramer#include "clang/AST/ASTContext.h"
1630660a898545416f0fea2d717f16f75640001e38Ted Kremenek#include "clang/AST/ExprCXX.h"
1755fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/AST/ExprObjC.h"
1830660a898545416f0fea2d717f16f75640001e38Ted Kremenek#include "clang/AST/NSAPI.h"
19a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis#include "clang/AST/ParentMap.h"
2055fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Edit/Commit.h"
2155fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Lex/Lexer.h"
2230660a898545416f0fea2d717f16f75640001e38Ted Kremenek
2330660a898545416f0fea2d717f16f75640001e38Ted Kremenekusing namespace clang;
2430660a898545416f0fea2d717f16f75640001e38Ted Kremenekusing namespace edit;
2530660a898545416f0fea2d717f16f75640001e38Ted Kremenek
2630660a898545416f0fea2d717f16f75640001e38Ted Kremenekstatic bool checkForLiteralCreation(const ObjCMessageExpr *Msg,
276b4db9b329c6964955153292e21de0a342354437Argyrios Kyrtzidis                                    IdentifierInfo *&ClassId,
286b4db9b329c6964955153292e21de0a342354437Argyrios Kyrtzidis                                    const LangOptions &LangOpts) {
2930660a898545416f0fea2d717f16f75640001e38Ted Kremenek  if (!Msg || Msg->isImplicit() || !Msg->getMethodDecl())
3030660a898545416f0fea2d717f16f75640001e38Ted Kremenek    return false;
3130660a898545416f0fea2d717f16f75640001e38Ted Kremenek
3230660a898545416f0fea2d717f16f75640001e38Ted Kremenek  const ObjCInterfaceDecl *Receiver = Msg->getReceiverInterface();
3330660a898545416f0fea2d717f16f75640001e38Ted Kremenek  if (!Receiver)
3430660a898545416f0fea2d717f16f75640001e38Ted Kremenek    return false;
3530660a898545416f0fea2d717f16f75640001e38Ted Kremenek  ClassId = Receiver->getIdentifier();
3630660a898545416f0fea2d717f16f75640001e38Ted Kremenek
3730660a898545416f0fea2d717f16f75640001e38Ted Kremenek  if (Msg->getReceiverKind() == ObjCMessageExpr::Class)
3830660a898545416f0fea2d717f16f75640001e38Ted Kremenek    return true;
3930660a898545416f0fea2d717f16f75640001e38Ted Kremenek
406b4db9b329c6964955153292e21de0a342354437Argyrios Kyrtzidis  // When in ARC mode we also convert "[[.. alloc] init]" messages to literals,
416b4db9b329c6964955153292e21de0a342354437Argyrios Kyrtzidis  // since the change from +1 to +0 will be handled fine by ARC.
426b4db9b329c6964955153292e21de0a342354437Argyrios Kyrtzidis  if (LangOpts.ObjCAutoRefCount) {
436b4db9b329c6964955153292e21de0a342354437Argyrios Kyrtzidis    if (Msg->getReceiverKind() == ObjCMessageExpr::Instance) {
446b4db9b329c6964955153292e21de0a342354437Argyrios Kyrtzidis      if (const ObjCMessageExpr *Rec = dyn_cast<ObjCMessageExpr>(
456b4db9b329c6964955153292e21de0a342354437Argyrios Kyrtzidis                           Msg->getInstanceReceiver()->IgnoreParenImpCasts())) {
466b4db9b329c6964955153292e21de0a342354437Argyrios Kyrtzidis        if (Rec->getMethodFamily() == OMF_alloc)
476b4db9b329c6964955153292e21de0a342354437Argyrios Kyrtzidis          return true;
486b4db9b329c6964955153292e21de0a342354437Argyrios Kyrtzidis      }
496b4db9b329c6964955153292e21de0a342354437Argyrios Kyrtzidis    }
506b4db9b329c6964955153292e21de0a342354437Argyrios Kyrtzidis  }
516b4db9b329c6964955153292e21de0a342354437Argyrios Kyrtzidis
5230660a898545416f0fea2d717f16f75640001e38Ted Kremenek  return false;
5330660a898545416f0fea2d717f16f75640001e38Ted Kremenek}
5430660a898545416f0fea2d717f16f75640001e38Ted Kremenek
5530660a898545416f0fea2d717f16f75640001e38Ted Kremenek//===----------------------------------------------------------------------===//
5630660a898545416f0fea2d717f16f75640001e38Ted Kremenek// rewriteObjCRedundantCallWithLiteral.
5730660a898545416f0fea2d717f16f75640001e38Ted Kremenek//===----------------------------------------------------------------------===//
5830660a898545416f0fea2d717f16f75640001e38Ted Kremenek
5930660a898545416f0fea2d717f16f75640001e38Ted Kremenekbool edit::rewriteObjCRedundantCallWithLiteral(const ObjCMessageExpr *Msg,
6030660a898545416f0fea2d717f16f75640001e38Ted Kremenek                                              const NSAPI &NS, Commit &commit) {
616bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  IdentifierInfo *II = nullptr;
626b4db9b329c6964955153292e21de0a342354437Argyrios Kyrtzidis  if (!checkForLiteralCreation(Msg, II, NS.getASTContext().getLangOpts()))
6330660a898545416f0fea2d717f16f75640001e38Ted Kremenek    return false;
6430660a898545416f0fea2d717f16f75640001e38Ted Kremenek  if (Msg->getNumArgs() != 1)
6530660a898545416f0fea2d717f16f75640001e38Ted Kremenek    return false;
6630660a898545416f0fea2d717f16f75640001e38Ted Kremenek
6730660a898545416f0fea2d717f16f75640001e38Ted Kremenek  const Expr *Arg = Msg->getArg(0)->IgnoreParenImpCasts();
6830660a898545416f0fea2d717f16f75640001e38Ted Kremenek  Selector Sel = Msg->getSelector();
6930660a898545416f0fea2d717f16f75640001e38Ted Kremenek
7030660a898545416f0fea2d717f16f75640001e38Ted Kremenek  if ((isa<ObjCStringLiteral>(Arg) &&
7130660a898545416f0fea2d717f16f75640001e38Ted Kremenek       NS.getNSClassId(NSAPI::ClassId_NSString) == II &&
726b4db9b329c6964955153292e21de0a342354437Argyrios Kyrtzidis       (NS.getNSStringSelector(NSAPI::NSStr_stringWithString) == Sel ||
736b4db9b329c6964955153292e21de0a342354437Argyrios Kyrtzidis        NS.getNSStringSelector(NSAPI::NSStr_initWithString) == Sel))   ||
7430660a898545416f0fea2d717f16f75640001e38Ted Kremenek
7530660a898545416f0fea2d717f16f75640001e38Ted Kremenek      (isa<ObjCArrayLiteral>(Arg) &&
7630660a898545416f0fea2d717f16f75640001e38Ted Kremenek       NS.getNSClassId(NSAPI::ClassId_NSArray) == II &&
776b4db9b329c6964955153292e21de0a342354437Argyrios Kyrtzidis       (NS.getNSArraySelector(NSAPI::NSArr_arrayWithArray) == Sel ||
786b4db9b329c6964955153292e21de0a342354437Argyrios Kyrtzidis        NS.getNSArraySelector(NSAPI::NSArr_initWithArray) == Sel))     ||
7930660a898545416f0fea2d717f16f75640001e38Ted Kremenek
8030660a898545416f0fea2d717f16f75640001e38Ted Kremenek      (isa<ObjCDictionaryLiteral>(Arg) &&
8130660a898545416f0fea2d717f16f75640001e38Ted Kremenek       NS.getNSClassId(NSAPI::ClassId_NSDictionary) == II &&
826b4db9b329c6964955153292e21de0a342354437Argyrios Kyrtzidis       (NS.getNSDictionarySelector(
836b4db9b329c6964955153292e21de0a342354437Argyrios Kyrtzidis                              NSAPI::NSDict_dictionaryWithDictionary) == Sel ||
846b4db9b329c6964955153292e21de0a342354437Argyrios Kyrtzidis        NS.getNSDictionarySelector(NSAPI::NSDict_initWithDictionary) == Sel))) {
8530660a898545416f0fea2d717f16f75640001e38Ted Kremenek
8630660a898545416f0fea2d717f16f75640001e38Ted Kremenek    commit.replaceWithInner(Msg->getSourceRange(),
8730660a898545416f0fea2d717f16f75640001e38Ted Kremenek                           Msg->getArg(0)->getSourceRange());
8830660a898545416f0fea2d717f16f75640001e38Ted Kremenek    return true;
8930660a898545416f0fea2d717f16f75640001e38Ted Kremenek  }
9030660a898545416f0fea2d717f16f75640001e38Ted Kremenek
9130660a898545416f0fea2d717f16f75640001e38Ted Kremenek  return false;
9230660a898545416f0fea2d717f16f75640001e38Ted Kremenek}
9330660a898545416f0fea2d717f16f75640001e38Ted Kremenek
9430660a898545416f0fea2d717f16f75640001e38Ted Kremenek//===----------------------------------------------------------------------===//
9530660a898545416f0fea2d717f16f75640001e38Ted Kremenek// rewriteToObjCSubscriptSyntax.
9630660a898545416f0fea2d717f16f75640001e38Ted Kremenek//===----------------------------------------------------------------------===//
9730660a898545416f0fea2d717f16f75640001e38Ted Kremenek
981838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis/// \brief Check for classes that accept 'objectForKey:' (or the other selectors
991838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis/// that the migrator handles) but return their instances as 'id', resulting
1001838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis/// in the compiler resolving 'objectForKey:' as the method from NSDictionary.
1011838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis///
1021838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis/// When checking if we can convert to subscripting syntax, check whether
1031838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis/// the receiver is a result of a class method from a hardcoded list of
1041838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis/// such classes. In such a case return the specific class as the interface
1051838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis/// of the receiver.
1061838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis///
1071838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis/// FIXME: Remove this when these classes start using 'instancetype'.
1081838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidisstatic const ObjCInterfaceDecl *
1091838703fea568b394407b83d1055b4c7f52fb105Argyrios KyrtzidismaybeAdjustInterfaceForSubscriptingCheck(const ObjCInterfaceDecl *IFace,
1101838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis                                         const Expr *Receiver,
1111838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis                                         ASTContext &Ctx) {
1121838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis  assert(IFace && Receiver);
1131838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis
1141838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis  // If the receiver has type 'id'...
1151838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis  if (!Ctx.isObjCIdType(Receiver->getType().getUnqualifiedType()))
1161838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis    return IFace;
1171838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis
1181838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis  const ObjCMessageExpr *
1191838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis    InnerMsg = dyn_cast<ObjCMessageExpr>(Receiver->IgnoreParenCasts());
1201838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis  if (!InnerMsg)
1211838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis    return IFace;
1221838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis
1231838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis  QualType ClassRec;
1241838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis  switch (InnerMsg->getReceiverKind()) {
1251838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis  case ObjCMessageExpr::Instance:
1261838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis  case ObjCMessageExpr::SuperInstance:
1271838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis    return IFace;
1281838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis
1291838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis  case ObjCMessageExpr::Class:
1301838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis    ClassRec = InnerMsg->getClassReceiver();
1311838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis    break;
1321838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis  case ObjCMessageExpr::SuperClass:
1331838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis    ClassRec = InnerMsg->getSuperType();
1341838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis    break;
1351838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis  }
1361838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis
1371838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis  if (ClassRec.isNull())
1381838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis    return IFace;
1391838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis
1401838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis  // ...and it is the result of a class message...
1411838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis
1421838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis  const ObjCObjectType *ObjTy = ClassRec->getAs<ObjCObjectType>();
1431838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis  if (!ObjTy)
1441838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis    return IFace;
1451838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis  const ObjCInterfaceDecl *OID = ObjTy->getInterface();
1461838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis
1471838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis  // ...and the receiving class is NSMapTable or NSLocale, return that
1481838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis  // class as the receiving interface.
1491838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis  if (OID->getName() == "NSMapTable" ||
1501838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis      OID->getName() == "NSLocale")
1511838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis    return OID;
1521838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis
1531838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis  return IFace;
1541838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis}
1551838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis
1561838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidisstatic bool canRewriteToSubscriptSyntax(const ObjCInterfaceDecl *&IFace,
1571838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis                                        const ObjCMessageExpr *Msg,
1581838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis                                        ASTContext &Ctx,
159c2abbe0b98ec21c0c0e844c20d037639ef284664Argyrios Kyrtzidis                                        Selector subscriptSel) {
1601838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis  const Expr *Rec = Msg->getInstanceReceiver();
1611838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis  if (!Rec)
1621838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis    return false;
1631838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis  IFace = maybeAdjustInterfaceForSubscriptingCheck(IFace, Rec, Ctx);
1641838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis
165c2abbe0b98ec21c0c0e844c20d037639ef284664Argyrios Kyrtzidis  if (const ObjCMethodDecl *MD = IFace->lookupInstanceMethod(subscriptSel)) {
166c2abbe0b98ec21c0c0e844c20d037639ef284664Argyrios Kyrtzidis    if (!MD->isUnavailable())
167c2abbe0b98ec21c0c0e844c20d037639ef284664Argyrios Kyrtzidis      return true;
168c2abbe0b98ec21c0c0e844c20d037639ef284664Argyrios Kyrtzidis  }
169c2abbe0b98ec21c0c0e844c20d037639ef284664Argyrios Kyrtzidis  return false;
170c2abbe0b98ec21c0c0e844c20d037639ef284664Argyrios Kyrtzidis}
171c2abbe0b98ec21c0c0e844c20d037639ef284664Argyrios Kyrtzidis
17220119a87fbb7719c161d81fc5f721f1ee6ed7e66Argyrios Kyrtzidisstatic bool subscriptOperatorNeedsParens(const Expr *FullExpr);
17320119a87fbb7719c161d81fc5f721f1ee6ed7e66Argyrios Kyrtzidis
17430660a898545416f0fea2d717f16f75640001e38Ted Kremenekstatic void maybePutParensOnReceiver(const Expr *Receiver, Commit &commit) {
17520119a87fbb7719c161d81fc5f721f1ee6ed7e66Argyrios Kyrtzidis  if (subscriptOperatorNeedsParens(Receiver)) {
17630660a898545416f0fea2d717f16f75640001e38Ted Kremenek    SourceRange RecRange = Receiver->getSourceRange();
17730660a898545416f0fea2d717f16f75640001e38Ted Kremenek    commit.insertWrap("(", RecRange, ")");
17830660a898545416f0fea2d717f16f75640001e38Ted Kremenek  }
17930660a898545416f0fea2d717f16f75640001e38Ted Kremenek}
18030660a898545416f0fea2d717f16f75640001e38Ted Kremenek
181cacf718381dda1b23efedf3deb02170186095cc0Argyrios Kyrtzidisstatic bool rewriteToSubscriptGetCommon(const ObjCMessageExpr *Msg,
182cacf718381dda1b23efedf3deb02170186095cc0Argyrios Kyrtzidis                                        Commit &commit) {
18330660a898545416f0fea2d717f16f75640001e38Ted Kremenek  if (Msg->getNumArgs() != 1)
18430660a898545416f0fea2d717f16f75640001e38Ted Kremenek    return false;
18530660a898545416f0fea2d717f16f75640001e38Ted Kremenek  const Expr *Rec = Msg->getInstanceReceiver();
18630660a898545416f0fea2d717f16f75640001e38Ted Kremenek  if (!Rec)
18730660a898545416f0fea2d717f16f75640001e38Ted Kremenek    return false;
18830660a898545416f0fea2d717f16f75640001e38Ted Kremenek
18930660a898545416f0fea2d717f16f75640001e38Ted Kremenek  SourceRange MsgRange = Msg->getSourceRange();
19030660a898545416f0fea2d717f16f75640001e38Ted Kremenek  SourceRange RecRange = Rec->getSourceRange();
19130660a898545416f0fea2d717f16f75640001e38Ted Kremenek  SourceRange ArgRange = Msg->getArg(0)->getSourceRange();
19230660a898545416f0fea2d717f16f75640001e38Ted Kremenek
19330660a898545416f0fea2d717f16f75640001e38Ted Kremenek  commit.replaceWithInner(CharSourceRange::getCharRange(MsgRange.getBegin(),
19430660a898545416f0fea2d717f16f75640001e38Ted Kremenek                                                       ArgRange.getBegin()),
19530660a898545416f0fea2d717f16f75640001e38Ted Kremenek                         CharSourceRange::getTokenRange(RecRange));
19630660a898545416f0fea2d717f16f75640001e38Ted Kremenek  commit.replaceWithInner(SourceRange(ArgRange.getBegin(), MsgRange.getEnd()),
19730660a898545416f0fea2d717f16f75640001e38Ted Kremenek                         ArgRange);
19830660a898545416f0fea2d717f16f75640001e38Ted Kremenek  commit.insertWrap("[", ArgRange, "]");
19930660a898545416f0fea2d717f16f75640001e38Ted Kremenek  maybePutParensOnReceiver(Rec, commit);
20030660a898545416f0fea2d717f16f75640001e38Ted Kremenek  return true;
20130660a898545416f0fea2d717f16f75640001e38Ted Kremenek}
20230660a898545416f0fea2d717f16f75640001e38Ted Kremenek
203cacf718381dda1b23efedf3deb02170186095cc0Argyrios Kyrtzidisstatic bool rewriteToArraySubscriptGet(const ObjCInterfaceDecl *IFace,
204cacf718381dda1b23efedf3deb02170186095cc0Argyrios Kyrtzidis                                       const ObjCMessageExpr *Msg,
205cacf718381dda1b23efedf3deb02170186095cc0Argyrios Kyrtzidis                                       const NSAPI &NS,
206cacf718381dda1b23efedf3deb02170186095cc0Argyrios Kyrtzidis                                       Commit &commit) {
2071838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis  if (!canRewriteToSubscriptSyntax(IFace, Msg, NS.getASTContext(),
208c2abbe0b98ec21c0c0e844c20d037639ef284664Argyrios Kyrtzidis                                   NS.getObjectAtIndexedSubscriptSelector()))
209cacf718381dda1b23efedf3deb02170186095cc0Argyrios Kyrtzidis    return false;
210cacf718381dda1b23efedf3deb02170186095cc0Argyrios Kyrtzidis  return rewriteToSubscriptGetCommon(Msg, commit);
211cacf718381dda1b23efedf3deb02170186095cc0Argyrios Kyrtzidis}
212cacf718381dda1b23efedf3deb02170186095cc0Argyrios Kyrtzidis
213cacf718381dda1b23efedf3deb02170186095cc0Argyrios Kyrtzidisstatic bool rewriteToDictionarySubscriptGet(const ObjCInterfaceDecl *IFace,
214cacf718381dda1b23efedf3deb02170186095cc0Argyrios Kyrtzidis                                            const ObjCMessageExpr *Msg,
215cacf718381dda1b23efedf3deb02170186095cc0Argyrios Kyrtzidis                                            const NSAPI &NS,
216cacf718381dda1b23efedf3deb02170186095cc0Argyrios Kyrtzidis                                            Commit &commit) {
2171838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis  if (!canRewriteToSubscriptSyntax(IFace, Msg, NS.getASTContext(),
218c2abbe0b98ec21c0c0e844c20d037639ef284664Argyrios Kyrtzidis                                  NS.getObjectForKeyedSubscriptSelector()))
219cacf718381dda1b23efedf3deb02170186095cc0Argyrios Kyrtzidis    return false;
220cacf718381dda1b23efedf3deb02170186095cc0Argyrios Kyrtzidis  return rewriteToSubscriptGetCommon(Msg, commit);
221cacf718381dda1b23efedf3deb02170186095cc0Argyrios Kyrtzidis}
222cacf718381dda1b23efedf3deb02170186095cc0Argyrios Kyrtzidis
223cacf718381dda1b23efedf3deb02170186095cc0Argyrios Kyrtzidisstatic bool rewriteToArraySubscriptSet(const ObjCInterfaceDecl *IFace,
224cacf718381dda1b23efedf3deb02170186095cc0Argyrios Kyrtzidis                                       const ObjCMessageExpr *Msg,
225cacf718381dda1b23efedf3deb02170186095cc0Argyrios Kyrtzidis                                       const NSAPI &NS,
22630660a898545416f0fea2d717f16f75640001e38Ted Kremenek                                       Commit &commit) {
2271838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis  if (!canRewriteToSubscriptSyntax(IFace, Msg, NS.getASTContext(),
228c2abbe0b98ec21c0c0e844c20d037639ef284664Argyrios Kyrtzidis                                   NS.getSetObjectAtIndexedSubscriptSelector()))
229c2abbe0b98ec21c0c0e844c20d037639ef284664Argyrios Kyrtzidis    return false;
230c2abbe0b98ec21c0c0e844c20d037639ef284664Argyrios Kyrtzidis
23130660a898545416f0fea2d717f16f75640001e38Ted Kremenek  if (Msg->getNumArgs() != 2)
23230660a898545416f0fea2d717f16f75640001e38Ted Kremenek    return false;
23330660a898545416f0fea2d717f16f75640001e38Ted Kremenek  const Expr *Rec = Msg->getInstanceReceiver();
23430660a898545416f0fea2d717f16f75640001e38Ted Kremenek  if (!Rec)
23530660a898545416f0fea2d717f16f75640001e38Ted Kremenek    return false;
23630660a898545416f0fea2d717f16f75640001e38Ted Kremenek
23730660a898545416f0fea2d717f16f75640001e38Ted Kremenek  SourceRange MsgRange = Msg->getSourceRange();
23830660a898545416f0fea2d717f16f75640001e38Ted Kremenek  SourceRange RecRange = Rec->getSourceRange();
23930660a898545416f0fea2d717f16f75640001e38Ted Kremenek  SourceRange Arg0Range = Msg->getArg(0)->getSourceRange();
24030660a898545416f0fea2d717f16f75640001e38Ted Kremenek  SourceRange Arg1Range = Msg->getArg(1)->getSourceRange();
24130660a898545416f0fea2d717f16f75640001e38Ted Kremenek
24230660a898545416f0fea2d717f16f75640001e38Ted Kremenek  commit.replaceWithInner(CharSourceRange::getCharRange(MsgRange.getBegin(),
24330660a898545416f0fea2d717f16f75640001e38Ted Kremenek                                                       Arg0Range.getBegin()),
24430660a898545416f0fea2d717f16f75640001e38Ted Kremenek                         CharSourceRange::getTokenRange(RecRange));
24530660a898545416f0fea2d717f16f75640001e38Ted Kremenek  commit.replaceWithInner(CharSourceRange::getCharRange(Arg0Range.getBegin(),
24630660a898545416f0fea2d717f16f75640001e38Ted Kremenek                                                       Arg1Range.getBegin()),
24730660a898545416f0fea2d717f16f75640001e38Ted Kremenek                         CharSourceRange::getTokenRange(Arg0Range));
24830660a898545416f0fea2d717f16f75640001e38Ted Kremenek  commit.replaceWithInner(SourceRange(Arg1Range.getBegin(), MsgRange.getEnd()),
24930660a898545416f0fea2d717f16f75640001e38Ted Kremenek                         Arg1Range);
25030660a898545416f0fea2d717f16f75640001e38Ted Kremenek  commit.insertWrap("[", CharSourceRange::getCharRange(Arg0Range.getBegin(),
25130660a898545416f0fea2d717f16f75640001e38Ted Kremenek                                                       Arg1Range.getBegin()),
25230660a898545416f0fea2d717f16f75640001e38Ted Kremenek                    "] = ");
25330660a898545416f0fea2d717f16f75640001e38Ted Kremenek  maybePutParensOnReceiver(Rec, commit);
25430660a898545416f0fea2d717f16f75640001e38Ted Kremenek  return true;
25530660a898545416f0fea2d717f16f75640001e38Ted Kremenek}
25630660a898545416f0fea2d717f16f75640001e38Ted Kremenek
257cacf718381dda1b23efedf3deb02170186095cc0Argyrios Kyrtzidisstatic bool rewriteToDictionarySubscriptSet(const ObjCInterfaceDecl *IFace,
258cacf718381dda1b23efedf3deb02170186095cc0Argyrios Kyrtzidis                                            const ObjCMessageExpr *Msg,
259cacf718381dda1b23efedf3deb02170186095cc0Argyrios Kyrtzidis                                            const NSAPI &NS,
26030660a898545416f0fea2d717f16f75640001e38Ted Kremenek                                            Commit &commit) {
2611838703fea568b394407b83d1055b4c7f52fb105Argyrios Kyrtzidis  if (!canRewriteToSubscriptSyntax(IFace, Msg, NS.getASTContext(),
262c2abbe0b98ec21c0c0e844c20d037639ef284664Argyrios Kyrtzidis                                   NS.getSetObjectForKeyedSubscriptSelector()))
263c2abbe0b98ec21c0c0e844c20d037639ef284664Argyrios Kyrtzidis    return false;
264c2abbe0b98ec21c0c0e844c20d037639ef284664Argyrios Kyrtzidis
26530660a898545416f0fea2d717f16f75640001e38Ted Kremenek  if (Msg->getNumArgs() != 2)
26630660a898545416f0fea2d717f16f75640001e38Ted Kremenek    return false;
26730660a898545416f0fea2d717f16f75640001e38Ted Kremenek  const Expr *Rec = Msg->getInstanceReceiver();
26830660a898545416f0fea2d717f16f75640001e38Ted Kremenek  if (!Rec)
26930660a898545416f0fea2d717f16f75640001e38Ted Kremenek    return false;
27030660a898545416f0fea2d717f16f75640001e38Ted Kremenek
27130660a898545416f0fea2d717f16f75640001e38Ted Kremenek  SourceRange MsgRange = Msg->getSourceRange();
27230660a898545416f0fea2d717f16f75640001e38Ted Kremenek  SourceRange RecRange = Rec->getSourceRange();
27330660a898545416f0fea2d717f16f75640001e38Ted Kremenek  SourceRange Arg0Range = Msg->getArg(0)->getSourceRange();
27430660a898545416f0fea2d717f16f75640001e38Ted Kremenek  SourceRange Arg1Range = Msg->getArg(1)->getSourceRange();
27530660a898545416f0fea2d717f16f75640001e38Ted Kremenek
27630660a898545416f0fea2d717f16f75640001e38Ted Kremenek  SourceLocation LocBeforeVal = Arg0Range.getBegin();
27730660a898545416f0fea2d717f16f75640001e38Ted Kremenek  commit.insertBefore(LocBeforeVal, "] = ");
27830660a898545416f0fea2d717f16f75640001e38Ted Kremenek  commit.insertFromRange(LocBeforeVal, Arg1Range, /*afterToken=*/false,
27930660a898545416f0fea2d717f16f75640001e38Ted Kremenek                         /*beforePreviousInsertions=*/true);
28030660a898545416f0fea2d717f16f75640001e38Ted Kremenek  commit.insertBefore(LocBeforeVal, "[");
28130660a898545416f0fea2d717f16f75640001e38Ted Kremenek  commit.replaceWithInner(CharSourceRange::getCharRange(MsgRange.getBegin(),
28230660a898545416f0fea2d717f16f75640001e38Ted Kremenek                                                       Arg0Range.getBegin()),
28330660a898545416f0fea2d717f16f75640001e38Ted Kremenek                         CharSourceRange::getTokenRange(RecRange));
28430660a898545416f0fea2d717f16f75640001e38Ted Kremenek  commit.replaceWithInner(SourceRange(Arg0Range.getBegin(), MsgRange.getEnd()),
28530660a898545416f0fea2d717f16f75640001e38Ted Kremenek                         Arg0Range);
28630660a898545416f0fea2d717f16f75640001e38Ted Kremenek  maybePutParensOnReceiver(Rec, commit);
28730660a898545416f0fea2d717f16f75640001e38Ted Kremenek  return true;
28830660a898545416f0fea2d717f16f75640001e38Ted Kremenek}
28930660a898545416f0fea2d717f16f75640001e38Ted Kremenek
29030660a898545416f0fea2d717f16f75640001e38Ted Kremenekbool edit::rewriteToObjCSubscriptSyntax(const ObjCMessageExpr *Msg,
291cacf718381dda1b23efedf3deb02170186095cc0Argyrios Kyrtzidis                                        const NSAPI &NS, Commit &commit) {
29230660a898545416f0fea2d717f16f75640001e38Ted Kremenek  if (!Msg || Msg->isImplicit() ||
29330660a898545416f0fea2d717f16f75640001e38Ted Kremenek      Msg->getReceiverKind() != ObjCMessageExpr::Instance)
29430660a898545416f0fea2d717f16f75640001e38Ted Kremenek    return false;
29530660a898545416f0fea2d717f16f75640001e38Ted Kremenek  const ObjCMethodDecl *Method = Msg->getMethodDecl();
29630660a898545416f0fea2d717f16f75640001e38Ted Kremenek  if (!Method)
29730660a898545416f0fea2d717f16f75640001e38Ted Kremenek    return false;
29830660a898545416f0fea2d717f16f75640001e38Ted Kremenek
29965303900ea1c0d44a0673f02f92faf8d73cc1b18Dmitri Gribenko  const ObjCInterfaceDecl *IFace =
30065303900ea1c0d44a0673f02f92faf8d73cc1b18Dmitri Gribenko      NS.getASTContext().getObjContainingInterface(Method);
30130660a898545416f0fea2d717f16f75640001e38Ted Kremenek  if (!IFace)
30230660a898545416f0fea2d717f16f75640001e38Ted Kremenek    return false;
30330660a898545416f0fea2d717f16f75640001e38Ted Kremenek  Selector Sel = Msg->getSelector();
30430660a898545416f0fea2d717f16f75640001e38Ted Kremenek
305c2abbe0b98ec21c0c0e844c20d037639ef284664Argyrios Kyrtzidis  if (Sel == NS.getNSArraySelector(NSAPI::NSArr_objectAtIndex))
306cacf718381dda1b23efedf3deb02170186095cc0Argyrios Kyrtzidis    return rewriteToArraySubscriptGet(IFace, Msg, NS, commit);
307cacf718381dda1b23efedf3deb02170186095cc0Argyrios Kyrtzidis
308c2abbe0b98ec21c0c0e844c20d037639ef284664Argyrios Kyrtzidis  if (Sel == NS.getNSDictionarySelector(NSAPI::NSDict_objectForKey))
309cacf718381dda1b23efedf3deb02170186095cc0Argyrios Kyrtzidis    return rewriteToDictionarySubscriptGet(IFace, Msg, NS, commit);
31030660a898545416f0fea2d717f16f75640001e38Ted Kremenek
31130660a898545416f0fea2d717f16f75640001e38Ted Kremenek  if (Msg->getNumArgs() != 2)
31230660a898545416f0fea2d717f16f75640001e38Ted Kremenek    return false;
31330660a898545416f0fea2d717f16f75640001e38Ted Kremenek
314c2abbe0b98ec21c0c0e844c20d037639ef284664Argyrios Kyrtzidis  if (Sel == NS.getNSArraySelector(NSAPI::NSMutableArr_replaceObjectAtIndex))
315cacf718381dda1b23efedf3deb02170186095cc0Argyrios Kyrtzidis    return rewriteToArraySubscriptSet(IFace, Msg, NS, commit);
31630660a898545416f0fea2d717f16f75640001e38Ted Kremenek
317c2abbe0b98ec21c0c0e844c20d037639ef284664Argyrios Kyrtzidis  if (Sel == NS.getNSDictionarySelector(NSAPI::NSMutableDict_setObjectForKey))
318cacf718381dda1b23efedf3deb02170186095cc0Argyrios Kyrtzidis    return rewriteToDictionarySubscriptSet(IFace, Msg, NS, commit);
31930660a898545416f0fea2d717f16f75640001e38Ted Kremenek
32030660a898545416f0fea2d717f16f75640001e38Ted Kremenek  return false;
32130660a898545416f0fea2d717f16f75640001e38Ted Kremenek}
32230660a898545416f0fea2d717f16f75640001e38Ted Kremenek
32330660a898545416f0fea2d717f16f75640001e38Ted Kremenek//===----------------------------------------------------------------------===//
32430660a898545416f0fea2d717f16f75640001e38Ted Kremenek// rewriteToObjCLiteralSyntax.
32530660a898545416f0fea2d717f16f75640001e38Ted Kremenek//===----------------------------------------------------------------------===//
32630660a898545416f0fea2d717f16f75640001e38Ted Kremenek
32730660a898545416f0fea2d717f16f75640001e38Ted Kremenekstatic bool rewriteToArrayLiteral(const ObjCMessageExpr *Msg,
328a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis                                  const NSAPI &NS, Commit &commit,
329a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis                                  const ParentMap *PMap);
33030660a898545416f0fea2d717f16f75640001e38Ted Kremenekstatic bool rewriteToDictionaryLiteral(const ObjCMessageExpr *Msg,
33130660a898545416f0fea2d717f16f75640001e38Ted Kremenek                                  const NSAPI &NS, Commit &commit);
33230660a898545416f0fea2d717f16f75640001e38Ted Kremenekstatic bool rewriteToNumberLiteral(const ObjCMessageExpr *Msg,
33330660a898545416f0fea2d717f16f75640001e38Ted Kremenek                                  const NSAPI &NS, Commit &commit);
3340d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidisstatic bool rewriteToNumericBoxedExpression(const ObjCMessageExpr *Msg,
3350d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis                                            const NSAPI &NS, Commit &commit);
3367fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidisstatic bool rewriteToStringBoxedExpression(const ObjCMessageExpr *Msg,
3377fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidis                                           const NSAPI &NS, Commit &commit);
33830660a898545416f0fea2d717f16f75640001e38Ted Kremenek
33930660a898545416f0fea2d717f16f75640001e38Ted Kremenekbool edit::rewriteToObjCLiteralSyntax(const ObjCMessageExpr *Msg,
340a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis                                      const NSAPI &NS, Commit &commit,
341a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis                                      const ParentMap *PMap) {
3426bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  IdentifierInfo *II = nullptr;
3436b4db9b329c6964955153292e21de0a342354437Argyrios Kyrtzidis  if (!checkForLiteralCreation(Msg, II, NS.getASTContext().getLangOpts()))
34430660a898545416f0fea2d717f16f75640001e38Ted Kremenek    return false;
34530660a898545416f0fea2d717f16f75640001e38Ted Kremenek
34630660a898545416f0fea2d717f16f75640001e38Ted Kremenek  if (II == NS.getNSClassId(NSAPI::ClassId_NSArray))
347a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis    return rewriteToArrayLiteral(Msg, NS, commit, PMap);
34830660a898545416f0fea2d717f16f75640001e38Ted Kremenek  if (II == NS.getNSClassId(NSAPI::ClassId_NSDictionary))
34930660a898545416f0fea2d717f16f75640001e38Ted Kremenek    return rewriteToDictionaryLiteral(Msg, NS, commit);
35030660a898545416f0fea2d717f16f75640001e38Ted Kremenek  if (II == NS.getNSClassId(NSAPI::ClassId_NSNumber))
35130660a898545416f0fea2d717f16f75640001e38Ted Kremenek    return rewriteToNumberLiteral(Msg, NS, commit);
3527fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidis  if (II == NS.getNSClassId(NSAPI::ClassId_NSString))
3537fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidis    return rewriteToStringBoxedExpression(Msg, NS, commit);
35430660a898545416f0fea2d717f16f75640001e38Ted Kremenek
35530660a898545416f0fea2d717f16f75640001e38Ted Kremenek  return false;
35630660a898545416f0fea2d717f16f75640001e38Ted Kremenek}
35730660a898545416f0fea2d717f16f75640001e38Ted Kremenek
358a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis/// \brief Returns true if the immediate message arguments of \c Msg should not
359a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis/// be rewritten because it will interfere with the rewrite of the parent
360a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis/// message expression. e.g.
361a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis/// \code
362a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis///   [NSDictionary dictionaryWithObjects:
363a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis///                                 [NSArray arrayWithObjects:@"1", @"2", nil]
364a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis///                         forKeys:[NSArray arrayWithObjects:@"A", @"B", nil]];
365a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis/// \endcode
366a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis/// It will return true for this because we are going to rewrite this directly
367a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis/// to a dictionary literal without any array literals.
368a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidisstatic bool shouldNotRewriteImmediateMessageArgs(const ObjCMessageExpr *Msg,
369a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis                                                 const NSAPI &NS);
370a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis
37130660a898545416f0fea2d717f16f75640001e38Ted Kremenek//===----------------------------------------------------------------------===//
37230660a898545416f0fea2d717f16f75640001e38Ted Kremenek// rewriteToArrayLiteral.
37330660a898545416f0fea2d717f16f75640001e38Ted Kremenek//===----------------------------------------------------------------------===//
37430660a898545416f0fea2d717f16f75640001e38Ted Kremenek
375055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidis/// \brief Adds an explicit cast to 'id' if the type is not objc object.
376055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidisstatic void objectifyExpr(const Expr *E, Commit &commit);
377055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidis
37830660a898545416f0fea2d717f16f75640001e38Ted Kremenekstatic bool rewriteToArrayLiteral(const ObjCMessageExpr *Msg,
379a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis                                  const NSAPI &NS, Commit &commit,
380a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis                                  const ParentMap *PMap) {
381a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis  if (PMap) {
382a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis    const ObjCMessageExpr *ParentMsg =
383a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis        dyn_cast_or_null<ObjCMessageExpr>(PMap->getParentIgnoreParenCasts(Msg));
384a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis    if (shouldNotRewriteImmediateMessageArgs(ParentMsg, NS))
385a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis      return false;
386a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis  }
387a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis
38830660a898545416f0fea2d717f16f75640001e38Ted Kremenek  Selector Sel = Msg->getSelector();
38930660a898545416f0fea2d717f16f75640001e38Ted Kremenek  SourceRange MsgRange = Msg->getSourceRange();
39030660a898545416f0fea2d717f16f75640001e38Ted Kremenek
39130660a898545416f0fea2d717f16f75640001e38Ted Kremenek  if (Sel == NS.getNSArraySelector(NSAPI::NSArr_array)) {
39230660a898545416f0fea2d717f16f75640001e38Ted Kremenek    if (Msg->getNumArgs() != 0)
39330660a898545416f0fea2d717f16f75640001e38Ted Kremenek      return false;
39430660a898545416f0fea2d717f16f75640001e38Ted Kremenek    commit.replace(MsgRange, "@[]");
39530660a898545416f0fea2d717f16f75640001e38Ted Kremenek    return true;
39630660a898545416f0fea2d717f16f75640001e38Ted Kremenek  }
39730660a898545416f0fea2d717f16f75640001e38Ted Kremenek
39830660a898545416f0fea2d717f16f75640001e38Ted Kremenek  if (Sel == NS.getNSArraySelector(NSAPI::NSArr_arrayWithObject)) {
39930660a898545416f0fea2d717f16f75640001e38Ted Kremenek    if (Msg->getNumArgs() != 1)
40030660a898545416f0fea2d717f16f75640001e38Ted Kremenek      return false;
401055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidis    objectifyExpr(Msg->getArg(0), commit);
40230660a898545416f0fea2d717f16f75640001e38Ted Kremenek    SourceRange ArgRange = Msg->getArg(0)->getSourceRange();
40330660a898545416f0fea2d717f16f75640001e38Ted Kremenek    commit.replaceWithInner(MsgRange, ArgRange);
40430660a898545416f0fea2d717f16f75640001e38Ted Kremenek    commit.insertWrap("@[", ArgRange, "]");
40530660a898545416f0fea2d717f16f75640001e38Ted Kremenek    return true;
40630660a898545416f0fea2d717f16f75640001e38Ted Kremenek  }
40730660a898545416f0fea2d717f16f75640001e38Ted Kremenek
4086b4db9b329c6964955153292e21de0a342354437Argyrios Kyrtzidis  if (Sel == NS.getNSArraySelector(NSAPI::NSArr_arrayWithObjects) ||
4096b4db9b329c6964955153292e21de0a342354437Argyrios Kyrtzidis      Sel == NS.getNSArraySelector(NSAPI::NSArr_initWithObjects)) {
41030660a898545416f0fea2d717f16f75640001e38Ted Kremenek    if (Msg->getNumArgs() == 0)
41130660a898545416f0fea2d717f16f75640001e38Ted Kremenek      return false;
41230660a898545416f0fea2d717f16f75640001e38Ted Kremenek    const Expr *SentinelExpr = Msg->getArg(Msg->getNumArgs() - 1);
41330660a898545416f0fea2d717f16f75640001e38Ted Kremenek    if (!NS.getASTContext().isSentinelNullExpr(SentinelExpr))
41430660a898545416f0fea2d717f16f75640001e38Ted Kremenek      return false;
41530660a898545416f0fea2d717f16f75640001e38Ted Kremenek
416055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidis    for (unsigned i = 0, e = Msg->getNumArgs() - 1; i != e; ++i)
417055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidis      objectifyExpr(Msg->getArg(i), commit);
418055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidis
41930660a898545416f0fea2d717f16f75640001e38Ted Kremenek    if (Msg->getNumArgs() == 1) {
42030660a898545416f0fea2d717f16f75640001e38Ted Kremenek      commit.replace(MsgRange, "@[]");
42130660a898545416f0fea2d717f16f75640001e38Ted Kremenek      return true;
42230660a898545416f0fea2d717f16f75640001e38Ted Kremenek    }
42330660a898545416f0fea2d717f16f75640001e38Ted Kremenek    SourceRange ArgRange(Msg->getArg(0)->getLocStart(),
42430660a898545416f0fea2d717f16f75640001e38Ted Kremenek                         Msg->getArg(Msg->getNumArgs()-2)->getLocEnd());
42530660a898545416f0fea2d717f16f75640001e38Ted Kremenek    commit.replaceWithInner(MsgRange, ArgRange);
42630660a898545416f0fea2d717f16f75640001e38Ted Kremenek    commit.insertWrap("@[", ArgRange, "]");
42730660a898545416f0fea2d717f16f75640001e38Ted Kremenek    return true;
42830660a898545416f0fea2d717f16f75640001e38Ted Kremenek  }
42930660a898545416f0fea2d717f16f75640001e38Ted Kremenek
43030660a898545416f0fea2d717f16f75640001e38Ted Kremenek  return false;
43130660a898545416f0fea2d717f16f75640001e38Ted Kremenek}
43230660a898545416f0fea2d717f16f75640001e38Ted Kremenek
43330660a898545416f0fea2d717f16f75640001e38Ted Kremenek//===----------------------------------------------------------------------===//
43430660a898545416f0fea2d717f16f75640001e38Ted Kremenek// rewriteToDictionaryLiteral.
43530660a898545416f0fea2d717f16f75640001e38Ted Kremenek//===----------------------------------------------------------------------===//
43630660a898545416f0fea2d717f16f75640001e38Ted Kremenek
437a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis/// \brief If \c Msg is an NSArray creation message or literal, this gets the
438a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis/// objects that were used to create it.
439a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis/// \returns true if it is an NSArray and we got objects, or false otherwise.
440a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidisstatic bool getNSArrayObjects(const Expr *E, const NSAPI &NS,
441a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis                              SmallVectorImpl<const Expr *> &Objs) {
442a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis  if (!E)
443a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis    return false;
444a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis
445a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis  E = E->IgnoreParenCasts();
446a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis  if (!E)
447a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis    return false;
448a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis
449a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis  if (const ObjCMessageExpr *Msg = dyn_cast<ObjCMessageExpr>(E)) {
4506bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    IdentifierInfo *Cls = nullptr;
451a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis    if (!checkForLiteralCreation(Msg, Cls, NS.getASTContext().getLangOpts()))
452a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis      return false;
453a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis
454a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis    if (Cls != NS.getNSClassId(NSAPI::ClassId_NSArray))
455a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis      return false;
456a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis
457a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis    Selector Sel = Msg->getSelector();
458a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis    if (Sel == NS.getNSArraySelector(NSAPI::NSArr_array))
459a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis      return true; // empty array.
460a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis
461a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis    if (Sel == NS.getNSArraySelector(NSAPI::NSArr_arrayWithObject)) {
462a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis      if (Msg->getNumArgs() != 1)
463a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis        return false;
464a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis      Objs.push_back(Msg->getArg(0));
465a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis      return true;
466a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis    }
467a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis
468a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis    if (Sel == NS.getNSArraySelector(NSAPI::NSArr_arrayWithObjects) ||
469a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis        Sel == NS.getNSArraySelector(NSAPI::NSArr_initWithObjects)) {
470a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis      if (Msg->getNumArgs() == 0)
471a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis        return false;
472a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis      const Expr *SentinelExpr = Msg->getArg(Msg->getNumArgs() - 1);
473a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis      if (!NS.getASTContext().isSentinelNullExpr(SentinelExpr))
474a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis        return false;
475a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis
476a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis      for (unsigned i = 0, e = Msg->getNumArgs() - 1; i != e; ++i)
477a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis        Objs.push_back(Msg->getArg(i));
478a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis      return true;
479a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis    }
480a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis
481a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis  } else if (const ObjCArrayLiteral *ArrLit = dyn_cast<ObjCArrayLiteral>(E)) {
482a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis    for (unsigned i = 0, e = ArrLit->getNumElements(); i != e; ++i)
483a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis      Objs.push_back(ArrLit->getElement(i));
484a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis    return true;
485a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis  }
486a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis
487a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis  return false;
488a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis}
489a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis
49030660a898545416f0fea2d717f16f75640001e38Ted Kremenekstatic bool rewriteToDictionaryLiteral(const ObjCMessageExpr *Msg,
49130660a898545416f0fea2d717f16f75640001e38Ted Kremenek                                       const NSAPI &NS, Commit &commit) {
49230660a898545416f0fea2d717f16f75640001e38Ted Kremenek  Selector Sel = Msg->getSelector();
49330660a898545416f0fea2d717f16f75640001e38Ted Kremenek  SourceRange MsgRange = Msg->getSourceRange();
49430660a898545416f0fea2d717f16f75640001e38Ted Kremenek
49530660a898545416f0fea2d717f16f75640001e38Ted Kremenek  if (Sel == NS.getNSDictionarySelector(NSAPI::NSDict_dictionary)) {
49630660a898545416f0fea2d717f16f75640001e38Ted Kremenek    if (Msg->getNumArgs() != 0)
49730660a898545416f0fea2d717f16f75640001e38Ted Kremenek      return false;
49830660a898545416f0fea2d717f16f75640001e38Ted Kremenek    commit.replace(MsgRange, "@{}");
49930660a898545416f0fea2d717f16f75640001e38Ted Kremenek    return true;
50030660a898545416f0fea2d717f16f75640001e38Ted Kremenek  }
50130660a898545416f0fea2d717f16f75640001e38Ted Kremenek
50230660a898545416f0fea2d717f16f75640001e38Ted Kremenek  if (Sel == NS.getNSDictionarySelector(
50330660a898545416f0fea2d717f16f75640001e38Ted Kremenek                                    NSAPI::NSDict_dictionaryWithObjectForKey)) {
50430660a898545416f0fea2d717f16f75640001e38Ted Kremenek    if (Msg->getNumArgs() != 2)
50530660a898545416f0fea2d717f16f75640001e38Ted Kremenek      return false;
506055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidis
507055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidis    objectifyExpr(Msg->getArg(0), commit);
508055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidis    objectifyExpr(Msg->getArg(1), commit);
509055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidis
51030660a898545416f0fea2d717f16f75640001e38Ted Kremenek    SourceRange ValRange = Msg->getArg(0)->getSourceRange();
51130660a898545416f0fea2d717f16f75640001e38Ted Kremenek    SourceRange KeyRange = Msg->getArg(1)->getSourceRange();
51230660a898545416f0fea2d717f16f75640001e38Ted Kremenek    // Insert key before the value.
51330660a898545416f0fea2d717f16f75640001e38Ted Kremenek    commit.insertBefore(ValRange.getBegin(), ": ");
51430660a898545416f0fea2d717f16f75640001e38Ted Kremenek    commit.insertFromRange(ValRange.getBegin(),
51530660a898545416f0fea2d717f16f75640001e38Ted Kremenek                           CharSourceRange::getTokenRange(KeyRange),
51630660a898545416f0fea2d717f16f75640001e38Ted Kremenek                       /*afterToken=*/false, /*beforePreviousInsertions=*/true);
51730660a898545416f0fea2d717f16f75640001e38Ted Kremenek    commit.insertBefore(ValRange.getBegin(), "@{");
51830660a898545416f0fea2d717f16f75640001e38Ted Kremenek    commit.insertAfterToken(ValRange.getEnd(), "}");
51930660a898545416f0fea2d717f16f75640001e38Ted Kremenek    commit.replaceWithInner(MsgRange, ValRange);
52030660a898545416f0fea2d717f16f75640001e38Ted Kremenek    return true;
52130660a898545416f0fea2d717f16f75640001e38Ted Kremenek  }
52230660a898545416f0fea2d717f16f75640001e38Ted Kremenek
52330660a898545416f0fea2d717f16f75640001e38Ted Kremenek  if (Sel == NS.getNSDictionarySelector(
5246b4db9b329c6964955153292e21de0a342354437Argyrios Kyrtzidis                                  NSAPI::NSDict_dictionaryWithObjectsAndKeys) ||
5256b4db9b329c6964955153292e21de0a342354437Argyrios Kyrtzidis      Sel == NS.getNSDictionarySelector(NSAPI::NSDict_initWithObjectsAndKeys)) {
52630660a898545416f0fea2d717f16f75640001e38Ted Kremenek    if (Msg->getNumArgs() % 2 != 1)
52730660a898545416f0fea2d717f16f75640001e38Ted Kremenek      return false;
52830660a898545416f0fea2d717f16f75640001e38Ted Kremenek    unsigned SentinelIdx = Msg->getNumArgs() - 1;
52930660a898545416f0fea2d717f16f75640001e38Ted Kremenek    const Expr *SentinelExpr = Msg->getArg(SentinelIdx);
53030660a898545416f0fea2d717f16f75640001e38Ted Kremenek    if (!NS.getASTContext().isSentinelNullExpr(SentinelExpr))
53130660a898545416f0fea2d717f16f75640001e38Ted Kremenek      return false;
53230660a898545416f0fea2d717f16f75640001e38Ted Kremenek
53330660a898545416f0fea2d717f16f75640001e38Ted Kremenek    if (Msg->getNumArgs() == 1) {
53430660a898545416f0fea2d717f16f75640001e38Ted Kremenek      commit.replace(MsgRange, "@{}");
53530660a898545416f0fea2d717f16f75640001e38Ted Kremenek      return true;
53630660a898545416f0fea2d717f16f75640001e38Ted Kremenek    }
53730660a898545416f0fea2d717f16f75640001e38Ted Kremenek
53830660a898545416f0fea2d717f16f75640001e38Ted Kremenek    for (unsigned i = 0; i < SentinelIdx; i += 2) {
539055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidis      objectifyExpr(Msg->getArg(i), commit);
540055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidis      objectifyExpr(Msg->getArg(i+1), commit);
541055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidis
54230660a898545416f0fea2d717f16f75640001e38Ted Kremenek      SourceRange ValRange = Msg->getArg(i)->getSourceRange();
54330660a898545416f0fea2d717f16f75640001e38Ted Kremenek      SourceRange KeyRange = Msg->getArg(i+1)->getSourceRange();
54430660a898545416f0fea2d717f16f75640001e38Ted Kremenek      // Insert value after key.
54530660a898545416f0fea2d717f16f75640001e38Ted Kremenek      commit.insertAfterToken(KeyRange.getEnd(), ": ");
54630660a898545416f0fea2d717f16f75640001e38Ted Kremenek      commit.insertFromRange(KeyRange.getEnd(), ValRange, /*afterToken=*/true);
54730660a898545416f0fea2d717f16f75640001e38Ted Kremenek      commit.remove(CharSourceRange::getCharRange(ValRange.getBegin(),
54830660a898545416f0fea2d717f16f75640001e38Ted Kremenek                                                  KeyRange.getBegin()));
54930660a898545416f0fea2d717f16f75640001e38Ted Kremenek    }
55030660a898545416f0fea2d717f16f75640001e38Ted Kremenek    // Range of arguments up until and including the last key.
55130660a898545416f0fea2d717f16f75640001e38Ted Kremenek    // The sentinel and first value are cut off, the value will move after the
55230660a898545416f0fea2d717f16f75640001e38Ted Kremenek    // key.
55330660a898545416f0fea2d717f16f75640001e38Ted Kremenek    SourceRange ArgRange(Msg->getArg(1)->getLocStart(),
55430660a898545416f0fea2d717f16f75640001e38Ted Kremenek                         Msg->getArg(SentinelIdx-1)->getLocEnd());
55530660a898545416f0fea2d717f16f75640001e38Ted Kremenek    commit.insertWrap("@{", ArgRange, "}");
55630660a898545416f0fea2d717f16f75640001e38Ted Kremenek    commit.replaceWithInner(MsgRange, ArgRange);
55730660a898545416f0fea2d717f16f75640001e38Ted Kremenek    return true;
55830660a898545416f0fea2d717f16f75640001e38Ted Kremenek  }
55930660a898545416f0fea2d717f16f75640001e38Ted Kremenek
560a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis  if (Sel == NS.getNSDictionarySelector(
561a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis                                  NSAPI::NSDict_dictionaryWithObjectsForKeys) ||
562a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis      Sel == NS.getNSDictionarySelector(NSAPI::NSDict_initWithObjectsForKeys)) {
563a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis    if (Msg->getNumArgs() != 2)
564a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis      return false;
565a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis
566a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis    SmallVector<const Expr *, 8> Vals;
567a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis    if (!getNSArrayObjects(Msg->getArg(0), NS, Vals))
568a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis      return false;
569a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis
570a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis    SmallVector<const Expr *, 8> Keys;
571a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis    if (!getNSArrayObjects(Msg->getArg(1), NS, Keys))
572a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis      return false;
573a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis
574a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis    if (Vals.size() != Keys.size())
575a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis      return false;
576a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis
577a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis    if (Vals.empty()) {
578a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis      commit.replace(MsgRange, "@{}");
579a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis      return true;
580a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis    }
581a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis
582a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis    for (unsigned i = 0, n = Vals.size(); i < n; ++i) {
583a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis      objectifyExpr(Vals[i], commit);
584a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis      objectifyExpr(Keys[i], commit);
585a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis
586a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis      SourceRange ValRange = Vals[i]->getSourceRange();
587a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis      SourceRange KeyRange = Keys[i]->getSourceRange();
588a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis      // Insert value after key.
589a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis      commit.insertAfterToken(KeyRange.getEnd(), ": ");
590a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis      commit.insertFromRange(KeyRange.getEnd(), ValRange, /*afterToken=*/true);
591a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis    }
592a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis    // Range of arguments up until and including the last key.
593a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis    // The first value is cut off, the value will move after the key.
594a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis    SourceRange ArgRange(Keys.front()->getLocStart(),
595a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis                         Keys.back()->getLocEnd());
596a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis    commit.insertWrap("@{", ArgRange, "}");
597a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis    commit.replaceWithInner(MsgRange, ArgRange);
598a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis    return true;
599a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis  }
600a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis
601a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis  return false;
602a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis}
603a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis
604a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidisstatic bool shouldNotRewriteImmediateMessageArgs(const ObjCMessageExpr *Msg,
605a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis                                                 const NSAPI &NS) {
606a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis  if (!Msg)
607a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis    return false;
608a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis
6096bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  IdentifierInfo *II = nullptr;
610a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis  if (!checkForLiteralCreation(Msg, II, NS.getASTContext().getLangOpts()))
611a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis    return false;
612a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis
613a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis  if (II != NS.getNSClassId(NSAPI::ClassId_NSDictionary))
614a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis    return false;
615a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis
616a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis  Selector Sel = Msg->getSelector();
617a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis  if (Sel == NS.getNSDictionarySelector(
618a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis                                  NSAPI::NSDict_dictionaryWithObjectsForKeys) ||
619a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis      Sel == NS.getNSDictionarySelector(NSAPI::NSDict_initWithObjectsForKeys)) {
620a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis    if (Msg->getNumArgs() != 2)
621a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis      return false;
622a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis
623a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis    SmallVector<const Expr *, 8> Vals;
624a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis    if (!getNSArrayObjects(Msg->getArg(0), NS, Vals))
625a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis      return false;
626a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis
627a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis    SmallVector<const Expr *, 8> Keys;
628a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis    if (!getNSArrayObjects(Msg->getArg(1), NS, Keys))
629a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis      return false;
630a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis
631a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis    if (Vals.size() != Keys.size())
632a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis      return false;
633a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis
634a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis    return true;
635a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis  }
636a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis
63730660a898545416f0fea2d717f16f75640001e38Ted Kremenek  return false;
63830660a898545416f0fea2d717f16f75640001e38Ted Kremenek}
63930660a898545416f0fea2d717f16f75640001e38Ted Kremenek
64030660a898545416f0fea2d717f16f75640001e38Ted Kremenek//===----------------------------------------------------------------------===//
64130660a898545416f0fea2d717f16f75640001e38Ted Kremenek// rewriteToNumberLiteral.
64230660a898545416f0fea2d717f16f75640001e38Ted Kremenek//===----------------------------------------------------------------------===//
64330660a898545416f0fea2d717f16f75640001e38Ted Kremenek
64430660a898545416f0fea2d717f16f75640001e38Ted Kremenekstatic bool rewriteToCharLiteral(const ObjCMessageExpr *Msg,
64530660a898545416f0fea2d717f16f75640001e38Ted Kremenek                                   const CharacterLiteral *Arg,
64630660a898545416f0fea2d717f16f75640001e38Ted Kremenek                                   const NSAPI &NS, Commit &commit) {
64730660a898545416f0fea2d717f16f75640001e38Ted Kremenek  if (Arg->getKind() != CharacterLiteral::Ascii)
64830660a898545416f0fea2d717f16f75640001e38Ted Kremenek    return false;
64930660a898545416f0fea2d717f16f75640001e38Ted Kremenek  if (NS.isNSNumberLiteralSelector(NSAPI::NSNumberWithChar,
65030660a898545416f0fea2d717f16f75640001e38Ted Kremenek                                   Msg->getSelector())) {
65130660a898545416f0fea2d717f16f75640001e38Ted Kremenek    SourceRange ArgRange = Arg->getSourceRange();
65230660a898545416f0fea2d717f16f75640001e38Ted Kremenek    commit.replaceWithInner(Msg->getSourceRange(), ArgRange);
65330660a898545416f0fea2d717f16f75640001e38Ted Kremenek    commit.insert(ArgRange.getBegin(), "@");
65430660a898545416f0fea2d717f16f75640001e38Ted Kremenek    return true;
65530660a898545416f0fea2d717f16f75640001e38Ted Kremenek  }
65630660a898545416f0fea2d717f16f75640001e38Ted Kremenek
6570d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis  return rewriteToNumericBoxedExpression(Msg, NS, commit);
65830660a898545416f0fea2d717f16f75640001e38Ted Kremenek}
65930660a898545416f0fea2d717f16f75640001e38Ted Kremenek
66030660a898545416f0fea2d717f16f75640001e38Ted Kremenekstatic bool rewriteToBoolLiteral(const ObjCMessageExpr *Msg,
66130660a898545416f0fea2d717f16f75640001e38Ted Kremenek                                   const Expr *Arg,
66230660a898545416f0fea2d717f16f75640001e38Ted Kremenek                                   const NSAPI &NS, Commit &commit) {
66330660a898545416f0fea2d717f16f75640001e38Ted Kremenek  if (NS.isNSNumberLiteralSelector(NSAPI::NSNumberWithBool,
66430660a898545416f0fea2d717f16f75640001e38Ted Kremenek                                   Msg->getSelector())) {
66530660a898545416f0fea2d717f16f75640001e38Ted Kremenek    SourceRange ArgRange = Arg->getSourceRange();
66630660a898545416f0fea2d717f16f75640001e38Ted Kremenek    commit.replaceWithInner(Msg->getSourceRange(), ArgRange);
66730660a898545416f0fea2d717f16f75640001e38Ted Kremenek    commit.insert(ArgRange.getBegin(), "@");
66830660a898545416f0fea2d717f16f75640001e38Ted Kremenek    return true;
66930660a898545416f0fea2d717f16f75640001e38Ted Kremenek  }
67030660a898545416f0fea2d717f16f75640001e38Ted Kremenek
6710d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis  return rewriteToNumericBoxedExpression(Msg, NS, commit);
67230660a898545416f0fea2d717f16f75640001e38Ted Kremenek}
67330660a898545416f0fea2d717f16f75640001e38Ted Kremenek
67430660a898545416f0fea2d717f16f75640001e38Ted Kremeneknamespace {
67530660a898545416f0fea2d717f16f75640001e38Ted Kremenek
67630660a898545416f0fea2d717f16f75640001e38Ted Kremenekstruct LiteralInfo {
67730660a898545416f0fea2d717f16f75640001e38Ted Kremenek  bool Hex, Octal;
67830660a898545416f0fea2d717f16f75640001e38Ted Kremenek  StringRef U, F, L, LL;
67930660a898545416f0fea2d717f16f75640001e38Ted Kremenek  CharSourceRange WithoutSuffRange;
68030660a898545416f0fea2d717f16f75640001e38Ted Kremenek};
68130660a898545416f0fea2d717f16f75640001e38Ted Kremenek
68230660a898545416f0fea2d717f16f75640001e38Ted Kremenek}
68330660a898545416f0fea2d717f16f75640001e38Ted Kremenek
68430660a898545416f0fea2d717f16f75640001e38Ted Kremenekstatic bool getLiteralInfo(SourceRange literalRange,
68530660a898545416f0fea2d717f16f75640001e38Ted Kremenek                           bool isFloat, bool isIntZero,
68630660a898545416f0fea2d717f16f75640001e38Ted Kremenek                          ASTContext &Ctx, LiteralInfo &Info) {
68730660a898545416f0fea2d717f16f75640001e38Ted Kremenek  if (literalRange.getBegin().isMacroID() ||
68830660a898545416f0fea2d717f16f75640001e38Ted Kremenek      literalRange.getEnd().isMacroID())
68930660a898545416f0fea2d717f16f75640001e38Ted Kremenek    return false;
69030660a898545416f0fea2d717f16f75640001e38Ted Kremenek  StringRef text = Lexer::getSourceText(
69130660a898545416f0fea2d717f16f75640001e38Ted Kremenek                                  CharSourceRange::getTokenRange(literalRange),
6924e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie                                  Ctx.getSourceManager(), Ctx.getLangOpts());
69330660a898545416f0fea2d717f16f75640001e38Ted Kremenek  if (text.empty())
69430660a898545416f0fea2d717f16f75640001e38Ted Kremenek    return false;
69530660a898545416f0fea2d717f16f75640001e38Ted Kremenek
696dc84cd5efdd3430efb22546b4ac656aa0540b210David Blaikie  Optional<bool> UpperU, UpperL;
69730660a898545416f0fea2d717f16f75640001e38Ted Kremenek  bool UpperF = false;
69830660a898545416f0fea2d717f16f75640001e38Ted Kremenek
69930660a898545416f0fea2d717f16f75640001e38Ted Kremenek  struct Suff {
70030660a898545416f0fea2d717f16f75640001e38Ted Kremenek    static bool has(StringRef suff, StringRef &text) {
70130660a898545416f0fea2d717f16f75640001e38Ted Kremenek      if (text.endswith(suff)) {
70230660a898545416f0fea2d717f16f75640001e38Ted Kremenek        text = text.substr(0, text.size()-suff.size());
70330660a898545416f0fea2d717f16f75640001e38Ted Kremenek        return true;
70430660a898545416f0fea2d717f16f75640001e38Ted Kremenek      }
70530660a898545416f0fea2d717f16f75640001e38Ted Kremenek      return false;
70630660a898545416f0fea2d717f16f75640001e38Ted Kremenek    }
70730660a898545416f0fea2d717f16f75640001e38Ted Kremenek  };
70830660a898545416f0fea2d717f16f75640001e38Ted Kremenek
70930660a898545416f0fea2d717f16f75640001e38Ted Kremenek  while (1) {
71030660a898545416f0fea2d717f16f75640001e38Ted Kremenek    if (Suff::has("u", text)) {
71130660a898545416f0fea2d717f16f75640001e38Ted Kremenek      UpperU = false;
71230660a898545416f0fea2d717f16f75640001e38Ted Kremenek    } else if (Suff::has("U", text)) {
71330660a898545416f0fea2d717f16f75640001e38Ted Kremenek      UpperU = true;
71430660a898545416f0fea2d717f16f75640001e38Ted Kremenek    } else if (Suff::has("ll", text)) {
71530660a898545416f0fea2d717f16f75640001e38Ted Kremenek      UpperL = false;
71630660a898545416f0fea2d717f16f75640001e38Ted Kremenek    } else if (Suff::has("LL", text)) {
71730660a898545416f0fea2d717f16f75640001e38Ted Kremenek      UpperL = true;
71830660a898545416f0fea2d717f16f75640001e38Ted Kremenek    } else if (Suff::has("l", text)) {
71930660a898545416f0fea2d717f16f75640001e38Ted Kremenek      UpperL = false;
72030660a898545416f0fea2d717f16f75640001e38Ted Kremenek    } else if (Suff::has("L", text)) {
72130660a898545416f0fea2d717f16f75640001e38Ted Kremenek      UpperL = true;
72230660a898545416f0fea2d717f16f75640001e38Ted Kremenek    } else if (isFloat && Suff::has("f", text)) {
72330660a898545416f0fea2d717f16f75640001e38Ted Kremenek      UpperF = false;
72430660a898545416f0fea2d717f16f75640001e38Ted Kremenek    } else if (isFloat && Suff::has("F", text)) {
72530660a898545416f0fea2d717f16f75640001e38Ted Kremenek      UpperF = true;
72630660a898545416f0fea2d717f16f75640001e38Ted Kremenek    } else
72730660a898545416f0fea2d717f16f75640001e38Ted Kremenek      break;
72830660a898545416f0fea2d717f16f75640001e38Ted Kremenek  }
72930660a898545416f0fea2d717f16f75640001e38Ted Kremenek
73030660a898545416f0fea2d717f16f75640001e38Ted Kremenek  if (!UpperU.hasValue() && !UpperL.hasValue())
73130660a898545416f0fea2d717f16f75640001e38Ted Kremenek    UpperU = UpperL = true;
73230660a898545416f0fea2d717f16f75640001e38Ted Kremenek  else if (UpperU.hasValue() && !UpperL.hasValue())
73330660a898545416f0fea2d717f16f75640001e38Ted Kremenek    UpperL = UpperU;
73430660a898545416f0fea2d717f16f75640001e38Ted Kremenek  else if (UpperL.hasValue() && !UpperU.hasValue())
73530660a898545416f0fea2d717f16f75640001e38Ted Kremenek    UpperU = UpperL;
73630660a898545416f0fea2d717f16f75640001e38Ted Kremenek
73730660a898545416f0fea2d717f16f75640001e38Ted Kremenek  Info.U = *UpperU ? "U" : "u";
73830660a898545416f0fea2d717f16f75640001e38Ted Kremenek  Info.L = *UpperL ? "L" : "l";
73930660a898545416f0fea2d717f16f75640001e38Ted Kremenek  Info.LL = *UpperL ? "LL" : "ll";
74030660a898545416f0fea2d717f16f75640001e38Ted Kremenek  Info.F = UpperF ? "F" : "f";
74130660a898545416f0fea2d717f16f75640001e38Ted Kremenek
74230660a898545416f0fea2d717f16f75640001e38Ted Kremenek  Info.Hex = Info.Octal = false;
74330660a898545416f0fea2d717f16f75640001e38Ted Kremenek  if (text.startswith("0x"))
74430660a898545416f0fea2d717f16f75640001e38Ted Kremenek    Info.Hex = true;
74530660a898545416f0fea2d717f16f75640001e38Ted Kremenek  else if (!isFloat && !isIntZero && text.startswith("0"))
74630660a898545416f0fea2d717f16f75640001e38Ted Kremenek    Info.Octal = true;
74730660a898545416f0fea2d717f16f75640001e38Ted Kremenek
74830660a898545416f0fea2d717f16f75640001e38Ted Kremenek  SourceLocation B = literalRange.getBegin();
74930660a898545416f0fea2d717f16f75640001e38Ted Kremenek  Info.WithoutSuffRange =
75030660a898545416f0fea2d717f16f75640001e38Ted Kremenek      CharSourceRange::getCharRange(B, B.getLocWithOffset(text.size()));
75130660a898545416f0fea2d717f16f75640001e38Ted Kremenek  return true;
75230660a898545416f0fea2d717f16f75640001e38Ted Kremenek}
75330660a898545416f0fea2d717f16f75640001e38Ted Kremenek
75430660a898545416f0fea2d717f16f75640001e38Ted Kremenekstatic bool rewriteToNumberLiteral(const ObjCMessageExpr *Msg,
75530660a898545416f0fea2d717f16f75640001e38Ted Kremenek                                   const NSAPI &NS, Commit &commit) {
75630660a898545416f0fea2d717f16f75640001e38Ted Kremenek  if (Msg->getNumArgs() != 1)
75730660a898545416f0fea2d717f16f75640001e38Ted Kremenek    return false;
75830660a898545416f0fea2d717f16f75640001e38Ted Kremenek
75930660a898545416f0fea2d717f16f75640001e38Ted Kremenek  const Expr *Arg = Msg->getArg(0)->IgnoreParenImpCasts();
76030660a898545416f0fea2d717f16f75640001e38Ted Kremenek  if (const CharacterLiteral *CharE = dyn_cast<CharacterLiteral>(Arg))
76130660a898545416f0fea2d717f16f75640001e38Ted Kremenek    return rewriteToCharLiteral(Msg, CharE, NS, commit);
76230660a898545416f0fea2d717f16f75640001e38Ted Kremenek  if (const ObjCBoolLiteralExpr *BE = dyn_cast<ObjCBoolLiteralExpr>(Arg))
76330660a898545416f0fea2d717f16f75640001e38Ted Kremenek    return rewriteToBoolLiteral(Msg, BE, NS, commit);
76430660a898545416f0fea2d717f16f75640001e38Ted Kremenek  if (const CXXBoolLiteralExpr *BE = dyn_cast<CXXBoolLiteralExpr>(Arg))
76530660a898545416f0fea2d717f16f75640001e38Ted Kremenek    return rewriteToBoolLiteral(Msg, BE, NS, commit);
76630660a898545416f0fea2d717f16f75640001e38Ted Kremenek
76730660a898545416f0fea2d717f16f75640001e38Ted Kremenek  const Expr *literalE = Arg;
76830660a898545416f0fea2d717f16f75640001e38Ted Kremenek  if (const UnaryOperator *UOE = dyn_cast<UnaryOperator>(literalE)) {
76930660a898545416f0fea2d717f16f75640001e38Ted Kremenek    if (UOE->getOpcode() == UO_Plus || UOE->getOpcode() == UO_Minus)
77030660a898545416f0fea2d717f16f75640001e38Ted Kremenek      literalE = UOE->getSubExpr();
77130660a898545416f0fea2d717f16f75640001e38Ted Kremenek  }
77230660a898545416f0fea2d717f16f75640001e38Ted Kremenek
7730d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis  // Only integer and floating literals, otherwise try to rewrite to boxed
7740d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis  // expression.
77530660a898545416f0fea2d717f16f75640001e38Ted Kremenek  if (!isa<IntegerLiteral>(literalE) && !isa<FloatingLiteral>(literalE))
7760d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    return rewriteToNumericBoxedExpression(Msg, NS, commit);
77730660a898545416f0fea2d717f16f75640001e38Ted Kremenek
77830660a898545416f0fea2d717f16f75640001e38Ted Kremenek  ASTContext &Ctx = NS.getASTContext();
77930660a898545416f0fea2d717f16f75640001e38Ted Kremenek  Selector Sel = Msg->getSelector();
780dc84cd5efdd3430efb22546b4ac656aa0540b210David Blaikie  Optional<NSAPI::NSNumberLiteralMethodKind>
78130660a898545416f0fea2d717f16f75640001e38Ted Kremenek    MKOpt = NS.getNSNumberLiteralMethodKind(Sel);
78230660a898545416f0fea2d717f16f75640001e38Ted Kremenek  if (!MKOpt)
78330660a898545416f0fea2d717f16f75640001e38Ted Kremenek    return false;
78430660a898545416f0fea2d717f16f75640001e38Ted Kremenek  NSAPI::NSNumberLiteralMethodKind MK = *MKOpt;
78530660a898545416f0fea2d717f16f75640001e38Ted Kremenek
786bea6c0a2e77a78e3d27ee44461613acdd1d8ee9cBenjamin Kramer  bool CallIsUnsigned = false, CallIsLong = false, CallIsLongLong = false;
78730660a898545416f0fea2d717f16f75640001e38Ted Kremenek  bool CallIsFloating = false, CallIsDouble = false;
78830660a898545416f0fea2d717f16f75640001e38Ted Kremenek
78930660a898545416f0fea2d717f16f75640001e38Ted Kremenek  switch (MK) {
79030660a898545416f0fea2d717f16f75640001e38Ted Kremenek  // We cannot have these calls with int/float literals.
79130660a898545416f0fea2d717f16f75640001e38Ted Kremenek  case NSAPI::NSNumberWithChar:
79230660a898545416f0fea2d717f16f75640001e38Ted Kremenek  case NSAPI::NSNumberWithUnsignedChar:
79330660a898545416f0fea2d717f16f75640001e38Ted Kremenek  case NSAPI::NSNumberWithShort:
79430660a898545416f0fea2d717f16f75640001e38Ted Kremenek  case NSAPI::NSNumberWithUnsignedShort:
79530660a898545416f0fea2d717f16f75640001e38Ted Kremenek  case NSAPI::NSNumberWithBool:
7960d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    return rewriteToNumericBoxedExpression(Msg, NS, commit);
79730660a898545416f0fea2d717f16f75640001e38Ted Kremenek
79830660a898545416f0fea2d717f16f75640001e38Ted Kremenek  case NSAPI::NSNumberWithUnsignedInt:
79930660a898545416f0fea2d717f16f75640001e38Ted Kremenek  case NSAPI::NSNumberWithUnsignedInteger:
80030660a898545416f0fea2d717f16f75640001e38Ted Kremenek    CallIsUnsigned = true;
80130660a898545416f0fea2d717f16f75640001e38Ted Kremenek  case NSAPI::NSNumberWithInt:
80230660a898545416f0fea2d717f16f75640001e38Ted Kremenek  case NSAPI::NSNumberWithInteger:
80330660a898545416f0fea2d717f16f75640001e38Ted Kremenek    break;
80430660a898545416f0fea2d717f16f75640001e38Ted Kremenek
80530660a898545416f0fea2d717f16f75640001e38Ted Kremenek  case NSAPI::NSNumberWithUnsignedLong:
80630660a898545416f0fea2d717f16f75640001e38Ted Kremenek    CallIsUnsigned = true;
80730660a898545416f0fea2d717f16f75640001e38Ted Kremenek  case NSAPI::NSNumberWithLong:
808bea6c0a2e77a78e3d27ee44461613acdd1d8ee9cBenjamin Kramer    CallIsLong = true;
80930660a898545416f0fea2d717f16f75640001e38Ted Kremenek    break;
81030660a898545416f0fea2d717f16f75640001e38Ted Kremenek
81130660a898545416f0fea2d717f16f75640001e38Ted Kremenek  case NSAPI::NSNumberWithUnsignedLongLong:
81230660a898545416f0fea2d717f16f75640001e38Ted Kremenek    CallIsUnsigned = true;
81330660a898545416f0fea2d717f16f75640001e38Ted Kremenek  case NSAPI::NSNumberWithLongLong:
814bea6c0a2e77a78e3d27ee44461613acdd1d8ee9cBenjamin Kramer    CallIsLongLong = true;
81530660a898545416f0fea2d717f16f75640001e38Ted Kremenek    break;
81630660a898545416f0fea2d717f16f75640001e38Ted Kremenek
81730660a898545416f0fea2d717f16f75640001e38Ted Kremenek  case NSAPI::NSNumberWithDouble:
81830660a898545416f0fea2d717f16f75640001e38Ted Kremenek    CallIsDouble = true;
81930660a898545416f0fea2d717f16f75640001e38Ted Kremenek  case NSAPI::NSNumberWithFloat:
82030660a898545416f0fea2d717f16f75640001e38Ted Kremenek    CallIsFloating = true;
82130660a898545416f0fea2d717f16f75640001e38Ted Kremenek    break;
82230660a898545416f0fea2d717f16f75640001e38Ted Kremenek  }
82330660a898545416f0fea2d717f16f75640001e38Ted Kremenek
82430660a898545416f0fea2d717f16f75640001e38Ted Kremenek  SourceRange ArgRange = Arg->getSourceRange();
82530660a898545416f0fea2d717f16f75640001e38Ted Kremenek  QualType ArgTy = Arg->getType();
82630660a898545416f0fea2d717f16f75640001e38Ted Kremenek  QualType CallTy = Msg->getArg(0)->getType();
82730660a898545416f0fea2d717f16f75640001e38Ted Kremenek
82830660a898545416f0fea2d717f16f75640001e38Ted Kremenek  // Check for the easy case, the literal maps directly to the call.
82930660a898545416f0fea2d717f16f75640001e38Ted Kremenek  if (Ctx.hasSameType(ArgTy, CallTy)) {
83030660a898545416f0fea2d717f16f75640001e38Ted Kremenek    commit.replaceWithInner(Msg->getSourceRange(), ArgRange);
83130660a898545416f0fea2d717f16f75640001e38Ted Kremenek    commit.insert(ArgRange.getBegin(), "@");
83230660a898545416f0fea2d717f16f75640001e38Ted Kremenek    return true;
83330660a898545416f0fea2d717f16f75640001e38Ted Kremenek  }
83430660a898545416f0fea2d717f16f75640001e38Ted Kremenek
83530660a898545416f0fea2d717f16f75640001e38Ted Kremenek  // We will need to modify the literal suffix to get the same type as the call.
8360d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis  // Try with boxed expression if it came from a macro.
83730660a898545416f0fea2d717f16f75640001e38Ted Kremenek  if (ArgRange.getBegin().isMacroID())
8380d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    return rewriteToNumericBoxedExpression(Msg, NS, commit);
83930660a898545416f0fea2d717f16f75640001e38Ted Kremenek
84030660a898545416f0fea2d717f16f75640001e38Ted Kremenek  bool LitIsFloat = ArgTy->isFloatingType();
8410d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis  // For a float passed to integer call, don't try rewriting to objc literal.
8420d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis  // It is difficult and a very uncommon case anyway.
8430d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis  // But try with boxed expression.
84430660a898545416f0fea2d717f16f75640001e38Ted Kremenek  if (LitIsFloat && !CallIsFloating)
8450d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    return rewriteToNumericBoxedExpression(Msg, NS, commit);
84630660a898545416f0fea2d717f16f75640001e38Ted Kremenek
84730660a898545416f0fea2d717f16f75640001e38Ted Kremenek  // Try to modify the literal make it the same type as the method call.
84830660a898545416f0fea2d717f16f75640001e38Ted Kremenek  // -Modify the suffix, and/or
84930660a898545416f0fea2d717f16f75640001e38Ted Kremenek  // -Change integer to float
85030660a898545416f0fea2d717f16f75640001e38Ted Kremenek
85130660a898545416f0fea2d717f16f75640001e38Ted Kremenek  LiteralInfo LitInfo;
85230660a898545416f0fea2d717f16f75640001e38Ted Kremenek  bool isIntZero = false;
85330660a898545416f0fea2d717f16f75640001e38Ted Kremenek  if (const IntegerLiteral *IntE = dyn_cast<IntegerLiteral>(literalE))
85430660a898545416f0fea2d717f16f75640001e38Ted Kremenek    isIntZero = !IntE->getValue().getBoolValue();
85530660a898545416f0fea2d717f16f75640001e38Ted Kremenek  if (!getLiteralInfo(ArgRange, LitIsFloat, isIntZero, Ctx, LitInfo))
8560d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    return rewriteToNumericBoxedExpression(Msg, NS, commit);
85730660a898545416f0fea2d717f16f75640001e38Ted Kremenek
85830660a898545416f0fea2d717f16f75640001e38Ted Kremenek  // Not easy to do int -> float with hex/octal and uncommon anyway.
85930660a898545416f0fea2d717f16f75640001e38Ted Kremenek  if (!LitIsFloat && CallIsFloating && (LitInfo.Hex || LitInfo.Octal))
8600d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    return rewriteToNumericBoxedExpression(Msg, NS, commit);
86130660a898545416f0fea2d717f16f75640001e38Ted Kremenek
86230660a898545416f0fea2d717f16f75640001e38Ted Kremenek  SourceLocation LitB = LitInfo.WithoutSuffRange.getBegin();
86330660a898545416f0fea2d717f16f75640001e38Ted Kremenek  SourceLocation LitE = LitInfo.WithoutSuffRange.getEnd();
86430660a898545416f0fea2d717f16f75640001e38Ted Kremenek
86530660a898545416f0fea2d717f16f75640001e38Ted Kremenek  commit.replaceWithInner(CharSourceRange::getTokenRange(Msg->getSourceRange()),
86630660a898545416f0fea2d717f16f75640001e38Ted Kremenek                         LitInfo.WithoutSuffRange);
86730660a898545416f0fea2d717f16f75640001e38Ted Kremenek  commit.insert(LitB, "@");
86830660a898545416f0fea2d717f16f75640001e38Ted Kremenek
86930660a898545416f0fea2d717f16f75640001e38Ted Kremenek  if (!LitIsFloat && CallIsFloating)
87030660a898545416f0fea2d717f16f75640001e38Ted Kremenek    commit.insert(LitE, ".0");
87130660a898545416f0fea2d717f16f75640001e38Ted Kremenek
87230660a898545416f0fea2d717f16f75640001e38Ted Kremenek  if (CallIsFloating) {
87330660a898545416f0fea2d717f16f75640001e38Ted Kremenek    if (!CallIsDouble)
87430660a898545416f0fea2d717f16f75640001e38Ted Kremenek      commit.insert(LitE, LitInfo.F);
87530660a898545416f0fea2d717f16f75640001e38Ted Kremenek  } else {
87630660a898545416f0fea2d717f16f75640001e38Ted Kremenek    if (CallIsUnsigned)
87730660a898545416f0fea2d717f16f75640001e38Ted Kremenek      commit.insert(LitE, LitInfo.U);
87830660a898545416f0fea2d717f16f75640001e38Ted Kremenek
87930660a898545416f0fea2d717f16f75640001e38Ted Kremenek    if (CallIsLong)
88030660a898545416f0fea2d717f16f75640001e38Ted Kremenek      commit.insert(LitE, LitInfo.L);
88130660a898545416f0fea2d717f16f75640001e38Ted Kremenek    else if (CallIsLongLong)
88230660a898545416f0fea2d717f16f75640001e38Ted Kremenek      commit.insert(LitE, LitInfo.LL);
88330660a898545416f0fea2d717f16f75640001e38Ted Kremenek  }
88430660a898545416f0fea2d717f16f75640001e38Ted Kremenek  return true;
88530660a898545416f0fea2d717f16f75640001e38Ted Kremenek}
886055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidis
88720119a87fbb7719c161d81fc5f721f1ee6ed7e66Argyrios Kyrtzidis// FIXME: Make determination of operator precedence more general and
88820119a87fbb7719c161d81fc5f721f1ee6ed7e66Argyrios Kyrtzidis// make it broadly available.
88920119a87fbb7719c161d81fc5f721f1ee6ed7e66Argyrios Kyrtzidisstatic bool subscriptOperatorNeedsParens(const Expr *FullExpr) {
89020119a87fbb7719c161d81fc5f721f1ee6ed7e66Argyrios Kyrtzidis  const Expr* Expr = FullExpr->IgnoreImpCasts();
89120119a87fbb7719c161d81fc5f721f1ee6ed7e66Argyrios Kyrtzidis  if (isa<ArraySubscriptExpr>(Expr) ||
89220119a87fbb7719c161d81fc5f721f1ee6ed7e66Argyrios Kyrtzidis      isa<CallExpr>(Expr) ||
89320119a87fbb7719c161d81fc5f721f1ee6ed7e66Argyrios Kyrtzidis      isa<DeclRefExpr>(Expr) ||
89420119a87fbb7719c161d81fc5f721f1ee6ed7e66Argyrios Kyrtzidis      isa<CXXNamedCastExpr>(Expr) ||
89520119a87fbb7719c161d81fc5f721f1ee6ed7e66Argyrios Kyrtzidis      isa<CXXConstructExpr>(Expr) ||
89620119a87fbb7719c161d81fc5f721f1ee6ed7e66Argyrios Kyrtzidis      isa<CXXThisExpr>(Expr) ||
89720119a87fbb7719c161d81fc5f721f1ee6ed7e66Argyrios Kyrtzidis      isa<CXXTypeidExpr>(Expr) ||
89820119a87fbb7719c161d81fc5f721f1ee6ed7e66Argyrios Kyrtzidis      isa<CXXUnresolvedConstructExpr>(Expr) ||
89920119a87fbb7719c161d81fc5f721f1ee6ed7e66Argyrios Kyrtzidis      isa<ObjCMessageExpr>(Expr) ||
90020119a87fbb7719c161d81fc5f721f1ee6ed7e66Argyrios Kyrtzidis      isa<ObjCPropertyRefExpr>(Expr) ||
90120119a87fbb7719c161d81fc5f721f1ee6ed7e66Argyrios Kyrtzidis      isa<ObjCProtocolExpr>(Expr) ||
90220119a87fbb7719c161d81fc5f721f1ee6ed7e66Argyrios Kyrtzidis      isa<MemberExpr>(Expr) ||
9032bddd43bd87efedc308094e80af3917ef2c9a0d4Argyrios Kyrtzidis      isa<ObjCIvarRefExpr>(Expr) ||
90420119a87fbb7719c161d81fc5f721f1ee6ed7e66Argyrios Kyrtzidis      isa<ParenExpr>(FullExpr) ||
90520119a87fbb7719c161d81fc5f721f1ee6ed7e66Argyrios Kyrtzidis      isa<ParenListExpr>(Expr) ||
90620119a87fbb7719c161d81fc5f721f1ee6ed7e66Argyrios Kyrtzidis      isa<SizeOfPackExpr>(Expr))
90720119a87fbb7719c161d81fc5f721f1ee6ed7e66Argyrios Kyrtzidis    return false;
90820119a87fbb7719c161d81fc5f721f1ee6ed7e66Argyrios Kyrtzidis
90920119a87fbb7719c161d81fc5f721f1ee6ed7e66Argyrios Kyrtzidis  return true;
91020119a87fbb7719c161d81fc5f721f1ee6ed7e66Argyrios Kyrtzidis}
911055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidisstatic bool castOperatorNeedsParens(const Expr *FullExpr) {
912055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidis  const Expr* Expr = FullExpr->IgnoreImpCasts();
913055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidis  if (isa<ArraySubscriptExpr>(Expr) ||
914055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidis      isa<CallExpr>(Expr) ||
915055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidis      isa<DeclRefExpr>(Expr) ||
916055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidis      isa<CastExpr>(Expr) ||
917055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidis      isa<CXXNewExpr>(Expr) ||
918055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidis      isa<CXXConstructExpr>(Expr) ||
919055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidis      isa<CXXDeleteExpr>(Expr) ||
920055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidis      isa<CXXNoexceptExpr>(Expr) ||
921055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidis      isa<CXXPseudoDestructorExpr>(Expr) ||
922055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidis      isa<CXXScalarValueInitExpr>(Expr) ||
923055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidis      isa<CXXThisExpr>(Expr) ||
924055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidis      isa<CXXTypeidExpr>(Expr) ||
925055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidis      isa<CXXUnresolvedConstructExpr>(Expr) ||
926055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidis      isa<ObjCMessageExpr>(Expr) ||
927055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidis      isa<ObjCPropertyRefExpr>(Expr) ||
928055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidis      isa<ObjCProtocolExpr>(Expr) ||
929055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidis      isa<MemberExpr>(Expr) ||
9302bddd43bd87efedc308094e80af3917ef2c9a0d4Argyrios Kyrtzidis      isa<ObjCIvarRefExpr>(Expr) ||
931055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidis      isa<ParenExpr>(FullExpr) ||
932055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidis      isa<ParenListExpr>(Expr) ||
933055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidis      isa<SizeOfPackExpr>(Expr) ||
934055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidis      isa<UnaryOperator>(Expr))
935055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidis    return false;
936055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidis
937055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidis  return true;
938055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidis}
939055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidis
940055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidisstatic void objectifyExpr(const Expr *E, Commit &commit) {
941055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidis  if (!E) return;
942055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidis
943055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidis  QualType T = E->getType();
944055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidis  if (T->isObjCObjectPointerType()) {
945055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidis    if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
946055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidis      if (ICE->getCastKind() != CK_CPointerToObjCPointerCast)
947055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidis        return;
948055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidis    } else {
949055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidis      return;
950055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidis    }
951055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidis  } else if (!T->isPointerType()) {
952055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidis    return;
953055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidis  }
954055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidis
955055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidis  SourceRange Range = E->getSourceRange();
956055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidis  if (castOperatorNeedsParens(E))
957055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidis    commit.insertWrap("(", Range, ")");
958055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidis  commit.insertBefore(Range.getBegin(), "(id)");
959055b395294d190a432e9d87bb665634636a1418aArgyrios Kyrtzidis}
9600d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis
9610d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis//===----------------------------------------------------------------------===//
9620d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis// rewriteToNumericBoxedExpression.
9630d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis//===----------------------------------------------------------------------===//
9640d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis
965c5d33e959b45987bb97a7fcf639cdf5ce55987edArgyrios Kyrtzidisstatic bool isEnumConstant(const Expr *E) {
966c5d33e959b45987bb97a7fcf639cdf5ce55987edArgyrios Kyrtzidis  if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts()))
967c5d33e959b45987bb97a7fcf639cdf5ce55987edArgyrios Kyrtzidis    if (const ValueDecl *VD = DRE->getDecl())
968c5d33e959b45987bb97a7fcf639cdf5ce55987edArgyrios Kyrtzidis      return isa<EnumConstantDecl>(VD);
969c5d33e959b45987bb97a7fcf639cdf5ce55987edArgyrios Kyrtzidis
970c5d33e959b45987bb97a7fcf639cdf5ce55987edArgyrios Kyrtzidis  return false;
971c5d33e959b45987bb97a7fcf639cdf5ce55987edArgyrios Kyrtzidis}
972c5d33e959b45987bb97a7fcf639cdf5ce55987edArgyrios Kyrtzidis
9730d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidisstatic bool rewriteToNumericBoxedExpression(const ObjCMessageExpr *Msg,
9740d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis                                            const NSAPI &NS, Commit &commit) {
9750d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis  if (Msg->getNumArgs() != 1)
9760d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    return false;
9770d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis
9780d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis  const Expr *Arg = Msg->getArg(0);
9790d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis  if (Arg->isTypeDependent())
9800d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    return false;
9810d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis
9820d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis  ASTContext &Ctx = NS.getASTContext();
9830d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis  Selector Sel = Msg->getSelector();
984dc84cd5efdd3430efb22546b4ac656aa0540b210David Blaikie  Optional<NSAPI::NSNumberLiteralMethodKind>
9850d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    MKOpt = NS.getNSNumberLiteralMethodKind(Sel);
9860d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis  if (!MKOpt)
9870d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    return false;
9880d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis  NSAPI::NSNumberLiteralMethodKind MK = *MKOpt;
9890d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis
9900d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis  const Expr *OrigArg = Arg->IgnoreImpCasts();
9910d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis  QualType FinalTy = Arg->getType();
9920d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis  QualType OrigTy = OrigArg->getType();
9930d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis  uint64_t FinalTySize = Ctx.getTypeSize(FinalTy);
9940d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis  uint64_t OrigTySize = Ctx.getTypeSize(OrigTy);
9950d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis
9960d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis  bool isTruncated = FinalTySize < OrigTySize;
9970d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis  bool needsCast = false;
9980d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis
9990d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis  if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Arg)) {
10000d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    switch (ICE->getCastKind()) {
10010d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    case CK_LValueToRValue:
10020d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    case CK_NoOp:
10030d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    case CK_UserDefinedConversion:
10040d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis      break;
10050d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis
10060d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    case CK_IntegralCast: {
10070d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis      if (MK == NSAPI::NSNumberWithBool && OrigTy->isBooleanType())
10080d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis        break;
10090d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis      // Be more liberal with Integer/UnsignedInteger which are very commonly
10100d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis      // used.
10110d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis      if ((MK == NSAPI::NSNumberWithInteger ||
10120d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis           MK == NSAPI::NSNumberWithUnsignedInteger) &&
10130d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis          !isTruncated) {
1014c5d33e959b45987bb97a7fcf639cdf5ce55987edArgyrios Kyrtzidis        if (OrigTy->getAs<EnumType>() || isEnumConstant(OrigArg))
10150d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis          break;
10160d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis        if ((MK==NSAPI::NSNumberWithInteger) == OrigTy->isSignedIntegerType() &&
10170d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis            OrigTySize >= Ctx.getTypeSize(Ctx.IntTy))
10180d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis          break;
10190d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis      }
10200d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis
10210d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis      needsCast = true;
10220d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis      break;
10230d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    }
10240d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis
10250d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    case CK_PointerToBoolean:
10260d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    case CK_IntegralToBoolean:
10270d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    case CK_IntegralToFloating:
10280d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    case CK_FloatingToIntegral:
10290d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    case CK_FloatingToBoolean:
10300d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    case CK_FloatingCast:
10310d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    case CK_FloatingComplexToReal:
10320d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    case CK_FloatingComplexToBoolean:
10330d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    case CK_IntegralComplexToReal:
10340d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    case CK_IntegralComplexToBoolean:
10350d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    case CK_AtomicToNonAtomic:
1036651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    case CK_AddressSpaceConversion:
10370d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis      needsCast = true;
10380d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis      break;
10390d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis
10400d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    case CK_Dependent:
10410d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    case CK_BitCast:
10420d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    case CK_LValueBitCast:
10430d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    case CK_BaseToDerived:
10440d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    case CK_DerivedToBase:
10450d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    case CK_UncheckedDerivedToBase:
10460d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    case CK_Dynamic:
10470d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    case CK_ToUnion:
10480d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    case CK_ArrayToPointerDecay:
10490d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    case CK_FunctionToPointerDecay:
10500d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    case CK_NullToPointer:
10510d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    case CK_NullToMemberPointer:
10520d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    case CK_BaseToDerivedMemberPointer:
10530d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    case CK_DerivedToBaseMemberPointer:
10540d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    case CK_MemberPointerToBoolean:
10550d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    case CK_ReinterpretMemberPointer:
10560d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    case CK_ConstructorConversion:
10570d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    case CK_IntegralToPointer:
10580d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    case CK_PointerToIntegral:
10590d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    case CK_ToVoid:
10600d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    case CK_VectorSplat:
10610d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    case CK_CPointerToObjCPointerCast:
10620d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    case CK_BlockPointerToObjCPointerCast:
10630d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    case CK_AnyPointerToBlockPointerCast:
10640d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    case CK_ObjCObjectLValueCast:
10650d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    case CK_FloatingRealToComplex:
10660d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    case CK_FloatingComplexCast:
10670d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    case CK_FloatingComplexToIntegralComplex:
10680d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    case CK_IntegralRealToComplex:
10690d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    case CK_IntegralComplexCast:
10700d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    case CK_IntegralComplexToFloatingComplex:
10710d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    case CK_ARCProduceObject:
10720d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    case CK_ARCConsumeObject:
10730d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    case CK_ARCReclaimReturnedObject:
10740d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    case CK_ARCExtendBlockObject:
10750d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    case CK_NonAtomicToAtomic:
10760d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    case CK_CopyAndAutoreleaseBlockObject:
1077a6c66cedc022c9e5d45a937d6b8cff491a6bf81bEli Friedman    case CK_BuiltinFnToFnPtr:
1078e6b9d802fb7b16d93474c4f1c179ab36202e8a8bGuy Benyei    case CK_ZeroToOCLEvent:
10790d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis      return false;
10800d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    }
10810d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis  }
10820d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis
1083013a254a5b85cfb54066e4022649368689c9ab06Argyrios Kyrtzidis  if (needsCast) {
1084013a254a5b85cfb54066e4022649368689c9ab06Argyrios Kyrtzidis    DiagnosticsEngine &Diags = Ctx.getDiagnostics();
1085013a254a5b85cfb54066e4022649368689c9ab06Argyrios Kyrtzidis    // FIXME: Use a custom category name to distinguish migration diagnostics.
1086013a254a5b85cfb54066e4022649368689c9ab06Argyrios Kyrtzidis    unsigned diagID = Diags.getCustomDiagID(DiagnosticsEngine::Warning,
10878b9fcd7cd1f92e67655899d00fbaeb125c5a0d88Argyrios Kyrtzidis                       "converting to boxing syntax requires casting %0 to %1");
10888b9fcd7cd1f92e67655899d00fbaeb125c5a0d88Argyrios Kyrtzidis    Diags.Report(Msg->getExprLoc(), diagID) << OrigTy << FinalTy
10898b9fcd7cd1f92e67655899d00fbaeb125c5a0d88Argyrios Kyrtzidis        << Msg->getSourceRange();
10900d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    return false;
1091013a254a5b85cfb54066e4022649368689c9ab06Argyrios Kyrtzidis  }
10920d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis
10930d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis  SourceRange ArgRange = OrigArg->getSourceRange();
10947fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidis  commit.replaceWithInner(Msg->getSourceRange(), ArgRange);
10950d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis
10960d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis  if (isa<ParenExpr>(OrigArg) || isa<IntegerLiteral>(OrigArg))
10970d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    commit.insertBefore(ArgRange.getBegin(), "@");
10980d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis  else
10990d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis    commit.insertWrap("@(", ArgRange, ")");
11000d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis
11010d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis  return true;
11020d578a6f873697309e6dd027352fa0716e29986fArgyrios Kyrtzidis}
11037fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidis
11047fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidis//===----------------------------------------------------------------------===//
11057fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidis// rewriteToStringBoxedExpression.
11067fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidis//===----------------------------------------------------------------------===//
11077fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidis
11087fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidisstatic bool doRewriteToUTF8StringBoxedExpressionHelper(
11097fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidis                                              const ObjCMessageExpr *Msg,
11107fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidis                                              const NSAPI &NS, Commit &commit) {
11117fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidis  const Expr *Arg = Msg->getArg(0);
11127fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidis  if (Arg->isTypeDependent())
11137fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidis    return false;
11147fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidis
11150773659881064e7773a63eabc26a4d90293e2f04Argyrios Kyrtzidis  ASTContext &Ctx = NS.getASTContext();
11160773659881064e7773a63eabc26a4d90293e2f04Argyrios Kyrtzidis
11177fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidis  const Expr *OrigArg = Arg->IgnoreImpCasts();
11187fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidis  QualType OrigTy = OrigArg->getType();
11190773659881064e7773a63eabc26a4d90293e2f04Argyrios Kyrtzidis  if (OrigTy->isArrayType())
11200773659881064e7773a63eabc26a4d90293e2f04Argyrios Kyrtzidis    OrigTy = Ctx.getArrayDecayedType(OrigTy);
11217fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidis
11227fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidis  if (const StringLiteral *
11237fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidis        StrE = dyn_cast<StringLiteral>(OrigArg->IgnoreParens())) {
11247fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidis    commit.replaceWithInner(Msg->getSourceRange(), StrE->getSourceRange());
11257fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidis    commit.insert(StrE->getLocStart(), "@");
11267fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidis    return true;
11277fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidis  }
11287fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidis
11297fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidis  if (const PointerType *PT = OrigTy->getAs<PointerType>()) {
11307fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidis    QualType PointeeType = PT->getPointeeType();
11317fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidis    if (Ctx.hasSameUnqualifiedType(PointeeType, Ctx.CharTy)) {
11327fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidis      SourceRange ArgRange = OrigArg->getSourceRange();
11337fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidis      commit.replaceWithInner(Msg->getSourceRange(), ArgRange);
11347fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidis
11357fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidis      if (isa<ParenExpr>(OrigArg) || isa<IntegerLiteral>(OrigArg))
11367fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidis        commit.insertBefore(ArgRange.getBegin(), "@");
11377fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidis      else
11387fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidis        commit.insertWrap("@(", ArgRange, ")");
11397fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidis
11407fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidis      return true;
11417fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidis    }
11427fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidis  }
11437fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidis
11447fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidis  return false;
11457fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidis}
11467fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidis
11477fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidisstatic bool rewriteToStringBoxedExpression(const ObjCMessageExpr *Msg,
11487fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidis                                           const NSAPI &NS, Commit &commit) {
11497fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidis  Selector Sel = Msg->getSelector();
11507fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidis
11517fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidis  if (Sel == NS.getNSStringSelector(NSAPI::NSStr_stringWithUTF8String) ||
11527fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidis      Sel == NS.getNSStringSelector(NSAPI::NSStr_stringWithCString)) {
11537fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidis    if (Msg->getNumArgs() != 1)
11547fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidis      return false;
11557fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidis    return doRewriteToUTF8StringBoxedExpressionHelper(Msg, NS, commit);
11567fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidis  }
11577fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidis
11587fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidis  if (Sel == NS.getNSStringSelector(NSAPI::NSStr_stringWithCStringEncoding)) {
11597fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidis    if (Msg->getNumArgs() != 2)
11607fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidis      return false;
11617fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidis
11627fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidis    const Expr *encodingArg = Msg->getArg(1);
11637fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidis    if (NS.isNSUTF8StringEncodingConstant(encodingArg) ||
11647fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidis        NS.isNSASCIIStringEncodingConstant(encodingArg))
11657fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidis      return doRewriteToUTF8StringBoxedExpressionHelper(Msg, NS, commit);
11667fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidis  }
11677fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidis
11687fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidis  return false;
11697fe103cdcc00a675aac04a11975dc078aba47db5Argyrios Kyrtzidis}
1170