[arcmt] Don't remove retains/releases on a global variable, flag them with errors. rdar://9402555.

llvm-svn: 135213
This commit is contained in:
Argyrios Kyrtzidis 2011-07-14 23:32:04 +00:00
parent 4771159f9f
commit f2a27f40d6
5 changed files with 28 additions and 11 deletions

View File

@ -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;

View File

@ -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

View File

@ -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> {

View File

@ -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> > {

View File

@ -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'}}