1 //===--- TransGCCalls.cpp - Transformations to ARC mode -------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "Transforms.h"
11 #include "Internals.h"
12 #include "clang/AST/ASTContext.h"
13 #include "clang/Sema/SemaDiagnostic.h"
15 using namespace clang;
16 using namespace arcmt;
17 using namespace trans;
21 class GCCollectableCallsChecker :
22 public RecursiveASTVisitor<GCCollectableCallsChecker> {
23 MigrationContext &MigrateCtx;
24 IdentifierInfo *NSMakeCollectableII;
25 IdentifierInfo *CFMakeCollectableII;
28 GCCollectableCallsChecker(MigrationContext &ctx)
30 IdentifierTable &Ids = MigrateCtx.Pass.Ctx.Idents;
31 NSMakeCollectableII = &Ids.get("NSMakeCollectable");
32 CFMakeCollectableII = &Ids.get("CFMakeCollectable");
35 bool shouldWalkTypesOfTypeLocs() const { return false; }
37 bool VisitCallExpr(CallExpr *E) {
38 TransformActions &TA = MigrateCtx.Pass.TA;
40 if (MigrateCtx.isGCOwnedNonObjC(E->getType())) {
41 if (MigrateCtx.Pass.noNSAllocReallocError())
42 TA.reportWarning("call returns pointer to GC managed memory; "
43 "it will become unmanaged in ARC",
44 E->getLocStart(), E->getSourceRange());
46 TA.reportError("call returns pointer to GC managed memory; "
47 "it will become unmanaged in ARC",
48 E->getLocStart(), E->getSourceRange());
52 Expr *CEE = E->getCallee()->IgnoreParenImpCasts();
53 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CEE)) {
54 if (FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(DRE->getDecl())) {
55 if (!FD->getDeclContext()->getRedeclContext()->isFileContext())
58 if (FD->getIdentifier() == NSMakeCollectableII) {
59 Transaction Trans(TA);
60 TA.clearDiagnostic(diag::err_unavailable,
61 diag::err_unavailable_message,
62 diag::err_ovl_deleted_call, // ObjC++
63 DRE->getSourceRange());
64 TA.replace(DRE->getSourceRange(), "CFBridgingRelease");
66 } else if (FD->getIdentifier() == CFMakeCollectableII) {
67 TA.reportError("CFMakeCollectable will leak the object that it "
68 "receives in ARC", DRE->getLocation(),
69 DRE->getSourceRange());
78 } // anonymous namespace
80 void GCCollectableCallsTraverser::traverseBody(BodyContext &BodyCtx) {
81 GCCollectableCallsChecker(BodyCtx.getMigrationContext())
82 .TraverseStmt(BodyCtx.getTopStmt());