forked from OSchip/llvm-project
ARC: make assignment to 'self' within class methods illegal. Fixes <rdar://problem/10416568>.
llvm-svn: 144572
This commit is contained in:
parent
8e7fbcc3e4
commit
1fcdaa9c05
|
@ -1482,9 +1482,12 @@ implementation.</p></div>
|
|||
<p>The <tt>self</tt> parameter variable of an Objective-C method is
|
||||
never actually retained by the implementation. It is undefined
|
||||
behavior, or at least dangerous, to cause an object to be deallocated
|
||||
during a message send to that object. To make this
|
||||
safe, <tt>self</tt> is implicitly <tt>const</tt> unless the method is
|
||||
in the <a href="#family.semantics.init"><tt>init</tt> family</a>.</p>
|
||||
during a message send to that object.</p>
|
||||
|
||||
<p>To make this safe, for Objective-C instance methods <tt>self</tt> is
|
||||
implicitly <tt>const</tt> unless the method is in the <a
|
||||
href="#family.semantics.init"><tt>init</tt> family</a>. Further, <tt>self</tt>
|
||||
is <b>always</b> implicitly <tt>const</tt> within a class method.</p>
|
||||
|
||||
<div class="rationale"><p>Rationale: the cost of
|
||||
retaining <tt>self</tt> in all methods was found to be prohibitive, as
|
||||
|
|
|
@ -3078,8 +3078,10 @@ def note_arc_gained_method_convention : Note<
|
|||
"declaration in interface is not in the '%select{alloc|copy|init|new}0' "
|
||||
"family because %select{its result type is not an object pointer|"
|
||||
"its result type is unrelated to its receiver type}1">;
|
||||
def err_typecheck_arr_assign_self : Error<
|
||||
def err_typecheck_arc_assign_self : Error<
|
||||
"cannot assign to 'self' outside of a method in the init family">;
|
||||
def err_typecheck_arc_assign_self_class_method : Error<
|
||||
"cannot assign to 'self' in a class method">;
|
||||
def err_typecheck_arr_assign_enumeration : Error<
|
||||
"fast enumeration variables can't be modified in ARC by default; "
|
||||
"declare the variable __strong to allow this">;
|
||||
|
|
|
@ -580,17 +580,26 @@ void ObjCMethodDecl::createImplicitParams(ASTContext &Context,
|
|||
|
||||
bool selfIsPseudoStrong = false;
|
||||
bool selfIsConsumed = false;
|
||||
if (isInstanceMethod() && Context.getLangOptions().ObjCAutoRefCount) {
|
||||
selfIsConsumed = hasAttr<NSConsumesSelfAttr>();
|
||||
|
||||
if (Context.getLangOptions().ObjCAutoRefCount) {
|
||||
if (isInstanceMethod()) {
|
||||
selfIsConsumed = hasAttr<NSConsumesSelfAttr>();
|
||||
|
||||
// 'self' is always __strong. It's actually pseudo-strong except
|
||||
// in init methods (or methods labeled ns_consumes_self), though.
|
||||
Qualifiers qs;
|
||||
qs.setObjCLifetime(Qualifiers::OCL_Strong);
|
||||
selfTy = Context.getQualifiedType(selfTy, qs);
|
||||
// 'self' is always __strong. It's actually pseudo-strong except
|
||||
// in init methods (or methods labeled ns_consumes_self), though.
|
||||
Qualifiers qs;
|
||||
qs.setObjCLifetime(Qualifiers::OCL_Strong);
|
||||
selfTy = Context.getQualifiedType(selfTy, qs);
|
||||
|
||||
// In addition, 'self' is const unless this is an init method.
|
||||
if (getMethodFamily() != OMF_init && !selfIsConsumed) {
|
||||
// In addition, 'self' is const unless this is an init method.
|
||||
if (getMethodFamily() != OMF_init && !selfIsConsumed) {
|
||||
selfTy = selfTy.withConst();
|
||||
selfIsPseudoStrong = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
assert(isClassMethod());
|
||||
// 'self' is always const in class methods.
|
||||
selfTy = selfTy.withConst();
|
||||
selfIsPseudoStrong = true;
|
||||
}
|
||||
|
|
|
@ -7063,7 +7063,9 @@ static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) {
|
|||
// - self
|
||||
ObjCMethodDecl *method = S.getCurMethodDecl();
|
||||
if (method && var == method->getSelfDecl())
|
||||
Diag = diag::err_typecheck_arr_assign_self;
|
||||
Diag = method->isClassMethod()
|
||||
? diag::err_typecheck_arc_assign_self_class_method
|
||||
: diag::err_typecheck_arc_assign_self;
|
||||
|
||||
// - fast enumeration variables
|
||||
else
|
||||
|
|
Loading…
Reference in New Issue