Allow downcasts of pointers to Objective-C interfaces, with a
warning. This matches GCC's behavior and addresses
<rdar://problem/6458293>.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@61246 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 3671711..f03c7a4 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -419,6 +419,7 @@
   // Standard conversions (C++ [conv])
   SCS.setAsIdentityConversion();
   SCS.Deprecated = false;
+  SCS.IncompatibleObjC = false;
   SCS.FromTypePtr = FromType.getAsOpaquePtr();
   SCS.CopyConstructor = 0;
 
@@ -494,6 +495,7 @@
   // point promotion, integral conversion, floating point conversion,
   // floating-integral conversion, pointer conversion,
   // pointer-to-member conversion, or boolean conversion (C++ 4p1).
+  bool IncompatibleObjC = false;
   if (Context.getCanonicalType(FromType).getUnqualifiedType() ==
       Context.getCanonicalType(ToType).getUnqualifiedType()) {
     // The unqualified versions of the types are the same: there's no
@@ -533,8 +535,10 @@
     FromType = ToType.getUnqualifiedType();
   }
   // Pointer conversions (C++ 4.10).
-  else if (IsPointerConversion(From, FromType, ToType, FromType)) {
+  else if (IsPointerConversion(From, FromType, ToType, FromType, 
+                               IncompatibleObjC)) {
     SCS.Second = ICK_Pointer_Conversion;
+    SCS.IncompatibleObjC = IncompatibleObjC;
   }
   // FIXME: Pointer to member conversions (4.11).
   // Boolean conversions (C++ 4.12).
@@ -751,10 +755,15 @@
 /// appropriate overloading rules for Objective-C, we may want to
 /// split the Objective-C checks into a different routine; however,
 /// GCC seems to consider all of these conversions to be pointer
-/// conversions, so for now they live here.
+/// conversions, so for now they live here. IncompatibleObjC will be
+/// set if the conversion is an allowed Objective-C conversion that
+/// should result in a warning.
 bool Sema::IsPointerConversion(Expr *From, QualType FromType, QualType ToType,
-                               QualType& ConvertedType)
+                               QualType& ConvertedType,
+                               bool &IncompatibleObjC)
 {
+  IncompatibleObjC = false;
+
   // Blocks: Block pointers can be converted to void*.
   if (FromType->isBlockPointerType() && ToType->isPointerType() &&
       ToType->getAsPointerType()->getPointeeType()->isVoidType()) {
@@ -836,6 +845,18 @@
     return true;
   }
 
+  if (FromIface && ToIface && 
+      Context.canAssignObjCInterfaces(FromIface, ToIface)) {
+    // Okay: this is some kind of implicit downcast of Objective-C
+    // interfaces, which is permitted. However, we're going to
+    // complain about it.
+    IncompatibleObjC = true;
+    ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr, 
+                                                       ToPointeeType,
+                                                       ToType, Context);
+    return true;
+  }
+
   // Objective C++: We're able to convert between "id" and a pointer
   // to any interface (in both directions).
   if ((FromIface && Context.isObjCIdType(ToPointeeType))
@@ -1533,7 +1554,7 @@
   if (ToType->isReferenceType())
     return CheckReferenceInit(From, ToType);
 
-  if (!PerformImplicitConversion(From, ToType))
+  if (!PerformImplicitConversion(From, ToType, Flavor))
     return false;
   
   return Diag(From->getSourceRange().getBegin(),