]> granicus.if.org Git - clang/commitdiff
ARC writeback isn't supposed to apply to local indirect pointers,
authorJohn McCall <rjmccall@apple.com>
Mon, 27 Jun 2011 23:59:58 +0000 (23:59 +0000)
committerJohn McCall <rjmccall@apple.com>
Mon, 27 Jun 2011 23:59:58 +0000 (23:59 +0000)
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

lib/Sema/SemaInit.cpp
test/SemaObjC/arc.m
test/SemaObjCXX/arc-overloading.mm

index 9891500efaa3d7aa3253de945841f42b0345820d..16ba2a2910606084f25013c5d1b9c7b8f08d84c4 100644 (file)
@@ -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)
index 8d42d101ddac646ce1836673df5e50fdbbc3af71..1202a2654e8f62cc889cf993f98cb865ec9118a9 100644 (file)
@@ -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); }();
+}
index 8141171eaf432886ea64a517450b227a8f609f65..2bce4bc894f83e605a09c99a150db69482a4b9e3 100644 (file)
@@ -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