1 //===--- TransUnusedInitDelegate.cpp - Transformations 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 // rewriteUnusedInitDelegate: 13 // 14 // Rewrites an unused result of calling a delegate initialization, to assigning 15 // the result to self. 16 // e.g 17 // [self init]; 18 // ----> 19 // self = [self init]; 20 // 21 //===----------------------------------------------------------------------===// 22 23 #include "Transforms.h" 24 #include "Internals.h" 25 #include "clang/AST/ASTContext.h" 26 #include "clang/Sema/SemaDiagnostic.h" 27 28 using namespace clang; 29 using namespace arcmt; 30 using namespace trans; 31 32 namespace { 33 34 class UnusedInitRewriter : public RecursiveASTVisitor<UnusedInitRewriter> { 35 Stmt *Body; 36 MigrationPass &Pass; 37 38 ExprSet Removables; 39 40 public: UnusedInitRewriter(MigrationPass & pass)41 UnusedInitRewriter(MigrationPass &pass) 42 : Body(nullptr), Pass(pass) { } 43 transformBody(Stmt * body,Decl * ParentD)44 void transformBody(Stmt *body, Decl *ParentD) { 45 Body = body; 46 collectRemovables(body, Removables); 47 TraverseStmt(body); 48 } 49 VisitObjCMessageExpr(ObjCMessageExpr * ME)50 bool VisitObjCMessageExpr(ObjCMessageExpr *ME) { 51 if (ME->isDelegateInitCall() && 52 isRemovable(ME) && 53 Pass.TA.hasDiagnostic(diag::err_arc_unused_init_message, 54 ME->getExprLoc())) { 55 Transaction Trans(Pass.TA); 56 Pass.TA.clearDiagnostic(diag::err_arc_unused_init_message, 57 ME->getExprLoc()); 58 SourceRange ExprRange = ME->getSourceRange(); 59 Pass.TA.insert(ExprRange.getBegin(), "if (!(self = "); 60 std::string retStr = ")) return "; 61 retStr += getNilString(Pass.Ctx); 62 Pass.TA.insertAfterToken(ExprRange.getEnd(), retStr); 63 } 64 return true; 65 } 66 67 private: isRemovable(Expr * E) const68 bool isRemovable(Expr *E) const { 69 return Removables.count(E); 70 } 71 }; 72 73 } // anonymous namespace 74 rewriteUnusedInitDelegate(MigrationPass & pass)75void trans::rewriteUnusedInitDelegate(MigrationPass &pass) { 76 BodyTransform<UnusedInitRewriter> trans(pass); 77 trans.TraverseDecl(pass.Ctx.getTranslationUnitDecl()); 78 } 79