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