blob: 249f20f01b22fd823222173c3e481c5ffe6469b8 [file] [log] [blame]
Benjamin Krameraccaf192012-11-14 15:08:31 +00001//===--- TransGCCalls.cpp - Transformations to ARC mode -------------------===//
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +00002//
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"
Benjamin Kramer471c8b42012-07-04 20:19:54 +000012#include "clang/AST/ASTContext.h"
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +000013#include "clang/Sema/SemaDiagnostic.h"
14
15using namespace clang;
16using namespace arcmt;
17using namespace trans;
18
19namespace {
20
21class GCCollectableCallsChecker :
22 public RecursiveASTVisitor<GCCollectableCallsChecker> {
23 MigrationContext &MigrateCtx;
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +000024 IdentifierInfo *NSMakeCollectableII;
Argyrios Kyrtzidis81eecde2011-11-04 15:58:17 +000025 IdentifierInfo *CFMakeCollectableII;
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +000026
27public:
Benjamin Kramerfacde172012-06-06 17:32:50 +000028 GCCollectableCallsChecker(MigrationContext &ctx)
29 : MigrateCtx(ctx) {
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())) {
Fariborz Jahanianb5c6bab2012-01-25 00:20:29 +000041 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());
45 else
46 TA.reportError("call returns pointer to GC managed memory; "
47 "it will become unmanaged in ARC",
48 E->getLocStart(), E->getSourceRange());
Argyrios Kyrtzidis1fe42032011-11-04 23:43:03 +000049 return true;
50 }
51
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +000052 Expr *CEE = E->getCallee()->IgnoreParenImpCasts();
53 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CEE)) {
54 if (FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(DRE->getDecl())) {
Argyrios Kyrtzidis81eecde2011-11-04 15:58:17 +000055 if (!FD->getDeclContext()->getRedeclContext()->isFileContext())
56 return true;
57
58 if (FD->getIdentifier() == NSMakeCollectableII) {
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +000059 Transaction Trans(TA);
60 TA.clearDiagnostic(diag::err_unavailable,
61 diag::err_unavailable_message,
Argyrios Kyrtzidis0d579b62011-11-04 15:58:13 +000062 diag::err_ovl_deleted_call, // ObjC++
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +000063 DRE->getSourceRange());
64 TA.replace(DRE->getSourceRange(), "CFBridgingRelease");
Argyrios Kyrtzidis81eecde2011-11-04 15:58:17 +000065
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());
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +000070 }
71 }
72 }
73
74 return true;
75 }
76};
77
78} // anonymous namespace
79
80void GCCollectableCallsTraverser::traverseBody(BodyContext &BodyCtx) {
Benjamin Kramerfacde172012-06-06 17:32:50 +000081 GCCollectableCallsChecker(BodyCtx.getMigrationContext())
Argyrios Kyrtzidise0ac7452011-11-04 15:58:08 +000082 .TraverseStmt(BodyCtx.getTopStmt());
83}