1*67e74705SXin Li //===--- TransGCCalls.cpp - Transformations to ARC mode -------------------===// 2*67e74705SXin Li // 3*67e74705SXin Li // The LLVM Compiler Infrastructure 4*67e74705SXin Li // 5*67e74705SXin Li // This file is distributed under the University of Illinois Open Source 6*67e74705SXin Li // License. See LICENSE.TXT for details. 7*67e74705SXin Li // 8*67e74705SXin Li //===----------------------------------------------------------------------===// 9*67e74705SXin Li 10*67e74705SXin Li #include "Transforms.h" 11*67e74705SXin Li #include "Internals.h" 12*67e74705SXin Li #include "clang/AST/ASTContext.h" 13*67e74705SXin Li #include "clang/Sema/SemaDiagnostic.h" 14*67e74705SXin Li 15*67e74705SXin Li using namespace clang; 16*67e74705SXin Li using namespace arcmt; 17*67e74705SXin Li using namespace trans; 18*67e74705SXin Li 19*67e74705SXin Li namespace { 20*67e74705SXin Li 21*67e74705SXin Li class GCCollectableCallsChecker : 22*67e74705SXin Li public RecursiveASTVisitor<GCCollectableCallsChecker> { 23*67e74705SXin Li MigrationContext &MigrateCtx; 24*67e74705SXin Li IdentifierInfo *NSMakeCollectableII; 25*67e74705SXin Li IdentifierInfo *CFMakeCollectableII; 26*67e74705SXin Li 27*67e74705SXin Li public: GCCollectableCallsChecker(MigrationContext & ctx)28*67e74705SXin Li GCCollectableCallsChecker(MigrationContext &ctx) 29*67e74705SXin Li : MigrateCtx(ctx) { 30*67e74705SXin Li IdentifierTable &Ids = MigrateCtx.Pass.Ctx.Idents; 31*67e74705SXin Li NSMakeCollectableII = &Ids.get("NSMakeCollectable"); 32*67e74705SXin Li CFMakeCollectableII = &Ids.get("CFMakeCollectable"); 33*67e74705SXin Li } 34*67e74705SXin Li shouldWalkTypesOfTypeLocs() const35*67e74705SXin Li bool shouldWalkTypesOfTypeLocs() const { return false; } 36*67e74705SXin Li VisitCallExpr(CallExpr * E)37*67e74705SXin Li bool VisitCallExpr(CallExpr *E) { 38*67e74705SXin Li TransformActions &TA = MigrateCtx.Pass.TA; 39*67e74705SXin Li 40*67e74705SXin Li if (MigrateCtx.isGCOwnedNonObjC(E->getType())) { 41*67e74705SXin Li TA.report(E->getLocStart(), diag::warn_arcmt_nsalloc_realloc, 42*67e74705SXin Li E->getSourceRange()); 43*67e74705SXin Li return true; 44*67e74705SXin Li } 45*67e74705SXin Li 46*67e74705SXin Li Expr *CEE = E->getCallee()->IgnoreParenImpCasts(); 47*67e74705SXin Li if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CEE)) { 48*67e74705SXin Li if (FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(DRE->getDecl())) { 49*67e74705SXin Li if (!FD->getDeclContext()->getRedeclContext()->isFileContext()) 50*67e74705SXin Li return true; 51*67e74705SXin Li 52*67e74705SXin Li if (FD->getIdentifier() == NSMakeCollectableII) { 53*67e74705SXin Li Transaction Trans(TA); 54*67e74705SXin Li TA.clearDiagnostic(diag::err_unavailable, 55*67e74705SXin Li diag::err_unavailable_message, 56*67e74705SXin Li diag::err_ovl_deleted_call, // ObjC++ 57*67e74705SXin Li DRE->getSourceRange()); 58*67e74705SXin Li TA.replace(DRE->getSourceRange(), "CFBridgingRelease"); 59*67e74705SXin Li 60*67e74705SXin Li } else if (FD->getIdentifier() == CFMakeCollectableII) { 61*67e74705SXin Li TA.reportError("CFMakeCollectable will leak the object that it " 62*67e74705SXin Li "receives in ARC", DRE->getLocation(), 63*67e74705SXin Li DRE->getSourceRange()); 64*67e74705SXin Li } 65*67e74705SXin Li } 66*67e74705SXin Li } 67*67e74705SXin Li 68*67e74705SXin Li return true; 69*67e74705SXin Li } 70*67e74705SXin Li }; 71*67e74705SXin Li 72*67e74705SXin Li } // anonymous namespace 73*67e74705SXin Li traverseBody(BodyContext & BodyCtx)74*67e74705SXin Livoid GCCollectableCallsTraverser::traverseBody(BodyContext &BodyCtx) { 75*67e74705SXin Li GCCollectableCallsChecker(BodyCtx.getMigrationContext()) 76*67e74705SXin Li .TraverseStmt(BodyCtx.getTopStmt()); 77*67e74705SXin Li } 78