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