clang  14.0.0git
RewriteObjCFoundationAPI.cpp
Go to the documentation of this file.
1 //===--- RewriteObjCFoundationAPI.cpp - Foundation API Rewriter -----------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Rewrites legacy method calls to modern syntax.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "clang/Edit/Rewriters.h"
14 #include "clang/AST/ASTContext.h"
15 #include "clang/AST/ExprCXX.h"
16 #include "clang/AST/ExprObjC.h"
17 #include "clang/AST/NSAPI.h"
18 #include "clang/AST/ParentMap.h"
19 #include "clang/Edit/Commit.h"
20 #include "clang/Lex/Lexer.h"
21 
22 using namespace clang;
23 using namespace edit;
24 
26  IdentifierInfo *&ClassId,
27  const LangOptions &LangOpts) {
28  if (!Msg || Msg->isImplicit() || !Msg->getMethodDecl())
29  return false;
30 
31  const ObjCInterfaceDecl *Receiver = Msg->getReceiverInterface();
32  if (!Receiver)
33  return false;
34  ClassId = Receiver->getIdentifier();
35 
37  return true;
38 
39  // When in ARC mode we also convert "[[.. alloc] init]" messages to literals,
40  // since the change from +1 to +0 will be handled fine by ARC.
41  if (LangOpts.ObjCAutoRefCount) {
43  if (const ObjCMessageExpr *Rec = dyn_cast<ObjCMessageExpr>(
45  if (Rec->getMethodFamily() == OMF_alloc)
46  return true;
47  }
48  }
49  }
50 
51  return false;
52 }
53 
54 //===----------------------------------------------------------------------===//
55 // rewriteObjCRedundantCallWithLiteral.
56 //===----------------------------------------------------------------------===//
57 
59  const NSAPI &NS, Commit &commit) {
60  IdentifierInfo *II = nullptr;
62  return false;
63  if (Msg->getNumArgs() != 1)
64  return false;
65 
66  const Expr *Arg = Msg->getArg(0)->IgnoreParenImpCasts();
67  Selector Sel = Msg->getSelector();
68 
69  if ((isa<ObjCStringLiteral>(Arg) &&
73 
74  (isa<ObjCArrayLiteral>(Arg) &&
78 
79  (isa<ObjCDictionaryLiteral>(Arg) &&
84 
85  commit.replaceWithInner(Msg->getSourceRange(),
86  Msg->getArg(0)->getSourceRange());
87  return true;
88  }
89 
90  return false;
91 }
92 
93 //===----------------------------------------------------------------------===//
94 // rewriteToObjCSubscriptSyntax.
95 //===----------------------------------------------------------------------===//
96 
97 /// Check for classes that accept 'objectForKey:' (or the other selectors
98 /// that the migrator handles) but return their instances as 'id', resulting
99 /// in the compiler resolving 'objectForKey:' as the method from NSDictionary.
100 ///
101 /// When checking if we can convert to subscripting syntax, check whether
102 /// the receiver is a result of a class method from a hardcoded list of
103 /// such classes. In such a case return the specific class as the interface
104 /// of the receiver.
105 ///
106 /// FIXME: Remove this when these classes start using 'instancetype'.
107 static const ObjCInterfaceDecl *
109  const Expr *Receiver,
110  ASTContext &Ctx) {
111  assert(IFace && Receiver);
112 
113  // If the receiver has type 'id'...
114  if (!Ctx.isObjCIdType(Receiver->getType().getUnqualifiedType()))
115  return IFace;
116 
117  const ObjCMessageExpr *
118  InnerMsg = dyn_cast<ObjCMessageExpr>(Receiver->IgnoreParenCasts());
119  if (!InnerMsg)
120  return IFace;
121 
122  QualType ClassRec;
123  switch (InnerMsg->getReceiverKind()) {
126  return IFace;
127 
129  ClassRec = InnerMsg->getClassReceiver();
130  break;
132  ClassRec = InnerMsg->getSuperType();
133  break;
134  }
135 
136  if (ClassRec.isNull())
137  return IFace;
138 
139  // ...and it is the result of a class message...
140 
141  const ObjCObjectType *ObjTy = ClassRec->getAs<ObjCObjectType>();
142  if (!ObjTy)
143  return IFace;
144  const ObjCInterfaceDecl *OID = ObjTy->getInterface();
145 
146  // ...and the receiving class is NSMapTable or NSLocale, return that
147  // class as the receiving interface.
148  if (OID->getName() == "NSMapTable" ||
149  OID->getName() == "NSLocale")
150  return OID;
151 
152  return IFace;
153 }
154 
156  const ObjCMessageExpr *Msg,
157  ASTContext &Ctx,
158  Selector subscriptSel) {
159  const Expr *Rec = Msg->getInstanceReceiver();
160  if (!Rec)
161  return false;
162  IFace = maybeAdjustInterfaceForSubscriptingCheck(IFace, Rec, Ctx);
163 
164  if (const ObjCMethodDecl *MD = IFace->lookupInstanceMethod(subscriptSel)) {
165  if (!MD->isUnavailable())
166  return true;
167  }
168  return false;
169 }
170 
171 static bool subscriptOperatorNeedsParens(const Expr *FullExpr);
172 
173 static void maybePutParensOnReceiver(const Expr *Receiver, Commit &commit) {
174  if (subscriptOperatorNeedsParens(Receiver)) {
175  SourceRange RecRange = Receiver->getSourceRange();
176  commit.insertWrap("(", RecRange, ")");
177  }
178 }
179 
181  Commit &commit) {
182  if (Msg->getNumArgs() != 1)
183  return false;
184  const Expr *Rec = Msg->getInstanceReceiver();
185  if (!Rec)
186  return false;
187 
188  SourceRange MsgRange = Msg->getSourceRange();
189  SourceRange RecRange = Rec->getSourceRange();
190  SourceRange ArgRange = Msg->getArg(0)->getSourceRange();
191 
193  ArgRange.getBegin()),
195  commit.replaceWithInner(SourceRange(ArgRange.getBegin(), MsgRange.getEnd()),
196  ArgRange);
197  commit.insertWrap("[", ArgRange, "]");
198  maybePutParensOnReceiver(Rec, commit);
199  return true;
200 }
201 
203  const ObjCMessageExpr *Msg,
204  const NSAPI &NS,
205  Commit &commit) {
206  if (!canRewriteToSubscriptSyntax(IFace, Msg, NS.getASTContext(),
208  return false;
209  return rewriteToSubscriptGetCommon(Msg, commit);
210 }
211 
213  const ObjCMessageExpr *Msg,
214  const NSAPI &NS,
215  Commit &commit) {
216  if (!canRewriteToSubscriptSyntax(IFace, Msg, NS.getASTContext(),
218  return false;
219  return rewriteToSubscriptGetCommon(Msg, commit);
220 }
221 
223  const ObjCMessageExpr *Msg,
224  const NSAPI &NS,
225  Commit &commit) {
226  if (!canRewriteToSubscriptSyntax(IFace, Msg, NS.getASTContext(),
228  return false;
229 
230  if (Msg->getNumArgs() != 2)
231  return false;
232  const Expr *Rec = Msg->getInstanceReceiver();
233  if (!Rec)
234  return false;
235 
236  SourceRange MsgRange = Msg->getSourceRange();
237  SourceRange RecRange = Rec->getSourceRange();
238  SourceRange Arg0Range = Msg->getArg(0)->getSourceRange();
239  SourceRange Arg1Range = Msg->getArg(1)->getSourceRange();
240 
242  Arg0Range.getBegin()),
245  Arg1Range.getBegin()),
246  CharSourceRange::getTokenRange(Arg0Range));
247  commit.replaceWithInner(SourceRange(Arg1Range.getBegin(), MsgRange.getEnd()),
248  Arg1Range);
249  commit.insertWrap("[", CharSourceRange::getCharRange(Arg0Range.getBegin(),
250  Arg1Range.getBegin()),
251  "] = ");
252  maybePutParensOnReceiver(Rec, commit);
253  return true;
254 }
255 
257  const ObjCMessageExpr *Msg,
258  const NSAPI &NS,
259  Commit &commit) {
260  if (!canRewriteToSubscriptSyntax(IFace, Msg, NS.getASTContext(),
262  return false;
263 
264  if (Msg->getNumArgs() != 2)
265  return false;
266  const Expr *Rec = Msg->getInstanceReceiver();
267  if (!Rec)
268  return false;
269 
270  SourceRange MsgRange = Msg->getSourceRange();
271  SourceRange RecRange = Rec->getSourceRange();
272  SourceRange Arg0Range = Msg->getArg(0)->getSourceRange();
273  SourceRange Arg1Range = Msg->getArg(1)->getSourceRange();
274 
275  SourceLocation LocBeforeVal = Arg0Range.getBegin();
276  commit.insertBefore(LocBeforeVal, "] = ");
277  commit.insertFromRange(LocBeforeVal, Arg1Range, /*afterToken=*/false,
278  /*beforePreviousInsertions=*/true);
279  commit.insertBefore(LocBeforeVal, "[");
281  Arg0Range.getBegin()),
283  commit.replaceWithInner(SourceRange(Arg0Range.getBegin(), MsgRange.getEnd()),
284  Arg0Range);
285  maybePutParensOnReceiver(Rec, commit);
286  return true;
287 }
288 
290  const NSAPI &NS, Commit &commit) {
291  if (!Msg || Msg->isImplicit() ||
293  return false;
294  const ObjCMethodDecl *Method = Msg->getMethodDecl();
295  if (!Method)
296  return false;
297 
298  const ObjCInterfaceDecl *IFace =
300  if (!IFace)
301  return false;
302  Selector Sel = Msg->getSelector();
303 
305  return rewriteToArraySubscriptGet(IFace, Msg, NS, commit);
306 
308  return rewriteToDictionarySubscriptGet(IFace, Msg, NS, commit);
309 
310  if (Msg->getNumArgs() != 2)
311  return false;
312 
314  return rewriteToArraySubscriptSet(IFace, Msg, NS, commit);
315 
317  return rewriteToDictionarySubscriptSet(IFace, Msg, NS, commit);
318 
319  return false;
320 }
321 
322 //===----------------------------------------------------------------------===//
323 // rewriteToObjCLiteralSyntax.
324 //===----------------------------------------------------------------------===//
325 
326 static bool rewriteToArrayLiteral(const ObjCMessageExpr *Msg,
327  const NSAPI &NS, Commit &commit,
328  const ParentMap *PMap);
329 static bool rewriteToDictionaryLiteral(const ObjCMessageExpr *Msg,
330  const NSAPI &NS, Commit &commit);
331 static bool rewriteToNumberLiteral(const ObjCMessageExpr *Msg,
332  const NSAPI &NS, Commit &commit);
333 static bool rewriteToNumericBoxedExpression(const ObjCMessageExpr *Msg,
334  const NSAPI &NS, Commit &commit);
335 static bool rewriteToStringBoxedExpression(const ObjCMessageExpr *Msg,
336  const NSAPI &NS, Commit &commit);
337 
339  const NSAPI &NS, Commit &commit,
340  const ParentMap *PMap) {
341  IdentifierInfo *II = nullptr;
342  if (!checkForLiteralCreation(Msg, II, NS.getASTContext().getLangOpts()))
343  return false;
344 
345  if (II == NS.getNSClassId(NSAPI::ClassId_NSArray))
346  return rewriteToArrayLiteral(Msg, NS, commit, PMap);
348  return rewriteToDictionaryLiteral(Msg, NS, commit);
350  return rewriteToNumberLiteral(Msg, NS, commit);
352  return rewriteToStringBoxedExpression(Msg, NS, commit);
353 
354  return false;
355 }
356 
357 /// Returns true if the immediate message arguments of \c Msg should not
358 /// be rewritten because it will interfere with the rewrite of the parent
359 /// message expression. e.g.
360 /// \code
361 /// [NSDictionary dictionaryWithObjects:
362 /// [NSArray arrayWithObjects:@"1", @"2", nil]
363 /// forKeys:[NSArray arrayWithObjects:@"A", @"B", nil]];
364 /// \endcode
365 /// It will return true for this because we are going to rewrite this directly
366 /// to a dictionary literal without any array literals.
368  const NSAPI &NS);
369 
370 //===----------------------------------------------------------------------===//
371 // rewriteToArrayLiteral.
372 //===----------------------------------------------------------------------===//
373 
374 /// Adds an explicit cast to 'id' if the type is not objc object.
375 static void objectifyExpr(const Expr *E, Commit &commit);
376 
377 static bool rewriteToArrayLiteral(const ObjCMessageExpr *Msg,
378  const NSAPI &NS, Commit &commit,
379  const ParentMap *PMap) {
380  if (PMap) {
381  const ObjCMessageExpr *ParentMsg =
382  dyn_cast_or_null<ObjCMessageExpr>(PMap->getParentIgnoreParenCasts(Msg));
383  if (shouldNotRewriteImmediateMessageArgs(ParentMsg, NS))
384  return false;
385  }
386 
387  Selector Sel = Msg->getSelector();
388  SourceRange MsgRange = Msg->getSourceRange();
389 
390  if (Sel == NS.getNSArraySelector(NSAPI::NSArr_array)) {
391  if (Msg->getNumArgs() != 0)
392  return false;
393  commit.replace(MsgRange, "@[]");
394  return true;
395  }
396 
398  if (Msg->getNumArgs() != 1)
399  return false;
400  objectifyExpr(Msg->getArg(0), commit);
401  SourceRange ArgRange = Msg->getArg(0)->getSourceRange();
402  commit.replaceWithInner(MsgRange, ArgRange);
403  commit.insertWrap("@[", ArgRange, "]");
404  return true;
405  }
406 
409  if (Msg->getNumArgs() == 0)
410  return false;
411  const Expr *SentinelExpr = Msg->getArg(Msg->getNumArgs() - 1);
412  if (!NS.getASTContext().isSentinelNullExpr(SentinelExpr))
413  return false;
414 
415  for (unsigned i = 0, e = Msg->getNumArgs() - 1; i != e; ++i)
416  objectifyExpr(Msg->getArg(i), commit);
417 
418  if (Msg->getNumArgs() == 1) {
419  commit.replace(MsgRange, "@[]");
420  return true;
421  }
422  SourceRange ArgRange(Msg->getArg(0)->getBeginLoc(),
423  Msg->getArg(Msg->getNumArgs() - 2)->getEndLoc());
424  commit.replaceWithInner(MsgRange, ArgRange);
425  commit.insertWrap("@[", ArgRange, "]");
426  return true;
427  }
428 
429  return false;
430 }
431 
432 //===----------------------------------------------------------------------===//
433 // rewriteToDictionaryLiteral.
434 //===----------------------------------------------------------------------===//
435 
436 /// If \c Msg is an NSArray creation message or literal, this gets the
437 /// objects that were used to create it.
438 /// \returns true if it is an NSArray and we got objects, or false otherwise.
439 static bool getNSArrayObjects(const Expr *E, const NSAPI &NS,
441  if (!E)
442  return false;
443 
444  E = E->IgnoreParenCasts();
445  if (!E)
446  return false;
447 
448  if (const ObjCMessageExpr *Msg = dyn_cast<ObjCMessageExpr>(E)) {
449  IdentifierInfo *Cls = nullptr;
450  if (!checkForLiteralCreation(Msg, Cls, NS.getASTContext().getLangOpts()))
451  return false;
452 
453  if (Cls != NS.getNSClassId(NSAPI::ClassId_NSArray))
454  return false;
455 
456  Selector Sel = Msg->getSelector();
457  if (Sel == NS.getNSArraySelector(NSAPI::NSArr_array))
458  return true; // empty array.
459 
461  if (Msg->getNumArgs() != 1)
462  return false;
463  Objs.push_back(Msg->getArg(0));
464  return true;
465  }
466 
469  if (Msg->getNumArgs() == 0)
470  return false;
471  const Expr *SentinelExpr = Msg->getArg(Msg->getNumArgs() - 1);
472  if (!NS.getASTContext().isSentinelNullExpr(SentinelExpr))
473  return false;
474 
475  for (unsigned i = 0, e = Msg->getNumArgs() - 1; i != e; ++i)
476  Objs.push_back(Msg->getArg(i));
477  return true;
478  }
479 
480  } else if (const ObjCArrayLiteral *ArrLit = dyn_cast<ObjCArrayLiteral>(E)) {
481  for (unsigned i = 0, e = ArrLit->getNumElements(); i != e; ++i)
482  Objs.push_back(ArrLit->getElement(i));
483  return true;
484  }
485 
486  return false;
487 }
488 
490  const NSAPI &NS, Commit &commit) {
491  Selector Sel = Msg->getSelector();
492  SourceRange MsgRange = Msg->getSourceRange();
493 
495  if (Msg->getNumArgs() != 0)
496  return false;
497  commit.replace(MsgRange, "@{}");
498  return true;
499  }
500 
501  if (Sel == NS.getNSDictionarySelector(
503  if (Msg->getNumArgs() != 2)
504  return false;
505 
506  objectifyExpr(Msg->getArg(0), commit);
507  objectifyExpr(Msg->getArg(1), commit);
508 
509  SourceRange ValRange = Msg->getArg(0)->getSourceRange();
510  SourceRange KeyRange = Msg->getArg(1)->getSourceRange();
511  // Insert key before the value.
512  commit.insertBefore(ValRange.getBegin(), ": ");
513  commit.insertFromRange(ValRange.getBegin(),
515  /*afterToken=*/false, /*beforePreviousInsertions=*/true);
516  commit.insertBefore(ValRange.getBegin(), "@{");
517  commit.insertAfterToken(ValRange.getEnd(), "}");
518  commit.replaceWithInner(MsgRange, ValRange);
519  return true;
520  }
521 
522  if (Sel == NS.getNSDictionarySelector(
525  if (Msg->getNumArgs() % 2 != 1)
526  return false;
527  unsigned SentinelIdx = Msg->getNumArgs() - 1;
528  const Expr *SentinelExpr = Msg->getArg(SentinelIdx);
529  if (!NS.getASTContext().isSentinelNullExpr(SentinelExpr))
530  return false;
531 
532  if (Msg->getNumArgs() == 1) {
533  commit.replace(MsgRange, "@{}");
534  return true;
535  }
536 
537  for (unsigned i = 0; i < SentinelIdx; i += 2) {
538  objectifyExpr(Msg->getArg(i), commit);
539  objectifyExpr(Msg->getArg(i+1), commit);
540 
541  SourceRange ValRange = Msg->getArg(i)->getSourceRange();
542  SourceRange KeyRange = Msg->getArg(i+1)->getSourceRange();
543  // Insert value after key.
544  commit.insertAfterToken(KeyRange.getEnd(), ": ");
545  commit.insertFromRange(KeyRange.getEnd(), ValRange, /*afterToken=*/true);
547  KeyRange.getBegin()));
548  }
549  // Range of arguments up until and including the last key.
550  // The sentinel and first value are cut off, the value will move after the
551  // key.
552  SourceRange ArgRange(Msg->getArg(1)->getBeginLoc(),
553  Msg->getArg(SentinelIdx - 1)->getEndLoc());
554  commit.insertWrap("@{", ArgRange, "}");
555  commit.replaceWithInner(MsgRange, ArgRange);
556  return true;
557  }
558 
559  if (Sel == NS.getNSDictionarySelector(
562  if (Msg->getNumArgs() != 2)
563  return false;
564 
566  if (!getNSArrayObjects(Msg->getArg(0), NS, Vals))
567  return false;
568 
570  if (!getNSArrayObjects(Msg->getArg(1), NS, Keys))
571  return false;
572 
573  if (Vals.size() != Keys.size())
574  return false;
575 
576  if (Vals.empty()) {
577  commit.replace(MsgRange, "@{}");
578  return true;
579  }
580 
581  for (unsigned i = 0, n = Vals.size(); i < n; ++i) {
582  objectifyExpr(Vals[i], commit);
583  objectifyExpr(Keys[i], commit);
584 
585  SourceRange ValRange = Vals[i]->getSourceRange();
586  SourceRange KeyRange = Keys[i]->getSourceRange();
587  // Insert value after key.
588  commit.insertAfterToken(KeyRange.getEnd(), ": ");
589  commit.insertFromRange(KeyRange.getEnd(), ValRange, /*afterToken=*/true);
590  }
591  // Range of arguments up until and including the last key.
592  // The first value is cut off, the value will move after the key.
593  SourceRange ArgRange(Keys.front()->getBeginLoc(), Keys.back()->getEndLoc());
594  commit.insertWrap("@{", ArgRange, "}");
595  commit.replaceWithInner(MsgRange, ArgRange);
596  return true;
597  }
598 
599  return false;
600 }
601 
603  const NSAPI &NS) {
604  if (!Msg)
605  return false;
606 
607  IdentifierInfo *II = nullptr;
608  if (!checkForLiteralCreation(Msg, II, NS.getASTContext().getLangOpts()))
609  return false;
610 
612  return false;
613 
614  Selector Sel = Msg->getSelector();
615  if (Sel == NS.getNSDictionarySelector(
618  if (Msg->getNumArgs() != 2)
619  return false;
620 
622  if (!getNSArrayObjects(Msg->getArg(0), NS, Vals))
623  return false;
624 
626  if (!getNSArrayObjects(Msg->getArg(1), NS, Keys))
627  return false;
628 
629  if (Vals.size() != Keys.size())
630  return false;
631 
632  return true;
633  }
634 
635  return false;
636 }
637 
638 //===----------------------------------------------------------------------===//
639 // rewriteToNumberLiteral.
640 //===----------------------------------------------------------------------===//
641 
642 static bool rewriteToCharLiteral(const ObjCMessageExpr *Msg,
643  const CharacterLiteral *Arg,
644  const NSAPI &NS, Commit &commit) {
645  if (Arg->getKind() != CharacterLiteral::Ascii)
646  return false;
648  Msg->getSelector())) {
649  SourceRange ArgRange = Arg->getSourceRange();
650  commit.replaceWithInner(Msg->getSourceRange(), ArgRange);
651  commit.insert(ArgRange.getBegin(), "@");
652  return true;
653  }
654 
655  return rewriteToNumericBoxedExpression(Msg, NS, commit);
656 }
657 
658 static bool rewriteToBoolLiteral(const ObjCMessageExpr *Msg,
659  const Expr *Arg,
660  const NSAPI &NS, Commit &commit) {
662  Msg->getSelector())) {
663  SourceRange ArgRange = Arg->getSourceRange();
664  commit.replaceWithInner(Msg->getSourceRange(), ArgRange);
665  commit.insert(ArgRange.getBegin(), "@");
666  return true;
667  }
668 
669  return rewriteToNumericBoxedExpression(Msg, NS, commit);
670 }
671 
672 namespace {
673 
674 struct LiteralInfo {
675  bool Hex, Octal;
676  StringRef U, F, L, LL;
677  CharSourceRange WithoutSuffRange;
678 };
679 
680 }
681 
682 static bool getLiteralInfo(SourceRange literalRange,
683  bool isFloat, bool isIntZero,
684  ASTContext &Ctx, LiteralInfo &Info) {
685  if (literalRange.getBegin().isMacroID() ||
686  literalRange.getEnd().isMacroID())
687  return false;
688  StringRef text = Lexer::getSourceText(
689  CharSourceRange::getTokenRange(literalRange),
690  Ctx.getSourceManager(), Ctx.getLangOpts());
691  if (text.empty())
692  return false;
693 
694  Optional<bool> UpperU, UpperL;
695  bool UpperF = false;
696 
697  struct Suff {
698  static bool has(StringRef suff, StringRef &text) {
699  if (text.endswith(suff)) {
700  text = text.substr(0, text.size()-suff.size());
701  return true;
702  }
703  return false;
704  }
705  };
706 
707  while (1) {
708  if (Suff::has("u", text)) {
709  UpperU = false;
710  } else if (Suff::has("U", text)) {
711  UpperU = true;
712  } else if (Suff::has("ll", text)) {
713  UpperL = false;
714  } else if (Suff::has("LL", text)) {
715  UpperL = true;
716  } else if (Suff::has("l", text)) {
717  UpperL = false;
718  } else if (Suff::has("L", text)) {
719  UpperL = true;
720  } else if (isFloat && Suff::has("f", text)) {
721  UpperF = false;
722  } else if (isFloat && Suff::has("F", text)) {
723  UpperF = true;
724  } else
725  break;
726  }
727 
728  if (!UpperU.hasValue() && !UpperL.hasValue())
729  UpperU = UpperL = true;
730  else if (UpperU.hasValue() && !UpperL.hasValue())
731  UpperL = UpperU;
732  else if (UpperL.hasValue() && !UpperU.hasValue())
733  UpperU = UpperL;
734 
735  Info.U = *UpperU ? "U" : "u";
736  Info.L = *UpperL ? "L" : "l";
737  Info.LL = *UpperL ? "LL" : "ll";
738  Info.F = UpperF ? "F" : "f";
739 
740  Info.Hex = Info.Octal = false;
741  if (text.startswith("0x"))
742  Info.Hex = true;
743  else if (!isFloat && !isIntZero && text.startswith("0"))
744  Info.Octal = true;
745 
746  SourceLocation B = literalRange.getBegin();
747  Info.WithoutSuffRange =
749  return true;
750 }
751 
753  const NSAPI &NS, Commit &commit) {
754  if (Msg->getNumArgs() != 1)
755  return false;
756 
757  const Expr *Arg = Msg->getArg(0)->IgnoreParenImpCasts();
758  if (const CharacterLiteral *CharE = dyn_cast<CharacterLiteral>(Arg))
759  return rewriteToCharLiteral(Msg, CharE, NS, commit);
760  if (const ObjCBoolLiteralExpr *BE = dyn_cast<ObjCBoolLiteralExpr>(Arg))
761  return rewriteToBoolLiteral(Msg, BE, NS, commit);
762  if (const CXXBoolLiteralExpr *BE = dyn_cast<CXXBoolLiteralExpr>(Arg))
763  return rewriteToBoolLiteral(Msg, BE, NS, commit);
764 
765  const Expr *literalE = Arg;
766  if (const UnaryOperator *UOE = dyn_cast<UnaryOperator>(literalE)) {
767  if (UOE->getOpcode() == UO_Plus || UOE->getOpcode() == UO_Minus)
768  literalE = UOE->getSubExpr();
769  }
770 
771  // Only integer and floating literals, otherwise try to rewrite to boxed
772  // expression.
773  if (!isa<IntegerLiteral>(literalE) && !isa<FloatingLiteral>(literalE))
774  return rewriteToNumericBoxedExpression(Msg, NS, commit);
775 
776  ASTContext &Ctx = NS.getASTContext();
777  Selector Sel = Msg->getSelector();
779  MKOpt = NS.getNSNumberLiteralMethodKind(Sel);
780  if (!MKOpt)
781  return false;
783 
784  bool CallIsUnsigned = false, CallIsLong = false, CallIsLongLong = false;
785  bool CallIsFloating = false, CallIsDouble = false;
786 
787  switch (MK) {
788  // We cannot have these calls with int/float literals.
794  return rewriteToNumericBoxedExpression(Msg, NS, commit);
795 
798  CallIsUnsigned = true;
799  LLVM_FALLTHROUGH;
802  break;
803 
805  CallIsUnsigned = true;
806  LLVM_FALLTHROUGH;
808  CallIsLong = true;
809  break;
810 
812  CallIsUnsigned = true;
813  LLVM_FALLTHROUGH;
815  CallIsLongLong = true;
816  break;
817 
819  CallIsDouble = true;
820  LLVM_FALLTHROUGH;
822  CallIsFloating = true;
823  break;
824  }
825 
826  SourceRange ArgRange = Arg->getSourceRange();
827  QualType ArgTy = Arg->getType();
828  QualType CallTy = Msg->getArg(0)->getType();
829 
830  // Check for the easy case, the literal maps directly to the call.
831  if (Ctx.hasSameType(ArgTy, CallTy)) {
832  commit.replaceWithInner(Msg->getSourceRange(), ArgRange);
833  commit.insert(ArgRange.getBegin(), "@");
834  return true;
835  }
836 
837  // We will need to modify the literal suffix to get the same type as the call.
838  // Try with boxed expression if it came from a macro.
839  if (ArgRange.getBegin().isMacroID())
840  return rewriteToNumericBoxedExpression(Msg, NS, commit);
841 
842  bool LitIsFloat = ArgTy->isFloatingType();
843  // For a float passed to integer call, don't try rewriting to objc literal.
844  // It is difficult and a very uncommon case anyway.
845  // But try with boxed expression.
846  if (LitIsFloat && !CallIsFloating)
847  return rewriteToNumericBoxedExpression(Msg, NS, commit);
848 
849  // Try to modify the literal make it the same type as the method call.
850  // -Modify the suffix, and/or
851  // -Change integer to float
852 
853  LiteralInfo LitInfo;
854  bool isIntZero = false;
855  if (const IntegerLiteral *IntE = dyn_cast<IntegerLiteral>(literalE))
856  isIntZero = !IntE->getValue().getBoolValue();
857  if (!getLiteralInfo(ArgRange, LitIsFloat, isIntZero, Ctx, LitInfo))
858  return rewriteToNumericBoxedExpression(Msg, NS, commit);
859 
860  // Not easy to do int -> float with hex/octal and uncommon anyway.
861  if (!LitIsFloat && CallIsFloating && (LitInfo.Hex || LitInfo.Octal))
862  return rewriteToNumericBoxedExpression(Msg, NS, commit);
863 
864  SourceLocation LitB = LitInfo.WithoutSuffRange.getBegin();
865  SourceLocation LitE = LitInfo.WithoutSuffRange.getEnd();
866 
868  LitInfo.WithoutSuffRange);
869  commit.insert(LitB, "@");
870 
871  if (!LitIsFloat && CallIsFloating)
872  commit.insert(LitE, ".0");
873 
874  if (CallIsFloating) {
875  if (!CallIsDouble)
876  commit.insert(LitE, LitInfo.F);
877  } else {
878  if (CallIsUnsigned)
879  commit.insert(LitE, LitInfo.U);
880 
881  if (CallIsLong)
882  commit.insert(LitE, LitInfo.L);
883  else if (CallIsLongLong)
884  commit.insert(LitE, LitInfo.LL);
885  }
886  return true;
887 }
888 
889 // FIXME: Make determination of operator precedence more general and
890 // make it broadly available.
892  const Expr* Expr = FullExpr->IgnoreImpCasts();
893  if (isa<ArraySubscriptExpr>(Expr) ||
894  isa<CallExpr>(Expr) ||
895  isa<DeclRefExpr>(Expr) ||
896  isa<CXXNamedCastExpr>(Expr) ||
897  isa<CXXConstructExpr>(Expr) ||
898  isa<CXXThisExpr>(Expr) ||
899  isa<CXXTypeidExpr>(Expr) ||
900  isa<CXXUnresolvedConstructExpr>(Expr) ||
901  isa<ObjCMessageExpr>(Expr) ||
902  isa<ObjCPropertyRefExpr>(Expr) ||
903  isa<ObjCProtocolExpr>(Expr) ||
904  isa<MemberExpr>(Expr) ||
905  isa<ObjCIvarRefExpr>(Expr) ||
906  isa<ParenExpr>(FullExpr) ||
907  isa<ParenListExpr>(Expr) ||
908  isa<SizeOfPackExpr>(Expr))
909  return false;
910 
911  return true;
912 }
913 static bool castOperatorNeedsParens(const Expr *FullExpr) {
914  const Expr* Expr = FullExpr->IgnoreImpCasts();
915  if (isa<ArraySubscriptExpr>(Expr) ||
916  isa<CallExpr>(Expr) ||
917  isa<DeclRefExpr>(Expr) ||
918  isa<CastExpr>(Expr) ||
919  isa<CXXNewExpr>(Expr) ||
920  isa<CXXConstructExpr>(Expr) ||
921  isa<CXXDeleteExpr>(Expr) ||
922  isa<CXXNoexceptExpr>(Expr) ||
923  isa<CXXPseudoDestructorExpr>(Expr) ||
924  isa<CXXScalarValueInitExpr>(Expr) ||
925  isa<CXXThisExpr>(Expr) ||
926  isa<CXXTypeidExpr>(Expr) ||
927  isa<CXXUnresolvedConstructExpr>(Expr) ||
928  isa<ObjCMessageExpr>(Expr) ||
929  isa<ObjCPropertyRefExpr>(Expr) ||
930  isa<ObjCProtocolExpr>(Expr) ||
931  isa<MemberExpr>(Expr) ||
932  isa<ObjCIvarRefExpr>(Expr) ||
933  isa<ParenExpr>(FullExpr) ||
934  isa<ParenListExpr>(Expr) ||
935  isa<SizeOfPackExpr>(Expr) ||
936  isa<UnaryOperator>(Expr))
937  return false;
938 
939  return true;
940 }
941 
942 static void objectifyExpr(const Expr *E, Commit &commit) {
943  if (!E) return;
944 
945  QualType T = E->getType();
946  if (T->isObjCObjectPointerType()) {
947  if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
948  if (ICE->getCastKind() != CK_CPointerToObjCPointerCast)
949  return;
950  } else {
951  return;
952  }
953  } else if (!T->isPointerType()) {
954  return;
955  }
956 
957  SourceRange Range = E->getSourceRange();
959  commit.insertWrap("(", Range, ")");
960  commit.insertBefore(Range.getBegin(), "(id)");
961 }
962 
963 //===----------------------------------------------------------------------===//
964 // rewriteToNumericBoxedExpression.
965 //===----------------------------------------------------------------------===//
966 
967 static bool isEnumConstant(const Expr *E) {
968  if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts()))
969  if (const ValueDecl *VD = DRE->getDecl())
970  return isa<EnumConstantDecl>(VD);
971 
972  return false;
973 }
974 
976  const NSAPI &NS, Commit &commit) {
977  if (Msg->getNumArgs() != 1)
978  return false;
979 
980  const Expr *Arg = Msg->getArg(0);
981  if (Arg->isTypeDependent())
982  return false;
983 
984  ASTContext &Ctx = NS.getASTContext();
985  Selector Sel = Msg->getSelector();
987  MKOpt = NS.getNSNumberLiteralMethodKind(Sel);
988  if (!MKOpt)
989  return false;
991 
992  const Expr *OrigArg = Arg->IgnoreImpCasts();
993  QualType FinalTy = Arg->getType();
994  QualType OrigTy = OrigArg->getType();
995  uint64_t FinalTySize = Ctx.getTypeSize(FinalTy);
996  uint64_t OrigTySize = Ctx.getTypeSize(OrigTy);
997 
998  bool isTruncated = FinalTySize < OrigTySize;
999  bool needsCast = false;
1000 
1001  if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Arg)) {
1002  switch (ICE->getCastKind()) {
1003  case CK_LValueToRValue:
1004  case CK_NoOp:
1005  case CK_UserDefinedConversion:
1006  break;
1007 
1008  case CK_IntegralCast: {
1009  if (MK == NSAPI::NSNumberWithBool && OrigTy->isBooleanType())
1010  break;
1011  // Be more liberal with Integer/UnsignedInteger which are very commonly
1012  // used.
1013  if ((MK == NSAPI::NSNumberWithInteger ||
1015  !isTruncated) {
1016  if (OrigTy->getAs<EnumType>() || isEnumConstant(OrigArg))
1017  break;
1018  if ((MK==NSAPI::NSNumberWithInteger) == OrigTy->isSignedIntegerType() &&
1019  OrigTySize >= Ctx.getTypeSize(Ctx.IntTy))
1020  break;
1021  }
1022 
1023  needsCast = true;
1024  break;
1025  }
1026 
1027  case CK_PointerToBoolean:
1028  case CK_IntegralToBoolean:
1029  case CK_IntegralToFloating:
1030  case CK_FloatingToIntegral:
1031  case CK_FloatingToBoolean:
1032  case CK_FloatingCast:
1033  case CK_FloatingComplexToReal:
1034  case CK_FloatingComplexToBoolean:
1035  case CK_IntegralComplexToReal:
1036  case CK_IntegralComplexToBoolean:
1037  case CK_AtomicToNonAtomic:
1038  case CK_AddressSpaceConversion:
1039  needsCast = true;
1040  break;
1041 
1042  case CK_Dependent:
1043  case CK_BitCast:
1044  case CK_LValueBitCast:
1045  case CK_LValueToRValueBitCast:
1046  case CK_BaseToDerived:
1047  case CK_DerivedToBase:
1048  case CK_UncheckedDerivedToBase:
1049  case CK_Dynamic:
1050  case CK_ToUnion:
1051  case CK_ArrayToPointerDecay:
1052  case CK_FunctionToPointerDecay:
1053  case CK_NullToPointer:
1054  case CK_NullToMemberPointer:
1055  case CK_BaseToDerivedMemberPointer:
1056  case CK_DerivedToBaseMemberPointer:
1057  case CK_MemberPointerToBoolean:
1058  case CK_ReinterpretMemberPointer:
1059  case CK_ConstructorConversion:
1060  case CK_IntegralToPointer:
1061  case CK_PointerToIntegral:
1062  case CK_ToVoid:
1063  case CK_VectorSplat:
1064  case CK_CPointerToObjCPointerCast:
1065  case CK_BlockPointerToObjCPointerCast:
1066  case CK_AnyPointerToBlockPointerCast:
1067  case CK_ObjCObjectLValueCast:
1068  case CK_FloatingRealToComplex:
1069  case CK_FloatingComplexCast:
1070  case CK_FloatingComplexToIntegralComplex:
1071  case CK_IntegralRealToComplex:
1072  case CK_IntegralComplexCast:
1073  case CK_IntegralComplexToFloatingComplex:
1074  case CK_ARCProduceObject:
1075  case CK_ARCConsumeObject:
1076  case CK_ARCReclaimReturnedObject:
1077  case CK_ARCExtendBlockObject:
1078  case CK_NonAtomicToAtomic:
1079  case CK_CopyAndAutoreleaseBlockObject:
1080  case CK_BuiltinFnToFnPtr:
1081  case CK_ZeroToOCLOpaqueType:
1082  case CK_IntToOCLSampler:
1083  case CK_MatrixCast:
1084  return false;
1085 
1086  case CK_BooleanToSignedIntegral:
1087  llvm_unreachable("OpenCL-specific cast in Objective-C?");
1088 
1089  case CK_FloatingToFixedPoint:
1090  case CK_FixedPointToFloating:
1091  case CK_FixedPointCast:
1092  case CK_FixedPointToBoolean:
1093  case CK_FixedPointToIntegral:
1094  case CK_IntegralToFixedPoint:
1095  llvm_unreachable("Fixed point types are disabled for Objective-C");
1096  }
1097  }
1098 
1099  if (needsCast) {
1100  DiagnosticsEngine &Diags = Ctx.getDiagnostics();
1101  // FIXME: Use a custom category name to distinguish migration diagnostics.
1102  unsigned diagID = Diags.getCustomDiagID(DiagnosticsEngine::Warning,
1103  "converting to boxing syntax requires casting %0 to %1");
1104  Diags.Report(Msg->getExprLoc(), diagID) << OrigTy << FinalTy
1105  << Msg->getSourceRange();
1106  return false;
1107  }
1108 
1109  SourceRange ArgRange = OrigArg->getSourceRange();
1110  commit.replaceWithInner(Msg->getSourceRange(), ArgRange);
1111 
1112  if (isa<ParenExpr>(OrigArg) || isa<IntegerLiteral>(OrigArg))
1113  commit.insertBefore(ArgRange.getBegin(), "@");
1114  else
1115  commit.insertWrap("@(", ArgRange, ")");
1116 
1117  return true;
1118 }
1119 
1120 //===----------------------------------------------------------------------===//
1121 // rewriteToStringBoxedExpression.
1122 //===----------------------------------------------------------------------===//
1123 
1125  const ObjCMessageExpr *Msg,
1126  const NSAPI &NS, Commit &commit) {
1127  const Expr *Arg = Msg->getArg(0);
1128  if (Arg->isTypeDependent())
1129  return false;
1130 
1131  ASTContext &Ctx = NS.getASTContext();
1132 
1133  const Expr *OrigArg = Arg->IgnoreImpCasts();
1134  QualType OrigTy = OrigArg->getType();
1135  if (OrigTy->isArrayType())
1136  OrigTy = Ctx.getArrayDecayedType(OrigTy);
1137 
1138  if (const StringLiteral *
1139  StrE = dyn_cast<StringLiteral>(OrigArg->IgnoreParens())) {
1140  commit.replaceWithInner(Msg->getSourceRange(), StrE->getSourceRange());
1141  commit.insert(StrE->getBeginLoc(), "@");
1142  return true;
1143  }
1144 
1145  if (const PointerType *PT = OrigTy->getAs<PointerType>()) {
1146  QualType PointeeType = PT->getPointeeType();
1147  if (Ctx.hasSameUnqualifiedType(PointeeType, Ctx.CharTy)) {
1148  SourceRange ArgRange = OrigArg->getSourceRange();
1149  commit.replaceWithInner(Msg->getSourceRange(), ArgRange);
1150 
1151  if (isa<ParenExpr>(OrigArg) || isa<IntegerLiteral>(OrigArg))
1152  commit.insertBefore(ArgRange.getBegin(), "@");
1153  else
1154  commit.insertWrap("@(", ArgRange, ")");
1155 
1156  return true;
1157  }
1158  }
1159 
1160  return false;
1161 }
1162 
1164  const NSAPI &NS, Commit &commit) {
1165  Selector Sel = Msg->getSelector();
1166 
1170  if (Msg->getNumArgs() != 1)
1171  return false;
1172  return doRewriteToUTF8StringBoxedExpressionHelper(Msg, NS, commit);
1173  }
1174 
1176  if (Msg->getNumArgs() != 2)
1177  return false;
1178 
1179  const Expr *encodingArg = Msg->getArg(1);
1180  if (NS.isNSUTF8StringEncodingConstant(encodingArg) ||
1181  NS.isNSASCIIStringEncodingConstant(encodingArg))
1182  return doRewriteToUTF8StringBoxedExpressionHelper(Msg, NS, commit);
1183  }
1184 
1185  return false;
1186 }
clang::ObjCMessageExpr::SuperInstance
@ SuperInstance
The receiver is the instance of the superclass object.
Definition: ExprObjC.h:1097
clang::ObjCInterfaceDecl
Represents an ObjC class declaration.
Definition: DeclObjC.h:1151
NSAPI.h
clang::comments::tok::text
@ text
Definition: CommentLexer.h:35
castOperatorNeedsParens
static bool castOperatorNeedsParens(const Expr *FullExpr)
Definition: RewriteObjCFoundationAPI.cpp:913
clang::NSAPI::NSNumberWithInteger
@ NSNumberWithInteger
Definition: NSAPI.h:188
clang::NSAPI::NSDict_objectForKey
@ NSDict_objectForKey
Definition: NSAPI.h:106
clang::ObjCMessageExpr::getReceiverInterface
ObjCInterfaceDecl * getReceiverInterface() const
Retrieve the Objective-C interface to which this message is being directed, if known.
Definition: ExprObjC.cpp:314
clang::NSAPI::NSStr_stringWithCString
@ NSStr_stringWithCString
Definition: NSAPI.h:47
clang::CXXBoolLiteralExpr
A boolean literal, per ([C++ lex.bool] Boolean literals).
Definition: ExprCXX.h:721
getLiteralInfo
static bool getLiteralInfo(SourceRange literalRange, bool isFloat, bool isIntZero, ASTContext &Ctx, LiteralInfo &Info)
Definition: RewriteObjCFoundationAPI.cpp:682
rewriteToArraySubscriptSet
static bool rewriteToArraySubscriptSet(const ObjCInterfaceDecl *IFace, const ObjCMessageExpr *Msg, const NSAPI &NS, Commit &commit)
Definition: RewriteObjCFoundationAPI.cpp:222
clang::NSAPI::getNSNumberLiteralMethodKind
Optional< NSNumberLiteralMethodKind > getNSNumberLiteralMethodKind(Selector Sel) const
Return NSNumberLiteralMethodKind if Sel is such a selector.
Definition: NSAPI.cpp:367
clang::SourceRange
A trivial tuple used to represent a source range.
Definition: SourceLocation.h:212
clang::NSAPI::NSDict_initWithObjectsAndKeys
@ NSDict_initWithObjectsAndKeys
Definition: NSAPI.h:104
clang::edit::Commit::insertWrap
bool insertWrap(StringRef before, CharSourceRange range, StringRef after)
Definition: Commit.cpp:103
clang::edit::Commit::insertFromRange
bool insertFromRange(SourceLocation loc, CharSourceRange range, bool afterToken=false, bool beforePreviousInsertions=false)
Definition: Commit.cpp:64
rewriteToDictionaryLiteral
static bool rewriteToDictionaryLiteral(const ObjCMessageExpr *Msg, const NSAPI &NS, Commit &commit)
Definition: RewriteObjCFoundationAPI.cpp:489
clang::NSAPI::isNSNumberLiteralSelector
bool isNSNumberLiteralSelector(NSNumberLiteralMethodKind MK, Selector Sel) const
Definition: NSAPI.h:199
clang::ObjCMessageExpr::getSelector
Selector getSelector() const
Definition: ExprObjC.cpp:293
clang::NSAPI::ClassId_NSNumber
@ ClassId_NSNumber
Definition: NSAPI.h:36
clang::NSAPI::getNSClassId
IdentifierInfo * getNSClassId(NSClassIdKindKind K) const
Definition: NSAPI.cpp:22
llvm::SmallVector
Definition: LLVM.h:38
clang::ParentMap::getParentIgnoreParenCasts
Stmt * getParentIgnoreParenCasts(Stmt *) const
Definition: ParentMap.cpp:145
clang::SourceLocation
Encodes a location in the source.
Definition: SourceLocation.h:88
clang::SourceLocation::getLocWithOffset
SourceLocation getLocWithOffset(IntTy Offset) const
Return a source location with the specified offset from this SourceLocation.
Definition: SourceLocation.h:136
clang::SourceRange::getBegin
SourceLocation getBegin() const
Definition: SourceLocation.h:221
rewriteToDictionarySubscriptSet
static bool rewriteToDictionarySubscriptSet(const ObjCInterfaceDecl *IFace, const ObjCMessageExpr *Msg, const NSAPI &NS, Commit &commit)
Definition: RewriteObjCFoundationAPI.cpp:256
clang::edit::Commit::insert
bool insert(SourceLocation loc, StringRef text, bool afterToken=false, bool beforePreviousInsertions=false)
Definition: Commit.cpp:48
clang::NSAPI::NSNumberWithUnsignedLongLong
@ NSNumberWithUnsignedLongLong
Definition: NSAPI.h:184
clang::Stmt::getSourceRange
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition: Stmt.cpp:324
clang::NSAPI::NSStr_stringWithCStringEncoding
@ NSStr_stringWithCStringEncoding
Definition: NSAPI.h:46
clang::QualType
A (possibly-)qualified type.
Definition: Type.h:673
clang::edit::Commit::replace
bool replace(CharSourceRange range, StringRef text)
Definition: Commit.cpp:116
clang::Type::isFloatingType
bool isFloatingType() const
Definition: Type.cpp:2104
clang::DiagnosticsEngine
Concrete class used by the front-end to report problems and issues.
Definition: Diagnostic.h:191
rewriteToNumberLiteral
static bool rewriteToNumberLiteral(const ObjCMessageExpr *Msg, const NSAPI &NS, Commit &commit)
Definition: RewriteObjCFoundationAPI.cpp:752
clang::NSAPI::NSMutableDict_setObjectForKey
@ NSMutableDict_setObjectForKey
Definition: NSAPI.h:107
clang::NSAPI::NSNumberWithShort
@ NSNumberWithShort
Definition: NSAPI.h:177
clang::NSAPI::NSStr_stringWithString
@ NSStr_stringWithString
Definition: NSAPI.h:44
clang::ObjCMessageExpr::getInstanceReceiver
Expr * getInstanceReceiver()
Returns the object expression (receiver) for an instance message, or null for a message that is not a...
Definition: ExprObjC.h:1250
llvm::Optional< bool >
clang::Lexer::getSourceText
static StringRef getSourceText(CharSourceRange Range, const SourceManager &SM, const LangOptions &LangOpts, bool *Invalid=nullptr)
Returns a string for the source that the range encompasses.
Definition: Lexer.cpp:957
clang::UnaryOperator
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Definition: Expr.h:2157
clang::NSAPI::NSArr_array
@ NSArr_array
Definition: NSAPI.h:73
rewriteToArrayLiteral
static bool rewriteToArrayLiteral(const ObjCMessageExpr *Msg, const NSAPI &NS, Commit &commit, const ParentMap *PMap)
Definition: RewriteObjCFoundationAPI.cpp:377
subscriptOperatorNeedsParens
static bool subscriptOperatorNeedsParens(const Expr *FullExpr)
Definition: RewriteObjCFoundationAPI.cpp:891
clang::edit::Commit::insertAfterToken
bool insertAfterToken(SourceLocation loc, StringRef text, bool beforePreviousInsertions=false)
Definition: Commit.h:73
clang::NSAPI::NSArr_objectAtIndex
@ NSArr_objectAtIndex
Definition: NSAPI.h:80
clang::ObjCMessageExpr::SuperClass
@ SuperClass
The receiver is a superclass.
Definition: ExprObjC.h:1094
clang::NSAPI::getNSArraySelector
Selector getNSArraySelector(NSArrayMethodKind MK) const
The Objective-C NSArray selectors.
Definition: NSAPI.cpp:78
clang::ObjCObjectType::getInterface
ObjCInterfaceDecl * getInterface() const
Gets the interface declaration for this object type, if the base type really is an interface.
Definition: Type.h:6051
clang::Expr::IgnoreImpCasts
Expr * IgnoreImpCasts() LLVM_READONLY
Skip past any implicit casts which might surround this expression until reaching a fixed point.
Definition: Expr.cpp:2899
clang::ASTContext::getSourceManager
SourceManager & getSourceManager()
Definition: ASTContext.h:695
clang::ObjCMessageExpr::getArg
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
Definition: ExprObjC.h:1385
clang::NSAPI::getASTContext
ASTContext & getASTContext() const
Definition: NSAPI.h:27
clang::transformer::edit
EditGenerator edit(ASTEdit E)
Generates a single (specified) edit.
Definition: RewriteRule.cpp:75
rewriteToArraySubscriptGet
static bool rewriteToArraySubscriptGet(const ObjCInterfaceDecl *IFace, const ObjCMessageExpr *Msg, const NSAPI &NS, Commit &commit)
Definition: RewriteObjCFoundationAPI.cpp:202
clang::NSAPI::NSNumberWithDouble
@ NSNumberWithDouble
Definition: NSAPI.h:186
clang::ObjCBoolLiteralExpr
ObjCBoolLiteralExpr - Objective-C Boolean Literal.
Definition: ExprObjC.h:88
clang::ObjCObjectType
Represents a class type in Objective C.
Definition: Type.h:5816
clang::FullExpr
FullExpr - Represents a "full-expression" node.
Definition: Expr.h:998
clang::ObjCArrayLiteral
ObjCArrayLiteral - used for objective-c array containers; as in: @["Hello", NSApp,...
Definition: ExprObjC.h:190
clang::NSAPI::NSDict_dictionary
@ NSDict_dictionary
Definition: NSAPI.h:97
clang::NSAPI::NSNumberWithUnsignedInteger
@ NSNumberWithUnsignedInteger
Definition: NSAPI.h:189
clang::NSAPI::NSStr_initWithUTF8String
@ NSStr_initWithUTF8String
Definition: NSAPI.h:49
U
clang::CharSourceRange::getCharRange
static CharSourceRange getCharRange(SourceRange R)
Definition: SourceLocation.h:267
clang::IntegerLiteral
Definition: Expr.h:1488
clang::NSAPI::NSStr_initWithString
@ NSStr_initWithString
Definition: NSAPI.h:48
clang::ObjCInterfaceDecl::lookupInstanceMethod
ObjCMethodDecl * lookupInstanceMethod(Selector Sel) const
Lookup an instance method for a given selector.
Definition: DeclObjC.h:1826
clang::Expr::isTypeDependent
bool isTypeDependent() const
Determines whether the type of this expression depends on.
Definition: Expr.h:185
clang::NSAPI::NSNumberWithLongLong
@ NSNumberWithLongLong
Definition: NSAPI.h:183
clang::NSAPI::NSDict_dictionaryWithObjectForKey
@ NSDict_dictionaryWithObjectForKey
Definition: NSAPI.h:99
clang::NSAPI::isNSUTF8StringEncodingConstant
bool isNSUTF8StringEncodingConstant(const Expr *E) const
Returns true if the expression.
Definition: NSAPI.h:60
clang::NSAPI::NSArr_initWithObjects
@ NSArr_initWithObjects
Definition: NSAPI.h:79
clang::NSAPI::NSMutableArr_replaceObjectAtIndex
@ NSMutableArr_replaceObjectAtIndex
Definition: NSAPI.h:81
clang::SourceRange::getEnd
SourceLocation getEnd() const
Definition: SourceLocation.h:222
clang::ASTContext
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:212
clang::NSAPI::NSDict_initWithObjectsForKeys
@ NSDict_initWithObjectsForKeys
Definition: NSAPI.h:105
clang::Type::getAs
const T * getAs() const
Member-template getAs<specific type>'.
Definition: Type.h:7161
clang::ObjCMessageExpr::getReceiverKind
ReceiverKind getReceiverKind() const
Determine the kind of receiver that this message is being sent to.
Definition: ExprObjC.h:1224
maybeAdjustInterfaceForSubscriptingCheck
static const ObjCInterfaceDecl * maybeAdjustInterfaceForSubscriptingCheck(const ObjCInterfaceDecl *IFace, const Expr *Receiver, ASTContext &Ctx)
Check for classes that accept 'objectForKey:' (or the other selectors that the migrator handles) but ...
Definition: RewriteObjCFoundationAPI.cpp:108
clang::NSAPI
Definition: NSAPI.h:23
clang::ASTContext::getTypeSize
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
Definition: ASTContext.h:2245
clang::Stmt::getEndLoc
SourceLocation getEndLoc() const LLVM_READONLY
Definition: Stmt.cpp:348
clang::NSAPI::NSNumberWithUnsignedShort
@ NSNumberWithUnsignedShort
Definition: NSAPI.h:178
Rewriters.h
clang::ObjCMessageExpr::Class
@ Class
The receiver is a class.
Definition: ExprObjC.h:1088
clang::NSAPI::ClassId_NSString
@ ClassId_NSString
Definition: NSAPI.h:31
clang::NSAPI::NSNumberWithFloat
@ NSNumberWithFloat
Definition: NSAPI.h:185
ASTContext.h
clang::ASTContext::getObjContainingInterface
const ObjCInterfaceDecl * getObjContainingInterface(const NamedDecl *ND) const
Returns the Objective-C interface that ND belongs to if it is an Objective-C method/property/ivar etc...
Definition: ASTContext.cpp:2903
clang::NSAPI::NSArr_arrayWithArray
@ NSArr_arrayWithArray
Definition: NSAPI.h:74
clang::Type::getPointeeType
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition: Type.cpp:625
clang::NSAPI::NSArr_initWithArray
@ NSArr_initWithArray
Definition: NSAPI.h:78
clang::StringLiteral
StringLiteral - This represents a string literal expression, e.g.
Definition: Expr.h:1761
clang::NSAPI::NSDict_dictionaryWithObjectsAndKeys
@ NSDict_dictionaryWithObjectsAndKeys
Definition: NSAPI.h:102
checkForLiteralCreation
static bool checkForLiteralCreation(const ObjCMessageExpr *Msg, IdentifierInfo *&ClassId, const LangOptions &LangOpts)
Definition: RewriteObjCFoundationAPI.cpp:25
rewriteToCharLiteral
static bool rewriteToCharLiteral(const ObjCMessageExpr *Msg, const CharacterLiteral *Arg, const NSAPI &NS, Commit &commit)
Definition: RewriteObjCFoundationAPI.cpp:642
clang::NSAPI::NSNumberWithUnsignedInt
@ NSNumberWithUnsignedInt
Definition: NSAPI.h:180
ExprObjC.h
ExprCXX.h
clang::NSAPI::NSNumberWithLong
@ NSNumberWithLong
Definition: NSAPI.h:181
objectifyExpr
static void objectifyExpr(const Expr *E, Commit &commit)
Adds an explicit cast to 'id' if the type is not objc object.
Definition: RewriteObjCFoundationAPI.cpp:942
rewriteToSubscriptGetCommon
static bool rewriteToSubscriptGetCommon(const ObjCMessageExpr *Msg, Commit &commit)
Definition: RewriteObjCFoundationAPI.cpp:180
clang::ObjCMessageExpr
An expression that sends a message to the given Objective-C object or class.
Definition: ExprObjC.h:940
clang::NSAPI::ClassId_NSDictionary
@ ClassId_NSDictionary
Definition: NSAPI.h:34
clang::NSAPI::getNSDictionarySelector
Selector getNSDictionarySelector(NSDictionaryMethodKind MK) const
The Objective-C NSDictionary selectors.
Definition: NSAPI.cpp:155
clang::NSAPI::NSNumberWithUnsignedLong
@ NSNumberWithUnsignedLong
Definition: NSAPI.h:182
clang::QualType::getUnqualifiedType
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
Definition: Type.h:6504
clang::NSAPI::getObjectForKeyedSubscriptSelector
Selector getObjectForKeyedSubscriptSelector() const
Returns selector for "objectForKeyedSubscript:".
Definition: NSAPI.h:137
clang::Type::isObjCObjectPointerType
bool isObjCObjectPointerType() const
Definition: Type.h:6794
clang::CharacterLiteral::Ascii
@ Ascii
Definition: Expr.h:1581
clang::CharacterLiteral
Definition: Expr.h:1578
clang::Expr::IgnoreParenCasts
Expr * IgnoreParenCasts() LLVM_READONLY
Skip past any parentheses and casts which might surround this expression until reaching a fixed point...
Definition: Expr.cpp:2924
clang::edit::rewriteObjCRedundantCallWithLiteral
bool rewriteObjCRedundantCallWithLiteral(const ObjCMessageExpr *Msg, const NSAPI &NS, Commit &commit)
Definition: RewriteObjCFoundationAPI.cpp:58
clang::NSAPI::isNSASCIIStringEncodingConstant
bool isNSASCIIStringEncodingConstant(const Expr *E) const
Returns true if the expression.
Definition: NSAPI.h:66
clang::ParentMap
Definition: ParentMap.h:20
clang::NSAPI::getSetObjectAtIndexedSubscriptSelector
Selector getSetObjectAtIndexedSubscriptSelector() const
Returns selector for "setObject:atIndexedSubscript".
Definition: NSAPI.h:155
clang::NSAPI::getObjectAtIndexedSubscriptSelector
Selector getObjectAtIndexedSubscriptSelector() const
Returns selector for "objectAtIndexedSubscript:".
Definition: NSAPI.h:143
clang::NSAPI::NSStr_stringWithUTF8String
@ NSStr_stringWithUTF8String
Definition: NSAPI.h:45
rewriteToBoolLiteral
static bool rewriteToBoolLiteral(const ObjCMessageExpr *Msg, const Expr *Arg, const NSAPI &NS, Commit &commit)
Definition: RewriteObjCFoundationAPI.cpp:658
rewriteToStringBoxedExpression
static bool rewriteToStringBoxedExpression(const ObjCMessageExpr *Msg, const NSAPI &NS, Commit &commit)
Definition: RewriteObjCFoundationAPI.cpp:1163
clang::NSAPI::NSDict_dictionaryWithObjectsForKeys
@ NSDict_dictionaryWithObjectsForKeys
Definition: NSAPI.h:100
clang::Type::isPointerType
bool isPointerType() const
Definition: Type.h:6672
clang::NSAPI::NSArr_arrayWithObjects
@ NSArr_arrayWithObjects
Definition: NSAPI.h:76
clang::NSAPI::NSNumberLiteralMethodKind
NSNumberLiteralMethodKind
Enumerates the NSNumber methods used to generate literals.
Definition: NSAPI.h:174
clang::edit::Commit
Definition: Commit.h:29
clang::ASTContext::isObjCIdType
bool isObjCIdType(QualType T) const
Definition: ASTContext.h:2756
clang::NamedDecl::getIdentifier
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Definition: Decl.h:270
clang::ValueDecl
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition: Decl.h:676
getNSArrayObjects
static bool getNSArrayObjects(const Expr *E, const NSAPI &NS, SmallVectorImpl< const Expr * > &Objs)
If Msg is an NSArray creation message or literal, this gets the objects that were used to create it.
Definition: RewriteObjCFoundationAPI.cpp:439
clang::ASTContext::IntTy
CanQualType IntTy
Definition: ASTContext.h:1084
clang::CharSourceRange::getTokenRange
static CharSourceRange getTokenRange(SourceRange R)
Definition: SourceLocation.h:263
clang::Expr::getExprLoc
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition: Expr.cpp:229
canRewriteToSubscriptSyntax
static bool canRewriteToSubscriptSyntax(const ObjCInterfaceDecl *&IFace, const ObjCMessageExpr *Msg, ASTContext &Ctx, Selector subscriptSel)
Definition: RewriteObjCFoundationAPI.cpp:155
clang::QualType::isNull
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition: Type.h:738
Lexer.h
clang::NSAPI::NSNumberWithInt
@ NSNumberWithInt
Definition: NSAPI.h:179
clang::Expr::IgnoreParenImpCasts
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Definition: Expr.cpp:2919
clang::NSAPI::NSDict_dictionaryWithDictionary
@ NSDict_dictionaryWithDictionary
Definition: NSAPI.h:98
clang::CharSourceRange
Represents a character-granular source range.
Definition: SourceLocation.h:255
Commit.h
clang::ASTContext::CharTy
CanQualType CharTy
Definition: ASTContext.h:1077
clang::Type::isSignedIntegerType
bool isSignedIntegerType() const
Return true if this is an integer type that is signed, according to C99 6.2.5p4 [char,...
Definition: Type.cpp:2013
clang::IdentifierInfo
One of these records is kept for each identifier that is lexed.
Definition: IdentifierTable.h:84
shouldNotRewriteImmediateMessageArgs
static bool shouldNotRewriteImmediateMessageArgs(const ObjCMessageExpr *Msg, const NSAPI &NS)
Returns true if the immediate message arguments of Msg should not be rewritten because it will interf...
Definition: RewriteObjCFoundationAPI.cpp:602
clang::ObjCMessageExpr::isImplicit
bool isImplicit() const
Indicates whether the message send was implicitly generated by the implementation.
Definition: ExprObjC.h:1220
clang::NSAPI::getSetObjectForKeyedSubscriptSelector
Selector getSetObjectForKeyedSubscriptSelector() const
Returns selector for "setObject:forKeyedSubscript".
Definition: NSAPI.h:149
clang::SourceLocation::isMacroID
bool isMacroID() const
Definition: SourceLocation.h:105
clang::LangOptions
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Definition: LangOptions.h:58
clang::Type::isBooleanType
bool isBooleanType() const
Definition: Type.h:7071
clang::NSAPI::getNSStringSelector
Selector getNSStringSelector(NSStringMethodKind MK) const
The Objective-C NSString selectors.
Definition: NSAPI.cpp:42
clang::ObjCMethodDecl
ObjCMethodDecl - Represents an instance or class method declaration.
Definition: DeclObjC.h:139
clang::NSAPI::NSNumberWithUnsignedChar
@ NSNumberWithUnsignedChar
Definition: NSAPI.h:176
clang::PointerType
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition: Type.h:2640
clang::ObjCMessageExpr::Instance
@ Instance
The receiver is an object instance.
Definition: ExprObjC.h:1091
ParentMap.h
clang::NSAPI::NSDict_initWithDictionary
@ NSDict_initWithDictionary
Definition: NSAPI.h:103
clang::DiagnosticsEngine::getCustomDiagID
unsigned getCustomDiagID(Level L, const char(&FormatString)[N])
Return an ID for a diagnostic with the specified format string and level.
Definition: Diagnostic.h:866
clang::Expr::IgnoreParens
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
Definition: Expr.cpp:2915
clang
Definition: CalledOnceCheck.h:17
clang::Selector
Smart pointer class that efficiently represents Objective-C method names.
Definition: IdentifierTable.h:748
clang::Type::isArrayType
bool isArrayType() const
Definition: Type.h:6738
clang::ASTContext::isSentinelNullExpr
bool isSentinelNullExpr(const Expr *E)
Definition: ASTContext.cpp:2840
clang::OMF_alloc
@ OMF_alloc
Definition: IdentifierTable.h:694
isEnumConstant
static bool isEnumConstant(const Expr *E)
Definition: RewriteObjCFoundationAPI.cpp:967
clang::Expr::getType
QualType getType() const
Definition: Expr.h:141
clang::edit::Commit::insertBefore
bool insertBefore(SourceLocation loc, StringRef text)
Definition: Commit.h:78
maybePutParensOnReceiver
static void maybePutParensOnReceiver(const Expr *Receiver, Commit &commit)
Definition: RewriteObjCFoundationAPI.cpp:173
clang::NSAPI::ClassId_NSArray
@ ClassId_NSArray
Definition: NSAPI.h:32
clang::ObjCMessageExpr::getMethodDecl
const ObjCMethodDecl * getMethodDecl() const
Definition: ExprObjC.h:1346
clang::Stmt::getBeginLoc
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Stmt.cpp:336
clang::ImplicitCastExpr
ImplicitCastExpr - Allows us to explicitly represent implicit type conversions, which have no direct ...
Definition: Expr.h:3618
clang::NSAPI::NSNumberWithChar
@ NSNumberWithChar
Definition: NSAPI.h:175
clang::NSAPI::NSNumberWithBool
@ NSNumberWithBool
Definition: NSAPI.h:187
clang::ASTContext::getArrayDecayedType
QualType getArrayDecayedType(QualType T) const
Return the properly qualified result of decaying the specified array type to a pointer.
Definition: ASTContext.cpp:6278
rewriteToDictionarySubscriptGet
static bool rewriteToDictionarySubscriptGet(const ObjCInterfaceDecl *IFace, const ObjCMessageExpr *Msg, const NSAPI &NS, Commit &commit)
Definition: RewriteObjCFoundationAPI.cpp:212
clang::ASTContext::hasSameType
bool hasSameType(QualType T1, QualType T2) const
Determine whether the given types T1 and T2 are equivalent.
Definition: ASTContext.h:2484
rewriteToNumericBoxedExpression
static bool rewriteToNumericBoxedExpression(const ObjCMessageExpr *Msg, const NSAPI &NS, Commit &commit)
Definition: RewriteObjCFoundationAPI.cpp:975
llvm::SmallVectorImpl
Definition: LLVM.h:39
clang::ObjCMessageExpr::getNumArgs
unsigned getNumArgs() const
Return the number of actual arguments in this message, not counting the receiver.
Definition: ExprObjC.h:1372
clang::ObjCMessageExpr::getClassReceiver
QualType getClassReceiver() const
Returns the type of a class message send, or NULL if the message is not a class message.
Definition: ExprObjC.h:1269
clang::ObjCMessageExpr::getSuperType
QualType getSuperType() const
Retrieve the type referred to by 'super'.
Definition: ExprObjC.h:1326
clang::edit::rewriteToObjCLiteralSyntax
bool rewriteToObjCLiteralSyntax(const ObjCMessageExpr *Msg, const NSAPI &NS, Commit &commit, const ParentMap *PMap)
Definition: RewriteObjCFoundationAPI.cpp:338
clang::edit::rewriteToObjCSubscriptSyntax
bool rewriteToObjCSubscriptSyntax(const ObjCMessageExpr *Msg, const NSAPI &NS, Commit &commit)
Definition: RewriteObjCFoundationAPI.cpp:289
clang::ASTContext::hasSameUnqualifiedType
bool hasSameUnqualifiedType(QualType T1, QualType T2) const
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
Definition: ASTContext.h:2508
doRewriteToUTF8StringBoxedExpressionHelper
static bool doRewriteToUTF8StringBoxedExpressionHelper(const ObjCMessageExpr *Msg, const NSAPI &NS, Commit &commit)
Definition: RewriteObjCFoundationAPI.cpp:1124
clang::Expr
This represents one expression.
Definition: Expr.h:109
clang::EnumType
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of enums.
Definition: Type.h:4639
clang::ast_matchers::has
const internal::ArgumentAdaptingMatcherFunc< internal::HasMatcher > has
Matches AST nodes that have child AST nodes that match the provided matcher.
Definition: ASTMatchersInternal.cpp:1007
clang::DiagnosticsEngine::Warning
@ Warning
Definition: Diagnostic.h:198
clang::DeclRefExpr
A reference to a declared variable, function, enum, etc.
Definition: Expr.h:1217
clang::edit::Commit::remove
bool remove(CharSourceRange range)
Definition: Commit.cpp:91
clang::ASTContext::getLangOpts
const LangOptions & getLangOpts() const
Definition: ASTContext.h:765
clang::edit::Commit::replaceWithInner
bool replaceWithInner(CharSourceRange range, CharSourceRange innerRange)
Definition: Commit.cpp:132
clang::ASTContext::getDiagnostics
DiagnosticsEngine & getDiagnostics() const
Definition: ASTContext.cpp:1499
clang::CharacterLiteral::getKind
CharacterKind getKind() const
Definition: Expr.h:1605
clang::DiagnosticsEngine::Report
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
Definition: Diagnostic.h:1523
clang::NSAPI::NSArr_arrayWithObject
@ NSArr_arrayWithObject
Definition: NSAPI.h:75
clang::NamedDecl::getName
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition: Decl.h:276