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(S: body, exprs&: 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(loc: ExprRange.getBegin(), text: "if (!(self = "); |
59 | std::string retStr = ")) return "; |
60 | retStr += getNilString(Pass); |
61 | Pass.TA.insertAfterToken(loc: ExprRange.getEnd(), text: 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 |