diff options
-rw-r--r-- | docs/AutomaticReferenceCounting.html | 9 | ||||
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 4 | ||||
-rw-r--r-- | lib/AST/DeclObjC.cpp | 31 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 4 |
4 files changed, 32 insertions, 16 deletions
diff --git a/docs/AutomaticReferenceCounting.html b/docs/AutomaticReferenceCounting.html index ab7debf20c..0265bbdd38 100644 --- a/docs/AutomaticReferenceCounting.html +++ b/docs/AutomaticReferenceCounting.html @@ -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 diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index ad175e465f..312ea82458 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -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">; diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp index 35ee7c6ccd..766b673bde 100644 --- a/lib/AST/DeclObjC.cpp +++ b/lib/AST/DeclObjC.cpp @@ -580,17 +580,26 @@ void ObjCMethodDecl::createImplicitParams(ASTContext &Context, bool selfIsPseudoStrong = false; bool selfIsConsumed = false; - if (isInstanceMethod() && Context.getLangOptions().ObjCAutoRefCount) { - 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); - - // In addition, 'self' is const unless this is an init method. - if (getMethodFamily() != OMF_init && !selfIsConsumed) { + + 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); + + // 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; } diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index d22a431d06..4f2f8c4eaf 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -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 |