summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2013-11-08 02:04:24 +0000
committerDouglas Gregor <dgregor@apple.com>2013-11-08 02:04:24 +0000
commitc9f019ab0f95eca0c02da99ec9e555670e189aa5 (patch)
tree622127415ebdace7afcc8982f0d34cc4e1b5b596 /clang
parent22626e7b4997a58ea1dc4a6e0bf3ed7b9dfabf83 (diff)
downloadbcm5719-llvm-c9f019ab0f95eca0c02da99ec9e555670e189aa5.tar.gz
bcm5719-llvm-c9f019ab0f95eca0c02da99ec9e555670e189aa5.zip
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>. llvm-svn: 194239
Diffstat (limited to 'clang')
-rw-r--r--clang/lib/Sema/SemaOverload.cpp19
-rw-r--r--clang/lib/Sema/SemaTemplateDeduction.cpp17
-rw-r--r--clang/test/SemaObjCXX/arc-templates.mm10
3 files changed, 37 insertions, 9 deletions
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index acfa8a3ac74..2c2cfd03b17 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -2790,6 +2790,18 @@ bool Sema::CheckMemberPointerConversion(Expr *From, QualType ToType,
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 FromType, QualType ToType,
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(SourceLocation Loc,
// 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)
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 6e510c2dbcb..b401db21a82 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -2687,13 +2687,16 @@ CheckOriginalCallArgDeduction(Sema &S, Sema::OriginalCallArg OriginalArg,
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, Sema::OriginalCallArg OriginalArg,
//
// 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()) &&
diff --git a/clang/test/SemaObjCXX/arc-templates.mm b/clang/test/SemaObjCXX/arc-templates.mm
index ef68b94e728..b3519b95737 100644
--- a/clang/test/SemaObjCXX/arc-templates.mm
+++ b/clang/test/SemaObjCXX/arc-templates.mm
@@ -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);
+ }
+}
OpenPOWER on IntegriCloud