r194239 - Objective-C++ ARC: Improve the conversion to a const __unsafe_unretained reference.
Douglas Gregor
dgregor at apple.com
Thu Nov 7 18:04:25 PST 2013
Author: dgregor
Date: Thu Nov 7 20:04:24 2013
New Revision: 194239
URL: http://llvm.org/viewvc/llvm-project?rev=194239&view=rev
Log:
Objective-C++ ARC: Improve the conversion to a const __unsafe_unretained reference.
Under ARC++, a reference to a const Objective-C pointer is implicitly
treated as __unsafe_unretained, and can be initialized with (e.g.) a
__strong lvalue. Make sure this behavior does not break template
argument deduction and (related) that partial ordering still prefers a
'T* const&' template over a 'T const&' template when this case kicks
in. Fixes <rdar://problem/14467941>.
Modified:
cfe/trunk/lib/Sema/SemaOverload.cpp
cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
cfe/trunk/test/SemaObjCXX/arc-templates.mm
Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=194239&r1=194238&r2=194239&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Thu Nov 7 20:04:24 2013
@@ -2790,6 +2790,18 @@ bool Sema::CheckMemberPointerConversion(
return false;
}
+/// Determine whether the lifetime conversion between the two given
+/// qualifiers sets is nontrivial.
+static bool isNonTrivialObjCLifetimeConversion(Qualifiers FromQuals,
+ Qualifiers ToQuals) {
+ // Converting anything to const __unsafe_unretained is trivial.
+ if (ToQuals.hasConst() &&
+ ToQuals.getObjCLifetime() == Qualifiers::OCL_ExplicitNone)
+ return false;
+
+ return true;
+}
+
/// IsQualificationConversion - Determines whether the conversion from
/// an rvalue of type FromType to ToType is a qualification conversion
/// (C++ 4.4).
@@ -2831,7 +2843,8 @@ Sema::IsQualificationConversion(QualType
if (FromQuals.getObjCLifetime() != ToQuals.getObjCLifetime() &&
UnwrappedAnyPointer) {
if (ToQuals.compatiblyIncludesObjCLifetime(FromQuals)) {
- ObjCLifetimeConversion = true;
+ if (isNonTrivialObjCLifetimeConversion(FromQuals, ToQuals))
+ ObjCLifetimeConversion = true;
FromQuals.removeObjCLifetime();
ToQuals.removeObjCLifetime();
} else {
@@ -3996,9 +4009,11 @@ Sema::CompareReferenceRelationship(Sourc
// space 2.
if (T1Quals.getObjCLifetime() != T2Quals.getObjCLifetime() &&
T1Quals.compatiblyIncludesObjCLifetime(T2Quals)) {
+ if (isNonTrivialObjCLifetimeConversion(T2Quals, T1Quals))
+ ObjCLifetimeConversion = true;
+
T1Quals.removeObjCLifetime();
T2Quals.removeObjCLifetime();
- ObjCLifetimeConversion = true;
}
if (T1Quals == T2Quals)
Modified: cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp?rev=194239&r1=194238&r2=194239&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp Thu Nov 7 20:04:24 2013
@@ -2687,13 +2687,16 @@ CheckOriginalCallArgDeduction(Sema &S, S
Qualifiers AQuals = A.getQualifiers();
Qualifiers DeducedAQuals = DeducedA.getQualifiers();
- // Under Objective-C++ ARC, the deduced type may have implicitly been
- // given strong lifetime. If so, update the original qualifiers to
- // include this strong lifetime.
+ // Under Objective-C++ ARC, the deduced type may have implicitly
+ // been given strong or (when dealing with a const reference)
+ // unsafe_unretained lifetime. If so, update the original
+ // qualifiers to include this lifetime.
if (S.getLangOpts().ObjCAutoRefCount &&
- DeducedAQuals.getObjCLifetime() == Qualifiers::OCL_Strong &&
- AQuals.getObjCLifetime() == Qualifiers::OCL_None) {
- AQuals.setObjCLifetime(Qualifiers::OCL_Strong);
+ ((DeducedAQuals.getObjCLifetime() == Qualifiers::OCL_Strong &&
+ AQuals.getObjCLifetime() == Qualifiers::OCL_None) ||
+ (DeducedAQuals.hasConst() &&
+ DeducedAQuals.getObjCLifetime() == Qualifiers::OCL_ExplicitNone))) {
+ AQuals.setObjCLifetime(DeducedAQuals.getObjCLifetime());
}
if (AQuals == DeducedAQuals) {
@@ -2714,7 +2717,7 @@ CheckOriginalCallArgDeduction(Sema &S, S
//
// Also allow conversions which merely strip [[noreturn]] from function types
// (recursively) as an extension.
- // FIXME: Currently, this doesn't place nicely with qualfication conversions.
+ // FIXME: Currently, this doesn't play nicely with qualification conversions.
bool ObjCLifetimeConversion = false;
QualType ResultTy;
if ((A->isAnyPointerType() || A->isMemberPointerType()) &&
Modified: cfe/trunk/test/SemaObjCXX/arc-templates.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/arc-templates.mm?rev=194239&r1=194238&r2=194239&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjCXX/arc-templates.mm (original)
+++ cfe/trunk/test/SemaObjCXX/arc-templates.mm Thu Nov 7 20:04:24 2013
@@ -292,3 +292,13 @@ namespace rdar12367446 {
A<id()> value;
}
}
+
+namespace rdar14467941 {
+ template<typename T> int &takePtr(const T &);
+ template<typename T> float &takePtr(T * const &);
+
+ void testTakePtr(A *a) {
+ float &fr1 = takePtr(a);
+ float &fr2 = takePtr<A>(a);
+ }
+}
More information about the cfe-commits
mailing list