1 //===--- TransGCCalls.cpp - Transformations to ARC mode -------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "Transforms.h"
10 #include "Internals.h"
11 #include "clang/AST/ASTContext.h"
12 #include "clang/Sema/SemaDiagnostic.h"
14 using namespace clang
;
15 using namespace arcmt
;
16 using namespace trans
;
20 class GCCollectableCallsChecker
:
21 public RecursiveASTVisitor
<GCCollectableCallsChecker
> {
22 MigrationContext
&MigrateCtx
;
23 IdentifierInfo
*NSMakeCollectableII
;
24 IdentifierInfo
*CFMakeCollectableII
;
27 GCCollectableCallsChecker(MigrationContext
&ctx
)
29 IdentifierTable
&Ids
= MigrateCtx
.Pass
.Ctx
.Idents
;
30 NSMakeCollectableII
= &Ids
.get("NSMakeCollectable");
31 CFMakeCollectableII
= &Ids
.get("CFMakeCollectable");
34 bool shouldWalkTypesOfTypeLocs() const { return false; }
36 bool VisitCallExpr(CallExpr
*E
) {
37 TransformActions
&TA
= MigrateCtx
.Pass
.TA
;
39 if (MigrateCtx
.isGCOwnedNonObjC(E
->getType())) {
40 TA
.report(E
->getBeginLoc(), diag::warn_arcmt_nsalloc_realloc
,
45 Expr
*CEE
= E
->getCallee()->IgnoreParenImpCasts();
46 if (DeclRefExpr
*DRE
= dyn_cast
<DeclRefExpr
>(CEE
)) {
47 if (FunctionDecl
*FD
= dyn_cast_or_null
<FunctionDecl
>(DRE
->getDecl())) {
48 if (!FD
->getDeclContext()->getRedeclContext()->isFileContext())
51 if (FD
->getIdentifier() == NSMakeCollectableII
) {
52 Transaction
Trans(TA
);
53 TA
.clearDiagnostic(diag::err_unavailable
,
54 diag::err_unavailable_message
,
55 diag::err_ovl_deleted_call
, // ObjC++
56 DRE
->getSourceRange());
57 TA
.replace(DRE
->getSourceRange(), "CFBridgingRelease");
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());
71 } // anonymous namespace
73 void GCCollectableCallsTraverser::traverseBody(BodyContext
&BodyCtx
) {
74 GCCollectableCallsChecker(BodyCtx
.getMigrationContext())
75 .TraverseStmt(BodyCtx
.getTopStmt());