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