forked from OSchip/llvm-project
[arcmt] Don't remove retains/releases on a global variable, flag them with errors. rdar://9402555.
llvm-svn: 135213
This commit is contained in:
parent
4771159f9f
commit
f2a27f40d6
|
@ -78,6 +78,15 @@ public:
|
|||
Pass.TA.reportError(err, rec->getLocStart());
|
||||
return true;
|
||||
}
|
||||
|
||||
if (isGlobalVar(rec) &&
|
||||
(E->getMethodFamily() != OMF_retain || isRemovable(E))) {
|
||||
std::string err = "it is not safe to remove '";
|
||||
err += E->getSelector().getAsString() + "' message on "
|
||||
"a global variable";
|
||||
Pass.TA.reportError(err, rec->getLocStart());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
case OMF_dealloc:
|
||||
break;
|
||||
|
|
|
@ -193,17 +193,6 @@ private:
|
|||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool isGlobalVar(Expr *E) {
|
||||
E = E->IgnoreParenCasts();
|
||||
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
|
||||
return DRE->getDecl()->getDeclContext()->isFileContext();
|
||||
if (ConditionalOperator *condOp = dyn_cast<ConditionalOperator>(E))
|
||||
return isGlobalVar(condOp->getTrueExpr()) &&
|
||||
isGlobalVar(condOp->getFalseExpr());
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
} // end anonymous namespace
|
||||
|
|
|
@ -152,6 +152,17 @@ bool trans::hasSideEffects(Expr *E, ASTContext &Ctx) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool trans::isGlobalVar(Expr *E) {
|
||||
E = E->IgnoreParenCasts();
|
||||
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
|
||||
return DRE->getDecl()->getDeclContext()->isFileContext();
|
||||
if (ConditionalOperator *condOp = dyn_cast<ConditionalOperator>(E))
|
||||
return isGlobalVar(condOp->getTrueExpr()) &&
|
||||
isGlobalVar(condOp->getFalseExpr());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
class ReferenceClear : public RecursiveASTVisitor<ReferenceClear> {
|
||||
|
|
|
@ -54,6 +54,8 @@ bool canApplyWeak(ASTContext &Ctx, QualType type);
|
|||
SourceLocation findLocationAfterSemi(SourceLocation loc, ASTContext &Ctx);
|
||||
|
||||
bool hasSideEffects(Expr *E, ASTContext &Ctx);
|
||||
bool isGlobalVar(Expr *E);
|
||||
|
||||
|
||||
template <typename BODY_TRANS>
|
||||
class BodyTransform : public RecursiveASTVisitor<BodyTransform<BODY_TRANS> > {
|
||||
|
|
|
@ -36,10 +36,16 @@ struct UnsafeS {
|
|||
- (oneway void)release { } // expected-error {{ARC forbids implementation}}
|
||||
@end
|
||||
|
||||
id global_foo;
|
||||
|
||||
void test1(A *a, BOOL b, struct UnsafeS *unsafeS) {
|
||||
[unsafeS->unsafeObj retain]; // expected-error {{it is not safe to remove 'retain' message on an __unsafe_unretained type}} \
|
||||
// expected-error {{ARC forbids explicit message send}}
|
||||
id foo = [unsafeS->unsafeObj retain]; // no warning.
|
||||
[global_foo retain]; // expected-error {{it is not safe to remove 'retain' message on a global variable}} \
|
||||
// expected-error {{ARC forbids explicit message send}}
|
||||
[global_foo release]; // expected-error {{it is not safe to remove 'release' message on a global variable}} \
|
||||
// expected-error {{ARC forbids explicit message send}}
|
||||
[a dealloc];
|
||||
[a retain];
|
||||
[a retainCount]; // expected-error {{ARC forbids explicit message send of 'retainCount'}}
|
||||
|
|
Loading…
Reference in New Issue