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(),