xref: /freebsd/contrib/llvm-project/clang/lib/ARCMigrate/TransUnusedInitDelegate.cpp (revision dd41de95a84d979615a2ef11df6850622bf6184e)
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 
27 using namespace clang;
28 using namespace arcmt;
29 using namespace trans;
30 
31 namespace {
32 
33 class UnusedInitRewriter : public RecursiveASTVisitor<UnusedInitRewriter> {
34   Stmt *Body;
35   MigrationPass &Pass;
36 
37   ExprSet Removables;
38 
39 public:
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 
66 private:
67   bool isRemovable(Expr *E) const {
68     return Removables.count(E);
69   }
70 };
71 
72 } // anonymous namespace
73 
74 void trans::rewriteUnusedInitDelegate(MigrationPass &pass) {
75   BodyTransform<UnusedInitRewriter> trans(pass);
76   trans.TraverseDecl(pass.Ctx.getTranslationUnitDecl());
77 }
78