[cfe-commits] r153725 - in /cfe/trunk: docs/AutomaticReferenceCounting.html include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaExpr.cpp test/SemaObjC/arc-invalid.m test/SemaObjCXX/arc-0x.mm

John McCall rjmccall at apple.com
Thu Mar 29 22:23:48 PDT 2012


Author: rjmccall
Date: Fri Mar 30 00:23:48 2012
New Revision: 153725

URL: http://llvm.org/viewvc/llvm-project?rev=153725&view=rev
Log:
Forbid the block and lambda copy-capture of __autoreleasing variables
in ARC, under the usual reasoning limiting the use of __autoreleasing.

Modified:
    cfe/trunk/docs/AutomaticReferenceCounting.html
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/test/SemaObjC/arc-invalid.m
    cfe/trunk/test/SemaObjCXX/arc-0x.mm

Modified: cfe/trunk/docs/AutomaticReferenceCounting.html
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/AutomaticReferenceCounting.html?rev=153725&r1=153724&r2=153725&view=diff
==============================================================================
--- cfe/trunk/docs/AutomaticReferenceCounting.html (original)
+++ cfe/trunk/docs/AutomaticReferenceCounting.html Fri Mar 30 00:23:48 2012
@@ -1006,7 +1006,9 @@
 <h1>Storage duration of <tt>__autoreleasing</tt> objects</h1>
 
 <p>A program is ill-formed if it declares an <tt>__autoreleasing</tt>
-object of non-automatic storage duration.</p>
+object of non-automatic storage duration.  A program is ill-formed
+if it captures an <tt>__autoreleasing</tt> object in a block or,
+unless by reference, in a C++11 lambda.</p>
 
 <div class="rationale"><p>Rationale: autorelease pools are tied to the
 current thread and scope by their nature.  While it is possible to

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=153725&r1=153724&r2=153725&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Mar 30 00:23:48 2012
@@ -3270,6 +3270,9 @@
 def err_arc_autoreleasing_var : Error<
   "%select{__block variables|global variables|fields|ivars}0 cannot have "
   "__autoreleasing ownership">;
+def err_arc_autoreleasing_capture : Error<
+  "cannot capture __autoreleasing variable in a "
+  "%select{block|lambda by copy}0">;
 def err_arc_thread_ownership : Error<
   "thread-local variable has non-trivial ownership: type is %0">;
 def err_arc_indirect_no_ownership : Error<

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=153725&r1=153724&r2=153725&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Fri Mar 30 00:23:48 2012
@@ -10087,6 +10087,17 @@
         return true;
       }
 
+      // Forbid the block-capture of autoreleasing variables.
+      if (CaptureType.getObjCLifetime() == Qualifiers::OCL_Autoreleasing) {
+        if (BuildAndDiagnose) {
+          Diag(Loc, diag::err_arc_autoreleasing_capture)
+            << /*block*/ 0;
+          Diag(Var->getLocation(), diag::note_previous_decl)
+            << Var->getDeclName();
+        }
+        return true;
+      }
+
       if (HasBlocksAttr || CaptureType->isReferenceType()) {
         // Block capture by reference does not change the capture or
         // declaration reference types.
@@ -10179,6 +10190,16 @@
         if (!RefType->getPointeeType()->isFunctionType())
           CaptureType = RefType->getPointeeType();
       }
+
+      // Forbid the lambda copy-capture of autoreleasing variables.
+      if (CaptureType.getObjCLifetime() == Qualifiers::OCL_Autoreleasing) {
+        if (BuildAndDiagnose) {
+          Diag(Loc, diag::err_arc_autoreleasing_capture) << /*lambda*/ 1;
+          Diag(Var->getLocation(), diag::note_previous_decl)
+            << Var->getDeclName();
+        }
+        return true;
+      }
     }
 
     // Capture this variable in the lambda.

Modified: cfe/trunk/test/SemaObjC/arc-invalid.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/arc-invalid.m?rev=153725&r1=153724&r2=153725&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/arc-invalid.m (original)
+++ cfe/trunk/test/SemaObjC/arc-invalid.m Fri Mar 30 00:23:48 2012
@@ -11,3 +11,8 @@
 void test0(id p) {
   takeBlock(^{ [p foo] + p; }); // expected-error {{invalid operands to binary expression}}
 }
+
+void test1(void) {
+  __autoreleasing id p; // expected-note {{'p' declared here}}
+  takeBlock(^{ (void) p; }); // expected-error {{cannot capture __autoreleasing variable in a block}}
+}

Modified: cfe/trunk/test/SemaObjCXX/arc-0x.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/arc-0x.mm?rev=153725&r1=153724&r2=153725&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjCXX/arc-0x.mm (original)
+++ cfe/trunk/test/SemaObjCXX/arc-0x.mm Fri Mar 30 00:23:48 2012
@@ -30,3 +30,24 @@
   } @catch (auto e) { // expected-error {{'auto' not allowed in exception declaration}}
   }
 }
+
+// rdar://problem/11068137
+void test1a() {
+  __autoreleasing id p; // expected-note 2 {{'p' declared here}}
+  (void) [&p] {};
+  (void) [p] {}; // expected-error {{cannot capture __autoreleasing variable in a lambda by copy}}
+  (void) [=] { (void) p; }; // expected-error {{cannot capture __autoreleasing variable in a lambda by copy}}
+}
+void test1b() {
+  __autoreleasing id v;
+  __autoreleasing id &p = v; // expected-note 2 {{'p' declared here}}
+  (void) [&p] {};
+  (void) [p] {}; // expected-error {{cannot capture __autoreleasing variable in a lambda by copy}}
+  (void) [=] { (void) p; }; // expected-error {{cannot capture __autoreleasing variable in a lambda by copy}}
+}
+void test1c() {
+  __autoreleasing id v; // expected-note {{'v' declared here}}
+  __autoreleasing id &p = v;
+  (void) ^{ (void) p; };
+  (void) ^{ (void) v; }; // expected-error {{cannot capture __autoreleasing variable in a block}}
+}





More information about the cfe-commits mailing list