Better overload resolution for rvalue references.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@67870 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Sebastian Redl 2009-03-27 21:36:42 +00:00
Родитель d8c938b0f6
Коммит f8738782e3
4 изменённых файлов: 53 добавлений и 31 удалений

Просмотреть файл

@ -1970,6 +1970,18 @@ Sema::CheckReferenceInit(Expr *&Init, QualType &DeclType,
// -- If the initializer expression
// Rvalue references cannot bind to lvalues (N2812).
// There is absolutely no situation where they can. In particular, note that
// this is ill-formed, even if B has a user-defined conversion to A&&:
// B b;
// A&& r = b;
if (isRValRef && InitLvalue == Expr::LV_Valid) {
if (!ICS)
Diag(Init->getSourceRange().getBegin(), diag::err_lvalue_to_rvalue_ref)
<< Init->getSourceRange();
return true;
}
bool BindsDirectly = false;
// -- is an lvalue (but is not a bit-field), and “cv1 T1” is
// reference-compatible with “cv2 T2,” or
@ -1980,14 +1992,6 @@ Sema::CheckReferenceInit(Expr *&Init, QualType &DeclType,
RefRelationship >= Ref_Compatible_With_Added_Qualification) {
BindsDirectly = true;
// Rvalue references cannot bind to lvalues (N2812).
if (isRValRef) {
if (!ICS)
Diag(Init->getSourceRange().getBegin(), diag::err_lvalue_to_rvalue_ref)
<< Init->getSourceRange();
return true;
}
if (ICS) {
// C++ [over.ics.ref]p1:
// When a parameter of reference type binds directly (8.5.3)
@ -2004,6 +2008,7 @@ Sema::CheckReferenceInit(Expr *&Init, QualType &DeclType,
ICS->Standard.ToTypePtr = T1.getAsOpaquePtr();
ICS->Standard.ReferenceBinding = true;
ICS->Standard.DirectBinding = true;
ICS->Standard.RRefBinding = false;
// Nothing more to do: the inaccessibility/ambiguity check for
// derived-to-base conversions is suppressed when we're
@ -2111,7 +2116,8 @@ Sema::CheckReferenceInit(Expr *&Init, QualType &DeclType,
}
// -- Otherwise, the reference shall be to a non-volatile const
// type (i.e., cv1 shall be const), or shall be an rvalue reference.
// type (i.e., cv1 shall be const), or the reference shall be an
// rvalue reference and the initializer expression shall be an rvalue.
if (!isRValRef && T1.getCVRQualifiers() != QualType::Const) {
if (!ICS)
Diag(Init->getSourceRange().getBegin(),
@ -2140,7 +2146,7 @@ Sema::CheckReferenceInit(Expr *&Init, QualType &DeclType,
// shall be callable whether or not the copy is actually
// done.
//
// Note that C++0x [dcl.ref.init]p5 takes away this implementation
// Note that C++0x [dcl.init.ref]p5 takes away this implementation
// freedom, so we will always take the first option and never build
// a temporary in this case. FIXME: We will, however, have to check
// for the presence of a copy constructor in C++98/03 mode.
@ -2154,7 +2160,8 @@ Sema::CheckReferenceInit(Expr *&Init, QualType &DeclType,
ICS->Standard.FromTypePtr = T2.getAsOpaquePtr();
ICS->Standard.ToTypePtr = T1.getAsOpaquePtr();
ICS->Standard.ReferenceBinding = true;
ICS->Standard.DirectBinding = false;
ICS->Standard.DirectBinding = false;
ICS->Standard.RRefBinding = isRValRef;
} else {
// FIXME: Binding to a subobject of the rvalue is going to require
// more AST annotation than this.
@ -2199,18 +2206,27 @@ Sema::CheckReferenceInit(Expr *&Init, QualType &DeclType,
// Actually try to convert the initializer to T1.
if (ICS) {
/// C++ [over.ics.ref]p2:
///
/// When a parameter of reference type is not bound directly to
/// an argument expression, the conversion sequence is the one
/// required to convert the argument expression to the
/// underlying type of the reference according to
/// 13.3.3.1. Conceptually, this conversion sequence corresponds
/// to copy-initializing a temporary of the underlying type with
/// the argument expression. Any difference in top-level
/// cv-qualification is subsumed by the initialization itself
/// and does not constitute a conversion.
// C++ [over.ics.ref]p2:
//
// When a parameter of reference type is not bound directly to
// an argument expression, the conversion sequence is the one
// required to convert the argument expression to the
// underlying type of the reference according to
// 13.3.3.1. Conceptually, this conversion sequence corresponds
// to copy-initializing a temporary of the underlying type with
// the argument expression. Any difference in top-level
// cv-qualification is subsumed by the initialization itself
// and does not constitute a conversion.
*ICS = TryImplicitConversion(Init, T1, SuppressUserConversions);
// Of course, that's still a reference binding.
if (ICS->ConversionKind == ImplicitConversionSequence::StandardConversion) {
ICS->Standard.ReferenceBinding = true;
ICS->Standard.RRefBinding = isRValRef;
} else if(ICS->ConversionKind ==
ImplicitConversionSequence::UserDefinedConversion) {
ICS->UserDefined.After.ReferenceBinding = true;
ICS->UserDefined.After.RRefBinding = isRValRef;
}
return ICS->ConversionKind == ImplicitConversionSequence::BadConversion;
} else {
return PerformImplicitConversion(Init, T1, "initializing");

Просмотреть файл

@ -1584,18 +1584,17 @@ Sema::CompareStandardConversionSequences(const StandardConversionSequence& SCS1,
return QualCK;
if (SCS1.ReferenceBinding && SCS2.ReferenceBinding) {
QualType T1 = QualType::getFromOpaquePtr(SCS1.ToTypePtr);
QualType T2 = QualType::getFromOpaquePtr(SCS2.ToTypePtr);
// C++0x [over.ics.rank]p3b4:
// -- S1 and S2 are reference bindings (8.5.3) and neither refers to an
// implicit object parameter of a non-static member function declared
// without a ref-qualifier, and S1 binds an rvalue reference to an
// rvalue and S2 binds an lvalue reference.
// FIXME: We have far too little information for this check. We don't know
// if the bound object is an rvalue. We don't know if the binding type is
// an rvalue or lvalue reference. We don't know if we're dealing with the
// implicit object parameter, or if the member function in this case has
// a ref qualifier.
// FIXME: We don't know if we're dealing with the implicit object parameter,
// or if the member function in this case has a ref qualifier.
// (Of course, we don't have ref qualifiers yet.)
if (SCS1.RRefBinding != SCS2.RRefBinding)
return SCS1.RRefBinding ? ImplicitConversionSequence::Better
: ImplicitConversionSequence::Worse;
// C++ [over.ics.rank]p3b4:
// -- S1 and S2 are reference bindings (8.5.3), and the types to
@ -1603,6 +1602,8 @@ Sema::CompareStandardConversionSequences(const StandardConversionSequence& SCS1,
// 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.
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()) {

Просмотреть файл

@ -114,6 +114,10 @@ namespace clang {
/// direct binding (C++ [dcl.init.ref]).
bool DirectBinding : 1;
/// RRefBinding - True when this is a reference binding of an rvalue
/// reference to an rvalue (C++0x [over.ics.rank]p3b4).
bool RRefBinding : 1;
/// FromType - The type that this conversion is converting
/// from. This is an opaque pointer that can be translated into a
/// QualType.

Просмотреть файл

@ -37,14 +37,15 @@ void f() {
not_int ni2 = over(ret_irr());
int i4 = over2(i1);
// not_int ni3 = over2(0); FIXME: this should be well-formed.
not_int ni3 = over2(0);
ilr_c1 vilr1 = i1;
ilr_c2 vilr2 = i1;
conv_to_not_int_rvalue cnir;
not_int &&ni4 = cnir;
not_int &&ni4 = cnir; // expected-error {{rvalue reference cannot bind to lvalue}}
not_int &ni5 = cnir; // expected-error{{non-const lvalue reference to type 'struct not_int' cannot be initialized with a value of type 'struct conv_to_not_int_rvalue'}}
not_int &&ni6 = conv_to_not_int_rvalue();
try {