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