Implement ranking of standard conversion sequences by their qualification
conversions (e.g., comparing int* -> const int* against
int* -> const volatile int*); see C++ 13.3.3.2p3 bullet 3.
Add Sema::UnwrapSimilarPointerTypes to simplify the control flow of
IsQualificationConversion and CompareQualificationConversion (and fix
the handling of the int* -> volatile int* conversion in the former).
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@57978 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 6d01709..8e44025 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -659,46 +659,32 @@
// A conversion can add cv-qualifiers at levels other than the first
// in multi-level pointers, subject to the following rules: [...]
bool PreviousToQualsIncludeConst = true;
- bool UnwrappedPointer;
bool UnwrappedAnyPointer = false;
- do {
+ while (UnwrapSimilarPointerTypes(FromType, ToType)) {
// Within each iteration of the loop, we check the qualifiers to
// determine if this still looks like a qualification
// conversion. Then, if all is well, we unwrap one more level of
// pointers (FIXME: or pointers-to-members) and do it all again
// until there are no more pointers or pointers-to-members left to
// unwrap.
- UnwrappedPointer = false;
-
- // -- the pointer types are similar.
- const PointerType *FromPtrType = FromType->getAsPointerType(),
- *ToPtrType = ToType->getAsPointerType();
- if (FromPtrType && ToPtrType) {
- // The pointer types appear similar. Look at their pointee types.
- FromType = FromPtrType->getPointeeType();
- ToType = ToPtrType->getPointeeType();
- UnwrappedPointer = true;
- UnwrappedAnyPointer = true;
- }
-
- // FIXME: Cope with pointer-to-member types.
+ UnwrappedAnyPointer = true;
// -- for every j > 0, if const is in cv 1,j then const is in cv
// 2,j, and similarly for volatile.
if (!ToType.isAtLeastAsQualifiedAs(FromType))
return false;
-
+
// -- if the cv 1,j and cv 2,j are different, then const is in
// every cv for 0 < k < j.
if (FromType.getCVRQualifiers() != ToType.getCVRQualifiers()
- && !PreviousToQualsIncludeConst)
+ && !PreviousToQualsIncludeConst)
return false;
-
+
// Keep track of whether all prior cv-qualifiers in the "to" type
// include const.
PreviousToQualsIncludeConst
= PreviousToQualsIncludeConst && ToType.isConstQualified();
- } while (UnwrappedPointer);
+ }
// We are left with FromType and ToType being the pointee types
// after unwrapping the original FromType and ToType the same number
@@ -791,26 +777,120 @@
return ImplicitConversionSequence::Better;
else if (Rank2 < Rank1)
return ImplicitConversionSequence::Worse;
- else {
- // (C++ 13.3.3.2p4): Two conversion sequences with the same rank
- // are indistinguishable unless one of the following rules
- // applies:
-
- // A conversion that is not a conversion of a pointer, or
- // pointer to member, to bool is better than another conversion
- // that is such a conversion.
- if (SCS1.isPointerConversionToBool() != SCS2.isPointerConversionToBool())
- return SCS2.isPointerConversionToBool()
- ? ImplicitConversionSequence::Better
- : ImplicitConversionSequence::Worse;
- // FIXME: The other bullets in (C++ 13.3.3.2p4) require support
- // for derived classes.
+ // (C++ 13.3.3.2p4): Two conversion sequences with the same rank
+ // are indistinguishable unless one of the following rules
+ // applies:
+
+ // A conversion that is not a conversion of a pointer, or
+ // pointer to member, to bool is better than another conversion
+ // that is such a conversion.
+ if (SCS1.isPointerConversionToBool() != SCS2.isPointerConversionToBool())
+ return SCS2.isPointerConversionToBool()
+ ? ImplicitConversionSequence::Better
+ : ImplicitConversionSequence::Worse;
+
+ // FIXME: The other bullets in (C++ 13.3.3.2p4) require support
+ // for derived classes.
+
+ // Compare based on qualification conversions (C++ 13.3.3.2p3,
+ // bullet 3).
+ if (ImplicitConversionSequence::CompareKind CK
+ = CompareQualificationConversions(SCS1, SCS2))
+ return CK;
+
+ // FIXME: Handle comparison of reference bindings.
+
+ return ImplicitConversionSequence::Indistinguishable;
+}
+
+/// CompareQualificationConversions - Compares two standard conversion
+/// sequences to determine whether they can be ranked based on their
+/// qualification conversions (C++ 13.3.3.2p3 bullet 3).
+ImplicitConversionSequence::CompareKind
+Sema::CompareQualificationConversions(const StandardConversionSequence& SCS1,
+ const StandardConversionSequence& SCS2)
+{
+ // -- S1 and S2 differ only in their qualification conversion and
+ // yield similar types T1 and T2 (C++ 4.4), respectively, and the
+ // cv-qualification signature of type T1 is a proper subset of
+ // the cv-qualification signature of type T2, and S1 is not the
+ // deprecated string literal array-to-pointer conversion (4.2).
+ if (SCS1.First != SCS2.First || SCS1.Second != SCS2.Second ||
+ SCS1.Third != SCS2.Third || SCS1.Third != ICK_Qualification)
+ return ImplicitConversionSequence::Indistinguishable;
+
+ // FIXME: the example in the standard doesn't use a qualification
+ // conversion (!)
+ QualType T1 = QualType::getFromOpaquePtr(SCS1.ToTypePtr);
+ QualType T2 = QualType::getFromOpaquePtr(SCS2.ToTypePtr);
+ T1 = Context.getCanonicalType(T1);
+ T2 = Context.getCanonicalType(T2);
+
+ // If the types are the same, we won't learn anything by unwrapped
+ // them.
+ if (T1.getUnqualifiedType() == T2.getUnqualifiedType())
+ return ImplicitConversionSequence::Indistinguishable;
+
+ ImplicitConversionSequence::CompareKind Result
+ = ImplicitConversionSequence::Indistinguishable;
+ while (UnwrapSimilarPointerTypes(T1, T2)) {
+ // Within each iteration of the loop, we check the qualifiers to
+ // determine if this still looks like a qualification
+ // conversion. Then, if all is well, we unwrap one more level of
+ // pointers (FIXME: or pointers-to-members) and do it all again
+ // until there are no more pointers or pointers-to-members left
+ // to unwrap. This essentially mimics what
+ // IsQualificationConversion does, but here we're checking for a
+ // strict subset of qualifiers.
+ if (T1.getCVRQualifiers() == T2.getCVRQualifiers())
+ // The qualifiers are the same, so this doesn't tell us anything
+ // about how the sequences rank.
+ ;
+ else if (T2.isMoreQualifiedThan(T1)) {
+ // T1 has fewer qualifiers, so it could be the better sequence.
+ if (Result == ImplicitConversionSequence::Worse)
+ // Neither has qualifiers that are a subset of the other's
+ // qualifiers.
+ return ImplicitConversionSequence::Indistinguishable;
+
+ Result = ImplicitConversionSequence::Better;
+ } else if (T1.isMoreQualifiedThan(T2)) {
+ // T2 has fewer qualifiers, so it could be the better sequence.
+ if (Result == ImplicitConversionSequence::Better)
+ // Neither has qualifiers that are a subset of the other's
+ // qualifiers.
+ return ImplicitConversionSequence::Indistinguishable;
+
+ Result = ImplicitConversionSequence::Worse;
+ } else {
+ // Qualifiers are disjoint.
+ return ImplicitConversionSequence::Indistinguishable;
+ }
+
+ // If the types after this point are equivalent, we're done.
+ if (T1.getUnqualifiedType() == T2.getUnqualifiedType())
+ break;
}
- // FIXME: Handle comparison by qualifications.
- // FIXME: Handle comparison of reference bindings.
- return ImplicitConversionSequence::Indistinguishable;
+ // Check that the winning standard conversion sequence isn't using
+ // the deprecated string literal array to pointer conversion.
+ switch (Result) {
+ case ImplicitConversionSequence::Better:
+ if (SCS1.Deprecated)
+ Result = ImplicitConversionSequence::Indistinguishable;
+ break;
+
+ case ImplicitConversionSequence::Indistinguishable:
+ break;
+
+ case ImplicitConversionSequence::Worse:
+ if (SCS2.Deprecated)
+ Result = ImplicitConversionSequence::Indistinguishable;
+ break;
+ }
+
+ return Result;
}
/// AddOverloadCandidate - Adds the given function to the set of