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