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