r299648 - [ObjC++] Conversions from specialized to non-specialized Objective-C generic
Alex Lorenz via cfe-commits
cfe-commits at lists.llvm.org
Thu Apr 6 06:06:34 PDT 2017
Author: arphaman
Date: Thu Apr 6 08:06:34 2017
New Revision: 299648
URL: http://llvm.org/viewvc/llvm-project?rev=299648&view=rev
Log:
[ObjC++] Conversions from specialized to non-specialized Objective-C generic
object types should be preferred over conversions to other object pointers
This change ensures that Clang will select the correct overload for the
following code sample:
void overload(Base *b);
void overload(Derived *d);
void test(Base<Base *> b) {
overload(b); // Select overload(Base *), not overload(Derived *)
}
rdar://20124827
Differential Revision: https://reviews.llvm.org/D31597
Modified:
cfe/trunk/lib/Sema/SemaOverload.cpp
cfe/trunk/test/SemaObjCXX/overload.mm
Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=299648&r1=299647&r2=299648&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Thu Apr 6 08:06:34 2017
@@ -4047,7 +4047,7 @@ CompareDerivedToBaseConversions(Sema &S,
= S.Context.canAssignObjCInterfaces(ToPtr1, ToPtr2);
bool ToAssignRight
= S.Context.canAssignObjCInterfaces(ToPtr2, ToPtr1);
-
+
// A conversion to an a non-id object pointer type or qualified 'id'
// type is better than a conversion to 'id'.
if (ToPtr1->isObjCIdType() &&
@@ -4081,11 +4081,25 @@ CompareDerivedToBaseConversions(Sema &S,
return ImplicitConversionSequence::Better;
// -- "conversion of C* to B* is better than conversion of C* to A*,"
- if (S.Context.hasSameType(FromType1, FromType2) &&
+ if (S.Context.hasSameType(FromType1, FromType2) &&
!FromPtr1->isObjCIdType() && !FromPtr1->isObjCClassType() &&
- (ToAssignLeft != ToAssignRight))
+ (ToAssignLeft != ToAssignRight)) {
+ if (FromPtr1->isSpecialized()) {
+ // "conversion of B<A> * to B * is better than conversion of B * to
+ // C *.
+ bool IsFirstSame =
+ FromPtr1->getInterfaceDecl() == ToPtr1->getInterfaceDecl();
+ bool IsSecondSame =
+ FromPtr1->getInterfaceDecl() == ToPtr2->getInterfaceDecl();
+ if (IsFirstSame) {
+ if (!IsSecondSame)
+ return ImplicitConversionSequence::Better;
+ } else if (IsSecondSame)
+ return ImplicitConversionSequence::Worse;
+ }
return ToAssignLeft? ImplicitConversionSequence::Worse
: ImplicitConversionSequence::Better;
+ }
// -- "conversion of B* to A* is better than conversion of C* to A*,"
if (S.Context.hasSameUnqualifiedType(ToType1, ToType2) &&
Modified: cfe/trunk/test/SemaObjCXX/overload.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/overload.mm?rev=299648&r1=299647&r2=299648&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjCXX/overload.mm (original)
+++ cfe/trunk/test/SemaObjCXX/overload.mm Thu Apr 6 08:06:34 2017
@@ -174,3 +174,30 @@ namespace class_id {
void f(Class) { }
void f(id) { }
}
+
+ at interface NSDictionary<__covariant KeyType, __covariant ObjectType> : A
+ at end
+
+ at interface NSMutableDictionary<KeyType, ObjectType> : NSDictionary<KeyType, ObjectType>
+ at end
+
+namespace rdar20124827 {
+
+int overload(NSDictionary *) { return 1; }
+
+__attribute__((deprecated)) // expected-note {{'overload' has been explicitly marked deprecated here}}
+int overload(NSMutableDictionary *) { return 0; }
+
+__attribute__((deprecated))
+void overload2(NSDictionary *); // expected-note {{candidate function}}
+void overload2(NSDictionary<A *, A *> *); // expected-note {{candidate function}}
+
+void test(NSDictionary *d1, NSDictionary<A *, A *> *d2, NSMutableDictionary<A *, A *> *m1) {
+ overload(d1);
+ overload(d2); // no warning
+ overload(m1); // expected-warning {{'overload' is deprecated}}
+ overload2(d2); // no warning
+ overload2(m1); // expected-error {{call to 'overload2' is ambiguous}}
+}
+
+}
More information about the cfe-commits
mailing list