Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/clang/lib/ARCMigrate/TransAPIUses.cpp
35236 views
1
//===--- TransAPIUses.cpp - Transformations to ARC mode -------------------===//
2
//
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
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// checkAPIUses:
10
//
11
// Emits error/fix with some API uses that are obsolete or not safe in ARC mode:
12
//
13
// - NSInvocation's [get/set]ReturnValue and [get/set]Argument are only safe
14
// with __unsafe_unretained objects.
15
// - Calling -zone gets replaced with 'nil'.
16
//
17
//===----------------------------------------------------------------------===//
18
19
#include "Transforms.h"
20
#include "Internals.h"
21
#include "clang/AST/ASTContext.h"
22
#include "clang/Sema/SemaDiagnostic.h"
23
24
using namespace clang;
25
using namespace arcmt;
26
using namespace trans;
27
28
namespace {
29
30
class APIChecker : public RecursiveASTVisitor<APIChecker> {
31
MigrationPass &Pass;
32
33
Selector getReturnValueSel, setReturnValueSel;
34
Selector getArgumentSel, setArgumentSel;
35
36
Selector zoneSel;
37
public:
38
APIChecker(MigrationPass &pass) : Pass(pass) {
39
SelectorTable &sels = Pass.Ctx.Selectors;
40
IdentifierTable &ids = Pass.Ctx.Idents;
41
getReturnValueSel = sels.getUnarySelector(&ids.get("getReturnValue"));
42
setReturnValueSel = sels.getUnarySelector(&ids.get("setReturnValue"));
43
44
const IdentifierInfo *selIds[2];
45
selIds[0] = &ids.get("getArgument");
46
selIds[1] = &ids.get("atIndex");
47
getArgumentSel = sels.getSelector(2, selIds);
48
selIds[0] = &ids.get("setArgument");
49
setArgumentSel = sels.getSelector(2, selIds);
50
51
zoneSel = sels.getNullarySelector(&ids.get("zone"));
52
}
53
54
bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
55
// NSInvocation.
56
if (E->isInstanceMessage() &&
57
E->getReceiverInterface() &&
58
E->getReceiverInterface()->getName() == "NSInvocation") {
59
StringRef selName;
60
if (E->getSelector() == getReturnValueSel)
61
selName = "getReturnValue";
62
else if (E->getSelector() == setReturnValueSel)
63
selName = "setReturnValue";
64
else if (E->getSelector() == getArgumentSel)
65
selName = "getArgument";
66
else if (E->getSelector() == setArgumentSel)
67
selName = "setArgument";
68
else
69
return true;
70
71
Expr *parm = E->getArg(0)->IgnoreParenCasts();
72
QualType pointee = parm->getType()->getPointeeType();
73
if (pointee.isNull())
74
return true;
75
76
if (pointee.getObjCLifetime() > Qualifiers::OCL_ExplicitNone)
77
Pass.TA.report(parm->getBeginLoc(),
78
diag::err_arcmt_nsinvocation_ownership,
79
parm->getSourceRange())
80
<< selName;
81
82
return true;
83
}
84
85
// -zone.
86
if (E->isInstanceMessage() &&
87
E->getInstanceReceiver() &&
88
E->getSelector() == zoneSel &&
89
Pass.TA.hasDiagnostic(diag::err_unavailable,
90
diag::err_unavailable_message,
91
E->getSelectorLoc(0))) {
92
// Calling -zone is meaningless in ARC, change it to nil.
93
Transaction Trans(Pass.TA);
94
Pass.TA.clearDiagnostic(diag::err_unavailable,
95
diag::err_unavailable_message,
96
E->getSelectorLoc(0));
97
Pass.TA.replace(E->getSourceRange(), getNilString(Pass));
98
}
99
return true;
100
}
101
};
102
103
} // anonymous namespace
104
105
void trans::checkAPIUses(MigrationPass &pass) {
106
APIChecker(pass).TraverseDecl(pass.Ctx.getTranslationUnitDecl());
107
}
108
109