blob: 7c0819a677c8363efc890677ef452393912786ce [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 Kyrtzidisf38fa732011-11-06 18:58:03 +000030 IdentifierTable &Ids = MigrateCtx.Pass.Ctx.Idents;
Argyrios Kyrtzidis81eecde2011-11-04 15:58:17 +000031 NSMakeCollectableII = &Ids.get("NSMakeCollectable");
32 CFMakeCollectableII = &Ids.get("CFMakeCollectable");
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +000033 }
34
Argyrios Kyrtzidisf38fa732011-11-06 18:58:03 +000035 bool shouldWalkTypesOfTypeLocs() const { return false; }
36
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +000037 bool VisitCallExpr(CallExpr *E) {
Argyrios Kyrtzidisf38fa732011-11-06 18:58:03 +000038 TransformActions &TA = MigrateCtx.Pass.TA;
Argyrios Kyrtzidis81eecde2011-11-04 15:58:17 +000039
Argyrios Kyrtzidis1fe42032011-11-04 23:43:03 +000040 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
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +000047 Expr *CEE = E->getCallee()->IgnoreParenImpCasts();
48 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CEE)) {
49 if (FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(DRE->getDecl())) {
Argyrios Kyrtzidis81eecde2011-11-04 15:58:17 +000050 if (!FD->getDeclContext()->getRedeclContext()->isFileContext())
51 return true;
52
53 if (FD->getIdentifier() == NSMakeCollectableII) {
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +000054 Transaction Trans(TA);
55 TA.clearDiagnostic(diag::err_unavailable,
56 diag::err_unavailable_message,
Argyrios Kyrtzidis0d579b62011-11-04 15:58:13 +000057 diag::err_ovl_deleted_call, // ObjC++
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +000058 DRE->getSourceRange());
59 TA.replace(DRE->getSourceRange(), "CFBridgingRelease");
Argyrios Kyrtzidis81eecde2011-11-04 15:58:17 +000060
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());
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +000065 }
66 }
67 }
68
69 return true;
70 }
71};
72
73} // anonymous namespace
74
75void GCCollectableCallsTraverser::traverseBody(BodyContext &BodyCtx) {
76 GCCollectableCallsChecker(BodyCtx.getMigrationContext(),
77 BodyCtx.getParentMap())
78 .TraverseStmt(BodyCtx.getTopStmt());
79}