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