blob: 94e965df188f38220428f639a2c2246fdfd08467 [file] [log] [blame]
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +00001//===--- 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
14using namespace clang;
15using namespace arcmt;
16using namespace trans;
17
18namespace {
19
20class GCCollectableCallsChecker :
21 public RecursiveASTVisitor<GCCollectableCallsChecker> {
22 MigrationContext &MigrateCtx;
23 ParentMap &PMap;
24 IdentifierInfo *NSMakeCollectableII;
Argyrios Kyrtzidis81eecde2011-11-04 15:58:17 +000025 IdentifierInfo *CFMakeCollectableII;
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +000026
27public:
28 GCCollectableCallsChecker(MigrationContext &ctx, ParentMap &map)
29 : MigrateCtx(ctx), PMap(map) {
Argyrios Kyrtzidis81eecde2011-11-04 15:58:17 +000030 IdentifierTable &Ids = MigrateCtx.getPass().Ctx.Idents;
31 NSMakeCollectableII = &Ids.get("NSMakeCollectable");
32 CFMakeCollectableII = &Ids.get("CFMakeCollectable");
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +000033 }
34
35 bool VisitCallExpr(CallExpr *E) {
Argyrios Kyrtzidis81eecde2011-11-04 15:58:17 +000036 TransformActions &TA = MigrateCtx.getPass().TA;
37
Argyrios Kyrtzidis1fe42032011-11-04 23:43:03 +000038 if (MigrateCtx.isGCOwnedNonObjC(E->getType())) {
39 TA.reportError("call returns pointer to GC managed memory; "
40 "it will become unmanaged in ARC",
41 E->getLocStart(), E->getSourceRange());
42 return true;
43 }
44
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +000045 Expr *CEE = E->getCallee()->IgnoreParenImpCasts();
46 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CEE)) {
47 if (FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(DRE->getDecl())) {
Argyrios Kyrtzidis81eecde2011-11-04 15:58:17 +000048 if (!FD->getDeclContext()->getRedeclContext()->isFileContext())
49 return true;
50
51 if (FD->getIdentifier() == NSMakeCollectableII) {
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +000052 Transaction Trans(TA);
53 TA.clearDiagnostic(diag::err_unavailable,
54 diag::err_unavailable_message,
Argyrios Kyrtzidis0d579b62011-11-04 15:58:13 +000055 diag::err_ovl_deleted_call, // ObjC++
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +000056 DRE->getSourceRange());
57 TA.replace(DRE->getSourceRange(), "CFBridgingRelease");
Argyrios Kyrtzidis81eecde2011-11-04 15:58:17 +000058
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());
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +000063 }
64 }
65 }
66
67 return true;
68 }
69};
70
71} // anonymous namespace
72
73void GCCollectableCallsTraverser::traverseBody(BodyContext &BodyCtx) {
74 GCCollectableCallsChecker(BodyCtx.getMigrationContext(),
75 BodyCtx.getParentMap())
76 .TraverseStmt(BodyCtx.getTopStmt());
77}