forked from OSchip/llvm-project
Reinstate r124236 (tweaking the rvalue-reference overload resolution
rules), now that we've actually have a clean build for me to sully. llvm-svn: 124290
This commit is contained in:
parent
ce0af9c961
commit
e696ebbd70
|
@ -133,24 +133,30 @@ namespace clang {
|
||||||
/// Deprecated - Whether this the deprecated conversion of a
|
/// Deprecated - Whether this the deprecated conversion of a
|
||||||
/// string literal to a pointer to non-const character data
|
/// string literal to a pointer to non-const character data
|
||||||
/// (C++ 4.2p2).
|
/// (C++ 4.2p2).
|
||||||
bool DeprecatedStringLiteralToCharPtr : 1;
|
unsigned DeprecatedStringLiteralToCharPtr : 1;
|
||||||
|
|
||||||
/// IncompatibleObjC - Whether this is an Objective-C conversion
|
/// IncompatibleObjC - Whether this is an Objective-C conversion
|
||||||
/// that we should warn about (if we actually use it).
|
/// that we should warn about (if we actually use it).
|
||||||
bool IncompatibleObjC : 1;
|
unsigned IncompatibleObjC : 1;
|
||||||
|
|
||||||
/// ReferenceBinding - True when this is a reference binding
|
/// ReferenceBinding - True when this is a reference binding
|
||||||
/// (C++ [over.ics.ref]).
|
/// (C++ [over.ics.ref]).
|
||||||
bool ReferenceBinding : 1;
|
unsigned ReferenceBinding : 1;
|
||||||
|
|
||||||
/// DirectBinding - True when this is a reference binding that is a
|
/// DirectBinding - True when this is a reference binding that is a
|
||||||
/// direct binding (C++ [dcl.init.ref]).
|
/// direct binding (C++ [dcl.init.ref]).
|
||||||
bool DirectBinding : 1;
|
unsigned 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;
|
|
||||||
|
|
||||||
|
/// \brief Whether this is an lvalue reference binding (otherwise, it's
|
||||||
|
/// an rvalue reference binding).
|
||||||
|
unsigned IsLvalueReference : 1;
|
||||||
|
|
||||||
|
/// \brief Whether we're binding to a function lvalue.
|
||||||
|
unsigned BindsToFunctionLvalue : 1;
|
||||||
|
|
||||||
|
/// \brief Whether we're binding to an rvalue.
|
||||||
|
unsigned BindsToRvalue : 1;
|
||||||
|
|
||||||
/// FromType - The type that this conversion is converting
|
/// FromType - The type that this conversion is converting
|
||||||
/// from. This is an opaque pointer that can be translated into a
|
/// from. This is an opaque pointer that can be translated into a
|
||||||
/// QualType.
|
/// QualType.
|
||||||
|
|
|
@ -170,7 +170,9 @@ void StandardConversionSequence::setAsIdentityConversion() {
|
||||||
DeprecatedStringLiteralToCharPtr = false;
|
DeprecatedStringLiteralToCharPtr = false;
|
||||||
ReferenceBinding = false;
|
ReferenceBinding = false;
|
||||||
DirectBinding = false;
|
DirectBinding = false;
|
||||||
RRefBinding = false;
|
IsLvalueReference = true;
|
||||||
|
BindsToFunctionLvalue = false;
|
||||||
|
BindsToRvalue = false;
|
||||||
CopyConstructor = 0;
|
CopyConstructor = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2324,6 +2326,33 @@ compareStandardConversionSubsets(ASTContext &Context,
|
||||||
return ImplicitConversionSequence::Indistinguishable;
|
return ImplicitConversionSequence::Indistinguishable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \brief Determine whether one of the given reference bindings is better
|
||||||
|
/// than the other based on what kind of bindings they are.
|
||||||
|
static bool isBetterReferenceBindingKind(const StandardConversionSequence &SCS1,
|
||||||
|
const StandardConversionSequence &SCS2) {
|
||||||
|
// 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 *either* S1 binds an rvalue reference
|
||||||
|
// to an rvalue and S2 binds an lvalue reference *or S1 binds an
|
||||||
|
// lvalue reference to a function lvalue and S2 binds an rvalue
|
||||||
|
// reference*.
|
||||||
|
//
|
||||||
|
// FIXME: Rvalue references. We're going rogue with the above edits,
|
||||||
|
// because the semantics in the current C++0x working paper (N3225 at the
|
||||||
|
// time of this writing) break the standard definition of std::forward
|
||||||
|
// and std::reference_wrapper when dealing with references to functions.
|
||||||
|
// Proposed wording changes submitted to CWG for consideration.
|
||||||
|
//
|
||||||
|
// FIXME: Rvalue references. 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.)
|
||||||
|
return (!SCS1.IsLvalueReference && SCS1.BindsToRvalue &&
|
||||||
|
SCS2.IsLvalueReference) ||
|
||||||
|
(SCS1.IsLvalueReference && SCS1.BindsToFunctionLvalue &&
|
||||||
|
!SCS2.IsLvalueReference);
|
||||||
|
}
|
||||||
|
|
||||||
/// CompareStandardConversionSequences - Compare two standard
|
/// CompareStandardConversionSequences - Compare two standard
|
||||||
/// conversion sequences to determine whether one is better than the
|
/// conversion sequences to determine whether one is better than the
|
||||||
/// other or if they are indistinguishable (C++ 13.3.3.2p3).
|
/// other or if they are indistinguishable (C++ 13.3.3.2p3).
|
||||||
|
@ -2429,18 +2458,12 @@ CompareStandardConversionSequences(Sema &S,
|
||||||
return QualCK;
|
return QualCK;
|
||||||
|
|
||||||
if (SCS1.ReferenceBinding && SCS2.ReferenceBinding) {
|
if (SCS1.ReferenceBinding && SCS2.ReferenceBinding) {
|
||||||
// C++0x [over.ics.rank]p3b4:
|
// Check for a better reference binding based on the kind of bindings.
|
||||||
// -- S1 and S2 are reference bindings (8.5.3) and neither refers to an
|
if (isBetterReferenceBindingKind(SCS1, SCS2))
|
||||||
// implicit object parameter of a non-static member function declared
|
return ImplicitConversionSequence::Better;
|
||||||
// without a ref-qualifier, and S1 binds an rvalue reference to an
|
else if (isBetterReferenceBindingKind(SCS2, SCS1))
|
||||||
// rvalue and S2 binds an lvalue reference.
|
return ImplicitConversionSequence::Worse;
|
||||||
// FIXME: Rvalue references. 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:
|
// C++ [over.ics.rank]p3b4:
|
||||||
// -- S1 and S2 are reference bindings (8.5.3), and the types to
|
// -- S1 and S2 are reference bindings (8.5.3), and the types to
|
||||||
// which the references refer are the same type except for
|
// which the references refer are the same type except for
|
||||||
|
@ -2966,7 +2989,9 @@ TryReferenceInit(Sema &S, Expr *&Init, QualType DeclType,
|
||||||
ICS.Standard.setToType(2, T1);
|
ICS.Standard.setToType(2, T1);
|
||||||
ICS.Standard.ReferenceBinding = true;
|
ICS.Standard.ReferenceBinding = true;
|
||||||
ICS.Standard.DirectBinding = true;
|
ICS.Standard.DirectBinding = true;
|
||||||
ICS.Standard.RRefBinding = isRValRef && InitCategory.isRValue();
|
ICS.Standard.IsLvalueReference = !isRValRef;
|
||||||
|
ICS.Standard.BindsToFunctionLvalue = T2->isFunctionType();
|
||||||
|
ICS.Standard.BindsToRvalue = false;
|
||||||
ICS.Standard.CopyConstructor = 0;
|
ICS.Standard.CopyConstructor = 0;
|
||||||
|
|
||||||
// Nothing more to do: the inaccessibility/ambiguity check for
|
// Nothing more to do: the inaccessibility/ambiguity check for
|
||||||
|
@ -3036,7 +3061,9 @@ TryReferenceInit(Sema &S, Expr *&Init, QualType DeclType,
|
||||||
ICS.Standard.DirectBinding =
|
ICS.Standard.DirectBinding =
|
||||||
S.getLangOptions().CPlusPlus0x ||
|
S.getLangOptions().CPlusPlus0x ||
|
||||||
(InitCategory.isPRValue() && !T2->isRecordType());
|
(InitCategory.isPRValue() && !T2->isRecordType());
|
||||||
ICS.Standard.RRefBinding = isRValRef && InitCategory.isRValue();
|
ICS.Standard.IsLvalueReference = !isRValRef;
|
||||||
|
ICS.Standard.BindsToFunctionLvalue = T2->isFunctionType();
|
||||||
|
ICS.Standard.BindsToRvalue = InitCategory.isRValue();
|
||||||
ICS.Standard.CopyConstructor = 0;
|
ICS.Standard.CopyConstructor = 0;
|
||||||
return ICS;
|
return ICS;
|
||||||
}
|
}
|
||||||
|
@ -3114,10 +3141,14 @@ TryReferenceInit(Sema &S, Expr *&Init, QualType DeclType,
|
||||||
// Of course, that's still a reference binding.
|
// Of course, that's still a reference binding.
|
||||||
if (ICS.isStandard()) {
|
if (ICS.isStandard()) {
|
||||||
ICS.Standard.ReferenceBinding = true;
|
ICS.Standard.ReferenceBinding = true;
|
||||||
ICS.Standard.RRefBinding = isRValRef;
|
ICS.Standard.IsLvalueReference = !isRValRef;
|
||||||
|
ICS.Standard.BindsToFunctionLvalue = T2->isFunctionType();
|
||||||
|
ICS.Standard.BindsToRvalue = true;
|
||||||
} else if (ICS.isUserDefined()) {
|
} else if (ICS.isUserDefined()) {
|
||||||
ICS.UserDefined.After.ReferenceBinding = true;
|
ICS.UserDefined.After.ReferenceBinding = true;
|
||||||
ICS.UserDefined.After.RRefBinding = isRValRef;
|
ICS.Standard.IsLvalueReference = !isRValRef;
|
||||||
|
ICS.Standard.BindsToFunctionLvalue = T2->isFunctionType();
|
||||||
|
ICS.Standard.BindsToRvalue = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ICS;
|
return ICS;
|
||||||
|
@ -3212,7 +3243,11 @@ TryObjectArgumentInitialization(Sema &S, QualType OrigFromType,
|
||||||
ICS.Standard.setAllToTypes(ImplicitParamType);
|
ICS.Standard.setAllToTypes(ImplicitParamType);
|
||||||
ICS.Standard.ReferenceBinding = true;
|
ICS.Standard.ReferenceBinding = true;
|
||||||
ICS.Standard.DirectBinding = true;
|
ICS.Standard.DirectBinding = true;
|
||||||
ICS.Standard.RRefBinding = false;
|
|
||||||
|
// FIXME: Rvalue references.
|
||||||
|
ICS.Standard.IsLvalueReference = true;
|
||||||
|
ICS.Standard.BindsToFunctionLvalue = false;
|
||||||
|
ICS.Standard.BindsToRvalue = false;
|
||||||
return ICS;
|
return ICS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -50,10 +50,10 @@ struct remove_reference<T&&> {
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace FunctionReferencesOverloading {
|
namespace FunctionReferencesOverloading {
|
||||||
template<typename T> int &f(typename remove_reference<T>::type&); // expected-note{{candidate function [with T = int (&)(int)]}}
|
template<typename T> int &f(typename remove_reference<T>::type&);
|
||||||
template<typename T> float &f(typename remove_reference<T>::type&&); // expected-note{{candidate function [with T = int (&)(int)]}}
|
template<typename T> float &f(typename remove_reference<T>::type&&);
|
||||||
|
|
||||||
void test_f(int (&func_ref)(int)) {
|
void test_f(int (&func_ref)(int)) {
|
||||||
f<int (&)(int)>(func_ref); // expected-error{{call to 'f' is ambiguous}}
|
int &ir = f<int (&)(int)>(func_ref);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue