clang 19.0.0git
Go to the documentation of this file.
1//===--- TransAPIUses.cpp - Transformations to ARC mode -------------------===//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
9// checkAPIUses:
11// Emits error/fix with some API uses that are obsolete or not safe in ARC mode:
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'.
19#include "Transforms.h"
20#include "Internals.h"
24using namespace clang;
25using namespace arcmt;
26using namespace trans;
28namespace {
30class APIChecker : public RecursiveASTVisitor<APIChecker> {
31 MigrationPass &Pass;
33 Selector getReturnValueSel, setReturnValueSel;
34 Selector getArgumentSel, setArgumentSel;
36 Selector zoneSel;
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"));
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);
51 zoneSel = sels.getNullarySelector(&ids.get("zone"));
52 }
54 bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
55 // NSInvocation.
56 if (E->isInstanceMessage() &&
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;
71 Expr *parm = E->getArg(0)->IgnoreParenCasts();
72 QualType pointee = parm->getType()->getPointeeType();
73 if (pointee.isNull())
74 return true;
78 diag::err_arcmt_nsinvocation_ownership,
79 parm->getSourceRange())
80 << selName;
82 return true;
83 }
85 // -zone.
86 if (E->isInstanceMessage() &&
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 }
103} // anonymous namespace
106 APIChecker(pass).TraverseDecl(pass.Ctx.getTranslationUnitDecl());
Defines the clang::ASTContext interface.
TranslationUnitDecl * getTranslationUnitDecl() const
Definition: ASTContext.h:1073
IdentifierTable & Idents
Definition: ASTContext.h:644
SelectorTable & Selectors
Definition: ASTContext.h:645
This represents one expression.
Definition: Expr.h:110
Expr * IgnoreParenCasts() LLVM_READONLY
Skip past any parentheses and casts which might surround this expression until reaching a fixed point...
Definition: Expr.cpp:3064
QualType getType() const
Definition: Expr.h:142
One of these records is kept for each identifier that is lexed.
Implements an efficient mapping from strings to IdentifierInfo nodes.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition: Decl.h:276
An expression that sends a message to the given Objective-C object or class.
Definition: ExprObjC.h:945
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
Definition: ExprObjC.h:1395
Expr * getInstanceReceiver()
Returns the object expression (receiver) for an instance message, or null for a message that is not a...
Definition: ExprObjC.h:1260
Selector getSelector() const
Definition: ExprObjC.cpp:293
bool isInstanceMessage() const
Determine whether this is an instance message to either a computed object or to super.
Definition: ExprObjC.h:1248
ObjCInterfaceDecl * getReceiverInterface() const
Retrieve the Objective-C interface to which this message is being directed, if known.
Definition: ExprObjC.cpp:314
SourceLocation getSelectorLoc(unsigned Index) const
Definition: ExprObjC.h:1425
A (possibly-)qualified type.
Definition: Type.h:940
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition: Type.h:1007
Qualifiers::ObjCLifetime getObjCLifetime() const
Returns lifetime attribute of this type.
Definition: Type.h:1432
@ OCL_ExplicitNone
This object can be modified without requiring retains or releases.
Definition: Type.h:340
A class that does preorder or postorder depth-first traversal on the entire Clang AST and visits each...
This table allows us to fully hide how we implement multi-keyword caching.
Selector getNullarySelector(const IdentifierInfo *ID)
Selector getSelector(unsigned NumArgs, const IdentifierInfo **IIV)
Can create any sort of selector.
Selector getUnarySelector(const IdentifierInfo *ID)
Smart pointer class that efficiently represents Objective-C method names.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition: Stmt.cpp:326
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Stmt.cpp:338
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition: Type.cpp:695
TransformActions & TA
Definition: Internals.h:152
DiagnosticBuilder report(SourceLocation loc, unsigned diagId, SourceRange range=SourceRange())
bool clearDiagnostic(ArrayRef< unsigned > IDs, SourceRange range)
void replace(SourceRange range, StringRef text)
bool hasDiagnostic(unsigned ID, SourceRange range)
Definition: Internals.h:89
StringRef getNilString(MigrationPass &Pass)
Returns "nil" or "0" if 'nil' macro is not actually defined.
Definition: Transforms.cpp:208
void checkAPIUses(MigrationPass &pass)
The JSON file list parser is used to communicate input to InstallAPI.