27 #include "llvm/ADT/StringSwitch.h" 29 using namespace clang;
30 using namespace arcmt;
31 using namespace trans;
35 class RetainReleaseDeallocRemover :
41 std::unique_ptr<ParentMap> StmtMap;
47 : Body(nullptr), Pass(pass) {
54 void transformBody(
Stmt *body,
Decl *ParentD) {
69 if (!isCommonUnusedAutorelease(E)) {
74 Pass.
TA.
reportError(
"it is not safe to remove an unused 'autorelease' " 75 "message; its receiver may be destroyed immediately",
86 rec = rec->IgnoreParenImpCasts();
89 std::string err =
"it is not safe to remove '";
91 "an __unsafe_unretained type";
98 std::string err =
"it is not safe to remove '";
107 "message on the result of a 'delegate' message; " 108 "the object that was passed to 'setDelegate:' may not be " 109 "properly retained", rec->getLocStart());
133 if (!rec)
return true;
139 Expr *RecContainer = Msg;
141 checkForGCDOrXPC(Msg, RecContainer, rec, RecRange);
144 isRemovable(RecContainer) && isInAtFinally(RecContainer)) {
148 std::string str =
" = ";
175 return isPlusOneAssignBeforeOrAfterAutorelease(E) ||
176 isReturnedAfterAutorelease(E);
184 Decl *RefD = getReferencedDecl(Rec);
188 Stmt *nextStmt = getNextStmt(E);
194 if (
ReturnStmt *RetS = dyn_cast<ReturnStmt>(nextStmt))
195 return RefD == getReferencedDecl(RetS->getRetValue());
205 Decl *RefD = getReferencedDecl(Rec);
209 Stmt *prevStmt, *nextStmt;
210 std::tie(prevStmt, nextStmt) = getPreviousAndNextStmt(E);
212 return isPlusOneAssignToVar(prevStmt, RefD) ||
213 isPlusOneAssignToVar(nextStmt, RefD);
216 bool isPlusOneAssignToVar(
Stmt *S,
Decl *RefD) {
223 return (RefD == getReferencedDecl(Bop->getLHS())) &&
isPlusOneAssign(Bop);
226 if (
DeclStmt *DS = dyn_cast<DeclStmt>(S)) {
227 if (DS->isSingleDecl() && DS->getSingleDecl() == RefD) {
228 if (
VarDecl *VD = dyn_cast<VarDecl>(RefD))
238 return getPreviousAndNextStmt(E).second;
241 std::pair<Stmt *, Stmt *> getPreviousAndNextStmt(
Expr *E) {
242 Stmt *prevStmt =
nullptr, *nextStmt =
nullptr;
244 return std::make_pair(prevStmt, nextStmt);
246 Stmt *OuterS = E, *InnerS;
249 OuterS = StmtMap->getParent(InnerS);
251 while (OuterS && (isa<ParenExpr>(OuterS) ||
252 isa<CastExpr>(OuterS) ||
253 isa<ExprWithCleanups>(OuterS)));
256 return std::make_pair(prevStmt, nextStmt);
261 for (; currChildS != childE; ++currChildS) {
262 if (*currChildS == InnerS)
264 prevChildS = currChildS;
267 if (prevChildS != childE) {
268 prevStmt = *prevChildS;
273 if (currChildS == childE)
274 return std::make_pair(prevStmt, nextStmt);
276 if (currChildS == childE)
277 return std::make_pair(prevStmt, nextStmt);
279 nextStmt = *currChildS;
283 return std::make_pair(prevStmt, nextStmt);
292 switch (ME->getMethodFamily()) {
297 return getReferencedDecl(ME->getInstanceReceiver());
303 return DRE->getDecl();
305 return ME->getMemberDecl();
307 return IRE->getDecl();
330 bool isGCDOrXPC = llvm::StringSwitch<bool>(MacroName)
331 .Case(
"dispatch_retain",
true)
332 .Case(
"dispatch_release",
true)
333 .Case(
"xpc_retain",
true)
334 .Case(
"xpc_release",
true)
342 if (
StmtExpr *SE = dyn_cast<StmtExpr>(S)) {
346 S = StmtMap->getParent(S);
353 if (StmtExprChild.begin() == StmtExprChild.end())
355 auto *CompS = dyn_cast_or_null<CompoundStmt>(*StmtExprChild.begin());
360 if (CompStmtChild.begin() == CompStmtChild.end())
362 auto *DeclS = dyn_cast_or_null<DeclStmt>(*CompStmtChild.begin());
365 if (!DeclS->isSingleDecl())
367 VarDecl *VD = dyn_cast_or_null<VarDecl>(DeclS->getSingleDecl());
374 RecContainer = StmtE;
387 diag::err_unavailable,
388 diag::err_unavailable_message,
392 bool isDelegateMessage(
Expr *E)
const {
393 if (!E)
return false;
402 return (ME->isInstanceMessage() && ME->getSelector() == DelegateSel);
407 bool isInAtFinally(
Expr *E)
const {
411 if (isa<ObjCAtFinallyStmt>(S))
413 S = StmtMap->getParent(S);
419 bool isRemovable(
Expr *E)
const {
420 return Removables.count(E);
423 bool tryRemoving(
Expr *E)
const {
424 if (isRemovable(E)) {
429 Stmt *parent = StmtMap->getParent(E);
432 return tryRemoving(castE);
434 if (
ParenExpr *parenE = dyn_cast_or_null<ParenExpr>(parent))
435 return tryRemoving(parenE);
438 bopE = dyn_cast_or_null<BinaryOperator>(parent)) {
439 if (bopE->getOpcode() == BO_Comma && bopE->getLHS() == E &&
441 Pass.
TA.
replace(bopE->getSourceRange(), bopE->getRHS()->getSourceRange());
child_iterator child_begin()
The receiver is the instance of the superclass object.
Defines the clang::ASTContext interface.
The receiver is an object instance.
Smart pointer class that efficiently represents Objective-C method names.
Selector getSelector() const
Stmt - This represents one statement.
Defines the SourceManager interface.
Decl - This represents one declaration (or definition), e.g.
ParenExpr - This represents a parethesized expression, e.g.
llvm::iterator_range< child_iterator > child_range
Stmt * IgnoreImplicit()
Skip past any implicit AST nodes which might surround this statement, such as ExprWithCleanups or Imp...
Represents a variable declaration or definition.
Expr * IgnoreImplicit() LLVM_READONLY
IgnoreImplicit - Skip past any implicit AST nodes which might surround this expression.
void setBegin(SourceLocation b)
Represents an expression – generally a full-expression – that introduces cleanups to be run at the ...
bool TraverseDecl(Decl *D)
Recursively visit a declaration, by dispatching to Traverse*Decl() based on the argument's dynamic ty...
bool isGlobalVar(Expr *E)
Selector getNullarySelector(IdentifierInfo *ID)
void removeRetainReleaseDeallocFinalize(MigrationPass &pass)
A builtin binary operation expression such as "x + y" or "x <= y".
Expr * IgnoreParenCasts() LLVM_READONLY
IgnoreParenCasts - Ignore parentheses and casts.
A class that does preorder or postorder depth-first traversal on the entire Clang AST and visits each...
bool isPlusOneAssign(const BinaryOperator *E)
This object can be modified without requiring retains or releases.
StringRef getNilString(MigrationPass &Pass)
Returns "nil" or "0" if 'nil' macro is not actually defined.
void collectRemovables(Stmt *S, ExprSet &exprs)
SourceLocation getImmediateSpellingLoc(SourceLocation Loc) const
Given a SourceLocation object, return the spelling location referenced by the ID. ...
Expr - This represents one expression.
ReturnStmt - This represents a return, optionally of an expression: return; return 4;...
An expression that sends a message to the given Objective-C object or class.
SourceLocation getEnd() const
ReceiverKind getReceiverKind() const
Determine the kind of receiver that this message is being sent to.
std::string getAsString() const
Derive the full selector name (e.g.
SelectorTable & Selectors
PseudoObjectExpr - An expression which accesses a pseudo-object l-value.
Encodes a location in the source.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
ObjCMethodFamily getMethodFamily() const
DeclStmt - Adaptor class for mixing declarations with statements and expressions. ...
SourceLocation getSelectorLoc(unsigned Index) const
ImplicitCastExpr - Allows us to explicitly represent implicit type conversions, which have no direct ...
StmtExpr - This is the GNU Statement Expression extension: ({int X=4; X;}).
static StringRef getImmediateMacroName(SourceLocation Loc, const SourceManager &SM, const LangOptions &LangOpts)
Retrieve the name of the immediate macro expansion.
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Expr * getInstanceReceiver()
Returns the object expression (receiver) for an instance message, or null for a message that is not a...
Dataflow Directional Tag Classes.
bool hasSideEffects(Expr *E, ASTContext &Ctx)
SourceLocation getLocStart() const LLVM_READONLY
const Expr * getInit() const
bool isPlusOne(const Expr *E)
Expr * IgnoreParenImpCasts() LLVM_READONLY
IgnoreParenImpCasts - Ignore parentheses and implicit casts.
bool isMacroArgExpansion(SourceLocation Loc, SourceLocation *StartLoc=nullptr) const
Tests whether the given source location represents a macro argument's expansion into the function-lik...
ObjCIvarRefExpr - A reference to an ObjC instance variable.
SourceManager & getSourceManager()
TranslationUnitDecl * getTranslationUnitDecl() const
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
void setEnd(SourceLocation e)
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
A reference to a declared variable, function, enum, etc.
A trivial tuple used to represent a source range.
bool isInstanceMessage() const
Determine whether this is an instance message to either a computed object or to super.
SourceLocation getBegin() const
const LangOptions & getLangOpts() const
This class handles loading and caching of source files into memory.
child_iterator child_end()