From: John McCall Date: Mon, 27 Jun 2011 23:59:58 +0000 (+0000) Subject: ARC writeback isn't supposed to apply to local indirect pointers, X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c03fa498b9598fe88ef8fb97315f27d09e56aa50;p=clang 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 --- 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(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(e)) { - switch (cast->getCastKind()) { + } else if (CastExpr *ce = dyn_cast(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(e)) { - if (VarDecl *var = dyn_cast(declRef->getDecl())) - return (var->hasLocalStorage() ? IIK_okay : IIK_nonlocal); + } else if (isa(e) || isa(e)) { + if (!isAddressOf) return IIK_nonlocal; + + VarDecl *var; + if (isa(e)) { + var = dyn_cast(cast(e)->getDecl()); + if (!var) return IIK_nonlocal; + } else { + var = cast(e)->getDecl(); + } + + return (var->hasLocalStorage() ? IIK_okay : IIK_nonlocal); // If we have a conditional operator, check both sides. } else if (ConditionalOperator *cond = dyn_cast(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(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) diff --git a/test/SemaObjC/arc.m b/test/SemaObjC/arc.m index 8d42d101dd..1202a2654e 100644 --- a/test/SemaObjC/arc.m +++ b/test/SemaObjC/arc.m @@ -592,3 +592,16 @@ int Test33(id someid) { @synthesize newName2; @end +void test35(void) { + extern void test36_helper(id*); + id x; + __strong id *xp = 0; + + test36_helper(&x); + test36_helper(xp); // expected-error {{passing address of non-local object to __autoreleasing parameter for write-back}} + + // rdar://problem/9665710 + __block id y; + test36_helper(&y); + ^{ test36_helper(&y); }(); +} diff --git a/test/SemaObjCXX/arc-overloading.mm b/test/SemaObjCXX/arc-overloading.mm index 8141171eaf..2bce4bc894 100644 --- a/test/SemaObjCXX/arc-overloading.mm +++ b/test/SemaObjCXX/arc-overloading.mm @@ -58,15 +58,15 @@ void test_f2() { int &f3(id __autoreleasing *); // expected-note{{candidate function not viable: 1st argument ('__unsafe_unretained id *') has __unsafe_unretained ownership, but parameter has __autoreleasing ownership}} void test_f3() { - id __strong *sip; - id __weak *wip; - id __autoreleasing *aip; - id __unsafe_unretained *uip; - - int &ir1 = f3(sip); - int &ir2 = f3(wip); - int &ir3 = f3(aip); - f3(uip); // expected-error{{no matching function for call to 'f3'}} + id __strong sip; + id __weak wip; + id __autoreleasing aip; + id __unsafe_unretained uip; + + int &ir1 = f3(&sip); + int &ir2 = f3(&wip); + int &ir3 = f3(&aip); + f3(&uip); // expected-error{{no matching function for call to 'f3'}} } // Writeback conversion vs. no conversion @@ -74,15 +74,15 @@ int &f4(id __autoreleasing *); float &f4(id __strong *); void test_f4() { - id __strong *sip; - id __weak *wip; - id __autoreleasing *aip; - extern __weak id *weak_global_ptr; - - float &fr1 = f4(sip); - int &ir1 = f4(wip); - int &ir2 = f4(aip); - int &ir3 = f4(weak_global_ptr); // expected-error{{passing address of non-local object to __autoreleasing parameter for write-back}} + id __strong sip; + id __weak wip; + id __autoreleasing aip; + extern __weak id weak_global_ptr; + + float &fr1 = f4(&sip); + int &ir1 = f4(&wip); + int &ir2 = f4(&aip); + int &ir3 = f4(&weak_global_ptr); // expected-error{{passing address of non-local object to __autoreleasing parameter for write-back}} } // Writeback conversion vs. other conversion. @@ -90,13 +90,13 @@ int &f5(id __autoreleasing *); float &f5(id const __unsafe_unretained *); void test_f5() { - id __strong *sip; - id __weak *wip; - id __autoreleasing *aip; + id __strong sip; + id __weak wip; + id __autoreleasing aip; - int &ir1 = f5(wip); - float &fr1 = f5(sip); - int &ir2 = f5(aip); + int &ir1 = f5(&wip); + float &fr1 = f5(&sip); + int &ir2 = f5(&aip); } @interface A @@ -106,13 +106,13 @@ int &f6(id __autoreleasing *); float &f6(id const __unsafe_unretained *); void test_f6() { - A* __strong *sip; - A* __weak *wip; - A* __autoreleasing *aip; + A* __strong sip; + A* __weak wip; + A* __autoreleasing aip; - int &ir1 = f6(wip); - float &fr1 = f6(sip); - int &ir2 = f6(aip); + int &ir1 = f6(&wip); + float &fr1 = f6(&sip); + int &ir2 = f6(&aip); } // Reference binding