diff options
author | Fariborz Jahanian <fjahanian@apple.com> | 2012-11-27 23:02:53 +0000 |
---|---|---|
committer | Fariborz Jahanian <fjahanian@apple.com> | 2012-11-27 23:02:53 +0000 |
commit | 82c458ea76bf8f0981e3d1b5070c0b0e5878d784 (patch) | |
tree | 1e5970626448a3183b607565ae355fa86956d644 /lib/Sema/SemaInit.cpp | |
parent | 7aa7eb9d0221bc67e2cd564e703a2427dc212b79 (diff) |
objective-C arc: load of a __weak object happens via call to
objc_loadWeak. This retains and autorelease the weakly-refereced
object. This hidden autorelease sometimes makes __weak variable alive even
after the weak reference is erased, because the object is still referenced
by an autorelease pool. This patch overcomes this behavior by loading a
weak object via call to objc_loadWeakRetained(), followng it by objc_release
at appropriate place, thereby removing the hidden autorelease. // rdar://10849570
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@168740 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaInit.cpp')
-rw-r--r-- | lib/Sema/SemaInit.cpp | 26 |
1 files changed, 19 insertions, 7 deletions
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 7ed3942332..5b7fb4656d 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -3846,14 +3846,15 @@ enum InvalidICRKind { IIK_okay, IIK_nonlocal, IIK_nonscalar }; /// Determines whether this expression is an acceptable ICR source. static InvalidICRKind isInvalidICRSource(ASTContext &C, Expr *e, - bool isAddressOf) { + bool isAddressOf, bool &isWeakAccess) { // Skip parens. e = e->IgnoreParens(); // Skip address-of nodes. if (UnaryOperator *op = dyn_cast<UnaryOperator>(e)) { if (op->getOpcode() == UO_AddrOf) - return isInvalidICRSource(C, op->getSubExpr(), /*addressof*/ true); + return isInvalidICRSource(C, op->getSubExpr(), /*addressof*/ true, + isWeakAccess); // Skip certain casts. } else if (CastExpr *ce = dyn_cast<CastExpr>(e)) { @@ -3862,7 +3863,7 @@ static InvalidICRKind isInvalidICRSource(ASTContext &C, Expr *e, case CK_BitCast: case CK_LValueBitCast: case CK_NoOp: - return isInvalidICRSource(C, ce->getSubExpr(), isAddressOf); + return isInvalidICRSource(C, ce->getSubExpr(), isAddressOf, isWeakAccess); case CK_ArrayToPointerDecay: return IIK_nonscalar; @@ -3876,6 +3877,11 @@ static InvalidICRKind isInvalidICRSource(ASTContext &C, Expr *e, // If we have a declaration reference, it had better be a local variable. } else if (isa<DeclRefExpr>(e)) { + // set isWeakAccess to true, to mean that there will be an implicit + // load which requires a cleanup. + if (e->getType().getObjCLifetime() == Qualifiers::OCL_Weak) + isWeakAccess = true; + if (!isAddressOf) return IIK_nonlocal; VarDecl *var = dyn_cast<VarDecl>(cast<DeclRefExpr>(e)->getDecl()); @@ -3885,10 +3891,11 @@ static InvalidICRKind isInvalidICRSource(ASTContext &C, Expr *e, // If we have a conditional operator, check both sides. } else if (ConditionalOperator *cond = dyn_cast<ConditionalOperator>(e)) { - if (InvalidICRKind iik = isInvalidICRSource(C, cond->getLHS(), isAddressOf)) + if (InvalidICRKind iik = isInvalidICRSource(C, cond->getLHS(), isAddressOf, + isWeakAccess)) return iik; - return isInvalidICRSource(C, cond->getRHS(), isAddressOf); + return isInvalidICRSource(C, cond->getRHS(), isAddressOf, isWeakAccess); // These are never scalar. } else if (isa<ArraySubscriptExpr>(e)) { @@ -3907,8 +3914,13 @@ static InvalidICRKind isInvalidICRSource(ASTContext &C, Expr *e, /// indirect copy/restore. static void checkIndirectCopyRestoreSource(Sema &S, Expr *src) { assert(src->isRValue()); - - InvalidICRKind iik = isInvalidICRSource(S.Context, src, false); + bool isWeakAccess = false; + InvalidICRKind iik = isInvalidICRSource(S.Context, src, false, isWeakAccess); + // If isWeakAccess to true, there will be an implicit + // load which requires a cleanup. + if (S.getLangOpts().ObjCAutoRefCount && isWeakAccess) + S.ExprNeedsCleanups = true; + if (iik == IIK_okay) return; S.Diag(src->getExprLoc(), diag::err_arc_nonlocal_writeback) |