]> granicus.if.org Git - clang/commitdiff
objc-arc: diagnose assignment/cast of a weak-unavailable
authorFariborz Jahanian <fjahanian@apple.com>
Thu, 7 Jul 2011 18:55:47 +0000 (18:55 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Thu, 7 Jul 2011 18:55:47 +0000 (18:55 +0000)
object to a __weak object/type. // rdar://9732636.
This is objc side of things. objc++ side tbd.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@134624 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
include/clang/Sema/Sema.h
lib/Sema/SemaExpr.cpp
test/SemaObjC/arc-unavailable-for-weakref.m

index b2301e18d7637b7e1f4a2adf83a595b25b9b8b3a..2feb043946ec308f113a8cb681ad6c124c48e717 100644 (file)
@@ -2572,6 +2572,11 @@ def err_arc_weak_no_runtime : Error<
   "the current deployment target does not support automated __weak references">;
 def err_arc_unsupported_weak_class : Error<
   "class is incompatible with __weak references">;
+def err_arc_weak_unavailable_assign : Error<
+  "assignment of a weak-unavailable object to a __weak object">;
+def err_arc_cast_of_weak_unavailable : Error<
+  "cast of weak-unavailable object of type %0 to"
+  " a __weak object of type %1">;
 def err_arc_illegal_explicit_message : Error<
   "ARC forbids explicit message send of %0">;
 def err_arc_unused_init_message : Error<
index 30719c1c01c6da822d4e24b8874fdde30f712db5..8c68a1da44d029cca476a7d1e96eae143efc5274 100644 (file)
@@ -5426,6 +5426,10 @@ public:
     /// "id <XXX>" = "Foo *", where "Foo *" doesn't implement the XXX protocol.
     IncompatibleObjCQualifiedId,
 
+    /// IncompatibleObjCWeakRef - Assigning a weak-unavailable object to an
+    /// object with __weak qualifier.
+    IncompatibleObjCWeakRef,
+
     /// Incompatible - We reject this conversion outright, it is invalid to
     /// represent it in the AST.
     Incompatible
index 68b767b474fb742c9637f506954b7c8faf32423f..cf03684c673e3bc18b392fdf0b8c631afae68049 100644 (file)
@@ -4065,6 +4065,23 @@ ExprResult Sema::CheckCastTypes(SourceLocation CastStartLoc, SourceRange TyR,
           return ExprError();
         }
       }
+    } 
+    else {
+      QualType canCastType = 
+        Context.getCanonicalType(castType).getUnqualifiedType();
+        if (isa<ObjCObjectPointerType>(canCastType) &&
+            castType.getObjCLifetime() == Qualifiers::OCL_Weak &&
+            castExprType->isObjCObjectPointerType()) {
+          if (const ObjCObjectPointerType *ObjT =
+              castExprType->getAs<ObjCObjectPointerType>())
+            if (ObjT->getInterfaceDecl()->isArcWeakrefUnavailable()) {
+              Diag(castExpr->getLocStart(), 
+                   diag::err_arc_cast_of_weak_unavailable)
+                << castExprType << castType 
+                << castExpr->getSourceRange();
+              return ExprError();
+            }
+        }
     }
   }
   
@@ -5124,6 +5141,7 @@ Sema::AssignConvertType
 Sema::CheckAssignmentConstraints(QualType lhsType, ExprResult &rhs,
                                  CastKind &Kind) {
   QualType rhsType = rhs.get()->getType();
+  QualType origLhsType = lhsType;
 
   // Get canonical types.  We're not formatting these types, just comparing
   // them.
@@ -5278,7 +5296,17 @@ Sema::CheckAssignmentConstraints(QualType lhsType, ExprResult &rhs,
     // A* -> B*
     if (rhsType->isObjCObjectPointerType()) {
       Kind = CK_BitCast;
-      return checkObjCPointerTypesForAssignment(*this, lhsType, rhsType);
+      Sema::AssignConvertType result = 
+        checkObjCPointerTypesForAssignment(*this, lhsType, rhsType);
+      if (getLangOptions().ObjCAutoRefCount &&
+          result == Compatible && 
+          origLhsType.getObjCLifetime() == Qualifiers::OCL_Weak) {
+        if (const ObjCObjectPointerType *ObjT = 
+              rhsType->getAs<ObjCObjectPointerType>())
+          if (ObjT->getInterfaceDecl()->isArcWeakrefUnavailable())
+            result = IncompatibleObjCWeakRef;
+      }
+      return result;
     }
 
     // int or null -> A*
@@ -8679,6 +8707,9 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
   case IncompatibleVectors:
     DiagKind = diag::warn_incompatible_vectors;
     break;
+  case IncompatibleObjCWeakRef:
+    DiagKind = diag::err_arc_weak_unavailable_assign;
+    break;
   case Incompatible:
     DiagKind = diag::err_typecheck_convert_incompatible;
     isInvalid = true;
index 07a7e7b975662c16ae19a1717d7197cd92023b2c..734fa53472e5828815845a86f934609420d663d7 100644 (file)
@@ -14,5 +14,22 @@ int main() {
 
   id obj;
 
-  ns1 = (__weak sub *)obj; // expected-error {{class is incompatible with __weak references}}
+  ns1 = (__weak sub *)obj; // expected-error {{assignment of a weak-unavailable object to a __weak object}} \
+                           // expected-error {{class is incompatible with __weak references}}
 }
+
+// rdar://9732636
+__attribute__((objc_arc_weak_reference_unavailable))
+@interface NOWEAK
++ (id) new;
+@end
+
+NOWEAK * Test9732636() {
+  NOWEAK * strong1 = [NOWEAK new];
+  __weak id weak1;
+  weak1 = strong1; // expected-error {{assignment of a weak-unavailable object to a __weak object}}
+
+  __weak id weak2 = strong1; // expected-error {{assignment of a weak-unavailable object to a __weak object}}
+  return (__weak id)strong1; // expected-error {{cast of weak-unavailable object of type 'NOWEAK *' to a __weak object of type '__weak id'}}
+}
+