xref: /freebsd-src/contrib/llvm-project/clang/lib/ARCMigrate/TransGCCalls.cpp (revision 0b57cec536236d46e3dba9bd041533462f33dbb7)
1*0b57cec5SDimitry Andric //===--- TransGCCalls.cpp - Transformations to ARC mode -------------------===//
2*0b57cec5SDimitry Andric //
3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0b57cec5SDimitry Andric //
7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
8*0b57cec5SDimitry Andric 
9*0b57cec5SDimitry Andric #include "Transforms.h"
10*0b57cec5SDimitry Andric #include "Internals.h"
11*0b57cec5SDimitry Andric #include "clang/AST/ASTContext.h"
12*0b57cec5SDimitry Andric #include "clang/Sema/SemaDiagnostic.h"
13*0b57cec5SDimitry Andric 
14*0b57cec5SDimitry Andric using namespace clang;
15*0b57cec5SDimitry Andric using namespace arcmt;
16*0b57cec5SDimitry Andric using namespace trans;
17*0b57cec5SDimitry Andric 
18*0b57cec5SDimitry Andric namespace {
19*0b57cec5SDimitry Andric 
20*0b57cec5SDimitry Andric class GCCollectableCallsChecker :
21*0b57cec5SDimitry Andric                          public RecursiveASTVisitor<GCCollectableCallsChecker> {
22*0b57cec5SDimitry Andric   MigrationContext &MigrateCtx;
23*0b57cec5SDimitry Andric   IdentifierInfo *NSMakeCollectableII;
24*0b57cec5SDimitry Andric   IdentifierInfo *CFMakeCollectableII;
25*0b57cec5SDimitry Andric 
26*0b57cec5SDimitry Andric public:
GCCollectableCallsChecker(MigrationContext & ctx)27*0b57cec5SDimitry Andric   GCCollectableCallsChecker(MigrationContext &ctx)
28*0b57cec5SDimitry Andric     : MigrateCtx(ctx) {
29*0b57cec5SDimitry Andric     IdentifierTable &Ids = MigrateCtx.Pass.Ctx.Idents;
30*0b57cec5SDimitry Andric     NSMakeCollectableII = &Ids.get("NSMakeCollectable");
31*0b57cec5SDimitry Andric     CFMakeCollectableII = &Ids.get("CFMakeCollectable");
32*0b57cec5SDimitry Andric   }
33*0b57cec5SDimitry Andric 
shouldWalkTypesOfTypeLocs() const34*0b57cec5SDimitry Andric   bool shouldWalkTypesOfTypeLocs() const { return false; }
35*0b57cec5SDimitry Andric 
VisitCallExpr(CallExpr * E)36*0b57cec5SDimitry Andric   bool VisitCallExpr(CallExpr *E) {
37*0b57cec5SDimitry Andric     TransformActions &TA = MigrateCtx.Pass.TA;
38*0b57cec5SDimitry Andric 
39*0b57cec5SDimitry Andric     if (MigrateCtx.isGCOwnedNonObjC(E->getType())) {
40*0b57cec5SDimitry Andric       TA.report(E->getBeginLoc(), diag::warn_arcmt_nsalloc_realloc,
41*0b57cec5SDimitry Andric                 E->getSourceRange());
42*0b57cec5SDimitry Andric       return true;
43*0b57cec5SDimitry Andric     }
44*0b57cec5SDimitry Andric 
45*0b57cec5SDimitry Andric     Expr *CEE = E->getCallee()->IgnoreParenImpCasts();
46*0b57cec5SDimitry Andric     if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CEE)) {
47*0b57cec5SDimitry Andric       if (FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(DRE->getDecl())) {
48*0b57cec5SDimitry Andric         if (!FD->getDeclContext()->getRedeclContext()->isFileContext())
49*0b57cec5SDimitry Andric           return true;
50*0b57cec5SDimitry Andric 
51*0b57cec5SDimitry Andric         if (FD->getIdentifier() == NSMakeCollectableII) {
52*0b57cec5SDimitry Andric           Transaction Trans(TA);
53*0b57cec5SDimitry Andric           TA.clearDiagnostic(diag::err_unavailable,
54*0b57cec5SDimitry Andric                              diag::err_unavailable_message,
55*0b57cec5SDimitry Andric                              diag::err_ovl_deleted_call, // ObjC++
56*0b57cec5SDimitry Andric                              DRE->getSourceRange());
57*0b57cec5SDimitry Andric           TA.replace(DRE->getSourceRange(), "CFBridgingRelease");
58*0b57cec5SDimitry Andric 
59*0b57cec5SDimitry Andric         } else if (FD->getIdentifier() == CFMakeCollectableII) {
60*0b57cec5SDimitry Andric           TA.reportError("CFMakeCollectable will leak the object that it "
61*0b57cec5SDimitry Andric                          "receives in ARC", DRE->getLocation(),
62*0b57cec5SDimitry Andric                          DRE->getSourceRange());
63*0b57cec5SDimitry Andric         }
64*0b57cec5SDimitry Andric       }
65*0b57cec5SDimitry Andric     }
66*0b57cec5SDimitry Andric 
67*0b57cec5SDimitry Andric     return true;
68*0b57cec5SDimitry Andric   }
69*0b57cec5SDimitry Andric };
70*0b57cec5SDimitry Andric 
71*0b57cec5SDimitry Andric } // anonymous namespace
72*0b57cec5SDimitry Andric 
traverseBody(BodyContext & BodyCtx)73*0b57cec5SDimitry Andric void GCCollectableCallsTraverser::traverseBody(BodyContext &BodyCtx) {
74*0b57cec5SDimitry Andric   GCCollectableCallsChecker(BodyCtx.getMigrationContext())
75*0b57cec5SDimitry Andric                                             .TraverseStmt(BodyCtx.getTopStmt());
76*0b57cec5SDimitry Andric }
77