forked from OSchip/llvm-project
Forbid the block and lambda copy-capture of __autoreleasing variables
in ARC, under the usual reasoning limiting the use of __autoreleasing. llvm-svn: 153725
This commit is contained in:
parent
678a53c350
commit
67cd5e094e
|
@ -1006,7 +1006,9 @@ operation has a weak-unavailable type.</p>
|
|||
<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
|
||||
|
|
|
@ -3270,6 +3270,9 @@ def warn_err_new_delete_object_array : Warning<
|
|||
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<
|
||||
|
|
|
@ -10087,6 +10087,17 @@ bool Sema::tryCaptureVariable(VarDecl *Var, SourceLocation Loc,
|
|||
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 @@ bool Sema::tryCaptureVariable(VarDecl *Var, SourceLocation Loc,
|
|||
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.
|
||||
|
|
|
@ -11,3 +11,8 @@ void takeBlock(void (^)(void));
|
|||
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}}
|
||||
}
|
||||
|
|
|
@ -30,3 +30,24 @@ void deduction(id obj) {
|
|||
} @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}}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue