]> granicus.if.org Git - clang/commitdiff
ARC: make assignment to 'self' within class methods illegal. Fixes <rdar://problem...
authorTed Kremenek <kremenek@apple.com>
Mon, 14 Nov 2011 21:59:25 +0000 (21:59 +0000)
committerTed Kremenek <kremenek@apple.com>
Mon, 14 Nov 2011 21:59:25 +0000 (21:59 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@144572 91177308-0d34-0410-b5e6-96231b3b80d8

docs/AutomaticReferenceCounting.html
include/clang/Basic/DiagnosticSemaKinds.td
lib/AST/DeclObjC.cpp
lib/Sema/SemaExpr.cpp

index ab7debf20c1b3956752a9c0d330ec8d2c71cd5ed..0265bbdd385643ed685a535a3acba189039514f3 100644 (file)
@@ -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
index ad175e465fcdab4b760500926870a56e44ad3fa0..312ea824588ce10bef38420883230c2db9ce6284 100644 (file)
@@ -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">;
index 35ee7c6ccdb4f735d316d8fa7eb8b82158f624c3..766b673bde616058ad538d5e6ac00b8eea786594 100644 (file)
@@ -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;
     }
index d22a431d065e50d1cc4a37990e4b821475d45d8e..4f2f8c4eafd55c647e92173b5afc63bbcec5cdd0 100644 (file)
@@ -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