aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaInit.cpp
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2011-06-27 23:59:58 +0000
committerJohn McCall <rjmccall@apple.com>2011-06-27 23:59:58 +0000
commitc03fa498b9598fe88ef8fb97315f27d09e56aa50 (patch)
tree4b0ef596639d97fb7ca252b0ba65cafc34e13108 /lib/Sema/SemaInit.cpp
parent0c051221bd06fe1b24b9459292584e5264a131c5 (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.cpp33
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)