26#include "llvm/ADT/StringSwitch.h"
34class RetainReleaseDeallocRemover :
40 std::unique_ptr<ParentMap> StmtMap;
46 : Body(nullptr), Pass(pass) {
53 void transformBody(
Stmt *body,
Decl *ParentD) {
61 switch (
E->getMethodFamily()) {
63 if (
E->isInstanceMessage() &&
E->getSelector() == FinalizeSel)
68 if (!isCommonUnusedAutorelease(
E)) {
74 "it is not safe to remove an unused 'autorelease' "
75 "message; its receiver may be destroyed immediately",
85 if (
Expr *rec =
E->getInstanceReceiver()) {
86 rec = rec->IgnoreParenImpCasts();
88 (
E->getMethodFamily() !=
OMF_retain || isRemovable(
E))) {
89 std::string err =
"it is not safe to remove '";
90 err +=
E->getSelector().getAsString() +
"' message on "
91 "an __unsafe_unretained type";
97 (
E->getMethodFamily() !=
OMF_retain || isRemovable(
E))) {
98 std::string err =
"it is not safe to remove '";
99 err +=
E->getSelector().getAsString() +
"' message on "
105 if (
E->getMethodFamily() ==
OMF_release && isDelegateMessage(rec)) {
107 "it is not safe to remove 'retain' "
108 "message on the result of a 'delegate' message; "
109 "the object that was passed to 'setDelegate:' may not be "
120 switch (
E->getReceiverKind()) {
125 clearDiagnostics(
E->getSelectorLoc(0));
135 Expr *rec =
E->getInstanceReceiver();
136 if (!rec)
return true;
139 clearDiagnostics(
E->getSelectorLoc(0));
142 Expr *RecContainer = Msg;
144 checkForGCDOrXPC(Msg, RecContainer, rec, RecRange);
147 isRemovable(RecContainer) && isInAtFinally(RecContainer)) {
151 std::string str =
" = ";
178 return isPlusOneAssignBeforeOrAfterAutorelease(
E) ||
179 isReturnedAfterAutorelease(
E);
183 Expr *Rec =
E->getInstanceReceiver();
187 Decl *RefD = getReferencedDecl(Rec);
191 Stmt *nextStmt = getNextStmt(
E);
197 if (
ReturnStmt *RetS = dyn_cast<ReturnStmt>(nextStmt))
198 return RefD == getReferencedDecl(RetS->getRetValue());
204 Expr *Rec =
E->getInstanceReceiver();
208 Decl *RefD = getReferencedDecl(Rec);
212 Stmt *prevStmt, *nextStmt;
213 std::tie(prevStmt, nextStmt) = getPreviousAndNextStmt(
E);
215 return isPlusOneAssignToVar(prevStmt, RefD) ||
216 isPlusOneAssignToVar(nextStmt, RefD);
219 bool isPlusOneAssignToVar(
Stmt *S,
Decl *RefD) {
226 return (RefD == getReferencedDecl(Bop->getLHS())) &&
isPlusOneAssign(Bop);
229 if (
DeclStmt *DS = dyn_cast<DeclStmt>(S)) {
230 if (DS->isSingleDecl() && DS->getSingleDecl() == RefD) {
231 if (
VarDecl *VD = dyn_cast<VarDecl>(RefD))
241 return getPreviousAndNextStmt(
E).second;
244 std::pair<Stmt *, Stmt *> getPreviousAndNextStmt(
Expr *
E) {
245 Stmt *prevStmt =
nullptr, *nextStmt =
nullptr;
247 return std::make_pair(prevStmt, nextStmt);
249 Stmt *OuterS =
E, *InnerS;
252 OuterS = StmtMap->getParent(InnerS);
254 while (OuterS && (isa<ParenExpr>(OuterS) ||
255 isa<CastExpr>(OuterS) ||
256 isa<FullExpr>(OuterS)));
259 return std::make_pair(prevStmt, nextStmt);
264 for (; currChildS != childE; ++currChildS) {
265 if (*currChildS == InnerS)
267 prevChildS = currChildS;
270 if (prevChildS != childE) {
271 prevStmt = *prevChildS;
272 if (
auto *
E = dyn_cast_or_null<Expr>(prevStmt))
276 if (currChildS == childE)
277 return std::make_pair(prevStmt, nextStmt);
279 if (currChildS == childE)
280 return std::make_pair(prevStmt, nextStmt);
282 nextStmt = *currChildS;
283 if (
auto *
E = dyn_cast_or_null<Expr>(nextStmt))
286 return std::make_pair(prevStmt, nextStmt);
295 switch (ME->getMethodFamily()) {
300 return getReferencedDecl(ME->getInstanceReceiver());
306 return DRE->getDecl();
308 return ME->getMemberDecl();
310 return IRE->getDecl();
333 bool isGCDOrXPC = llvm::StringSwitch<bool>(MacroName)
334 .Case(
"dispatch_retain",
true)
335 .Case(
"dispatch_release",
true)
336 .Case(
"xpc_retain",
true)
337 .Case(
"xpc_release",
true)
345 if (
StmtExpr *SE = dyn_cast<StmtExpr>(S)) {
349 S = StmtMap->getParent(S);
356 if (StmtExprChild.begin() == StmtExprChild.end())
358 auto *CompS = dyn_cast_or_null<CompoundStmt>(*StmtExprChild.begin());
363 if (CompStmtChild.begin() == CompStmtChild.end())
365 auto *DeclS = dyn_cast_or_null<DeclStmt>(*CompStmtChild.begin());
368 if (!DeclS->isSingleDecl())
370 VarDecl *VD = dyn_cast_or_null<VarDecl>(DeclS->getSingleDecl());
377 RecContainer = StmtE;
378 Rec =
Init->IgnoreParenImpCasts();
379 if (
FullExpr *FE = dyn_cast<FullExpr>(Rec))
382 if (
SM.isMacroArgExpansion(RecRange.
getBegin()))
384 if (
SM.isMacroArgExpansion(RecRange.
getEnd()))
390 diag::err_unavailable,
391 diag::err_unavailable_message,
395 bool isDelegateMessage(
Expr *
E)
const {
396 if (!
E)
return false;
405 return (ME->isInstanceMessage() && ME->getSelector() == DelegateSel);
410 bool isInAtFinally(
Expr *
E)
const {
414 if (isa<ObjCAtFinallyStmt>(S))
416 S = StmtMap->getParent(S);
422 bool isRemovable(
Expr *
E)
const {
423 return Removables.count(
E);
426 bool tryRemoving(
Expr *
E)
const {
427 if (isRemovable(
E)) {
432 Stmt *parent = StmtMap->getParent(
E);
435 return tryRemoving(castE);
437 if (
ParenExpr *parenE = dyn_cast_or_null<ParenExpr>(parent))
438 return tryRemoving(parenE);
441 bopE = dyn_cast_or_null<BinaryOperator>(parent)) {
442 if (bopE->getOpcode() == BO_Comma && bopE->getLHS() ==
E &&
444 Pass.
TA.
replace(bopE->getSourceRange(), bopE->getRHS()->getSourceRange());
Defines the clang::ASTContext interface.
Defines the SourceManager interface.
SourceManager & getSourceManager()
TranslationUnitDecl * getTranslationUnitDecl() const
const LangOptions & getLangOpts() const
SelectorTable & Selectors
A builtin binary operation expression such as "x + y" or "x <= y".
A reference to a declared variable, function, enum, etc.
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
Decl - This represents one declaration (or definition), e.g.
This represents one expression.
Expr * IgnoreParenCasts() LLVM_READONLY
Skip past any parentheses and casts which might surround this expression until reaching a fixed point...
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Expr * IgnoreImplicit() LLVM_READONLY
Skip past any implicit AST nodes which might surround this expression until reaching a fixed point.
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
FullExpr - Represents a "full-expression" node.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
ImplicitCastExpr - Allows us to explicitly represent implicit type conversions, which have no direct ...
static StringRef getImmediateMacroName(SourceLocation Loc, const SourceManager &SM, const LangOptions &LangOpts)
Retrieve the name of the immediate macro expansion.
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
ObjCIvarRefExpr - A reference to an ObjC instance variable.
An expression that sends a message to the given Objective-C object or class.
ObjCMethodFamily getMethodFamily() const
@ SuperInstance
The receiver is the instance of the superclass object.
@ Instance
The receiver is an object instance.
ParenExpr - This represents a parenthesized expression, e.g.
PseudoObjectExpr - An expression which accesses a pseudo-object l-value.
@ OCL_ExplicitNone
This object can be modified without requiring retains or releases.
A class that does preorder or postorder depth-first traversal on the entire Clang AST and visits each...
bool TraverseStmt(Stmt *S, DataRecursionQueue *Queue=nullptr)
Recursively visit a statement or expression, by dispatching to Traverse*() based on the argument's dy...
bool TraverseDecl(Decl *D)
Recursively visit a declaration, by dispatching to Traverse*Decl() based on the argument's dynamic ty...
ReturnStmt - This represents a return, optionally of an expression: return; return 4;.
Selector getNullarySelector(const IdentifierInfo *ID)
Smart pointer class that efficiently represents Objective-C method names.
Encodes a location in the source.
This class handles loading and caching of source files into memory.
A trivial tuple used to represent a source range.
void setBegin(SourceLocation b)
SourceLocation getEnd() const
SourceLocation getBegin() const
void setEnd(SourceLocation e)
StmtExpr - This is the GNU Statement Expression extension: ({int X=4; X;}).
Stmt - This represents one statement.
child_iterator child_begin()
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
child_iterator child_end()
llvm::iterator_range< child_iterator > child_range
SourceLocation getBeginLoc() const LLVM_READONLY
Represents a variable declaration or definition.
const Expr * getInit() const
StringRef getNilString(MigrationPass &Pass)
Returns "nil" or "0" if 'nil' macro is not actually defined.
bool hasSideEffects(Expr *E, ASTContext &Ctx)
void removeRetainReleaseDeallocFinalize(MigrationPass &pass)
llvm::DenseSet< Expr * > ExprSet
bool isPlusOneAssign(const BinaryOperator *E)
bool isPlusOne(const Expr *E)
bool isGlobalVar(Expr *E)
void collectRemovables(Stmt *S, ExprSet &exprs)
The JSON file list parser is used to communicate input to InstallAPI.