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