Transforms.cpp revision 7acddacc921cd0b3f813443a8641eeddb82dfbd4
1//===--- Tranforms.cpp - Tranformations to ARC mode -----------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9// Transformations:
10//===----------------------------------------------------------------------===//
11//
12// castNonObjCToObjC:
13//
14// A cast of non-objc pointer to an objc one is checked. If the non-objc pointer
15// is from a file-level variable, objc_unretainedObject function is used to
16// convert it.
17//
18//  NSString *str = (NSString *)kUTTypePlainText;
19//  str = b ? kUTTypeRTF : kUTTypePlainText;
20// ---->
21//  NSString *str = objc_unretainedObject(kUTTypePlainText);
22//  str = objc_unretainedObject(b ? kUTTypeRTF : kUTTypePlainText);
23//
24// For a C pointer to ObjC, objc_unretainedPointer is used.
25//
26//  void *vp = str; // NSString*
27// ---->
28//  void *vp = (void*)objc_unretainedPointer(str);
29//
30//===----------------------------------------------------------------------===//
31//
32// rewriteAllocCopyWithZone:
33//
34// Calls to +allocWithZone/-copyWithZone/-mutableCopyWithZone are changed to
35// +alloc/-copy/-mutableCopy if we can safely remove the given parameter.
36//
37//  Foo *foo1 = [[Foo allocWithZone:[self zone]] init];
38// ---->
39//  Foo *foo1 = [[Foo alloc] init];
40//
41//===----------------------------------------------------------------------===//
42//
43// rewriteAutoreleasePool:
44//
45// Calls to NSAutoreleasePools will be rewritten as an @autorelease scope.
46//
47//  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
48//  ...
49//  [pool release];
50// ---->
51//  @autorelease {
52//  ...
53//  }
54//
55// An NSAutoreleasePool will not be touched if:
56// - There is not a corresponding -release/-drain in the same scope
57// - Not all references of the NSAutoreleasePool variable can be removed
58// - There is a variable that is declared inside the intended @autorelease scope
59//   which is also used outside it.
60//
61//===----------------------------------------------------------------------===//
62//
63// makeAssignARCSafe:
64//
65// Add '__strong' where appropriate.
66//
67//  for (id x in collection) {
68//    x = 0;
69//  }
70// ---->
71//  for (__strong id x in collection) {
72//    x = 0;
73//  }
74//
75//===----------------------------------------------------------------------===//
76//
77// removeRetainReleaseDealloc:
78//
79// Removes retain/release/autorelease/dealloc messages.
80//
81//  return [[foo retain] autorelease];
82// ---->
83//  return foo;
84//
85//===----------------------------------------------------------------------===//
86//
87// removeEmptyStatements:
88//
89// Removes empty statements that are leftovers from previous transformations.
90// e.g for
91//
92//  [x retain];
93//
94// removeRetainReleaseDealloc will leave an empty ";" that removeEmptyStatements
95// will remove.
96//
97//===----------------------------------------------------------------------===//
98//
99// changeIvarsOfAssignProperties:
100//
101// If a property is synthesized with 'assign' attribute and the user didn't
102// set a lifetime attribute, change the property to 'weak' or add
103// __unsafe_unretained if the ARC runtime is not available.
104//
105//  @interface Foo : NSObject {
106//      NSObject *x;
107//  }
108//  @property (assign) id x;
109//  @end
110// ---->
111//  @interface Foo : NSObject {
112//      NSObject *__weak x;
113//  }
114//  @property (weak) id x;
115//  @end
116//
117//===----------------------------------------------------------------------===//
118//
119// rewriteUnusedDelegateInit:
120//
121// Rewrites an unused result of calling a delegate initialization, to assigning
122// the result to self.
123// e.g
124//  [self init];
125// ---->
126//  self = [self init];
127//
128//===----------------------------------------------------------------------===//
129//
130// rewriteBlockObjCVariable:
131//
132// Adding __block to an obj-c variable could be either because the the variable
133// is used for output storage or the user wanted to break a retain cycle.
134// This transformation checks whether a reference of the variable for the block
135// is actually needed (it is assigned to or its address is taken) or not.
136// If the reference is not needed it will assume __block was added to break a
137// cycle so it will remove '__block' and add __weak/__unsafe_unretained.
138// e.g
139//
140//   __block Foo *x;
141//   bar(^ { [x cake]; });
142// ---->
143//   __weak Foo *x;
144//   bar(^ { [x cake]; });
145//
146//===----------------------------------------------------------------------===//
147//
148// removeZeroOutIvarsInDealloc:
149//
150// Removes zero'ing out "strong" @synthesized properties in a -dealloc method.
151//
152//===----------------------------------------------------------------------===//
153
154#include "Internals.h"
155#include "clang/Sema/SemaDiagnostic.h"
156#include "clang/AST/RecursiveASTVisitor.h"
157#include "clang/AST/StmtVisitor.h"
158#include "clang/AST/ParentMap.h"
159#include "clang/Analysis/DomainSpecific/CocoaConventions.h"
160#include "clang/Lex/Lexer.h"
161#include "clang/Basic/SourceManager.h"
162#include "llvm/ADT/StringSwitch.h"
163#include "llvm/ADT/DenseSet.h"
164#include <map>
165
166using namespace clang;
167using namespace arcmt;
168using llvm::StringRef;
169
170//===----------------------------------------------------------------------===//
171// Transformations.
172//===----------------------------------------------------------------------===//
173
174namespace {
175
176class RemovablesCollector : public RecursiveASTVisitor<RemovablesCollector> {
177  llvm::DenseSet<Expr *> &Removables;
178
179public:
180  RemovablesCollector(llvm::DenseSet<Expr *> &removables)
181  : Removables(removables) { }
182
183  bool shouldWalkTypesOfTypeLocs() const { return false; }
184
185  bool TraverseStmtExpr(StmtExpr *E) {
186    CompoundStmt *S = E->getSubStmt();
187    for (CompoundStmt::body_iterator
188        I = S->body_begin(), E = S->body_end(); I != E; ++I) {
189      if (I != E - 1)
190        mark(*I);
191      TraverseStmt(*I);
192    }
193    return true;
194  }
195
196  bool VisitCompoundStmt(CompoundStmt *S) {
197    for (CompoundStmt::body_iterator
198        I = S->body_begin(), E = S->body_end(); I != E; ++I)
199      mark(*I);
200    return true;
201  }
202
203  bool VisitIfStmt(IfStmt *S) {
204    mark(S->getThen());
205    mark(S->getElse());
206    return true;
207  }
208
209  bool VisitWhileStmt(WhileStmt *S) {
210    mark(S->getBody());
211    return true;
212  }
213
214  bool VisitDoStmt(DoStmt *S) {
215    mark(S->getBody());
216    return true;
217  }
218
219  bool VisitForStmt(ForStmt *S) {
220    mark(S->getInit());
221    mark(S->getInc());
222    mark(S->getBody());
223    return true;
224  }
225
226private:
227  void mark(Stmt *S) {
228    if (!S) return;
229
230    if (LabelStmt *Label = dyn_cast<LabelStmt>(S))
231      return mark(Label->getSubStmt());
232    if (ImplicitCastExpr *CE = dyn_cast<ImplicitCastExpr>(S))
233      return mark(CE->getSubExpr());
234    if (ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(S))
235      return mark(EWC->getSubExpr());
236    if (Expr *E = dyn_cast<Expr>(S))
237      Removables.insert(E);
238  }
239};
240
241} // end anonymous namespace.
242
243static bool HasSideEffects(Expr *E, ASTContext &Ctx) {
244  if (!E || !E->HasSideEffects(Ctx))
245    return false;
246
247  E = E->IgnoreParenCasts();
248  ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(E);
249  if (!ME)
250    return true;
251  switch (ME->getMethodFamily()) {
252  case OMF_autorelease:
253  case OMF_dealloc:
254  case OMF_release:
255  case OMF_retain:
256    switch (ME->getReceiverKind()) {
257    case ObjCMessageExpr::SuperInstance:
258      return false;
259    case ObjCMessageExpr::Instance:
260      return HasSideEffects(ME->getInstanceReceiver(), Ctx);
261    default:
262      break;
263    }
264    break;
265  default:
266    break;
267  }
268
269  return true;
270}
271
272static void removeDeallocMethod(MigrationPass &pass) {
273    ASTContext &Ctx = pass.Ctx;
274    TransformActions &TA = pass.TA;
275    DeclContext *DC = Ctx.getTranslationUnitDecl();
276    ObjCMethodDecl *DeallocMethodDecl = 0;
277    IdentifierInfo *II = &Ctx.Idents.get("dealloc");
278
279    for (DeclContext::decl_iterator I = DC->decls_begin(), E = DC->decls_end();
280         I != E; ++I) {
281        Decl *D = *I;
282        if (ObjCImplementationDecl *IMD =
283            dyn_cast<ObjCImplementationDecl>(D)) {
284            DeallocMethodDecl = 0;
285            for (ObjCImplementationDecl::instmeth_iterator I =
286                 IMD->instmeth_begin(), E = IMD->instmeth_end();
287                 I != E; ++I) {
288                ObjCMethodDecl *OMD = *I;
289                if (OMD->isInstanceMethod() &&
290                    OMD->getSelector() == Ctx.Selectors.getSelector(0, &II)) {
291                    DeallocMethodDecl = OMD;
292                    break;
293                }
294            }
295            if (DeallocMethodDecl &&
296                DeallocMethodDecl->getCompoundBody()->body_empty()) {
297              Transaction Trans(TA);
298              TA.remove(DeallocMethodDecl->getSourceRange());
299            }
300        }
301    }
302}
303
304namespace {
305
306class ReferenceClear : public RecursiveASTVisitor<ReferenceClear> {
307  llvm::DenseSet<Expr *> &Refs;
308public:
309  ReferenceClear(llvm::DenseSet<Expr *> &refs) : Refs(refs) { }
310  bool VisitDeclRefExpr(DeclRefExpr *E) { Refs.erase(E); return true; }
311  bool VisitBlockDeclRefExpr(BlockDeclRefExpr *E) { Refs.erase(E); return true; }
312  void clearRefsIn(Stmt *S) { TraverseStmt(S); }
313  template <typename iterator>
314  void clearRefsIn(iterator begin, iterator end) {
315    for (; begin != end; ++begin)
316      TraverseStmt(*begin);
317  }
318};
319
320class ReferenceCollector : public RecursiveASTVisitor<ReferenceCollector> {
321  ValueDecl *Dcl;
322  llvm::DenseSet<Expr *> &Refs;
323
324public:
325  ReferenceCollector(llvm::DenseSet<Expr *> &refs)
326    : Dcl(0), Refs(refs) { }
327
328  void lookFor(ValueDecl *D, Stmt *S) {
329    Dcl = D;
330    TraverseStmt(S);
331  }
332
333  bool VisitDeclRefExpr(DeclRefExpr *E) {
334    if (E->getDecl() == Dcl)
335      Refs.insert(E);
336    return true;
337  }
338
339  bool VisitBlockDeclRefExpr(BlockDeclRefExpr *E) {
340    if (E->getDecl() == Dcl)
341      Refs.insert(E);
342    return true;
343  }
344};
345
346class ReleaseCollector : public RecursiveASTVisitor<ReleaseCollector> {
347  Decl *Dcl;
348  llvm::SmallVectorImpl<ObjCMessageExpr *> &Releases;
349
350public:
351  ReleaseCollector(Decl *D, llvm::SmallVectorImpl<ObjCMessageExpr *> &releases)
352    : Dcl(D), Releases(releases) { }
353
354  bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
355    if (!E->isInstanceMessage())
356      return true;
357    if (E->getMethodFamily() != OMF_release)
358      return true;
359    Expr *instance = E->getInstanceReceiver()->IgnoreParenCasts();
360    if (DeclRefExpr *DE = dyn_cast<DeclRefExpr>(instance)) {
361      if (DE->getDecl() == Dcl)
362        Releases.push_back(E);
363    }
364    return true;
365  }
366};
367
368template <typename BODY_TRANS>
369class BodyTransform : public RecursiveASTVisitor<BodyTransform<BODY_TRANS> > {
370  MigrationPass &Pass;
371
372public:
373  BodyTransform(MigrationPass &pass) : Pass(pass) { }
374
375  void handleBody(Decl *D) {
376    Stmt *body = D->getBody();
377    if (body) {
378      BODY_TRANS(D, Pass).transformBody(body);
379    }
380  }
381
382  bool TraverseBlockDecl(BlockDecl *D) {
383    handleBody(D);
384    return true;
385  }
386  bool TraverseObjCMethodDecl(ObjCMethodDecl *D) {
387    if (D->isThisDeclarationADefinition())
388      handleBody(D);
389    return true;
390  }
391  bool TraverseFunctionDecl(FunctionDecl *D) {
392    if (D->isThisDeclarationADefinition())
393      handleBody(D);
394    return true;
395  }
396};
397
398} // anonymous namespace
399
400//===----------------------------------------------------------------------===//
401// makeAssignARCSafe
402//===----------------------------------------------------------------------===//
403
404namespace {
405
406class ARCAssignChecker : public RecursiveASTVisitor<ARCAssignChecker> {
407  MigrationPass &Pass;
408  llvm::DenseSet<VarDecl *> ModifiedVars;
409
410public:
411  ARCAssignChecker(MigrationPass &pass) : Pass(pass) { }
412
413  bool VisitBinaryOperator(BinaryOperator *Exp) {
414    Expr *E = Exp->getLHS();
415    SourceLocation OrigLoc = E->getExprLoc();
416    SourceLocation Loc = OrigLoc;
417    DeclRefExpr *declRef = dyn_cast<DeclRefExpr>(E->IgnoreParenCasts());
418    if (declRef && isa<VarDecl>(declRef->getDecl())) {
419      ASTContext &Ctx = Pass.Ctx;
420      Expr::isModifiableLvalueResult IsLV = E->isModifiableLvalue(Ctx, &Loc);
421      if (IsLV != Expr::MLV_ConstQualified)
422        return true;
423      VarDecl *var = cast<VarDecl>(declRef->getDecl());
424      if (var->isARCPseudoStrong()) {
425        Transaction Trans(Pass.TA);
426        if (Pass.TA.clearDiagnostic(diag::err_typecheck_arr_assign_enumeration,
427                                    Exp->getOperatorLoc())) {
428          if (!ModifiedVars.count(var)) {
429            TypeLoc TLoc = var->getTypeSourceInfo()->getTypeLoc();
430            Pass.TA.insert(TLoc.getBeginLoc(), "__strong ");
431            ModifiedVars.insert(var);
432          }
433        }
434      }
435    }
436
437    return true;
438  }
439};
440
441} // anonymous namespace
442
443static void makeAssignARCSafe(MigrationPass &pass) {
444  ARCAssignChecker assignCheck(pass);
445  assignCheck.TraverseDecl(pass.Ctx.getTranslationUnitDecl());
446}
447
448//===----------------------------------------------------------------------===//
449// castNonObjCToObjC
450//===----------------------------------------------------------------------===//
451
452namespace {
453
454class NonObjCToObjCCaster : public RecursiveASTVisitor<NonObjCToObjCCaster> {
455  MigrationPass &Pass;
456public:
457  NonObjCToObjCCaster(MigrationPass &pass) : Pass(pass) { }
458
459  bool VisitCastExpr(CastExpr *E) {
460    if (E->getCastKind() != CK_AnyPointerToObjCPointerCast
461        && E->getCastKind() != CK_BitCast)
462      return true;
463
464    QualType castType = E->getType();
465    Expr *castExpr = E->getSubExpr();
466    QualType castExprType = castExpr->getType();
467
468    if (castType->isObjCObjectPointerType() &&
469        castExprType->isObjCObjectPointerType())
470      return true;
471    if (!castType->isObjCObjectPointerType() &&
472        !castExprType->isObjCObjectPointerType())
473      return true;
474
475    bool exprRetainable = castExprType->isObjCIndirectLifetimeType();
476    bool castRetainable = castType->isObjCIndirectLifetimeType();
477    if (exprRetainable == castRetainable) return true;
478
479    if (castExpr->isNullPointerConstant(Pass.Ctx,
480                                        Expr::NPC_ValueDependentIsNull))
481      return true;
482
483    SourceLocation loc = castExpr->getExprLoc();
484    if (loc.isValid() && Pass.Ctx.getSourceManager().isInSystemHeader(loc))
485      return true;
486
487    if (castType->isObjCObjectPointerType())
488      transformNonObjCToObjCCast(E);
489    else
490      transformObjCToNonObjCCast(E);
491
492    return true;
493  }
494
495private:
496  void transformNonObjCToObjCCast(CastExpr *E) {
497    if (!E) return;
498
499    // Global vars are assumed that are cast as unretained.
500    if (isGlobalVar(E))
501      if (E->getSubExpr()->getType()->isPointerType()) {
502        castToObjCObject(E, /*retained=*/false);
503        return;
504      }
505
506    // If the cast is directly over the result of a Core Foundation function
507    // try to figure out whether it should be cast as retained or unretained.
508    Expr *inner = E->IgnoreParenCasts();
509    if (CallExpr *callE = dyn_cast<CallExpr>(inner)) {
510      if (FunctionDecl *FD = callE->getDirectCallee()) {
511        if (FD->getAttr<CFReturnsRetainedAttr>()) {
512          castToObjCObject(E, /*retained=*/true);
513          return;
514        }
515        if (FD->getAttr<CFReturnsNotRetainedAttr>()) {
516          castToObjCObject(E, /*retained=*/false);
517          return;
518        }
519        if (FD->isGlobal() &&
520            FD->getIdentifier() &&
521            ento::cocoa::isRefType(E->getSubExpr()->getType(), "CF",
522                                   FD->getIdentifier()->getName())) {
523          StringRef fname = FD->getIdentifier()->getName();
524          if (fname.endswith("Retain") ||
525              fname.find("Create") != StringRef::npos ||
526              fname.find("Copy") != StringRef::npos) {
527            castToObjCObject(E, /*retained=*/true);
528            return;
529          }
530
531          if (fname.find("Get") != StringRef::npos) {
532            castToObjCObject(E, /*retained=*/false);
533            return;
534          }
535        }
536      }
537    }
538  }
539
540  void castToObjCObject(CastExpr *E, bool retained) {
541    TransformActions &TA = Pass.TA;
542
543    // We will remove the compiler diagnostic.
544    if (!TA.hasDiagnostic(diag::err_arc_mismatched_cast,
545                          diag::err_arc_cast_requires_bridge,
546                          E->getLocStart()))
547      return;
548
549    Transaction Trans(TA);
550    TA.clearDiagnostic(diag::err_arc_mismatched_cast,
551                       diag::err_arc_cast_requires_bridge,
552                       E->getLocStart());
553    if (CStyleCastExpr *CCE = dyn_cast<CStyleCastExpr>(E)) {
554      TA.insertAfterToken(CCE->getLParenLoc(), retained ? "__bridge_transfer "
555                                                        : "__bridge ");
556    } else {
557      SourceLocation insertLoc = E->getSubExpr()->getLocStart();
558      llvm::SmallString<128> newCast;
559      newCast += '(';
560      newCast +=  retained ? "__bridge_transfer " : "__bridge ";
561      newCast += E->getType().getAsString(Pass.Ctx.PrintingPolicy);
562      newCast += ')';
563
564      if (isa<ParenExpr>(E->getSubExpr())) {
565        TA.insert(insertLoc, newCast.str());
566      } else {
567        newCast += '(';
568        TA.insert(insertLoc, newCast.str());
569        TA.insertAfterToken(E->getLocEnd(), ")");
570      }
571    }
572  }
573
574  void transformObjCToNonObjCCast(CastExpr *E) {
575    // FIXME: Handle these casts.
576    return;
577#if 0
578    TransformActions &TA = Pass.TA;
579
580    // We will remove the compiler diagnostic.
581    if (!TA.hasDiagnostic(diag::err_arc_mismatched_cast,
582                          diag::err_arc_cast_requires_bridge,
583                          E->getLocStart()))
584      return;
585
586    Transaction Trans(TA);
587    TA.clearDiagnostic(diag::err_arc_mismatched_cast,
588                              diag::err_arc_cast_requires_bridge,
589                              E->getLocStart());
590
591    assert(!E->getType()->isObjCObjectPointerType());
592
593    bool shouldCast = !isa<CStyleCastExpr>(E) &&
594                      !E->getType()->getPointeeType().isConstQualified();
595    SourceLocation loc = E->getSubExpr()->getLocStart();
596    if (isa<ParenExpr>(E->getSubExpr())) {
597      TA.insert(loc, shouldCast ? "(void*)objc_unretainedPointer"
598                                : "objc_unretainedPointer");
599    } else {
600      TA.insert(loc, shouldCast ? "(void*)objc_unretainedPointer("
601                                : "objc_unretainedPointer(");
602      TA.insertAfterToken(E->getLocEnd(), ")");
603    }
604#endif
605  }
606
607  static bool isGlobalVar(Expr *E) {
608    E = E->IgnoreParenCasts();
609    if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
610      return DRE->getDecl()->getDeclContext()->isFileContext();
611    if (ConditionalOperator *condOp = dyn_cast<ConditionalOperator>(E))
612      return isGlobalVar(condOp->getTrueExpr()) &&
613             isGlobalVar(condOp->getFalseExpr());
614
615    return false;
616  }
617};
618
619} // end anonymous namespace
620
621static void castNonObjCToObjC(MigrationPass &pass) {
622  NonObjCToObjCCaster trans(pass);
623  trans.TraverseDecl(pass.Ctx.getTranslationUnitDecl());
624}
625
626//===----------------------------------------------------------------------===//
627// rewriteAllocCopyWithZone
628//===----------------------------------------------------------------------===//
629
630namespace {
631
632class AllocCopyWithZoneRewriter :
633                         public RecursiveASTVisitor<AllocCopyWithZoneRewriter> {
634  Decl *Dcl;
635  Stmt *Body;
636  MigrationPass &Pass;
637
638  Selector allocWithZoneSel;
639  Selector copyWithZoneSel;
640  Selector mutableCopyWithZoneSel;
641  Selector zoneSel;
642  IdentifierInfo *NSZoneII;
643
644  std::vector<DeclStmt *> NSZoneVars;
645  std::vector<Expr *> Removals;
646
647public:
648  AllocCopyWithZoneRewriter(Decl *D, MigrationPass &pass)
649    : Dcl(D), Body(0), Pass(pass) {
650    SelectorTable &sels = pass.Ctx.Selectors;
651    IdentifierTable &ids = pass.Ctx.Idents;
652    allocWithZoneSel = sels.getUnarySelector(&ids.get("allocWithZone"));
653    copyWithZoneSel = sels.getUnarySelector(&ids.get("copyWithZone"));
654    mutableCopyWithZoneSel = sels.getUnarySelector(
655                                               &ids.get("mutableCopyWithZone"));
656    zoneSel = sels.getNullarySelector(&ids.get("zone"));
657    NSZoneII = &ids.get("_NSZone");
658  }
659
660  void transformBody(Stmt *body) {
661    Body = body;
662    // Don't change allocWithZone/copyWithZone messages inside
663    // custom implementations of such methods, it can lead to infinite loops.
664    if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(Dcl)) {
665      Selector sel = MD->getSelector();
666      if (sel == allocWithZoneSel ||
667          sel == copyWithZoneSel ||
668          sel == mutableCopyWithZoneSel ||
669          sel == zoneSel)
670        return;
671    }
672
673    TraverseStmt(body);
674  }
675
676  ~AllocCopyWithZoneRewriter() {
677    for (std::vector<DeclStmt *>::reverse_iterator
678           I = NSZoneVars.rbegin(), E = NSZoneVars.rend(); I != E; ++I) {
679      DeclStmt *DS = *I;
680      DeclGroupRef group = DS->getDeclGroup();
681      std::vector<Expr *> varRemovals = Removals;
682
683      bool areAllVarsUnused = true;
684      for (std::reverse_iterator<DeclGroupRef::iterator>
685             DI(group.end()), DE(group.begin()); DI != DE; ++DI) {
686        VarDecl *VD = cast<VarDecl>(*DI);
687        if (isNSZoneVarUsed(VD, varRemovals)) {
688          areAllVarsUnused = false;
689          break;
690        }
691        varRemovals.push_back(VD->getInit());
692      }
693
694      if (areAllVarsUnused) {
695        Transaction Trans(Pass.TA);
696        clearUnavailableDiags(DS);
697        Pass.TA.removeStmt(DS);
698        Removals.swap(varRemovals);
699      }
700    }
701  }
702
703  bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
704    if (!isAllocCopyWithZoneCall(E))
705      return true;
706    Expr *arg = E->getArg(0);
707    if (paramToAllocWithZoneHasSideEffects(arg))
708      return true;
709
710    Pass.TA.startTransaction();
711
712    clearUnavailableDiags(arg);
713    Pass.TA.clearDiagnostic(diag::err_unavailable_message,
714                            E->getReceiverRange().getBegin());
715
716    Pass.TA.remove(SourceRange(E->getSelectorLoc(), arg->getLocEnd()));
717    StringRef rewrite;
718    if (E->getSelector() == allocWithZoneSel)
719      rewrite = "alloc";
720    else if (E->getSelector() == copyWithZoneSel)
721      rewrite = "copy";
722    else {
723      assert(E->getSelector() == mutableCopyWithZoneSel);
724      rewrite = "mutableCopy";
725    }
726    Pass.TA.insert(E->getSelectorLoc(), rewrite);
727
728    bool failed = Pass.TA.commitTransaction();
729    if (!failed)
730      Removals.push_back(arg);
731
732    return true;
733  }
734
735  bool VisitDeclStmt(DeclStmt *DS) {
736    DeclGroupRef group = DS->getDeclGroup();
737    if (group.begin() == group.end())
738      return true;
739    for (DeclGroupRef::iterator
740           DI = group.begin(), DE = group.end(); DI != DE; ++DI)
741      if (!isRemovableNSZoneVar(*DI))
742        return true;
743
744    NSZoneVars.push_back(DS);
745    return true;
746  }
747
748private:
749  bool isRemovableNSZoneVar(Decl *D) {
750    if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
751      if (isNSZone(VD->getType()))
752        return !paramToAllocWithZoneHasSideEffects(VD->getInit());
753    }
754    return false;
755  }
756
757  bool isNSZone(RecordDecl *RD) {
758    return RD && RD->getIdentifier() == NSZoneII;
759  }
760
761  bool isNSZone(QualType Ty) {
762    QualType pointee = Ty->getPointeeType();
763    if (pointee.isNull())
764      return false;
765    if (const RecordType *recT = pointee->getAsStructureType())
766      return isNSZone(recT->getDecl());
767    return false;
768  }
769
770  bool isNSZoneVarUsed(VarDecl *D, std::vector<Expr *> &removals) {
771    llvm::DenseSet<Expr *> refs;
772
773    ReferenceCollector refColl(refs);
774    refColl.lookFor(D, Body);
775
776    ReferenceClear refClear(refs);
777    refClear.clearRefsIn(removals.begin(), removals.end());
778
779    return !refs.empty();
780  }
781
782  bool isAllocCopyWithZoneCall(ObjCMessageExpr *E) {
783    if (E->getNumArgs() == 1 &&
784        E->getSelector() == allocWithZoneSel &&
785        (E->isClassMessage() ||
786         Pass.TA.hasDiagnostic(diag::err_unavailable_message,
787                               E->getReceiverRange().getBegin())))
788      return true;
789
790    return E->isInstanceMessage() &&
791           E->getNumArgs() == 1   &&
792           (E->getSelector() == copyWithZoneSel ||
793            E->getSelector() == mutableCopyWithZoneSel);
794  }
795
796  bool isZoneCall(ObjCMessageExpr *E) {
797    return E->isInstanceMessage() &&
798           E->getNumArgs() == 0   &&
799           E->getSelector() == zoneSel;
800  }
801
802  bool paramToAllocWithZoneHasSideEffects(Expr *E) {
803    if (!HasSideEffects(E, Pass.Ctx))
804      return false;
805    E = E->IgnoreParenCasts();
806    ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(E);
807    if (!ME)
808      return true;
809    if (!isZoneCall(ME))
810      return true;
811    return HasSideEffects(ME->getInstanceReceiver(), Pass.Ctx);
812  }
813
814  void clearUnavailableDiags(Stmt *S) {
815    if (S)
816      Pass.TA.clearDiagnostic(diag::err_unavailable,
817                              diag::err_unavailable_message,
818                              S->getSourceRange());
819  }
820};
821
822} // end anonymous namespace
823
824static void rewriteAllocCopyWithZone(MigrationPass &pass) {
825  BodyTransform<AllocCopyWithZoneRewriter> trans(pass);
826  trans.TraverseDecl(pass.Ctx.getTranslationUnitDecl());
827}
828
829//===----------------------------------------------------------------------===//
830// rewriteAutoreleasePool
831//===----------------------------------------------------------------------===//
832
833/// \brief 'Loc' is the end of a statement range. This returns the location
834/// immediately after the semicolon following the statement.
835/// If no semicolon is found or the location is inside a macro, the returned
836/// source location will be invalid.
837static SourceLocation findLocationAfterSemi(ASTContext &Ctx,
838                                            SourceLocation loc) {
839  SourceManager &SM = Ctx.getSourceManager();
840  if (loc.isMacroID()) {
841    if (!SM.isAtEndOfMacroInstantiation(loc))
842      return SourceLocation();
843    loc = SM.getInstantiationRange(loc).second;
844  }
845  loc = Lexer::getLocForEndOfToken(loc, /*Offset=*/0, SM, Ctx.getLangOptions());
846
847  // Break down the source location.
848  std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(loc);
849
850  // Try to load the file buffer.
851  bool invalidTemp = false;
852  llvm::StringRef file = SM.getBufferData(locInfo.first, &invalidTemp);
853  if (invalidTemp)
854    return SourceLocation();
855
856  const char *tokenBegin = file.data() + locInfo.second;
857
858  // Lex from the start of the given location.
859  Lexer lexer(SM.getLocForStartOfFile(locInfo.first),
860              Ctx.getLangOptions(),
861              file.begin(), tokenBegin, file.end());
862  Token tok;
863  lexer.LexFromRawLexer(tok);
864  if (tok.isNot(tok::semi))
865    return SourceLocation();
866
867  return tok.getLocation().getFileLocWithOffset(1);
868}
869
870namespace {
871
872class AutoreleasePoolRewriter
873                         : public RecursiveASTVisitor<AutoreleasePoolRewriter> {
874public:
875  AutoreleasePoolRewriter(Decl *D, MigrationPass &pass)
876    : Dcl(D), Body(0), Pass(pass) {
877    PoolII = &pass.Ctx.Idents.get("NSAutoreleasePool");
878    DrainSel = pass.Ctx.Selectors.getNullarySelector(
879                                                 &pass.Ctx.Idents.get("drain"));
880  }
881
882  void transformBody(Stmt *body) {
883    Body = body;
884    TraverseStmt(body);
885  }
886
887  ~AutoreleasePoolRewriter() {
888    llvm::SmallVector<VarDecl *, 8> VarsToHandle;
889
890    for (std::map<VarDecl *, PoolVarInfo>::iterator
891           I = PoolVars.begin(), E = PoolVars.end(); I != E; ++I) {
892      VarDecl *var = I->first;
893      PoolVarInfo &info = I->second;
894
895      // Check that we can handle/rewrite all references of the pool.
896
897      ReferenceClear refClear(info.Refs);
898      refClear.clearRefsIn(info.Dcl);
899      for (llvm::SmallVectorImpl<PoolScope>::iterator
900             scpI = info.Scopes.begin(),
901             scpE = info.Scopes.end(); scpI != scpE; ++scpI) {
902        PoolScope &scope = *scpI;
903        refClear.clearRefsIn(*scope.Begin);
904        refClear.clearRefsIn(*scope.End);
905        refClear.clearRefsIn(scope.Releases.begin(), scope.Releases.end());
906      }
907
908      // Even if one reference is not handled we will not do anything about that
909      // pool variable.
910      if (info.Refs.empty())
911        VarsToHandle.push_back(var);
912    }
913
914    for (unsigned i = 0, e = VarsToHandle.size(); i != e; ++i) {
915      PoolVarInfo &info = PoolVars[VarsToHandle[i]];
916
917      Transaction Trans(Pass.TA);
918
919      clearUnavailableDiags(info.Dcl);
920      Pass.TA.removeStmt(info.Dcl);
921
922      // Add "@autoreleasepool { }"
923      for (llvm::SmallVectorImpl<PoolScope>::iterator
924             scpI = info.Scopes.begin(),
925             scpE = info.Scopes.end(); scpI != scpE; ++scpI) {
926        PoolScope &scope = *scpI;
927        clearUnavailableDiags(*scope.Begin);
928        clearUnavailableDiags(*scope.End);
929        if (scope.IsFollowedBySimpleReturnStmt) {
930          // Include the return in the scope.
931          Pass.TA.replaceStmt(*scope.Begin, "@autoreleasepool {");
932          Pass.TA.removeStmt(*scope.End);
933          Stmt::child_iterator retI = scope.End;
934          ++retI;
935          SourceLocation afterSemi = findLocationAfterSemi(Pass.Ctx,
936                                                          (*retI)->getLocEnd());
937          assert(afterSemi.isValid() &&
938                 "Didn't we check before setting IsFollowedBySimpleReturnStmt "
939                 "to true?");
940          Pass.TA.insertAfterToken(afterSemi, "\n}");
941          Pass.TA.increaseIndentation(
942                                SourceRange(scope.getIndentedRange().getBegin(),
943                                            (*retI)->getLocEnd()),
944                                      scope.CompoundParent->getLocStart());
945        } else {
946          Pass.TA.replaceStmt(*scope.Begin, "@autoreleasepool {");
947          Pass.TA.replaceStmt(*scope.End, "}");
948          Pass.TA.increaseIndentation(scope.getIndentedRange(),
949                                      scope.CompoundParent->getLocStart());
950        }
951      }
952
953      // Remove rest of pool var references.
954      for (llvm::SmallVectorImpl<PoolScope>::iterator
955             scpI = info.Scopes.begin(),
956             scpE = info.Scopes.end(); scpI != scpE; ++scpI) {
957        PoolScope &scope = *scpI;
958        for (llvm::SmallVectorImpl<ObjCMessageExpr *>::iterator
959               relI = scope.Releases.begin(),
960               relE = scope.Releases.end(); relI != relE; ++relI) {
961          clearUnavailableDiags(*relI);
962          Pass.TA.removeStmt(*relI);
963        }
964      }
965    }
966  }
967
968  bool VisitCompoundStmt(CompoundStmt *S) {
969    llvm::SmallVector<PoolScope, 4> Scopes;
970
971    for (Stmt::child_iterator
972           I = S->body_begin(), E = S->body_end(); I != E; ++I) {
973      Stmt *child = getEssential(*I);
974      if (DeclStmt *DclS = dyn_cast<DeclStmt>(child)) {
975        if (DclS->isSingleDecl()) {
976          if (VarDecl *VD = dyn_cast<VarDecl>(DclS->getSingleDecl())) {
977            if (isNSAutoreleasePool(VD->getType())) {
978              PoolVarInfo &info = PoolVars[VD];
979              info.Dcl = DclS;
980              ReferenceCollector refColl(info.Refs);
981              refColl.lookFor(VD, S);
982              // Does this statement follow the pattern:
983              // NSAutoreleasePool * pool = [NSAutoreleasePool  new];
984              if (isPoolCreation(VD->getInit())) {
985                Scopes.push_back(PoolScope());
986                Scopes.back().PoolVar = VD;
987                Scopes.back().CompoundParent = S;
988                Scopes.back().Begin = I;
989              }
990            }
991          }
992        }
993      } else if (BinaryOperator *bop = dyn_cast<BinaryOperator>(child)) {
994        if (DeclRefExpr *dref = dyn_cast<DeclRefExpr>(bop->getLHS())) {
995          if (VarDecl *VD = dyn_cast<VarDecl>(dref->getDecl())) {
996            // Does this statement follow the pattern:
997            // pool = [NSAutoreleasePool  new];
998            if (isNSAutoreleasePool(VD->getType()) &&
999                isPoolCreation(bop->getRHS())) {
1000              Scopes.push_back(PoolScope());
1001              Scopes.back().PoolVar = VD;
1002              Scopes.back().CompoundParent = S;
1003              Scopes.back().Begin = I;
1004            }
1005          }
1006        }
1007      }
1008
1009      if (Scopes.empty())
1010        continue;
1011
1012      if (isPoolDrain(Scopes.back().PoolVar, child)) {
1013        PoolScope &scope = Scopes.back();
1014        scope.End = I;
1015        handlePoolScope(scope, S);
1016        Scopes.pop_back();
1017      }
1018    }
1019    return true;
1020  }
1021
1022private:
1023  void clearUnavailableDiags(Stmt *S) {
1024    if (S)
1025      Pass.TA.clearDiagnostic(diag::err_unavailable,
1026                              diag::err_unavailable_message,
1027                              S->getSourceRange());
1028  }
1029
1030  struct PoolScope {
1031    VarDecl *PoolVar;
1032    CompoundStmt *CompoundParent;
1033    Stmt::child_iterator Begin;
1034    Stmt::child_iterator End;
1035    bool IsFollowedBySimpleReturnStmt;
1036    llvm::SmallVector<ObjCMessageExpr *, 4> Releases;
1037
1038    PoolScope() : PoolVar(0), CompoundParent(0), Begin(), End(),
1039                  IsFollowedBySimpleReturnStmt(false) { }
1040
1041    SourceRange getIndentedRange() const {
1042      Stmt::child_iterator rangeS = Begin;
1043      ++rangeS;
1044      if (rangeS == End)
1045        return SourceRange();
1046      Stmt::child_iterator rangeE = Begin;
1047      for (Stmt::child_iterator I = rangeS; I != End; ++I)
1048        ++rangeE;
1049      return SourceRange((*rangeS)->getLocStart(), (*rangeE)->getLocEnd());
1050    }
1051  };
1052
1053  class NameReferenceChecker : public RecursiveASTVisitor<NameReferenceChecker>{
1054    ASTContext &Ctx;
1055    SourceRange ScopeRange;
1056    SourceLocation &referenceLoc, &declarationLoc;
1057
1058  public:
1059    NameReferenceChecker(ASTContext &ctx, PoolScope &scope,
1060                         SourceLocation &referenceLoc,
1061                         SourceLocation &declarationLoc)
1062      : Ctx(ctx), referenceLoc(referenceLoc),
1063        declarationLoc(declarationLoc) {
1064      ScopeRange = SourceRange((*scope.Begin)->getLocStart(),
1065                               (*scope.End)->getLocStart());
1066    }
1067
1068    bool VisitDeclRefExpr(DeclRefExpr *E) {
1069      return checkRef(E->getLocation(), E->getDecl()->getLocation());
1070    }
1071
1072    bool VisitBlockDeclRefExpr(BlockDeclRefExpr *E) {
1073      return checkRef(E->getLocation(), E->getDecl()->getLocation());
1074    }
1075
1076    bool VisitTypedefTypeLoc(TypedefTypeLoc TL) {
1077      return checkRef(TL.getBeginLoc(), TL.getTypedefNameDecl()->getLocation());
1078    }
1079
1080    bool VisitTagTypeLoc(TagTypeLoc TL) {
1081      return checkRef(TL.getBeginLoc(), TL.getDecl()->getLocation());
1082    }
1083
1084  private:
1085    bool checkRef(SourceLocation refLoc, SourceLocation declLoc) {
1086      if (isInScope(declLoc)) {
1087        referenceLoc = refLoc;
1088        declarationLoc = declLoc;
1089        return false;
1090      }
1091      return true;
1092    }
1093
1094    bool isInScope(SourceLocation loc) {
1095      SourceManager &SM = Ctx.getSourceManager();
1096      if (SM.isBeforeInTranslationUnit(loc, ScopeRange.getBegin()))
1097        return false;
1098      return SM.isBeforeInTranslationUnit(loc, ScopeRange.getEnd());
1099    }
1100  };
1101
1102  void handlePoolScope(PoolScope &scope, CompoundStmt *compoundS) {
1103    // Check that all names declared inside the scope are not used
1104    // outside the scope.
1105    {
1106      bool nameUsedOutsideScope = false;
1107      SourceLocation referenceLoc, declarationLoc;
1108      Stmt::child_iterator SI = scope.End, SE = compoundS->body_end();
1109      ++SI;
1110      // Check if the autoreleasepool scope is followed by a simple return
1111      // statement, in which case we will include the return in the scope.
1112      if (SI != SE)
1113        if (ReturnStmt *retS = dyn_cast<ReturnStmt>(*SI))
1114          if ((retS->getRetValue() == 0 ||
1115               isa<DeclRefExpr>(retS->getRetValue()->IgnoreParenCasts())) &&
1116              findLocationAfterSemi(Pass.Ctx, retS->getLocEnd()).isValid()) {
1117            scope.IsFollowedBySimpleReturnStmt = true;
1118            ++SI; // the return will be included in scope, don't check it.
1119          }
1120
1121      for (; SI != SE; ++SI) {
1122        nameUsedOutsideScope = !NameReferenceChecker(Pass.Ctx, scope,
1123                                                     referenceLoc,
1124                                              declarationLoc).TraverseStmt(*SI);
1125        if (nameUsedOutsideScope)
1126          break;
1127      }
1128
1129      // If not all references were cleared it means some variables/typenames/etc
1130      // declared inside the pool scope are used outside of it.
1131      // We won't try to rewrite the pool.
1132      if (nameUsedOutsideScope) {
1133        Pass.TA.reportError("a name is referenced outside the "
1134            "NSAutoreleasePool scope that it was declared in", referenceLoc);
1135        Pass.TA.reportNote("name declared here", declarationLoc);
1136        Pass.TA.reportNote("intended @autoreleasepool scope begins here",
1137                           (*scope.Begin)->getLocStart());
1138        Pass.TA.reportNote("intended @autoreleasepool scope ends here",
1139                           (*scope.End)->getLocStart());
1140        return;
1141      }
1142    }
1143
1144    // Collect all releases of the pool; they will be removed.
1145    {
1146      ReleaseCollector releaseColl(scope.PoolVar, scope.Releases);
1147      Stmt::child_iterator I = scope.Begin;
1148      ++I;
1149      for (; I != scope.End; ++I)
1150        releaseColl.TraverseStmt(*I);
1151    }
1152
1153    PoolVars[scope.PoolVar].Scopes.push_back(scope);
1154  }
1155
1156  bool isPoolCreation(Expr *E) {
1157    if (!E) return false;
1158    E = getEssential(E);
1159    ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(E);
1160    if (!ME) return false;
1161    if (ME->getMethodFamily() == OMF_new &&
1162        ME->getReceiverKind() == ObjCMessageExpr::Class &&
1163        isNSAutoreleasePool(ME->getReceiverInterface()))
1164      return true;
1165    if (ME->getReceiverKind() == ObjCMessageExpr::Instance &&
1166        ME->getMethodFamily() == OMF_init) {
1167      Expr *rec = getEssential(ME->getInstanceReceiver());
1168      if (ObjCMessageExpr *recME = dyn_cast_or_null<ObjCMessageExpr>(rec)) {
1169        if (recME->getMethodFamily() == OMF_alloc &&
1170            recME->getReceiverKind() == ObjCMessageExpr::Class &&
1171            isNSAutoreleasePool(recME->getReceiverInterface()))
1172          return true;
1173      }
1174    }
1175
1176    return false;
1177  }
1178
1179  bool isPoolDrain(VarDecl *poolVar, Stmt *S) {
1180    if (!S) return false;
1181    S = getEssential(S);
1182    ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(S);
1183    if (!ME) return false;
1184    if (ME->getReceiverKind() == ObjCMessageExpr::Instance) {
1185      Expr *rec = getEssential(ME->getInstanceReceiver());
1186      if (DeclRefExpr *dref = dyn_cast<DeclRefExpr>(rec))
1187        if (dref->getDecl() == poolVar)
1188          return ME->getMethodFamily() == OMF_release ||
1189                 ME->getSelector() == DrainSel;
1190    }
1191
1192    return false;
1193  }
1194
1195  bool isNSAutoreleasePool(ObjCInterfaceDecl *IDecl) {
1196    return IDecl && IDecl->getIdentifier() == PoolII;
1197  }
1198
1199  bool isNSAutoreleasePool(QualType Ty) {
1200    QualType pointee = Ty->getPointeeType();
1201    if (pointee.isNull())
1202      return false;
1203    if (const ObjCInterfaceType *interT = pointee->getAs<ObjCInterfaceType>())
1204      return isNSAutoreleasePool(interT->getDecl());
1205    return false;
1206  }
1207
1208  static Expr *getEssential(Expr *E) {
1209    return cast<Expr>(getEssential((Stmt*)E));
1210  }
1211  static Stmt *getEssential(Stmt *S) {
1212    if (ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(S))
1213      S = EWC->getSubExpr();
1214    if (Expr *E = dyn_cast<Expr>(S))
1215      S = E->IgnoreParenCasts();
1216    return S;
1217  }
1218
1219  Decl *Dcl;
1220  Stmt *Body;
1221  MigrationPass &Pass;
1222
1223  IdentifierInfo *PoolII;
1224  Selector DrainSel;
1225
1226  struct PoolVarInfo {
1227    DeclStmt *Dcl;
1228    llvm::DenseSet<Expr *> Refs;
1229    llvm::SmallVector<PoolScope, 2> Scopes;
1230
1231    PoolVarInfo() : Dcl(0) { }
1232  };
1233
1234  std::map<VarDecl *, PoolVarInfo> PoolVars;
1235};
1236
1237} // anonymous namespace
1238
1239static void rewriteAutoreleasePool(MigrationPass &pass) {
1240  BodyTransform<AutoreleasePoolRewriter> trans(pass);
1241  trans.TraverseDecl(pass.Ctx.getTranslationUnitDecl());
1242}
1243
1244//===----------------------------------------------------------------------===//
1245// removeRetainReleaseDealloc
1246//===----------------------------------------------------------------------===//
1247
1248namespace {
1249
1250class RetainReleaseDeallocRemover :
1251                       public RecursiveASTVisitor<RetainReleaseDeallocRemover> {
1252  Decl *Dcl;
1253  Stmt *Body;
1254  MigrationPass &Pass;
1255
1256  llvm::DenseSet<Expr *> Removables;
1257  llvm::OwningPtr<ParentMap> StmtMap;
1258
1259public:
1260  RetainReleaseDeallocRemover(Decl *D, MigrationPass &pass)
1261    : Dcl(D), Body(0), Pass(pass) { }
1262
1263  void transformBody(Stmt *body) {
1264    Body = body;
1265    RemovablesCollector(Removables).TraverseStmt(body);
1266    StmtMap.reset(new ParentMap(body));
1267    TraverseStmt(body);
1268  }
1269
1270  bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
1271    switch (E->getMethodFamily()) {
1272    default:
1273      return true;
1274    case OMF_retain:
1275    case OMF_release:
1276    case OMF_autorelease:
1277      if (E->getReceiverKind() == ObjCMessageExpr::Instance)
1278        if (Expr *rec = E->getInstanceReceiver()) {
1279          rec = rec->IgnoreParenImpCasts();
1280          if (rec->getType().getObjCLifetime() == Qualifiers::OCL_ExplicitNone){
1281            std::string err = "It is not safe to remove '";
1282            err += E->getSelector().getAsString() + "' message on "
1283                "an __unsafe_unretained type";
1284            Pass.TA.reportError(err, rec->getLocStart());
1285            return true;
1286          }
1287        }
1288    case OMF_dealloc:
1289      break;
1290    }
1291
1292    switch (E->getReceiverKind()) {
1293    default:
1294      return true;
1295    case ObjCMessageExpr::SuperInstance: {
1296      Transaction Trans(Pass.TA);
1297      Pass.TA.clearDiagnostic(diag::err_arc_illegal_explicit_message,
1298                              diag::err_unavailable,
1299                              diag::err_unavailable_message,
1300                              E->getSuperLoc());
1301      if (tryRemoving(E))
1302        return true;
1303      Pass.TA.replace(E->getSourceRange(), "self");
1304      return true;
1305    }
1306    case ObjCMessageExpr::Instance:
1307      break;
1308    }
1309
1310    Expr *rec = E->getInstanceReceiver();
1311    if (!rec) return true;
1312
1313    Transaction Trans(Pass.TA);
1314    Pass.TA.clearDiagnostic(diag::err_arc_illegal_explicit_message,
1315                            diag::err_unavailable,
1316                            diag::err_unavailable_message,
1317                            rec->getExprLoc());
1318    if (!HasSideEffects(E, Pass.Ctx)) {
1319      if (tryRemoving(E))
1320        return true;
1321    }
1322    Pass.TA.replace(E->getSourceRange(), rec->getSourceRange());
1323
1324    return true;
1325  }
1326
1327private:
1328  bool isRemovable(Expr *E) const {
1329    return Removables.count(E);
1330  }
1331
1332  bool tryRemoving(Expr *E) const {
1333    if (isRemovable(E)) {
1334      Pass.TA.removeStmt(E);
1335      return true;
1336    }
1337
1338    if (ParenExpr *parenE = dyn_cast_or_null<ParenExpr>(StmtMap->getParent(E)))
1339      return tryRemoving(parenE);
1340
1341    if (BinaryOperator *
1342          bopE = dyn_cast_or_null<BinaryOperator>(StmtMap->getParent(E))) {
1343      if (bopE->getOpcode() == BO_Comma && bopE->getLHS() == E &&
1344          isRemovable(bopE)) {
1345        Pass.TA.replace(bopE->getSourceRange(), bopE->getRHS()->getSourceRange());
1346        return true;
1347      }
1348    }
1349
1350    return false;
1351  }
1352
1353};
1354
1355} // anonymous namespace
1356
1357static void removeRetainReleaseDealloc(MigrationPass &pass) {
1358  BodyTransform<RetainReleaseDeallocRemover> trans(pass);
1359  trans.TraverseDecl(pass.Ctx.getTranslationUnitDecl());
1360}
1361
1362//===----------------------------------------------------------------------===//
1363// removeEmptyStatements
1364//===----------------------------------------------------------------------===//
1365
1366namespace {
1367
1368class EmptyStatementsRemover :
1369                            public RecursiveASTVisitor<EmptyStatementsRemover> {
1370  MigrationPass &Pass;
1371  llvm::DenseSet<unsigned> MacroLocs;
1372
1373public:
1374  EmptyStatementsRemover(MigrationPass &pass) : Pass(pass) {
1375    for (unsigned i = 0, e = Pass.ARCMTMacroLocs.size(); i != e; ++i)
1376      MacroLocs.insert(Pass.ARCMTMacroLocs[i].getRawEncoding());
1377  }
1378
1379  bool TraverseStmtExpr(StmtExpr *E) {
1380    CompoundStmt *S = E->getSubStmt();
1381    for (CompoundStmt::body_iterator
1382           I = S->body_begin(), E = S->body_end(); I != E; ++I) {
1383      if (I != E - 1)
1384        check(*I);
1385      TraverseStmt(*I);
1386    }
1387    return true;
1388  }
1389
1390  bool VisitCompoundStmt(CompoundStmt *S) {
1391    for (CompoundStmt::body_iterator
1392           I = S->body_begin(), E = S->body_end(); I != E; ++I)
1393      check(*I);
1394    return true;
1395  }
1396
1397  bool isMacroLoc(SourceLocation loc) {
1398    if (loc.isInvalid()) return false;
1399    return MacroLocs.count(loc.getRawEncoding());
1400  }
1401
1402  ASTContext &getContext() { return Pass.Ctx; }
1403
1404private:
1405  /// \brief Returns true if the statement became empty due to previous
1406  /// transformations.
1407  class EmptyChecker : public StmtVisitor<EmptyChecker, bool> {
1408    EmptyStatementsRemover &Trans;
1409
1410  public:
1411    EmptyChecker(EmptyStatementsRemover &trans) : Trans(trans) { }
1412
1413    bool VisitNullStmt(NullStmt *S) {
1414      return Trans.isMacroLoc(S->getLeadingEmptyMacroLoc());
1415    }
1416    bool VisitCompoundStmt(CompoundStmt *S) {
1417      if (S->body_empty())
1418        return false; // was already empty, not because of transformations.
1419      for (CompoundStmt::body_iterator
1420             I = S->body_begin(), E = S->body_end(); I != E; ++I)
1421        if (!Visit(*I))
1422          return false;
1423      return true;
1424    }
1425    bool VisitIfStmt(IfStmt *S) {
1426      if (S->getConditionVariable())
1427        return false;
1428      Expr *condE = S->getCond();
1429      if (!condE)
1430        return false;
1431      if (HasSideEffects(condE, Trans.getContext()))
1432        return false;
1433      if (!S->getThen() || !Visit(S->getThen()))
1434        return false;
1435      if (S->getElse() && !Visit(S->getElse()))
1436        return false;
1437      return true;
1438    }
1439    bool VisitWhileStmt(WhileStmt *S) {
1440      if (S->getConditionVariable())
1441        return false;
1442      Expr *condE = S->getCond();
1443      if (!condE)
1444        return false;
1445      if (HasSideEffects(condE, Trans.getContext()))
1446        return false;
1447      if (!S->getBody())
1448        return false;
1449      return Visit(S->getBody());
1450    }
1451    bool VisitDoStmt(DoStmt *S) {
1452      Expr *condE = S->getCond();
1453      if (!condE)
1454        return false;
1455      if (HasSideEffects(condE, Trans.getContext()))
1456        return false;
1457      if (!S->getBody())
1458        return false;
1459      return Visit(S->getBody());
1460    }
1461    bool VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) {
1462      Expr *Exp = S->getCollection();
1463      if (!Exp)
1464        return false;
1465      if (HasSideEffects(Exp, Trans.getContext()))
1466        return false;
1467      if (!S->getBody())
1468        return false;
1469      return Visit(S->getBody());
1470    }
1471    bool VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S) {
1472      if (!S->getSubStmt())
1473        return false;
1474      return Visit(S->getSubStmt());
1475    }
1476  };
1477
1478  void check(Stmt *S) {
1479    if (!S) return;
1480    if (EmptyChecker(*this).Visit(S)) {
1481      Transaction Trans(Pass.TA);
1482      Pass.TA.removeStmt(S);
1483    }
1484  }
1485};
1486
1487} // anonymous namespace
1488
1489static void removeEmptyStatements(MigrationPass &pass) {
1490  EmptyStatementsRemover(pass).TraverseDecl(pass.Ctx.getTranslationUnitDecl());
1491
1492  for (unsigned i = 0, e = pass.ARCMTMacroLocs.size(); i != e; ++i) {
1493    Transaction Trans(pass.TA);
1494    pass.TA.remove(pass.ARCMTMacroLocs[i]);
1495  }
1496}
1497
1498//===----------------------------------------------------------------------===//
1499// changeIvarsOfAssignProperties.
1500//===----------------------------------------------------------------------===//
1501
1502namespace {
1503
1504class AssignPropertiesTrans {
1505  MigrationPass &Pass;
1506  struct PropData {
1507    ObjCPropertyDecl *PropD;
1508    ObjCIvarDecl *IvarD;
1509    bool ShouldChangeToWeak;
1510    SourceLocation ArcPropAssignErrorLoc;
1511  };
1512
1513  typedef llvm::SmallVector<PropData, 2> PropsTy;
1514  typedef llvm::DenseMap<unsigned, PropsTy> PropsMapTy;
1515  PropsMapTy PropsMap;
1516
1517public:
1518  AssignPropertiesTrans(MigrationPass &pass) : Pass(pass) { }
1519
1520  void doTransform(ObjCImplementationDecl *D) {
1521    SourceManager &SM = Pass.Ctx.getSourceManager();
1522
1523    ObjCInterfaceDecl *IFace = D->getClassInterface();
1524    for (ObjCInterfaceDecl::prop_iterator
1525           I = IFace->prop_begin(), E = IFace->prop_end(); I != E; ++I) {
1526      ObjCPropertyDecl *propD = *I;
1527      unsigned loc = SM.getInstantiationLoc(propD->getAtLoc()).getRawEncoding();
1528      PropsTy &props = PropsMap[loc];
1529      props.push_back(PropData());
1530      props.back().PropD = propD;
1531      props.back().IvarD = 0;
1532      props.back().ShouldChangeToWeak = false;
1533    }
1534
1535    typedef DeclContext::specific_decl_iterator<ObjCPropertyImplDecl>
1536        prop_impl_iterator;
1537    for (prop_impl_iterator
1538           I = prop_impl_iterator(D->decls_begin()),
1539           E = prop_impl_iterator(D->decls_end()); I != E; ++I) {
1540      VisitObjCPropertyImplDecl(*I);
1541    }
1542
1543    for (PropsMapTy::iterator
1544           I = PropsMap.begin(), E = PropsMap.end(); I != E; ++I) {
1545      SourceLocation atLoc = SourceLocation::getFromRawEncoding(I->first);
1546      PropsTy &props = I->second;
1547      if (shouldApplyWeakToAllProp(props)) {
1548        if (changeAssignToWeak(atLoc)) {
1549          // Couldn't add the 'weak' property attribute,
1550          // try adding __unsafe_unretained.
1551          applyUnsafeUnretained(props);
1552        } else {
1553          for (PropsTy::iterator
1554                 PI = props.begin(), PE = props.end(); PI != PE; ++PI) {
1555            applyWeak(*PI);
1556          }
1557        }
1558      } else {
1559        // We should not add 'weak' attribute since not all properties need it.
1560        // So just add __unsafe_unretained to the ivars.
1561        applyUnsafeUnretained(props);
1562      }
1563    }
1564  }
1565
1566  bool shouldApplyWeakToAllProp(PropsTy &props) {
1567    for (PropsTy::iterator
1568           PI = props.begin(), PE = props.end(); PI != PE; ++PI) {
1569      if (!PI->ShouldChangeToWeak)
1570        return false;
1571    }
1572    return true;
1573  }
1574
1575  void applyWeak(PropData &prop) {
1576    assert(!Pass.Ctx.getLangOptions().ObjCNoAutoRefCountRuntime);
1577
1578    Transaction Trans(Pass.TA);
1579    Pass.TA.insert(prop.IvarD->getLocation(), "__weak ");
1580    Pass.TA.clearDiagnostic(diag::err_arc_assign_property_lifetime,
1581                            prop.ArcPropAssignErrorLoc);
1582  }
1583
1584  void applyUnsafeUnretained(PropsTy &props) {
1585    for (PropsTy::iterator
1586           PI = props.begin(), PE = props.end(); PI != PE; ++PI) {
1587      if (PI->ShouldChangeToWeak) {
1588        Transaction Trans(Pass.TA);
1589        Pass.TA.insert(PI->IvarD->getLocation(), "__unsafe_unretained ");
1590        Pass.TA.clearDiagnostic(diag::err_arc_assign_property_lifetime,
1591                                PI->ArcPropAssignErrorLoc);
1592      }
1593    }
1594  }
1595
1596  bool VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) {
1597    SourceManager &SM = Pass.Ctx.getSourceManager();
1598
1599    if (D->getPropertyImplementation() != ObjCPropertyImplDecl::Synthesize)
1600      return true;
1601    ObjCPropertyDecl *propD = D->getPropertyDecl();
1602    if (!propD || propD->isInvalidDecl())
1603      return true;
1604    ObjCIvarDecl *ivarD = D->getPropertyIvarDecl();
1605    if (!ivarD || ivarD->isInvalidDecl())
1606      return true;
1607    if (!(propD->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_assign))
1608      return true;
1609    if (isa<AttributedType>(ivarD->getType().getTypePtr()))
1610      return true;
1611    if (ivarD->getType().getLocalQualifiers().getObjCLifetime()
1612          != Qualifiers::OCL_Strong)
1613      return true;
1614    if (!Pass.TA.hasDiagnostic(
1615                      diag::err_arc_assign_property_lifetime, D->getLocation()))
1616      return true;
1617
1618    // There is a "error: existing ivar for assign property must be
1619    // __unsafe_unretained"; fix it.
1620
1621    if (Pass.Ctx.getLangOptions().ObjCNoAutoRefCountRuntime) {
1622      // We will just add __unsafe_unretained to the ivar.
1623      Transaction Trans(Pass.TA);
1624      Pass.TA.insert(ivarD->getLocation(), "__unsafe_unretained ");
1625      Pass.TA.clearDiagnostic(
1626                      diag::err_arc_assign_property_lifetime, D->getLocation());
1627    } else {
1628      // Mark that we want the ivar to become weak.
1629      unsigned loc = SM.getInstantiationLoc(propD->getAtLoc()).getRawEncoding();
1630      PropsTy &props = PropsMap[loc];
1631      for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
1632        if (I->PropD == propD) {
1633          I->IvarD = ivarD;
1634          I->ShouldChangeToWeak = true;
1635          I->ArcPropAssignErrorLoc = D->getLocation();
1636        }
1637      }
1638    }
1639
1640    return true;
1641  }
1642
1643private:
1644  bool changeAssignToWeak(SourceLocation atLoc) {
1645    SourceManager &SM = Pass.Ctx.getSourceManager();
1646
1647    // Break down the source location.
1648    std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(atLoc);
1649
1650    // Try to load the file buffer.
1651    bool invalidTemp = false;
1652    llvm::StringRef file = SM.getBufferData(locInfo.first, &invalidTemp);
1653    if (invalidTemp)
1654      return true;
1655
1656    const char *tokenBegin = file.data() + locInfo.second;
1657
1658    // Lex from the start of the given location.
1659    Lexer lexer(SM.getLocForStartOfFile(locInfo.first),
1660                Pass.Ctx.getLangOptions(),
1661                file.begin(), tokenBegin, file.end());
1662    Token tok;
1663    lexer.LexFromRawLexer(tok);
1664    if (tok.isNot(tok::at)) return true;
1665    lexer.LexFromRawLexer(tok);
1666    if (tok.isNot(tok::raw_identifier)) return true;
1667    if (llvm::StringRef(tok.getRawIdentifierData(), tok.getLength())
1668          != "property")
1669      return true;
1670    lexer.LexFromRawLexer(tok);
1671    if (tok.isNot(tok::l_paren)) return true;
1672
1673    SourceLocation LParen = tok.getLocation();
1674    SourceLocation assignLoc;
1675    bool isEmpty = false;
1676
1677    lexer.LexFromRawLexer(tok);
1678    if (tok.is(tok::r_paren)) {
1679      isEmpty = true;
1680    } else {
1681      while (1) {
1682        if (tok.isNot(tok::raw_identifier)) return true;
1683        llvm::StringRef ident(tok.getRawIdentifierData(), tok.getLength());
1684        if (ident == "assign")
1685          assignLoc = tok.getLocation();
1686
1687        do {
1688          lexer.LexFromRawLexer(tok);
1689        } while (tok.isNot(tok::comma) && tok.isNot(tok::r_paren));
1690        if (tok.is(tok::r_paren))
1691          break;
1692        lexer.LexFromRawLexer(tok);
1693      }
1694    }
1695
1696    Transaction Trans(Pass.TA);
1697    if (assignLoc.isValid())
1698      Pass.TA.replaceText(assignLoc, "assign", "weak");
1699    else
1700      Pass.TA.insertAfterToken(LParen, isEmpty ? "weak" : "weak, ");
1701    return false;
1702  }
1703};
1704
1705class PropertiesChecker : public RecursiveASTVisitor<PropertiesChecker> {
1706  MigrationPass &Pass;
1707
1708public:
1709  PropertiesChecker(MigrationPass &pass) : Pass(pass) { }
1710
1711  bool TraverseObjCImplementationDecl(ObjCImplementationDecl *D) {
1712    AssignPropertiesTrans(Pass).doTransform(D);
1713    return true;
1714  }
1715};
1716
1717} // anonymous namespace
1718
1719static void changeIvarsOfAssignProperties(MigrationPass &pass) {
1720  PropertiesChecker(pass).TraverseDecl(pass.Ctx.getTranslationUnitDecl());
1721}
1722
1723//===----------------------------------------------------------------------===//
1724// rewriteUnusedDelegateInit
1725//===----------------------------------------------------------------------===//
1726
1727namespace {
1728
1729class UnusedInitRewriter : public RecursiveASTVisitor<UnusedInitRewriter> {
1730  Decl *Dcl;
1731  Stmt *Body;
1732  MigrationPass &Pass;
1733
1734  llvm::DenseSet<Expr *> Removables;
1735
1736public:
1737  UnusedInitRewriter(Decl *D, MigrationPass &pass)
1738    : Dcl(D), Body(0), Pass(pass) { }
1739
1740  void transformBody(Stmt *body) {
1741    Body = body;
1742    RemovablesCollector(Removables).TraverseStmt(body);
1743    TraverseStmt(body);
1744  }
1745
1746  bool VisitObjCMessageExpr(ObjCMessageExpr *ME) {
1747    if (ME->isDelegateInitCall() &&
1748        isRemovable(ME) &&
1749        Pass.TA.hasDiagnostic(diag::err_arc_unused_init_message,
1750                              ME->getExprLoc())) {
1751      Transaction Trans(Pass.TA);
1752      Pass.TA.clearDiagnostic(diag::err_arc_unused_init_message,
1753                              ME->getExprLoc());
1754      Pass.TA.insert(ME->getExprLoc(), "self = ");
1755    }
1756    return true;
1757  }
1758
1759private:
1760  bool isRemovable(Expr *E) const {
1761    return Removables.count(E);
1762  }
1763};
1764
1765} // anonymous namespace
1766
1767static void rewriteUnusedDelegateInit(MigrationPass &pass) {
1768  BodyTransform<UnusedInitRewriter> trans(pass);
1769  trans.TraverseDecl(pass.Ctx.getTranslationUnitDecl());
1770}
1771
1772//===----------------------------------------------------------------------===//
1773// rewriteBlockObjCVariable
1774//===----------------------------------------------------------------------===//
1775
1776namespace {
1777
1778class RootBlockObjCVarRewriter :
1779                          public RecursiveASTVisitor<RootBlockObjCVarRewriter> {
1780  MigrationPass &Pass;
1781  llvm::DenseSet<VarDecl *> CheckedVars;
1782
1783  class BlockVarChecker : public RecursiveASTVisitor<BlockVarChecker> {
1784    VarDecl *Var;
1785
1786    typedef RecursiveASTVisitor<BlockVarChecker> base;
1787  public:
1788    BlockVarChecker(VarDecl *var) : Var(var) { }
1789
1790    bool TraverseImplicitCastExpr(ImplicitCastExpr *castE) {
1791      if (BlockDeclRefExpr *
1792            ref = dyn_cast<BlockDeclRefExpr>(castE->getSubExpr())) {
1793        if (ref->getDecl() == Var) {
1794          if (castE->getCastKind() == CK_LValueToRValue)
1795            return true; // Using the value of the variable.
1796          if (castE->getCastKind() == CK_NoOp && castE->isLValue() &&
1797              Var->getASTContext().getLangOptions().CPlusPlus)
1798            return true; // Binding to const C++ reference.
1799        }
1800      }
1801
1802      return base::TraverseImplicitCastExpr(castE);
1803    }
1804
1805    bool VisitBlockDeclRefExpr(BlockDeclRefExpr *E) {
1806      if (E->getDecl() == Var)
1807        return false; // The reference of the variable, and not just its value,
1808                      //  is needed.
1809      return true;
1810    }
1811  };
1812
1813public:
1814  RootBlockObjCVarRewriter(MigrationPass &pass) : Pass(pass) { }
1815
1816  bool VisitBlockDecl(BlockDecl *block) {
1817    llvm::SmallVector<VarDecl *, 4> BlockVars;
1818
1819    for (BlockDecl::capture_iterator
1820           I = block->capture_begin(), E = block->capture_end(); I != E; ++I) {
1821      VarDecl *var = I->getVariable();
1822      if (I->isByRef() &&
1823          !isAlreadyChecked(var) &&
1824          var->getType()->isObjCObjectPointerType() &&
1825          isImplicitStrong(var->getType())) {
1826        BlockVars.push_back(var);
1827      }
1828    }
1829
1830    for (unsigned i = 0, e = BlockVars.size(); i != e; ++i) {
1831      VarDecl *var = BlockVars[i];
1832      CheckedVars.insert(var);
1833
1834      BlockVarChecker checker(var);
1835      bool onlyValueOfVarIsNeeded = checker.TraverseStmt(block->getBody());
1836      if (onlyValueOfVarIsNeeded) {
1837        BlocksAttr *attr = var->getAttr<BlocksAttr>();
1838        if(!attr)
1839          continue;
1840        bool hasARCRuntime = !Pass.Ctx.getLangOptions().ObjCNoAutoRefCountRuntime;
1841        SourceManager &SM = Pass.Ctx.getSourceManager();
1842        Transaction Trans(Pass.TA);
1843        Pass.TA.replaceText(SM.getInstantiationLoc(attr->getLocation()),
1844                            "__block",
1845                            hasARCRuntime ? "__weak" : "__unsafe_unretained");
1846      }
1847
1848    }
1849
1850    return true;
1851  }
1852
1853private:
1854  bool isAlreadyChecked(VarDecl *VD) {
1855    return CheckedVars.count(VD);
1856  }
1857
1858  bool isImplicitStrong(QualType ty) {
1859    if (isa<AttributedType>(ty.getTypePtr()))
1860      return false;
1861    return ty.getLocalQualifiers().getObjCLifetime() == Qualifiers::OCL_Strong;
1862  }
1863};
1864
1865class BlockObjCVarRewriter : public RecursiveASTVisitor<BlockObjCVarRewriter> {
1866  MigrationPass &Pass;
1867
1868public:
1869  BlockObjCVarRewriter(MigrationPass &pass) : Pass(pass) { }
1870
1871  bool TraverseBlockDecl(BlockDecl *block) {
1872    RootBlockObjCVarRewriter(Pass).TraverseDecl(block);
1873    return true;
1874  }
1875};
1876
1877} // anonymous namespace
1878
1879static void rewriteBlockObjCVariable(MigrationPass &pass) {
1880  BlockObjCVarRewriter trans(pass);
1881  trans.TraverseDecl(pass.Ctx.getTranslationUnitDecl());
1882}
1883
1884//===----------------------------------------------------------------------===//
1885// removeZeroOutIvarsInDealloc
1886//===----------------------------------------------------------------------===//
1887
1888namespace {
1889
1890class ZeroOutInDeallocRemover :
1891                           public RecursiveASTVisitor<ZeroOutInDeallocRemover> {
1892  typedef RecursiveASTVisitor<ZeroOutInDeallocRemover> base;
1893
1894  MigrationPass &Pass;
1895
1896  llvm::DenseMap<ObjCPropertyDecl*, ObjCPropertyImplDecl*> SynthesizedProperties;
1897  ImplicitParamDecl *SelfD;
1898  llvm::DenseSet<Expr *> Removables;
1899
1900public:
1901  ZeroOutInDeallocRemover(MigrationPass &pass) : Pass(pass), SelfD(0) { }
1902
1903  bool VisitObjCMessageExpr(ObjCMessageExpr *ME) {
1904    ASTContext &Ctx = Pass.Ctx;
1905    TransformActions &TA = Pass.TA;
1906
1907    if (ME->getReceiverKind() != ObjCMessageExpr::Instance)
1908      return true;
1909    Expr *receiver = ME->getInstanceReceiver();
1910    if (!receiver)
1911      return true;
1912
1913    DeclRefExpr *refE = dyn_cast<DeclRefExpr>(receiver->IgnoreParenCasts());
1914    if (!refE || refE->getDecl() != SelfD)
1915      return true;
1916
1917    bool BackedBySynthesizeSetter = false;
1918    for (llvm::DenseMap<ObjCPropertyDecl*, ObjCPropertyImplDecl*>::iterator
1919         P = SynthesizedProperties.begin(),
1920         E = SynthesizedProperties.end(); P != E; ++P) {
1921      ObjCPropertyDecl *PropDecl = P->first;
1922      if (PropDecl->getSetterName() == ME->getSelector()) {
1923        BackedBySynthesizeSetter = true;
1924        break;
1925      }
1926    }
1927    if (!BackedBySynthesizeSetter)
1928      return true;
1929
1930    // Remove the setter message if RHS is null
1931    Transaction Trans(TA);
1932    Expr *RHS = ME->getArg(0);
1933    bool RHSIsNull =
1934      RHS->isNullPointerConstant(Ctx,
1935                                 Expr::NPC_ValueDependentIsNull);
1936    if (RHSIsNull && isRemovable(ME))
1937      TA.removeStmt(ME);
1938
1939    return true;
1940  }
1941
1942  bool VisitBinaryOperator(BinaryOperator *BOE) {
1943    if (isZeroingPropIvar(BOE) && isRemovable(BOE)) {
1944      Transaction Trans(Pass.TA);
1945      Pass.TA.removeStmt(BOE);
1946    }
1947
1948    return true;
1949  }
1950
1951  bool TraverseObjCMethodDecl(ObjCMethodDecl *D) {
1952    if (D->getMethodFamily() != OMF_dealloc)
1953      return true;
1954    if (!D->hasBody())
1955      return true;
1956
1957    ObjCImplDecl *IMD = dyn_cast<ObjCImplDecl>(D->getDeclContext());
1958    if (!IMD)
1959      return true;
1960
1961    SelfD = D->getSelfDecl();
1962    RemovablesCollector(Removables).TraverseStmt(D->getBody());
1963
1964    // For a 'dealloc' method use, find all property implementations in
1965    // this class implementation.
1966    for (ObjCImplDecl::propimpl_iterator
1967           I = IMD->propimpl_begin(), EI = IMD->propimpl_end(); I != EI; ++I) {
1968        ObjCPropertyImplDecl *PID = *I;
1969        if (PID->getPropertyImplementation() ==
1970            ObjCPropertyImplDecl::Synthesize) {
1971          ObjCPropertyDecl *PD = PID->getPropertyDecl();
1972          ObjCMethodDecl *setterM = PD->getSetterMethodDecl();
1973          if (!(setterM && setterM->isDefined())) {
1974            ObjCPropertyDecl::PropertyAttributeKind AttrKind =
1975              PD->getPropertyAttributes();
1976              if (AttrKind &
1977                  (ObjCPropertyDecl::OBJC_PR_retain |
1978                   ObjCPropertyDecl::OBJC_PR_copy   |
1979                   ObjCPropertyDecl::OBJC_PR_strong))
1980                SynthesizedProperties[PD] = PID;
1981          }
1982        }
1983    }
1984
1985    // Now, remove all zeroing of ivars etc.
1986    base::TraverseObjCMethodDecl(D);
1987
1988    // clear out for next method.
1989    SynthesizedProperties.clear();
1990    SelfD = 0;
1991    Removables.clear();
1992    return true;
1993  }
1994
1995  bool TraverseFunctionDecl(FunctionDecl *D) { return true; }
1996  bool TraverseBlockDecl(BlockDecl *block) { return true; }
1997  bool TraverseBlockExpr(BlockExpr *block) { return true; }
1998
1999private:
2000  bool isRemovable(Expr *E) const {
2001    return Removables.count(E);
2002  }
2003
2004  bool isZeroingPropIvar(Expr *E) {
2005    BinaryOperator *BOE = dyn_cast_or_null<BinaryOperator>(E);
2006    if (!BOE) return false;
2007
2008    if (BOE->getOpcode() == BO_Comma)
2009      return isZeroingPropIvar(BOE->getLHS()) &&
2010             isZeroingPropIvar(BOE->getRHS());
2011
2012    if (BOE->getOpcode() != BO_Assign)
2013        return false;
2014
2015    ASTContext &Ctx = Pass.Ctx;
2016
2017    Expr *LHS = BOE->getLHS();
2018    if (ObjCIvarRefExpr *IV = dyn_cast<ObjCIvarRefExpr>(LHS)) {
2019      ObjCIvarDecl *IVDecl = IV->getDecl();
2020      if (!IVDecl->getType()->isObjCObjectPointerType())
2021        return false;
2022      bool IvarBacksPropertySynthesis = false;
2023      for (llvm::DenseMap<ObjCPropertyDecl*, ObjCPropertyImplDecl*>::iterator
2024           P = SynthesizedProperties.begin(),
2025           E = SynthesizedProperties.end(); P != E; ++P) {
2026        ObjCPropertyImplDecl *PropImpDecl = P->second;
2027        if (PropImpDecl && PropImpDecl->getPropertyIvarDecl() == IVDecl) {
2028          IvarBacksPropertySynthesis = true;
2029          break;
2030        }
2031      }
2032      if (!IvarBacksPropertySynthesis)
2033        return false;
2034    }
2035    else if (ObjCPropertyRefExpr *PropRefExp = dyn_cast<ObjCPropertyRefExpr>(LHS)) {
2036      // TODO: Using implicit property decl.
2037      if (PropRefExp->isImplicitProperty())
2038        return false;
2039      if (ObjCPropertyDecl *PDecl = PropRefExp->getExplicitProperty()) {
2040        if (!SynthesizedProperties.count(PDecl))
2041          return false;
2042      }
2043    }
2044    else
2045        return false;
2046
2047    Expr *RHS = BOE->getRHS();
2048    bool RHSIsNull = RHS->isNullPointerConstant(Ctx,
2049                                                Expr::NPC_ValueDependentIsNull);
2050    if (RHSIsNull)
2051      return true;
2052
2053    return isZeroingPropIvar(RHS);
2054  }
2055};
2056
2057} // anonymous namespace
2058
2059static void removeZeroOutIvarsInDealloc(MigrationPass &pass) {
2060  ZeroOutInDeallocRemover trans(pass);
2061  trans.TraverseDecl(pass.Ctx.getTranslationUnitDecl());
2062}
2063
2064//===----------------------------------------------------------------------===//
2065// getAllTransformations.
2066//===----------------------------------------------------------------------===//
2067
2068static void independentTransforms(MigrationPass &pass) {
2069  rewriteAutoreleasePool(pass);
2070  changeIvarsOfAssignProperties(pass);
2071  removeRetainReleaseDealloc(pass);
2072  rewriteUnusedDelegateInit(pass);
2073  removeZeroOutIvarsInDealloc(pass);
2074  makeAssignARCSafe(pass);
2075  castNonObjCToObjC(pass);
2076  rewriteBlockObjCVariable(pass);
2077  rewriteAllocCopyWithZone(pass);
2078}
2079
2080std::vector<TransformFn> arcmt::getAllTransformations() {
2081  std::vector<TransformFn> transforms;
2082
2083  // This must come first since rewriteAutoreleasePool depends on -release
2084  // calls being present to determine the @autorelease ending scope.
2085  transforms.push_back(independentTransforms);
2086
2087  transforms.push_back(removeEmptyStatements);
2088  transforms.push_back(removeDeallocMethod);
2089
2090  return transforms;
2091}
2092