objc++-arc: more diagnosis of converting a weak-unavailable
object to a __weak object type. // rdar://9732636


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@134706 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 2feb043..d7b16cf 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2574,9 +2574,9 @@
   "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_convesion_of_weak_unavailable : Error<
+  "%select{implicit conversion|cast}0 of weak-unavailable object of type %1 to"
+  " a __weak object of type %2">;
 def err_arc_illegal_explicit_message : Error<
   "ARC forbids explicit message send of %0">;
 def err_arc_unused_init_message : Error<
diff --git a/lib/Sema/SemaCXXCast.cpp b/lib/Sema/SemaCXXCast.cpp
index 0721814..50e39e0 100644
--- a/lib/Sema/SemaCXXCast.cpp
+++ b/lib/Sema/SemaCXXCast.cpp
@@ -1774,15 +1774,8 @@
     }
   }
 
-  if (getLangOptions().ObjCAutoRefCount && tcr == TC_Success) {
+  if (getLangOptions().ObjCAutoRefCount && tcr == TC_Success)
     CheckObjCARCConversion(R, CastTy, CastExpr, CCK);
-    if (!CheckObjCARCUnavailableWeakConversion(CastTy, 
-                                               origCastExprType))
-      Diag(CastExpr->getLocStart(), 
-           diag::err_arc_cast_of_weak_unavailable)
-      << origCastExprType << CastTy 
-      << CastExpr->getSourceRange();
-  }
 
   if (tcr != TC_Success && msg != 0) {
     if (CastExpr->getType() == Context.OverloadTy) {
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index fea31aa..09c68ae 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -4068,7 +4068,7 @@
     } 
     else if (!CheckObjCARCUnavailableWeakConversion(castType, castExprType)) {
            Diag(castExpr->getLocStart(), 
-                diag::err_arc_cast_of_weak_unavailable)
+                diag::err_arc_convesion_of_weak_unavailable) << 1
                 << castExprType << castType 
                 << castExpr->getSourceRange();
           return ExprError();
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 4c096fe..7ee9c1b 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -2340,8 +2340,20 @@
       if (From->getType()->isObjCObjectPointerType() &&
           ToType->isObjCObjectPointerType())
         EmitRelatedResultTypeNote(From);
-    }
-
+    } 
+    else if (getLangOptions().ObjCAutoRefCount &&
+             !CheckObjCARCUnavailableWeakConversion(ToType, 
+                                                    From->getType())) {
+           if (Action == AA_Initializing)
+             Diag(From->getSourceRange().getBegin(), 
+                  diag::err_arc_weak_unavailable_assign);
+           else
+             Diag(From->getSourceRange().getBegin(),
+                  diag::err_arc_convesion_of_weak_unavailable) 
+                  << (Action == AA_Casting) << From->getType() << ToType 
+                  << From->getSourceRange();
+         }
+             
     CastKind Kind = CK_Invalid;
     CXXCastPath BasePath;
     if (CheckPointerConversion(From, ToType, Kind, BasePath, CStyle))
diff --git a/test/SemaObjC/arc-unavailable-for-weakref.m b/test/SemaObjC/arc-unavailable-for-weakref.m
index 734fa53..104314e 100644
--- a/test/SemaObjC/arc-unavailable-for-weakref.m
+++ b/test/SemaObjC/arc-unavailable-for-weakref.m
@@ -24,7 +24,7 @@
 + (id) new;
 @end
 
-NOWEAK * Test9732636() {
+NOWEAK * Test1() {
   NOWEAK * strong1 = [NOWEAK new];
   __weak id weak1;
   weak1 = strong1; // expected-error {{assignment of a weak-unavailable object to a __weak object}}
@@ -33,3 +33,15 @@
   return (__weak id)strong1; // expected-error {{cast of weak-unavailable object of type 'NOWEAK *' to a __weak object of type '__weak id'}}
 }
 
+@protocol P @end
+@protocol P1 @end
+
+NOWEAK<P, P1> * Test2() {
+  NOWEAK<P, P1> * strong1 = 0;
+  __weak id<P> weak1;
+  weak1 = strong1; // expected-error {{assignment of a weak-unavailable object to a __weak object}}
+
+  __weak id<P> weak2 = strong1; // expected-error {{assignment of a weak-unavailable object to a __weak object}}
+  return (__weak id<P>)strong1; // expected-error {{cast of weak-unavailable object of type 'NOWEAK<P,P1> *' to a __weak object of type '__weak id<P>'}}
+}
+
diff --git a/test/SemaObjCXX/arc-unavailable-for-weakref.mm b/test/SemaObjCXX/arc-unavailable-for-weakref.mm
index a22d797..a7b3570 100644
--- a/test/SemaObjCXX/arc-unavailable-for-weakref.mm
+++ b/test/SemaObjCXX/arc-unavailable-for-weakref.mm
@@ -24,13 +24,24 @@
 + (id) new;
 @end
 
-NOWEAK * Test9732636() {
+NOWEAK * Test1() {
   NOWEAK * strong1 = [NOWEAK new];
   __weak id weak1;
   weak1 = strong1; // expected-error {{assignment of a weak-unavailable object to a __weak object}}
 
-// FIXME. NYI.
-  __weak id weak2 = strong1; // expected-FIXME {{assignment of a weak-unavailable object to a __weak object}}
-  return (__weak id)strong1; // expected-error {{cast of weak-unavailable object of type 'NOWEAK *__strong' to a __weak object of type '__weak id'}}
+  __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'}}
+}
+
+@protocol P @end
+@protocol P1 @end
+
+NOWEAK<P, P1> * Test2() {
+  NOWEAK<P, P1> * strong1 = 0;
+  __weak id<P> weak1;
+  weak1 = strong1; // expected-error {{assignment of a weak-unavailable object to a __weak object}}
+
+  __weak id<P> weak2 = strong1; // expected-error {{assignment of a weak-unavailable object to a __weak object}}
+  return (__weak id<P, P1>)strong1; // expected-error {{cast of weak-unavailable object of type 'NOWEAK<P,P1> *' to a __weak object of type '__weak id<P,P1>'}}
 }