blob: 401e788084473b430fc1aceaa30bbe8e7072c60c [file] [log] [blame]
Benjamin Kramerd81108f2012-11-14 15:08:31 +00001//===--- TransGCCalls.cpp - Transformations to ARC mode -------------------===//
Argyrios Kyrtzidisd208ef92011-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 Kramer4ab984e2012-07-04 20:19:54 +000012#include "clang/AST/ASTContext.h"
Argyrios Kyrtzidisd208ef92011-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 Kyrtzidisd208ef92011-11-04 15:58:08 +000024 IdentifierInfo *NSMakeCollectableII;
Argyrios Kyrtzidisd8cdfbc2011-11-04 15:58:17 +000025 IdentifierInfo *CFMakeCollectableII;
Argyrios Kyrtzidisd208ef92011-11-04 15:58:08 +000026
27public:
Benjamin Kramerd1d76b22012-06-06 17:32:50 +000028 GCCollectableCallsChecker(MigrationContext &ctx)
29 : MigrateCtx(ctx) {
Argyrios Kyrtzidise43ae792011-11-06 18:58:03 +000030 IdentifierTable &Ids = MigrateCtx.Pass.Ctx.Idents;
Argyrios Kyrtzidisd8cdfbc2011-11-04 15:58:17 +000031 NSMakeCollectableII = &Ids.get("NSMakeCollectable");
32 CFMakeCollectableII = &Ids.get("CFMakeCollectable");
Argyrios Kyrtzidisd208ef92011-11-04 15:58:08 +000033 }
34
Argyrios Kyrtzidise43ae792011-11-06 18:58:03 +000035 bool shouldWalkTypesOfTypeLocs() const { return false; }
36
Argyrios Kyrtzidisd208ef92011-11-04 15:58:08 +000037 bool VisitCallExpr(CallExpr *E) {
Argyrios Kyrtzidise43ae792011-11-06 18:58:03 +000038 TransformActions &TA = MigrateCtx.Pass.TA;
Argyrios Kyrtzidisd8cdfbc2011-11-04 15:58:17 +000039
Argyrios Kyrtzidis6b2d47d2011-11-04 23:43:03 +000040 if (MigrateCtx.isGCOwnedNonObjC(E->getType())) {
Alp Toker42aa2122014-01-26 05:07:32 +000041 TA.report(E->getLocStart(), diag::err_arcmt_nsalloc_realloc,
42 E->getSourceRange());
Argyrios Kyrtzidis6b2d47d2011-11-04 23:43:03 +000043 return true;
44 }
45
Argyrios Kyrtzidisd208ef92011-11-04 15:58:08 +000046 Expr *CEE = E->getCallee()->IgnoreParenImpCasts();
47 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CEE)) {
48 if (FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(DRE->getDecl())) {
Argyrios Kyrtzidisd8cdfbc2011-11-04 15:58:17 +000049 if (!FD->getDeclContext()->getRedeclContext()->isFileContext())
50 return true;
51
52 if (FD->getIdentifier() == NSMakeCollectableII) {
Argyrios Kyrtzidisd208ef92011-11-04 15:58:08 +000053 Transaction Trans(TA);
54 TA.clearDiagnostic(diag::err_unavailable,
55 diag::err_unavailable_message,
Argyrios Kyrtzidis3eaa22a2011-11-04 15:58:13 +000056 diag::err_ovl_deleted_call, // ObjC++
Argyrios Kyrtzidisd208ef92011-11-04 15:58:08 +000057 DRE->getSourceRange());
58 TA.replace(DRE->getSourceRange(), "CFBridgingRelease");
Argyrios Kyrtzidisd8cdfbc2011-11-04 15:58:17 +000059
60 } else if (FD->getIdentifier() == CFMakeCollectableII) {
61 TA.reportError("CFMakeCollectable will leak the object that it "
62 "receives in ARC", DRE->getLocation(),
63 DRE->getSourceRange());
Argyrios Kyrtzidisd208ef92011-11-04 15:58:08 +000064 }
65 }
66 }
67
68 return true;
69 }
70};
71
72} // anonymous namespace
73
74void GCCollectableCallsTraverser::traverseBody(BodyContext &BodyCtx) {
Benjamin Kramerd1d76b22012-06-06 17:32:50 +000075 GCCollectableCallsChecker(BodyCtx.getMigrationContext())
Argyrios Kyrtzidisd208ef92011-11-04 15:58:08 +000076 .TraverseStmt(BodyCtx.getTopStmt());
77}