blob: e316c73fc3cdecfe8c5e3b1bbb067307ae3e2c24 [file] [log] [blame]
Benjamin Krameraccaf192012-11-14 15:08:31 +00001//===--- TransUnusedInitDelegate.cpp - Transformations to ARC mode --------===//
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9// Transformations:
10//===----------------------------------------------------------------------===//
11//
12// rewriteUnusedInitDelegate:
13//
14// Rewrites an unused result of calling a delegate initialization, to assigning
15// the result to self.
16// e.g
17// [self init];
18// ---->
19// self = [self init];
20//
21//===----------------------------------------------------------------------===//
22
23#include "Transforms.h"
24#include "Internals.h"
Benjamin Kramer471c8b42012-07-04 20:19:54 +000025#include "clang/AST/ASTContext.h"
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +000026#include "clang/Sema/SemaDiagnostic.h"
27
28using namespace clang;
29using namespace arcmt;
30using namespace trans;
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +000031
32namespace {
33
34class UnusedInitRewriter : public RecursiveASTVisitor<UnusedInitRewriter> {
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +000035 Stmt *Body;
36 MigrationPass &Pass;
37
38 ExprSet Removables;
39
40public:
Argyrios Kyrtzidisb1094a02011-06-23 21:21:33 +000041 UnusedInitRewriter(MigrationPass &pass)
42 : Body(0), Pass(pass) { }
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +000043
Argyrios Kyrtzidis76a52452012-06-07 00:44:06 +000044 void transformBody(Stmt *body, Decl *ParentD) {
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +000045 Body = body;
46 collectRemovables(body, Removables);
47 TraverseStmt(body);
48 }
49
50 bool VisitObjCMessageExpr(ObjCMessageExpr *ME) {
51 if (ME->isDelegateInitCall() &&
52 isRemovable(ME) &&
53 Pass.TA.hasDiagnostic(diag::err_arc_unused_init_message,
54 ME->getExprLoc())) {
55 Transaction Trans(Pass.TA);
56 Pass.TA.clearDiagnostic(diag::err_arc_unused_init_message,
57 ME->getExprLoc());
Argyrios Kyrtzidisd76e1cd2012-03-31 01:34:06 +000058 SourceRange ExprRange = ME->getSourceRange();
59 Pass.TA.insert(ExprRange.getBegin(), "if (!(self = ");
60 std::string retStr = ")) return ";
61 retStr += getNilString(Pass.Ctx);
62 Pass.TA.insertAfterToken(ExprRange.getEnd(), retStr);
Argyrios Kyrtzidis7196d062011-06-21 20:20:39 +000063 }
64 return true;
65 }
66
67private:
68 bool isRemovable(Expr *E) const {
69 return Removables.count(E);
70 }
71};
72
73} // anonymous namespace
74
75void trans::rewriteUnusedInitDelegate(MigrationPass &pass) {
76 BodyTransform<UnusedInitRewriter> trans(pass);
77 trans.TraverseDecl(pass.Ctx.getTranslationUnitDecl());
78}