clang API Documentation

TransUnusedInitDelegate.cpp
Go to the documentation of this file.
00001 //===--- TransUnusedInitDelegate.cpp - Transformations to ARC mode --------===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 // Transformations:
00010 //===----------------------------------------------------------------------===//
00011 //
00012 // rewriteUnusedInitDelegate:
00013 //
00014 // Rewrites an unused result of calling a delegate initialization, to assigning
00015 // the result to self.
00016 // e.g
00017 //  [self init];
00018 // ---->
00019 //  self = [self init];
00020 //
00021 //===----------------------------------------------------------------------===//
00022 
00023 #include "Transforms.h"
00024 #include "Internals.h"
00025 #include "clang/AST/ASTContext.h"
00026 #include "clang/Sema/SemaDiagnostic.h"
00027 
00028 using namespace clang;
00029 using namespace arcmt;
00030 using namespace trans;
00031 
00032 namespace {
00033 
00034 class UnusedInitRewriter : public RecursiveASTVisitor<UnusedInitRewriter> {
00035   Stmt *Body;
00036   MigrationPass &Pass;
00037 
00038   ExprSet Removables;
00039 
00040 public:
00041   UnusedInitRewriter(MigrationPass &pass)
00042     : Body(nullptr), Pass(pass) { }
00043 
00044   void transformBody(Stmt *body, Decl *ParentD) {
00045     Body = body;
00046     collectRemovables(body, Removables);
00047     TraverseStmt(body);
00048   }
00049 
00050   bool VisitObjCMessageExpr(ObjCMessageExpr *ME) {
00051     if (ME->isDelegateInitCall() &&
00052         isRemovable(ME) &&
00053         Pass.TA.hasDiagnostic(diag::err_arc_unused_init_message,
00054                               ME->getExprLoc())) {
00055       Transaction Trans(Pass.TA);
00056       Pass.TA.clearDiagnostic(diag::err_arc_unused_init_message,
00057                               ME->getExprLoc());
00058       SourceRange ExprRange = ME->getSourceRange();
00059       Pass.TA.insert(ExprRange.getBegin(), "if (!(self = ");
00060       std::string retStr = ")) return ";
00061       retStr += getNilString(Pass.Ctx);
00062       Pass.TA.insertAfterToken(ExprRange.getEnd(), retStr);
00063     }
00064     return true;
00065   }
00066 
00067 private:
00068   bool isRemovable(Expr *E) const {
00069     return Removables.count(E);
00070   }
00071 };
00072 
00073 } // anonymous namespace
00074 
00075 void trans::rewriteUnusedInitDelegate(MigrationPass &pass) {
00076   BodyTransform<UnusedInitRewriter> trans(pass);
00077   trans.TraverseDecl(pass.Ctx.getTranslationUnitDecl());
00078 }