diff options
| author | 2020-08-03 15:06:44 +0000 | |
|---|---|---|
| committer | 2020-08-03 15:06:44 +0000 | |
| commit | b64793999546ed8adebaeebd9d8345d18db8927d (patch) | |
| tree | 4357c27b561d73b0e089727c6ed659f2ceff5f47 /gnu/llvm/tools/clang/lib/Edit/RewriteObjCFoundationAPI.cpp | |
| parent | Add support for UTF-8 DISPLAY-HINTs with octet length. For now only (diff) | |
| download | wireguard-openbsd-b64793999546ed8adebaeebd9d8345d18db8927d.tar.xz wireguard-openbsd-b64793999546ed8adebaeebd9d8345d18db8927d.zip | |
Remove LLVM 8.0.1 files.
Diffstat (limited to 'gnu/llvm/tools/clang/lib/Edit/RewriteObjCFoundationAPI.cpp')
| -rw-r--r-- | gnu/llvm/tools/clang/lib/Edit/RewriteObjCFoundationAPI.cpp | 1181 |
1 files changed, 0 insertions, 1181 deletions
diff --git a/gnu/llvm/tools/clang/lib/Edit/RewriteObjCFoundationAPI.cpp b/gnu/llvm/tools/clang/lib/Edit/RewriteObjCFoundationAPI.cpp deleted file mode 100644 index 7c9ab170093..00000000000 --- a/gnu/llvm/tools/clang/lib/Edit/RewriteObjCFoundationAPI.cpp +++ /dev/null @@ -1,1181 +0,0 @@ -//===--- RewriteObjCFoundationAPI.cpp - Foundation API Rewriter -----------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Rewrites legacy method calls to modern syntax. -// -//===----------------------------------------------------------------------===// - -#include "clang/Edit/Rewriters.h" -#include "clang/AST/ASTContext.h" -#include "clang/AST/ExprCXX.h" -#include "clang/AST/ExprObjC.h" -#include "clang/AST/NSAPI.h" -#include "clang/AST/ParentMap.h" -#include "clang/Edit/Commit.h" -#include "clang/Lex/Lexer.h" - -using namespace clang; -using namespace edit; - -static bool checkForLiteralCreation(const ObjCMessageExpr *Msg, - IdentifierInfo *&ClassId, - const LangOptions &LangOpts) { - if (!Msg || Msg->isImplicit() || !Msg->getMethodDecl()) - return false; - - const ObjCInterfaceDecl *Receiver = Msg->getReceiverInterface(); - if (!Receiver) - return false; - ClassId = Receiver->getIdentifier(); - - if (Msg->getReceiverKind() == ObjCMessageExpr::Class) - return true; - - // When in ARC mode we also convert "[[.. alloc] init]" messages to literals, - // since the change from +1 to +0 will be handled fine by ARC. - if (LangOpts.ObjCAutoRefCount) { - if (Msg->getReceiverKind() == ObjCMessageExpr::Instance) { - if (const ObjCMessageExpr *Rec = dyn_cast<ObjCMessageExpr>( - Msg->getInstanceReceiver()->IgnoreParenImpCasts())) { - if (Rec->getMethodFamily() == OMF_alloc) - return true; - } - } - } - - return false; -} - -//===----------------------------------------------------------------------===// -// rewriteObjCRedundantCallWithLiteral. -//===----------------------------------------------------------------------===// - -bool edit::rewriteObjCRedundantCallWithLiteral(const ObjCMessageExpr *Msg, - const NSAPI &NS, Commit &commit) { - IdentifierInfo *II = nullptr; - if (!checkForLiteralCreation(Msg, II, NS.getASTContext().getLangOpts())) - return false; - if (Msg->getNumArgs() != 1) - return false; - - const Expr *Arg = Msg->getArg(0)->IgnoreParenImpCasts(); - Selector Sel = Msg->getSelector(); - - if ((isa<ObjCStringLiteral>(Arg) && - NS.getNSClassId(NSAPI::ClassId_NSString) == II && - (NS.getNSStringSelector(NSAPI::NSStr_stringWithString) == Sel || - NS.getNSStringSelector(NSAPI::NSStr_initWithString) == Sel)) || - - (isa<ObjCArrayLiteral>(Arg) && - NS.getNSClassId(NSAPI::ClassId_NSArray) == II && - (NS.getNSArraySelector(NSAPI::NSArr_arrayWithArray) == Sel || - NS.getNSArraySelector(NSAPI::NSArr_initWithArray) == Sel)) || - - (isa<ObjCDictionaryLiteral>(Arg) && - NS.getNSClassId(NSAPI::ClassId_NSDictionary) == II && - (NS.getNSDictionarySelector( - NSAPI::NSDict_dictionaryWithDictionary) == Sel || - NS.getNSDictionarySelector(NSAPI::NSDict_initWithDictionary) == Sel))) { - - commit.replaceWithInner(Msg->getSourceRange(), - Msg->getArg(0)->getSourceRange()); - return true; - } - - return false; -} - -//===----------------------------------------------------------------------===// -// rewriteToObjCSubscriptSyntax. -//===----------------------------------------------------------------------===// - -/// Check for classes that accept 'objectForKey:' (or the other selectors -/// that the migrator handles) but return their instances as 'id', resulting -/// in the compiler resolving 'objectForKey:' as the method from NSDictionary. -/// -/// When checking if we can convert to subscripting syntax, check whether -/// the receiver is a result of a class method from a hardcoded list of -/// such classes. In such a case return the specific class as the interface -/// of the receiver. -/// -/// FIXME: Remove this when these classes start using 'instancetype'. -static const ObjCInterfaceDecl * -maybeAdjustInterfaceForSubscriptingCheck(const ObjCInterfaceDecl *IFace, - const Expr *Receiver, - ASTContext &Ctx) { - assert(IFace && Receiver); - - // If the receiver has type 'id'... - if (!Ctx.isObjCIdType(Receiver->getType().getUnqualifiedType())) - return IFace; - - const ObjCMessageExpr * - InnerMsg = dyn_cast<ObjCMessageExpr>(Receiver->IgnoreParenCasts()); - if (!InnerMsg) - return IFace; - - QualType ClassRec; - switch (InnerMsg->getReceiverKind()) { - case ObjCMessageExpr::Instance: - case ObjCMessageExpr::SuperInstance: - return IFace; - - case ObjCMessageExpr::Class: - ClassRec = InnerMsg->getClassReceiver(); - break; - case ObjCMessageExpr::SuperClass: - ClassRec = InnerMsg->getSuperType(); - break; - } - - if (ClassRec.isNull()) - return IFace; - - // ...and it is the result of a class message... - - const ObjCObjectType *ObjTy = ClassRec->getAs<ObjCObjectType>(); - if (!ObjTy) - return IFace; - const ObjCInterfaceDecl *OID = ObjTy->getInterface(); - - // ...and the receiving class is NSMapTable or NSLocale, return that - // class as the receiving interface. - if (OID->getName() == "NSMapTable" || - OID->getName() == "NSLocale") - return OID; - - return IFace; -} - -static bool canRewriteToSubscriptSyntax(const ObjCInterfaceDecl *&IFace, - const ObjCMessageExpr *Msg, - ASTContext &Ctx, - Selector subscriptSel) { - const Expr *Rec = Msg->getInstanceReceiver(); - if (!Rec) - return false; - IFace = maybeAdjustInterfaceForSubscriptingCheck(IFace, Rec, Ctx); - - if (const ObjCMethodDecl *MD = IFace->lookupInstanceMethod(subscriptSel)) { - if (!MD->isUnavailable()) - return true; - } - return false; -} - -static bool subscriptOperatorNeedsParens(const Expr *FullExpr); - -static void maybePutParensOnReceiver(const Expr *Receiver, Commit &commit) { - if (subscriptOperatorNeedsParens(Receiver)) { - SourceRange RecRange = Receiver->getSourceRange(); - commit.insertWrap("(", RecRange, ")"); - } -} - -static bool rewriteToSubscriptGetCommon(const ObjCMessageExpr *Msg, - Commit &commit) { - if (Msg->getNumArgs() != 1) - return false; - const Expr *Rec = Msg->getInstanceReceiver(); - if (!Rec) - return false; - - SourceRange MsgRange = Msg->getSourceRange(); - SourceRange RecRange = Rec->getSourceRange(); - SourceRange ArgRange = Msg->getArg(0)->getSourceRange(); - - commit.replaceWithInner(CharSourceRange::getCharRange(MsgRange.getBegin(), - ArgRange.getBegin()), - CharSourceRange::getTokenRange(RecRange)); - commit.replaceWithInner(SourceRange(ArgRange.getBegin(), MsgRange.getEnd()), - ArgRange); - commit.insertWrap("[", ArgRange, "]"); - maybePutParensOnReceiver(Rec, commit); - return true; -} - -static bool rewriteToArraySubscriptGet(const ObjCInterfaceDecl *IFace, - const ObjCMessageExpr *Msg, - const NSAPI &NS, - Commit &commit) { - if (!canRewriteToSubscriptSyntax(IFace, Msg, NS.getASTContext(), - NS.getObjectAtIndexedSubscriptSelector())) - return false; - return rewriteToSubscriptGetCommon(Msg, commit); -} - -static bool rewriteToDictionarySubscriptGet(const ObjCInterfaceDecl *IFace, - const ObjCMessageExpr *Msg, - const NSAPI &NS, - Commit &commit) { - if (!canRewriteToSubscriptSyntax(IFace, Msg, NS.getASTContext(), - NS.getObjectForKeyedSubscriptSelector())) - return false; - return rewriteToSubscriptGetCommon(Msg, commit); -} - -static bool rewriteToArraySubscriptSet(const ObjCInterfaceDecl *IFace, - const ObjCMessageExpr *Msg, - const NSAPI &NS, - Commit &commit) { - if (!canRewriteToSubscriptSyntax(IFace, Msg, NS.getASTContext(), - NS.getSetObjectAtIndexedSubscriptSelector())) - return false; - - if (Msg->getNumArgs() != 2) - return false; - const Expr *Rec = Msg->getInstanceReceiver(); - if (!Rec) - return false; - - SourceRange MsgRange = Msg->getSourceRange(); - SourceRange RecRange = Rec->getSourceRange(); - SourceRange Arg0Range = Msg->getArg(0)->getSourceRange(); - SourceRange Arg1Range = Msg->getArg(1)->getSourceRange(); - - commit.replaceWithInner(CharSourceRange::getCharRange(MsgRange.getBegin(), - Arg0Range.getBegin()), - CharSourceRange::getTokenRange(RecRange)); - commit.replaceWithInner(CharSourceRange::getCharRange(Arg0Range.getBegin(), - Arg1Range.getBegin()), - CharSourceRange::getTokenRange(Arg0Range)); - commit.replaceWithInner(SourceRange(Arg1Range.getBegin(), MsgRange.getEnd()), - Arg1Range); - commit.insertWrap("[", CharSourceRange::getCharRange(Arg0Range.getBegin(), - Arg1Range.getBegin()), - "] = "); - maybePutParensOnReceiver(Rec, commit); - return true; -} - -static bool rewriteToDictionarySubscriptSet(const ObjCInterfaceDecl *IFace, - const ObjCMessageExpr *Msg, - const NSAPI &NS, - Commit &commit) { - if (!canRewriteToSubscriptSyntax(IFace, Msg, NS.getASTContext(), - NS.getSetObjectForKeyedSubscriptSelector())) - return false; - - if (Msg->getNumArgs() != 2) - return false; - const Expr *Rec = Msg->getInstanceReceiver(); - if (!Rec) - return false; - - SourceRange MsgRange = Msg->getSourceRange(); - SourceRange RecRange = Rec->getSourceRange(); - SourceRange Arg0Range = Msg->getArg(0)->getSourceRange(); - SourceRange Arg1Range = Msg->getArg(1)->getSourceRange(); - - SourceLocation LocBeforeVal = Arg0Range.getBegin(); - commit.insertBefore(LocBeforeVal, "] = "); - commit.insertFromRange(LocBeforeVal, Arg1Range, /*afterToken=*/false, - /*beforePreviousInsertions=*/true); - commit.insertBefore(LocBeforeVal, "["); - commit.replaceWithInner(CharSourceRange::getCharRange(MsgRange.getBegin(), - Arg0Range.getBegin()), - CharSourceRange::getTokenRange(RecRange)); - commit.replaceWithInner(SourceRange(Arg0Range.getBegin(), MsgRange.getEnd()), - Arg0Range); - maybePutParensOnReceiver(Rec, commit); - return true; -} - -bool edit::rewriteToObjCSubscriptSyntax(const ObjCMessageExpr *Msg, - const NSAPI &NS, Commit &commit) { - if (!Msg || Msg->isImplicit() || - Msg->getReceiverKind() != ObjCMessageExpr::Instance) - return false; - const ObjCMethodDecl *Method = Msg->getMethodDecl(); - if (!Method) - return false; - - const ObjCInterfaceDecl *IFace = - NS.getASTContext().getObjContainingInterface(Method); - if (!IFace) - return false; - Selector Sel = Msg->getSelector(); - - if (Sel == NS.getNSArraySelector(NSAPI::NSArr_objectAtIndex)) - return rewriteToArraySubscriptGet(IFace, Msg, NS, commit); - - if (Sel == NS.getNSDictionarySelector(NSAPI::NSDict_objectForKey)) - return rewriteToDictionarySubscriptGet(IFace, Msg, NS, commit); - - if (Msg->getNumArgs() != 2) - return false; - - if (Sel == NS.getNSArraySelector(NSAPI::NSMutableArr_replaceObjectAtIndex)) - return rewriteToArraySubscriptSet(IFace, Msg, NS, commit); - - if (Sel == NS.getNSDictionarySelector(NSAPI::NSMutableDict_setObjectForKey)) - return rewriteToDictionarySubscriptSet(IFace, Msg, NS, commit); - - return false; -} - -//===----------------------------------------------------------------------===// -// rewriteToObjCLiteralSyntax. -//===----------------------------------------------------------------------===// - -static bool rewriteToArrayLiteral(const ObjCMessageExpr *Msg, - const NSAPI &NS, Commit &commit, - const ParentMap *PMap); -static bool rewriteToDictionaryLiteral(const ObjCMessageExpr *Msg, - const NSAPI &NS, Commit &commit); -static bool rewriteToNumberLiteral(const ObjCMessageExpr *Msg, - const NSAPI &NS, Commit &commit); -static bool rewriteToNumericBoxedExpression(const ObjCMessageExpr *Msg, - const NSAPI &NS, Commit &commit); -static bool rewriteToStringBoxedExpression(const ObjCMessageExpr *Msg, - const NSAPI &NS, Commit &commit); - -bool edit::rewriteToObjCLiteralSyntax(const ObjCMessageExpr *Msg, - const NSAPI &NS, Commit &commit, - const ParentMap *PMap) { - IdentifierInfo *II = nullptr; - if (!checkForLiteralCreation(Msg, II, NS.getASTContext().getLangOpts())) - return false; - - if (II == NS.getNSClassId(NSAPI::ClassId_NSArray)) - return rewriteToArrayLiteral(Msg, NS, commit, PMap); - if (II == NS.getNSClassId(NSAPI::ClassId_NSDictionary)) - return rewriteToDictionaryLiteral(Msg, NS, commit); - if (II == NS.getNSClassId(NSAPI::ClassId_NSNumber)) - return rewriteToNumberLiteral(Msg, NS, commit); - if (II == NS.getNSClassId(NSAPI::ClassId_NSString)) - return rewriteToStringBoxedExpression(Msg, NS, commit); - - return false; -} - -/// Returns true if the immediate message arguments of \c Msg should not -/// be rewritten because it will interfere with the rewrite of the parent -/// message expression. e.g. -/// \code -/// [NSDictionary dictionaryWithObjects: -/// [NSArray arrayWithObjects:@"1", @"2", nil] -/// forKeys:[NSArray arrayWithObjects:@"A", @"B", nil]]; -/// \endcode -/// It will return true for this because we are going to rewrite this directly -/// to a dictionary literal without any array literals. -static bool shouldNotRewriteImmediateMessageArgs(const ObjCMessageExpr *Msg, - const NSAPI &NS); - -//===----------------------------------------------------------------------===// -// rewriteToArrayLiteral. -//===----------------------------------------------------------------------===// - -/// Adds an explicit cast to 'id' if the type is not objc object. -static void objectifyExpr(const Expr *E, Commit &commit); - -static bool rewriteToArrayLiteral(const ObjCMessageExpr *Msg, - const NSAPI &NS, Commit &commit, - const ParentMap *PMap) { - if (PMap) { - const ObjCMessageExpr *ParentMsg = - dyn_cast_or_null<ObjCMessageExpr>(PMap->getParentIgnoreParenCasts(Msg)); - if (shouldNotRewriteImmediateMessageArgs(ParentMsg, NS)) - return false; - } - - Selector Sel = Msg->getSelector(); - SourceRange MsgRange = Msg->getSourceRange(); - - if (Sel == NS.getNSArraySelector(NSAPI::NSArr_array)) { - if (Msg->getNumArgs() != 0) - return false; - commit.replace(MsgRange, "@[]"); - return true; - } - - if (Sel == NS.getNSArraySelector(NSAPI::NSArr_arrayWithObject)) { - if (Msg->getNumArgs() != 1) - return false; - objectifyExpr(Msg->getArg(0), commit); - SourceRange ArgRange = Msg->getArg(0)->getSourceRange(); - commit.replaceWithInner(MsgRange, ArgRange); - commit.insertWrap("@[", ArgRange, "]"); - return true; - } - - if (Sel == NS.getNSArraySelector(NSAPI::NSArr_arrayWithObjects) || - Sel == NS.getNSArraySelector(NSAPI::NSArr_initWithObjects)) { - if (Msg->getNumArgs() == 0) - return false; - const Expr *SentinelExpr = Msg->getArg(Msg->getNumArgs() - 1); - if (!NS.getASTContext().isSentinelNullExpr(SentinelExpr)) - return false; - - for (unsigned i = 0, e = Msg->getNumArgs() - 1; i != e; ++i) - objectifyExpr(Msg->getArg(i), commit); - - if (Msg->getNumArgs() == 1) { - commit.replace(MsgRange, "@[]"); - return true; - } - SourceRange ArgRange(Msg->getArg(0)->getBeginLoc(), - Msg->getArg(Msg->getNumArgs() - 2)->getEndLoc()); - commit.replaceWithInner(MsgRange, ArgRange); - commit.insertWrap("@[", ArgRange, "]"); - return true; - } - - return false; -} - -//===----------------------------------------------------------------------===// -// rewriteToDictionaryLiteral. -//===----------------------------------------------------------------------===// - -/// If \c Msg is an NSArray creation message or literal, this gets the -/// objects that were used to create it. -/// \returns true if it is an NSArray and we got objects, or false otherwise. -static bool getNSArrayObjects(const Expr *E, const NSAPI &NS, - SmallVectorImpl<const Expr *> &Objs) { - if (!E) - return false; - - E = E->IgnoreParenCasts(); - if (!E) - return false; - - if (const ObjCMessageExpr *Msg = dyn_cast<ObjCMessageExpr>(E)) { - IdentifierInfo *Cls = nullptr; - if (!checkForLiteralCreation(Msg, Cls, NS.getASTContext().getLangOpts())) - return false; - - if (Cls != NS.getNSClassId(NSAPI::ClassId_NSArray)) - return false; - - Selector Sel = Msg->getSelector(); - if (Sel == NS.getNSArraySelector(NSAPI::NSArr_array)) - return true; // empty array. - - if (Sel == NS.getNSArraySelector(NSAPI::NSArr_arrayWithObject)) { - if (Msg->getNumArgs() != 1) - return false; - Objs.push_back(Msg->getArg(0)); - return true; - } - - if (Sel == NS.getNSArraySelector(NSAPI::NSArr_arrayWithObjects) || - Sel == NS.getNSArraySelector(NSAPI::NSArr_initWithObjects)) { - if (Msg->getNumArgs() == 0) - return false; - const Expr *SentinelExpr = Msg->getArg(Msg->getNumArgs() - 1); - if (!NS.getASTContext().isSentinelNullExpr(SentinelExpr)) - return false; - - for (unsigned i = 0, e = Msg->getNumArgs() - 1; i != e; ++i) - Objs.push_back(Msg->getArg(i)); - return true; - } - - } else if (const ObjCArrayLiteral *ArrLit = dyn_cast<ObjCArrayLiteral>(E)) { - for (unsigned i = 0, e = ArrLit->getNumElements(); i != e; ++i) - Objs.push_back(ArrLit->getElement(i)); - return true; - } - - return false; -} - -static bool rewriteToDictionaryLiteral(const ObjCMessageExpr *Msg, - const NSAPI &NS, Commit &commit) { - Selector Sel = Msg->getSelector(); - SourceRange MsgRange = Msg->getSourceRange(); - - if (Sel == NS.getNSDictionarySelector(NSAPI::NSDict_dictionary)) { - if (Msg->getNumArgs() != 0) - return false; - commit.replace(MsgRange, "@{}"); - return true; - } - - if (Sel == NS.getNSDictionarySelector( - NSAPI::NSDict_dictionaryWithObjectForKey)) { - if (Msg->getNumArgs() != 2) - return false; - - objectifyExpr(Msg->getArg(0), commit); - objectifyExpr(Msg->getArg(1), commit); - - SourceRange ValRange = Msg->getArg(0)->getSourceRange(); - SourceRange KeyRange = Msg->getArg(1)->getSourceRange(); - // Insert key before the value. - commit.insertBefore(ValRange.getBegin(), ": "); - commit.insertFromRange(ValRange.getBegin(), - CharSourceRange::getTokenRange(KeyRange), - /*afterToken=*/false, /*beforePreviousInsertions=*/true); - commit.insertBefore(ValRange.getBegin(), "@{"); - commit.insertAfterToken(ValRange.getEnd(), "}"); - commit.replaceWithInner(MsgRange, ValRange); - return true; - } - - if (Sel == NS.getNSDictionarySelector( - NSAPI::NSDict_dictionaryWithObjectsAndKeys) || - Sel == NS.getNSDictionarySelector(NSAPI::NSDict_initWithObjectsAndKeys)) { - if (Msg->getNumArgs() % 2 != 1) - return false; - unsigned SentinelIdx = Msg->getNumArgs() - 1; - const Expr *SentinelExpr = Msg->getArg(SentinelIdx); - if (!NS.getASTContext().isSentinelNullExpr(SentinelExpr)) - return false; - - if (Msg->getNumArgs() == 1) { - commit.replace(MsgRange, "@{}"); - return true; - } - - for (unsigned i = 0; i < SentinelIdx; i += 2) { - objectifyExpr(Msg->getArg(i), commit); - objectifyExpr(Msg->getArg(i+1), commit); - - SourceRange ValRange = Msg->getArg(i)->getSourceRange(); - SourceRange KeyRange = Msg->getArg(i+1)->getSourceRange(); - // Insert value after key. - commit.insertAfterToken(KeyRange.getEnd(), ": "); - commit.insertFromRange(KeyRange.getEnd(), ValRange, /*afterToken=*/true); - commit.remove(CharSourceRange::getCharRange(ValRange.getBegin(), - KeyRange.getBegin())); - } - // Range of arguments up until and including the last key. - // The sentinel and first value are cut off, the value will move after the - // key. - SourceRange ArgRange(Msg->getArg(1)->getBeginLoc(), - Msg->getArg(SentinelIdx - 1)->getEndLoc()); - commit.insertWrap("@{", ArgRange, "}"); - commit.replaceWithInner(MsgRange, ArgRange); - return true; - } - - if (Sel == NS.getNSDictionarySelector( - NSAPI::NSDict_dictionaryWithObjectsForKeys) || - Sel == NS.getNSDictionarySelector(NSAPI::NSDict_initWithObjectsForKeys)) { - if (Msg->getNumArgs() != 2) - return false; - - SmallVector<const Expr *, 8> Vals; - if (!getNSArrayObjects(Msg->getArg(0), NS, Vals)) - return false; - - SmallVector<const Expr *, 8> Keys; - if (!getNSArrayObjects(Msg->getArg(1), NS, Keys)) - return false; - - if (Vals.size() != Keys.size()) - return false; - - if (Vals.empty()) { - commit.replace(MsgRange, "@{}"); - return true; - } - - for (unsigned i = 0, n = Vals.size(); i < n; ++i) { - objectifyExpr(Vals[i], commit); - objectifyExpr(Keys[i], commit); - - SourceRange ValRange = Vals[i]->getSourceRange(); - SourceRange KeyRange = Keys[i]->getSourceRange(); - // Insert value after key. - commit.insertAfterToken(KeyRange.getEnd(), ": "); - commit.insertFromRange(KeyRange.getEnd(), ValRange, /*afterToken=*/true); - } - // Range of arguments up until and including the last key. - // The first value is cut off, the value will move after the key. - SourceRange ArgRange(Keys.front()->getBeginLoc(), Keys.back()->getEndLoc()); - commit.insertWrap("@{", ArgRange, "}"); - commit.replaceWithInner(MsgRange, ArgRange); - return true; - } - - return false; -} - -static bool shouldNotRewriteImmediateMessageArgs(const ObjCMessageExpr *Msg, - const NSAPI &NS) { - if (!Msg) - return false; - - IdentifierInfo *II = nullptr; - if (!checkForLiteralCreation(Msg, II, NS.getASTContext().getLangOpts())) - return false; - - if (II != NS.getNSClassId(NSAPI::ClassId_NSDictionary)) - return false; - - Selector Sel = Msg->getSelector(); - if (Sel == NS.getNSDictionarySelector( - NSAPI::NSDict_dictionaryWithObjectsForKeys) || - Sel == NS.getNSDictionarySelector(NSAPI::NSDict_initWithObjectsForKeys)) { - if (Msg->getNumArgs() != 2) - return false; - - SmallVector<const Expr *, 8> Vals; - if (!getNSArrayObjects(Msg->getArg(0), NS, Vals)) - return false; - - SmallVector<const Expr *, 8> Keys; - if (!getNSArrayObjects(Msg->getArg(1), NS, Keys)) - return false; - - if (Vals.size() != Keys.size()) - return false; - - return true; - } - - return false; -} - -//===----------------------------------------------------------------------===// -// rewriteToNumberLiteral. -//===----------------------------------------------------------------------===// - -static bool rewriteToCharLiteral(const ObjCMessageExpr *Msg, - const CharacterLiteral *Arg, - const NSAPI &NS, Commit &commit) { - if (Arg->getKind() != CharacterLiteral::Ascii) - return false; - if (NS.isNSNumberLiteralSelector(NSAPI::NSNumberWithChar, - Msg->getSelector())) { - SourceRange ArgRange = Arg->getSourceRange(); - commit.replaceWithInner(Msg->getSourceRange(), ArgRange); - commit.insert(ArgRange.getBegin(), "@"); - return true; - } - - return rewriteToNumericBoxedExpression(Msg, NS, commit); -} - -static bool rewriteToBoolLiteral(const ObjCMessageExpr *Msg, - const Expr *Arg, - const NSAPI &NS, Commit &commit) { - if (NS.isNSNumberLiteralSelector(NSAPI::NSNumberWithBool, - Msg->getSelector())) { - SourceRange ArgRange = Arg->getSourceRange(); - commit.replaceWithInner(Msg->getSourceRange(), ArgRange); - commit.insert(ArgRange.getBegin(), "@"); - return true; - } - - return rewriteToNumericBoxedExpression(Msg, NS, commit); -} - -namespace { - -struct LiteralInfo { - bool Hex, Octal; - StringRef U, F, L, LL; - CharSourceRange WithoutSuffRange; -}; - -} - -static bool getLiteralInfo(SourceRange literalRange, - bool isFloat, bool isIntZero, - ASTContext &Ctx, LiteralInfo &Info) { - if (literalRange.getBegin().isMacroID() || - literalRange.getEnd().isMacroID()) - return false; - StringRef text = Lexer::getSourceText( - CharSourceRange::getTokenRange(literalRange), - Ctx.getSourceManager(), Ctx.getLangOpts()); - if (text.empty()) - return false; - - Optional<bool> UpperU, UpperL; - bool UpperF = false; - - struct Suff { - static bool has(StringRef suff, StringRef &text) { - if (text.endswith(suff)) { - text = text.substr(0, text.size()-suff.size()); - return true; - } - return false; - } - }; - - while (1) { - if (Suff::has("u", text)) { - UpperU = false; - } else if (Suff::has("U", text)) { - UpperU = true; - } else if (Suff::has("ll", text)) { - UpperL = false; - } else if (Suff::has("LL", text)) { - UpperL = true; - } else if (Suff::has("l", text)) { - UpperL = false; - } else if (Suff::has("L", text)) { - UpperL = true; - } else if (isFloat && Suff::has("f", text)) { - UpperF = false; - } else if (isFloat && Suff::has("F", text)) { - UpperF = true; - } else - break; - } - - if (!UpperU.hasValue() && !UpperL.hasValue()) - UpperU = UpperL = true; - else if (UpperU.hasValue() && !UpperL.hasValue()) - UpperL = UpperU; - else if (UpperL.hasValue() && !UpperU.hasValue()) - UpperU = UpperL; - - Info.U = *UpperU ? "U" : "u"; - Info.L = *UpperL ? "L" : "l"; - Info.LL = *UpperL ? "LL" : "ll"; - Info.F = UpperF ? "F" : "f"; - - Info.Hex = Info.Octal = false; - if (text.startswith("0x")) - Info.Hex = true; - else if (!isFloat && !isIntZero && text.startswith("0")) - Info.Octal = true; - - SourceLocation B = literalRange.getBegin(); - Info.WithoutSuffRange = - CharSourceRange::getCharRange(B, B.getLocWithOffset(text.size())); - return true; -} - -static bool rewriteToNumberLiteral(const ObjCMessageExpr *Msg, - const NSAPI &NS, Commit &commit) { - if (Msg->getNumArgs() != 1) - return false; - - const Expr *Arg = Msg->getArg(0)->IgnoreParenImpCasts(); - if (const CharacterLiteral *CharE = dyn_cast<CharacterLiteral>(Arg)) - return rewriteToCharLiteral(Msg, CharE, NS, commit); - if (const ObjCBoolLiteralExpr *BE = dyn_cast<ObjCBoolLiteralExpr>(Arg)) - return rewriteToBoolLiteral(Msg, BE, NS, commit); - if (const CXXBoolLiteralExpr *BE = dyn_cast<CXXBoolLiteralExpr>(Arg)) - return rewriteToBoolLiteral(Msg, BE, NS, commit); - - const Expr *literalE = Arg; - if (const UnaryOperator *UOE = dyn_cast<UnaryOperator>(literalE)) { - if (UOE->getOpcode() == UO_Plus || UOE->getOpcode() == UO_Minus) - literalE = UOE->getSubExpr(); - } - - // Only integer and floating literals, otherwise try to rewrite to boxed - // expression. - if (!isa<IntegerLiteral>(literalE) && !isa<FloatingLiteral>(literalE)) - return rewriteToNumericBoxedExpression(Msg, NS, commit); - - ASTContext &Ctx = NS.getASTContext(); - Selector Sel = Msg->getSelector(); - Optional<NSAPI::NSNumberLiteralMethodKind> - MKOpt = NS.getNSNumberLiteralMethodKind(Sel); - if (!MKOpt) - return false; - NSAPI::NSNumberLiteralMethodKind MK = *MKOpt; - - bool CallIsUnsigned = false, CallIsLong = false, CallIsLongLong = false; - bool CallIsFloating = false, CallIsDouble = false; - - switch (MK) { - // We cannot have these calls with int/float literals. - case NSAPI::NSNumberWithChar: - case NSAPI::NSNumberWithUnsignedChar: - case NSAPI::NSNumberWithShort: - case NSAPI::NSNumberWithUnsignedShort: - case NSAPI::NSNumberWithBool: - return rewriteToNumericBoxedExpression(Msg, NS, commit); - - case NSAPI::NSNumberWithUnsignedInt: - case NSAPI::NSNumberWithUnsignedInteger: - CallIsUnsigned = true; - LLVM_FALLTHROUGH; - case NSAPI::NSNumberWithInt: - case NSAPI::NSNumberWithInteger: - break; - - case NSAPI::NSNumberWithUnsignedLong: - CallIsUnsigned = true; - LLVM_FALLTHROUGH; - case NSAPI::NSNumberWithLong: - CallIsLong = true; - break; - - case NSAPI::NSNumberWithUnsignedLongLong: - CallIsUnsigned = true; - LLVM_FALLTHROUGH; - case NSAPI::NSNumberWithLongLong: - CallIsLongLong = true; - break; - - case NSAPI::NSNumberWithDouble: - CallIsDouble = true; - LLVM_FALLTHROUGH; - case NSAPI::NSNumberWithFloat: - CallIsFloating = true; - break; - } - - SourceRange ArgRange = Arg->getSourceRange(); - QualType ArgTy = Arg->getType(); - QualType CallTy = Msg->getArg(0)->getType(); - - // Check for the easy case, the literal maps directly to the call. - if (Ctx.hasSameType(ArgTy, CallTy)) { - commit.replaceWithInner(Msg->getSourceRange(), ArgRange); - commit.insert(ArgRange.getBegin(), "@"); - return true; - } - - // We will need to modify the literal suffix to get the same type as the call. - // Try with boxed expression if it came from a macro. - if (ArgRange.getBegin().isMacroID()) - return rewriteToNumericBoxedExpression(Msg, NS, commit); - - bool LitIsFloat = ArgTy->isFloatingType(); - // For a float passed to integer call, don't try rewriting to objc literal. - // It is difficult and a very uncommon case anyway. - // But try with boxed expression. - if (LitIsFloat && !CallIsFloating) - return rewriteToNumericBoxedExpression(Msg, NS, commit); - - // Try to modify the literal make it the same type as the method call. - // -Modify the suffix, and/or - // -Change integer to float - - LiteralInfo LitInfo; - bool isIntZero = false; - if (const IntegerLiteral *IntE = dyn_cast<IntegerLiteral>(literalE)) - isIntZero = !IntE->getValue().getBoolValue(); - if (!getLiteralInfo(ArgRange, LitIsFloat, isIntZero, Ctx, LitInfo)) - return rewriteToNumericBoxedExpression(Msg, NS, commit); - - // Not easy to do int -> float with hex/octal and uncommon anyway. - if (!LitIsFloat && CallIsFloating && (LitInfo.Hex || LitInfo.Octal)) - return rewriteToNumericBoxedExpression(Msg, NS, commit); - - SourceLocation LitB = LitInfo.WithoutSuffRange.getBegin(); - SourceLocation LitE = LitInfo.WithoutSuffRange.getEnd(); - - commit.replaceWithInner(CharSourceRange::getTokenRange(Msg->getSourceRange()), - LitInfo.WithoutSuffRange); - commit.insert(LitB, "@"); - - if (!LitIsFloat && CallIsFloating) - commit.insert(LitE, ".0"); - - if (CallIsFloating) { - if (!CallIsDouble) - commit.insert(LitE, LitInfo.F); - } else { - if (CallIsUnsigned) - commit.insert(LitE, LitInfo.U); - - if (CallIsLong) - commit.insert(LitE, LitInfo.L); - else if (CallIsLongLong) - commit.insert(LitE, LitInfo.LL); - } - return true; -} - -// FIXME: Make determination of operator precedence more general and -// make it broadly available. -static bool subscriptOperatorNeedsParens(const Expr *FullExpr) { - const Expr* Expr = FullExpr->IgnoreImpCasts(); - if (isa<ArraySubscriptExpr>(Expr) || - isa<CallExpr>(Expr) || - isa<DeclRefExpr>(Expr) || - isa<CXXNamedCastExpr>(Expr) || - isa<CXXConstructExpr>(Expr) || - isa<CXXThisExpr>(Expr) || - isa<CXXTypeidExpr>(Expr) || - isa<CXXUnresolvedConstructExpr>(Expr) || - isa<ObjCMessageExpr>(Expr) || - isa<ObjCPropertyRefExpr>(Expr) || - isa<ObjCProtocolExpr>(Expr) || - isa<MemberExpr>(Expr) || - isa<ObjCIvarRefExpr>(Expr) || - isa<ParenExpr>(FullExpr) || - isa<ParenListExpr>(Expr) || - isa<SizeOfPackExpr>(Expr)) - return false; - - return true; -} -static bool castOperatorNeedsParens(const Expr *FullExpr) { - const Expr* Expr = FullExpr->IgnoreImpCasts(); - if (isa<ArraySubscriptExpr>(Expr) || - isa<CallExpr>(Expr) || - isa<DeclRefExpr>(Expr) || - isa<CastExpr>(Expr) || - isa<CXXNewExpr>(Expr) || - isa<CXXConstructExpr>(Expr) || - isa<CXXDeleteExpr>(Expr) || - isa<CXXNoexceptExpr>(Expr) || - isa<CXXPseudoDestructorExpr>(Expr) || - isa<CXXScalarValueInitExpr>(Expr) || - isa<CXXThisExpr>(Expr) || - isa<CXXTypeidExpr>(Expr) || - isa<CXXUnresolvedConstructExpr>(Expr) || - isa<ObjCMessageExpr>(Expr) || - isa<ObjCPropertyRefExpr>(Expr) || - isa<ObjCProtocolExpr>(Expr) || - isa<MemberExpr>(Expr) || - isa<ObjCIvarRefExpr>(Expr) || - isa<ParenExpr>(FullExpr) || - isa<ParenListExpr>(Expr) || - isa<SizeOfPackExpr>(Expr) || - isa<UnaryOperator>(Expr)) - return false; - - return true; -} - -static void objectifyExpr(const Expr *E, Commit &commit) { - if (!E) return; - - QualType T = E->getType(); - if (T->isObjCObjectPointerType()) { - if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) { - if (ICE->getCastKind() != CK_CPointerToObjCPointerCast) - return; - } else { - return; - } - } else if (!T->isPointerType()) { - return; - } - - SourceRange Range = E->getSourceRange(); - if (castOperatorNeedsParens(E)) - commit.insertWrap("(", Range, ")"); - commit.insertBefore(Range.getBegin(), "(id)"); -} - -//===----------------------------------------------------------------------===// -// rewriteToNumericBoxedExpression. -//===----------------------------------------------------------------------===// - -static bool isEnumConstant(const Expr *E) { - if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts())) - if (const ValueDecl *VD = DRE->getDecl()) - return isa<EnumConstantDecl>(VD); - - return false; -} - -static bool rewriteToNumericBoxedExpression(const ObjCMessageExpr *Msg, - const NSAPI &NS, Commit &commit) { - if (Msg->getNumArgs() != 1) - return false; - - const Expr *Arg = Msg->getArg(0); - if (Arg->isTypeDependent()) - return false; - - ASTContext &Ctx = NS.getASTContext(); - Selector Sel = Msg->getSelector(); - Optional<NSAPI::NSNumberLiteralMethodKind> - MKOpt = NS.getNSNumberLiteralMethodKind(Sel); - if (!MKOpt) - return false; - NSAPI::NSNumberLiteralMethodKind MK = *MKOpt; - - const Expr *OrigArg = Arg->IgnoreImpCasts(); - QualType FinalTy = Arg->getType(); - QualType OrigTy = OrigArg->getType(); - uint64_t FinalTySize = Ctx.getTypeSize(FinalTy); - uint64_t OrigTySize = Ctx.getTypeSize(OrigTy); - - bool isTruncated = FinalTySize < OrigTySize; - bool needsCast = false; - - if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Arg)) { - switch (ICE->getCastKind()) { - case CK_LValueToRValue: - case CK_NoOp: - case CK_UserDefinedConversion: - break; - - case CK_IntegralCast: { - if (MK == NSAPI::NSNumberWithBool && OrigTy->isBooleanType()) - break; - // Be more liberal with Integer/UnsignedInteger which are very commonly - // used. - if ((MK == NSAPI::NSNumberWithInteger || - MK == NSAPI::NSNumberWithUnsignedInteger) && - !isTruncated) { - if (OrigTy->getAs<EnumType>() || isEnumConstant(OrigArg)) - break; - if ((MK==NSAPI::NSNumberWithInteger) == OrigTy->isSignedIntegerType() && - OrigTySize >= Ctx.getTypeSize(Ctx.IntTy)) - break; - } - - needsCast = true; - break; - } - - case CK_PointerToBoolean: - case CK_IntegralToBoolean: - case CK_IntegralToFloating: - case CK_FloatingToIntegral: - case CK_FloatingToBoolean: - case CK_FloatingCast: - case CK_FloatingComplexToReal: - case CK_FloatingComplexToBoolean: - case CK_IntegralComplexToReal: - case CK_IntegralComplexToBoolean: - case CK_AtomicToNonAtomic: - case CK_AddressSpaceConversion: - needsCast = true; - break; - - case CK_Dependent: - case CK_BitCast: - case CK_LValueBitCast: - case CK_BaseToDerived: - case CK_DerivedToBase: - case CK_UncheckedDerivedToBase: - case CK_Dynamic: - case CK_ToUnion: - case CK_ArrayToPointerDecay: - case CK_FunctionToPointerDecay: - case CK_NullToPointer: - case CK_NullToMemberPointer: - case CK_BaseToDerivedMemberPointer: - case CK_DerivedToBaseMemberPointer: - case CK_MemberPointerToBoolean: - case CK_ReinterpretMemberPointer: - case CK_ConstructorConversion: - case CK_IntegralToPointer: - case CK_PointerToIntegral: - case CK_ToVoid: - case CK_VectorSplat: - case CK_CPointerToObjCPointerCast: - case CK_BlockPointerToObjCPointerCast: - case CK_AnyPointerToBlockPointerCast: - case CK_ObjCObjectLValueCast: - case CK_FloatingRealToComplex: - case CK_FloatingComplexCast: - case CK_FloatingComplexToIntegralComplex: - case CK_IntegralRealToComplex: - case CK_IntegralComplexCast: - case CK_IntegralComplexToFloatingComplex: - case CK_ARCProduceObject: - case CK_ARCConsumeObject: - case CK_ARCReclaimReturnedObject: - case CK_ARCExtendBlockObject: - case CK_NonAtomicToAtomic: - case CK_CopyAndAutoreleaseBlockObject: - case CK_BuiltinFnToFnPtr: - case CK_ZeroToOCLOpaqueType: - case CK_IntToOCLSampler: - return false; - - case CK_BooleanToSignedIntegral: - llvm_unreachable("OpenCL-specific cast in Objective-C?"); - - case CK_FixedPointCast: - case CK_FixedPointToBoolean: - llvm_unreachable("Fixed point types are disabled for Objective-C"); - } - } - - if (needsCast) { - DiagnosticsEngine &Diags = Ctx.getDiagnostics(); - // FIXME: Use a custom category name to distinguish migration diagnostics. - unsigned diagID = Diags.getCustomDiagID(DiagnosticsEngine::Warning, - "converting to boxing syntax requires casting %0 to %1"); - Diags.Report(Msg->getExprLoc(), diagID) << OrigTy << FinalTy - << Msg->getSourceRange(); - return false; - } - - SourceRange ArgRange = OrigArg->getSourceRange(); - commit.replaceWithInner(Msg->getSourceRange(), ArgRange); - - if (isa<ParenExpr>(OrigArg) || isa<IntegerLiteral>(OrigArg)) - commit.insertBefore(ArgRange.getBegin(), "@"); - else - commit.insertWrap("@(", ArgRange, ")"); - - return true; -} - -//===----------------------------------------------------------------------===// -// rewriteToStringBoxedExpression. -//===----------------------------------------------------------------------===// - -static bool doRewriteToUTF8StringBoxedExpressionHelper( - const ObjCMessageExpr *Msg, - const NSAPI &NS, Commit &commit) { - const Expr *Arg = Msg->getArg(0); - if (Arg->isTypeDependent()) - return false; - - ASTContext &Ctx = NS.getASTContext(); - - const Expr *OrigArg = Arg->IgnoreImpCasts(); - QualType OrigTy = OrigArg->getType(); - if (OrigTy->isArrayType()) - OrigTy = Ctx.getArrayDecayedType(OrigTy); - - if (const StringLiteral * - StrE = dyn_cast<StringLiteral>(OrigArg->IgnoreParens())) { - commit.replaceWithInner(Msg->getSourceRange(), StrE->getSourceRange()); - commit.insert(StrE->getBeginLoc(), "@"); - return true; - } - - if (const PointerType *PT = OrigTy->getAs<PointerType>()) { - QualType PointeeType = PT->getPointeeType(); - if (Ctx.hasSameUnqualifiedType(PointeeType, Ctx.CharTy)) { - SourceRange ArgRange = OrigArg->getSourceRange(); - commit.replaceWithInner(Msg->getSourceRange(), ArgRange); - - if (isa<ParenExpr>(OrigArg) || isa<IntegerLiteral>(OrigArg)) - commit.insertBefore(ArgRange.getBegin(), "@"); - else - commit.insertWrap("@(", ArgRange, ")"); - - return true; - } - } - - return false; -} - -static bool rewriteToStringBoxedExpression(const ObjCMessageExpr *Msg, - const NSAPI &NS, Commit &commit) { - Selector Sel = Msg->getSelector(); - - if (Sel == NS.getNSStringSelector(NSAPI::NSStr_stringWithUTF8String) || - Sel == NS.getNSStringSelector(NSAPI::NSStr_stringWithCString) || - Sel == NS.getNSStringSelector(NSAPI::NSStr_initWithUTF8String)) { - if (Msg->getNumArgs() != 1) - return false; - return doRewriteToUTF8StringBoxedExpressionHelper(Msg, NS, commit); - } - - if (Sel == NS.getNSStringSelector(NSAPI::NSStr_stringWithCStringEncoding)) { - if (Msg->getNumArgs() != 2) - return false; - - const Expr *encodingArg = Msg->getArg(1); - if (NS.isNSUTF8StringEncodingConstant(encodingArg) || - NS.isNSASCIIStringEncodingConstant(encodingArg)) - return doRewriteToUTF8StringBoxedExpressionHelper(Msg, NS, commit); - } - - return false; -} |
