зеркало из https://github.com/microsoft/clang-1.git
Implement overloading rules for reference binding
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@58381 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
a206b0614a
Коммит
f70bdb9463
|
@ -785,8 +785,8 @@ Sema::CheckReferenceInit(Expr *&Init, QualType &DeclType,
|
|||
ICS->Standard.Third = ICK_Identity;
|
||||
ICS->Standard.FromTypePtr = T2.getAsOpaquePtr();
|
||||
ICS->Standard.ToTypePtr = T1.getAsOpaquePtr();
|
||||
ICS->ReferenceBinding = true;
|
||||
ICS->DirectBinding = true;
|
||||
ICS->Standard.ReferenceBinding = true;
|
||||
ICS->Standard.DirectBinding = true;
|
||||
|
||||
// Nothing more to do: the inaccessibility/ambiguity check for
|
||||
// derived-to-base conversions is suppressed when we're
|
||||
|
@ -876,8 +876,8 @@ Sema::CheckReferenceInit(Expr *&Init, QualType &DeclType,
|
|||
ICS->Standard.Third = ICK_Identity;
|
||||
ICS->Standard.FromTypePtr = T2.getAsOpaquePtr();
|
||||
ICS->Standard.ToTypePtr = T1.getAsOpaquePtr();
|
||||
ICS->ReferenceBinding = true;
|
||||
ICS->DirectBinding = false;
|
||||
ICS->Standard.ReferenceBinding = true;
|
||||
ICS->Standard.DirectBinding = false;
|
||||
} else {
|
||||
// FIXME: Binding to a subobject of the rvalue is going to require
|
||||
// more AST annotation than this.
|
||||
|
|
|
@ -471,7 +471,7 @@ Sema::TryImplicitConversion(Expr* From, QualType ToType)
|
|||
ICS.Standard.Third = ICK_Identity;
|
||||
|
||||
// C++ [dcl.init]p14 last bullet:
|
||||
// Note: an expression of type "cv1 T" can initialize an object
|
||||
// [ Note: an expression of type "cv1 T" can initialize an object
|
||||
// of type “cv2 T” independently of the cv-qualifiers cv1 and
|
||||
// cv2. -- end note]
|
||||
//
|
||||
|
@ -877,21 +877,48 @@ Sema::CompareStandardConversionSequences(const StandardConversionSequence& SCS1,
|
|||
// C++ [over.ics.rank]p4b2:
|
||||
//
|
||||
// If class B is derived directly or indirectly from class A,
|
||||
// conversion of B* to A* is better than conversion of B* to void*,
|
||||
// and (FIXME) conversion of A* to void* is better than conversion of B*
|
||||
// to void*.
|
||||
// conversion of B* to A* is better than conversion of B* to
|
||||
// void*, and conversion of A* to void* is better than conversion
|
||||
// of B* to void*.
|
||||
bool SCS1ConvertsToVoid
|
||||
= SCS1.isPointerConversionToVoidPointer(Context);
|
||||
bool SCS2ConvertsToVoid
|
||||
= SCS2.isPointerConversionToVoidPointer(Context);
|
||||
if (SCS1ConvertsToVoid != SCS2ConvertsToVoid)
|
||||
if (SCS1ConvertsToVoid != SCS2ConvertsToVoid) {
|
||||
// Exactly one of the conversion sequences is a conversion to
|
||||
// a void pointer; it's the worse conversion.
|
||||
return SCS2ConvertsToVoid ? ImplicitConversionSequence::Better
|
||||
: ImplicitConversionSequence::Worse;
|
||||
|
||||
if (!SCS1ConvertsToVoid && !SCS2ConvertsToVoid)
|
||||
} else if (!SCS1ConvertsToVoid && !SCS2ConvertsToVoid) {
|
||||
// Neither conversion sequence converts to a void pointer; compare
|
||||
// their derived-to-base conversions.
|
||||
if (ImplicitConversionSequence::CompareKind DerivedCK
|
||||
= CompareDerivedToBaseConversions(SCS1, SCS2))
|
||||
return DerivedCK;
|
||||
} else if (SCS1ConvertsToVoid && SCS2ConvertsToVoid) {
|
||||
// Both conversion sequences are conversions to void
|
||||
// pointers. Compare the source types to determine if there's an
|
||||
// inheritance relationship in their sources.
|
||||
QualType FromType1 = QualType::getFromOpaquePtr(SCS1.FromTypePtr);
|
||||
QualType FromType2 = QualType::getFromOpaquePtr(SCS2.FromTypePtr);
|
||||
|
||||
// Adjust the types we're converting from via the array-to-pointer
|
||||
// conversion, if we need to.
|
||||
if (SCS1.First == ICK_Array_To_Pointer)
|
||||
FromType1 = Context.getArrayDecayedType(FromType1);
|
||||
if (SCS2.First == ICK_Array_To_Pointer)
|
||||
FromType2 = Context.getArrayDecayedType(FromType2);
|
||||
|
||||
QualType FromPointee1
|
||||
= FromType1->getAsPointerType()->getPointeeType().getUnqualifiedType();
|
||||
QualType FromPointee2
|
||||
= FromType2->getAsPointerType()->getPointeeType().getUnqualifiedType();
|
||||
|
||||
if (IsDerivedFrom(FromPointee2, FromPointee1))
|
||||
return ImplicitConversionSequence::Better;
|
||||
else if (IsDerivedFrom(FromPointee1, FromPointee2))
|
||||
return ImplicitConversionSequence::Worse;
|
||||
}
|
||||
|
||||
// Compare based on qualification conversions (C++ 13.3.3.2p3,
|
||||
// bullet 3).
|
||||
|
@ -899,7 +926,24 @@ Sema::CompareStandardConversionSequences(const StandardConversionSequence& SCS1,
|
|||
= CompareQualificationConversions(SCS1, SCS2))
|
||||
return QualCK;
|
||||
|
||||
// FIXME: Handle comparison of reference bindings.
|
||||
// C++ [over.ics.rank]p3b4:
|
||||
// -- S1 and S2 are reference bindings (8.5.3), and the types to
|
||||
// which the references refer are the same type except for
|
||||
// top-level cv-qualifiers, and the type to which the reference
|
||||
// initialized by S2 refers is more cv-qualified than the type
|
||||
// to which the reference initialized by S1 refers.
|
||||
if (SCS1.ReferenceBinding && SCS2.ReferenceBinding) {
|
||||
QualType T1 = QualType::getFromOpaquePtr(SCS1.ToTypePtr);
|
||||
QualType T2 = QualType::getFromOpaquePtr(SCS2.ToTypePtr);
|
||||
T1 = Context.getCanonicalType(T1);
|
||||
T2 = Context.getCanonicalType(T2);
|
||||
if (T1.getUnqualifiedType() == T2.getUnqualifiedType()) {
|
||||
if (T2.isMoreQualifiedThan(T1))
|
||||
return ImplicitConversionSequence::Better;
|
||||
else if (T1.isMoreQualifiedThan(T2))
|
||||
return ImplicitConversionSequence::Worse;
|
||||
}
|
||||
}
|
||||
|
||||
return ImplicitConversionSequence::Indistinguishable;
|
||||
}
|
||||
|
@ -1018,16 +1062,14 @@ Sema::CompareDerivedToBaseConversions(const StandardConversionSequence& SCS1,
|
|||
FromType2 = Context.getCanonicalType(FromType2);
|
||||
ToType2 = Context.getCanonicalType(ToType2);
|
||||
|
||||
// C++ [over.ics.rank]p4b4:
|
||||
// C++ [over.ics.rank]p4b3:
|
||||
//
|
||||
// If class B is derived directly or indirectly from class A and
|
||||
// class C is derived directly or indirectly from B,
|
||||
//
|
||||
// FIXME: Verify that in this section we're talking about the
|
||||
// unqualified forms of C, B, and A.
|
||||
|
||||
// Compare based on pointer conversions.
|
||||
if (SCS1.Second == ICK_Pointer_Conversion &&
|
||||
SCS2.Second == ICK_Pointer_Conversion) {
|
||||
// -- conversion of C* to B* is better than conversion of C* to A*,
|
||||
QualType FromPointee1
|
||||
= FromType1->getAsPointerType()->getPointeeType().getUnqualifiedType();
|
||||
QualType ToPointee1
|
||||
|
@ -1036,16 +1078,60 @@ Sema::CompareDerivedToBaseConversions(const StandardConversionSequence& SCS1,
|
|||
= FromType2->getAsPointerType()->getPointeeType().getUnqualifiedType();
|
||||
QualType ToPointee2
|
||||
= ToType2->getAsPointerType()->getPointeeType().getUnqualifiedType();
|
||||
// -- conversion of C* to B* is better than conversion of C* to A*,
|
||||
if (FromPointee1 == FromPointee2 && ToPointee1 != ToPointee2) {
|
||||
if (IsDerivedFrom(ToPointee1, ToPointee2))
|
||||
return ImplicitConversionSequence::Better;
|
||||
else if (IsDerivedFrom(ToPointee2, ToPointee1))
|
||||
return ImplicitConversionSequence::Worse;
|
||||
}
|
||||
|
||||
// -- conversion of B* to A* is better than conversion of C* to A*,
|
||||
if (FromPointee1 != FromPointee2 && ToPointee1 == ToPointee2) {
|
||||
if (IsDerivedFrom(FromPointee2, FromPointee1))
|
||||
return ImplicitConversionSequence::Better;
|
||||
else if (IsDerivedFrom(FromPointee1, FromPointee2))
|
||||
return ImplicitConversionSequence::Worse;
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: many more sub-bullets of C++ [over.ics.rank]p4b4 to
|
||||
// implement.
|
||||
// Compare based on reference bindings.
|
||||
if (SCS1.ReferenceBinding && SCS2.ReferenceBinding &&
|
||||
SCS1.Second == ICK_Derived_To_Base) {
|
||||
// -- binding of an expression of type C to a reference of type
|
||||
// B& is better than binding an expression of type C to a
|
||||
// reference of type A&,
|
||||
if (FromType1.getUnqualifiedType() == FromType2.getUnqualifiedType() &&
|
||||
ToType1.getUnqualifiedType() != ToType2.getUnqualifiedType()) {
|
||||
if (IsDerivedFrom(ToType1, ToType2))
|
||||
return ImplicitConversionSequence::Better;
|
||||
else if (IsDerivedFrom(ToType2, ToType1))
|
||||
return ImplicitConversionSequence::Worse;
|
||||
}
|
||||
|
||||
// -- binding of an expression of type B to a reference of type
|
||||
// A& is better than binding an expression of type C to a
|
||||
// reference of type A&,
|
||||
if (FromType1.getUnqualifiedType() != FromType2.getUnqualifiedType() &&
|
||||
ToType1.getUnqualifiedType() == ToType2.getUnqualifiedType()) {
|
||||
if (IsDerivedFrom(FromType2, FromType1))
|
||||
return ImplicitConversionSequence::Better;
|
||||
else if (IsDerivedFrom(FromType1, FromType2))
|
||||
return ImplicitConversionSequence::Worse;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// FIXME: conversion of A::* to B::* is better than conversion of
|
||||
// A::* to C::*,
|
||||
|
||||
// FIXME: conversion of B::* to C::* is better than conversion of
|
||||
// A::* to C::*, and
|
||||
|
||||
// FIXME: conversion of C to B is better than conversion of C to A,
|
||||
|
||||
// FIXME: conversion of B to A is better than conversion of C to A.
|
||||
|
||||
return ImplicitConversionSequence::Indistinguishable;
|
||||
}
|
||||
|
||||
|
|
|
@ -97,6 +97,14 @@ namespace clang {
|
|||
/// (C++ 4.2p2).
|
||||
bool Deprecated : 1;
|
||||
|
||||
/// ReferenceBinding - True when this is a reference binding
|
||||
/// (C++ [over.ics.ref]).
|
||||
bool ReferenceBinding : 1;
|
||||
|
||||
/// DirectBinding - True when this is a reference binding that is a
|
||||
/// direct binding (C++ [dcl.init.ref]).
|
||||
bool DirectBinding : 1;
|
||||
|
||||
/// FromType - The type that this conversion is converting
|
||||
/// from. This is an opaque pointer that can be translated into a
|
||||
/// QualType.
|
||||
|
@ -155,17 +163,7 @@ namespace clang {
|
|||
};
|
||||
|
||||
/// ConversionKind - The kind of implicit conversion sequence.
|
||||
/// As usual, we use "unsigned" here because VC++ makes enum bitfields
|
||||
/// signed.
|
||||
unsigned ConversionKind : 2;
|
||||
|
||||
/// ReferenceBinding - True when this is a reference binding
|
||||
/// (C++ [over.ics.ref]).
|
||||
bool ReferenceBinding : 1;
|
||||
|
||||
/// DirectBinding - True when this is a reference binding that is a
|
||||
/// direct binding (C++ [dcl.init.ref]).
|
||||
bool DirectBinding : 1;
|
||||
Kind ConversionKind;
|
||||
|
||||
union {
|
||||
/// When ConversionKind == StandardConversion, provides the
|
||||
|
|
|
@ -253,3 +253,25 @@ void cvqual_subsume_test(Z z) {
|
|||
cvqual_subsume(z); // expected-error{{call to 'cvqual_subsume' is ambiguous; candidates are:}}
|
||||
int& x = cvqual_subsume2(get_Z()); // okay: only binds to the first one
|
||||
}
|
||||
|
||||
// Test overloading with cv-qualification differences in reference
|
||||
// binding.
|
||||
int& cvqual_diff(X&);
|
||||
float& cvqual_diff(const X&);
|
||||
|
||||
void cvqual_diff_test(X x, Z z) {
|
||||
int& i1 = cvqual_diff(x);
|
||||
int& i2 = cvqual_diff(z);
|
||||
}
|
||||
|
||||
// Test overloading with derived-to-base differences in reference
|
||||
// binding.
|
||||
struct Z2 : Z { };
|
||||
|
||||
int& db_rebind(X&);
|
||||
long& db_rebind(Y&);
|
||||
float& db_rebind(Z&);
|
||||
|
||||
void db_rebind_test(Z2 z2) {
|
||||
float& f1 = db_rebind(z2);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче