diff options
author | John McCall <rjmccall@apple.com> | 2011-06-27 23:59:58 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2011-06-27 23:59:58 +0000 |
commit | c03fa498b9598fe88ef8fb97315f27d09e56aa50 (patch) | |
tree | 4b0ef596639d97fb7ca252b0ba65cafc34e13108 /lib/Sema/SemaInit.cpp | |
parent | 0c051221bd06fe1b24b9459292584e5264a131c5 (diff) |
ARC writeback isn't supposed to apply to local indirect pointers,
only to pointers to locals. But it should work inside blocks, too.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@133969 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaInit.cpp')
-rw-r--r-- | lib/Sema/SemaInit.cpp | 33 |
1 files changed, 21 insertions, 12 deletions
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 9891500efa..16ba2a2910 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -3195,24 +3195,24 @@ static void TryUserDefinedConversion(Sema &S, enum InvalidICRKind { IIK_okay, IIK_nonlocal, IIK_nonscalar }; /// Determines whether this expression is an acceptable ICR source. -static InvalidICRKind isInvalidICRSource(ASTContext &C, Expr *e) { +static InvalidICRKind isInvalidICRSource(ASTContext &C, Expr *e, + bool isAddressOf) { // 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()); + return isInvalidICRSource(C, op->getSubExpr(), /*addressof*/ true); // Skip certain casts. - } else if (CastExpr *cast = dyn_cast<CastExpr>(e)) { - switch (cast->getCastKind()) { + } else if (CastExpr *ce = dyn_cast<CastExpr>(e)) { + switch (ce->getCastKind()) { case CK_Dependent: case CK_BitCast: case CK_LValueBitCast: - case CK_LValueToRValue: case CK_NoOp: - return isInvalidICRSource(C, cast->getSubExpr()); + return isInvalidICRSource(C, ce->getSubExpr(), isAddressOf); case CK_ArrayToPointerDecay: return IIK_nonscalar; @@ -3225,16 +3225,25 @@ static InvalidICRKind isInvalidICRSource(ASTContext &C, Expr *e) { } // If we have a declaration reference, it had better be a local variable. - } else if (DeclRefExpr *declRef = dyn_cast<DeclRefExpr>(e)) { - if (VarDecl *var = dyn_cast<VarDecl>(declRef->getDecl())) - return (var->hasLocalStorage() ? IIK_okay : IIK_nonlocal); + } else if (isa<DeclRefExpr>(e) || isa<BlockDeclRefExpr>(e)) { + if (!isAddressOf) return IIK_nonlocal; + + VarDecl *var; + if (isa<DeclRefExpr>(e)) { + var = dyn_cast<VarDecl>(cast<DeclRefExpr>(e)->getDecl()); + if (!var) return IIK_nonlocal; + } else { + var = cast<BlockDeclRefExpr>(e)->getDecl(); + } + + return (var->hasLocalStorage() ? IIK_okay : IIK_nonlocal); // If we have a conditional operator, check both sides. } else if (ConditionalOperator *cond = dyn_cast<ConditionalOperator>(e)) { - if (InvalidICRKind iik = isInvalidICRSource(C, cond->getLHS())) + if (InvalidICRKind iik = isInvalidICRSource(C, cond->getLHS(), isAddressOf)) return iik; - return isInvalidICRSource(C, cond->getRHS()); + return isInvalidICRSource(C, cond->getRHS(), isAddressOf); // These are never scalar. } else if (isa<ArraySubscriptExpr>(e)) { @@ -3254,7 +3263,7 @@ static InvalidICRKind isInvalidICRSource(ASTContext &C, Expr *e) { static void checkIndirectCopyRestoreSource(Sema &S, Expr *src) { assert(src->isRValue()); - InvalidICRKind iik = isInvalidICRSource(S.Context, src); + InvalidICRKind iik = isInvalidICRSource(S.Context, src, false); if (iik == IIK_okay) return; S.Diag(src->getExprLoc(), diag::err_arc_nonlocal_writeback) |