1 //===--- TransGCCalls.cpp - Tranformations to ARC mode --------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "Transforms.h" 11 #include "Internals.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 ParentMap &PMap; 24 IdentifierInfo *NSMakeCollectableII; 25 IdentifierInfo *CFMakeCollectableII; 26 27 public: 28 GCCollectableCallsChecker(MigrationContext &ctx, ParentMap &map) 29 : MigrateCtx(ctx), PMap(map) { 30 IdentifierTable &Ids = MigrateCtx.Pass.Ctx.Idents; 31 NSMakeCollectableII = &Ids.get("NSMakeCollectable"); 32 CFMakeCollectableII = &Ids.get("CFMakeCollectable"); 33 } 34 35 bool shouldWalkTypesOfTypeLocs() const { return false; } 36 37 bool VisitCallExpr(CallExpr *E) { 38 TransformActions &TA = MigrateCtx.Pass.TA; 39 40 if (MigrateCtx.isGCOwnedNonObjC(E->getType())) { 41 TA.reportError("call returns pointer to GC managed memory; " 42 "it will become unmanaged in ARC", 43 E->getLocStart(), E->getSourceRange()); 44 return true; 45 } 46 47 Expr *CEE = E->getCallee()->IgnoreParenImpCasts(); 48 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CEE)) { 49 if (FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(DRE->getDecl())) { 50 if (!FD->getDeclContext()->getRedeclContext()->isFileContext()) 51 return true; 52 53 if (FD->getIdentifier() == NSMakeCollectableII) { 54 Transaction Trans(TA); 55 TA.clearDiagnostic(diag::err_unavailable, 56 diag::err_unavailable_message, 57 diag::err_ovl_deleted_call, // ObjC++ 58 DRE->getSourceRange()); 59 TA.replace(DRE->getSourceRange(), "CFBridgingRelease"); 60 61 } else if (FD->getIdentifier() == CFMakeCollectableII) { 62 TA.reportError("CFMakeCollectable will leak the object that it " 63 "receives in ARC", DRE->getLocation(), 64 DRE->getSourceRange()); 65 } 66 } 67 } 68 69 return true; 70 } 71 }; 72 73 } // anonymous namespace 74 75 void GCCollectableCallsTraverser::traverseBody(BodyContext &BodyCtx) { 76 GCCollectableCallsChecker(BodyCtx.getMigrationContext(), 77 BodyCtx.getParentMap()) 78 .TraverseStmt(BodyCtx.getTopStmt()); 79 } 80