summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaOverload.cpp
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2014-07-14 02:28:44 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2014-07-14 02:28:44 +0000
commit19172c4f70face3b717d5f5ba7104aa9e72b30af (patch)
tree766bce5fcf44d5eb94f0a72f720b1bafa4bd4fe3 /clang/lib/Sema/SemaOverload.cpp
parent67d8b2e2b0174783b3d6ba4737978c190a4c0414 (diff)
downloadbcm5719-llvm-19172c4f70face3b717d5f5ba7104aa9e72b30af.tar.gz
bcm5719-llvm-19172c4f70face3b717d5f5ba7104aa9e72b30af.zip
Superficial fix for PR20218: binding a function lvalue to a const reference to
a function pointer is neither better nor worse than binding a function lvalue to a function rvalue reference. Don't get confused and think that both bindings are binding to a function lvalue (which would make the lvalue form win); the const reference is binding to an rvalue. The "real" bug in PR20218 is still present: we're getting the wrong answer from template argument deduction, and that's what leads us to this weird overload set. llvm-svn: 212916
Diffstat (limited to 'clang/lib/Sema/SemaOverload.cpp')
-rw-r--r--clang/lib/Sema/SemaOverload.cpp45
1 files changed, 28 insertions, 17 deletions
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 4eed8c1467e..5c9ee653fe9 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -3465,8 +3465,9 @@ compareStandardConversionSubsets(ASTContext &Context,
/// \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) {
+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
@@ -3487,7 +3488,7 @@ static bool isBetterReferenceBindingKind(const StandardConversionSequence &SCS1,
return (!SCS1.IsLvalueReference && SCS1.BindsToRvalue &&
SCS2.IsLvalueReference) ||
(SCS1.IsLvalueReference && SCS1.BindsToFunctionLvalue &&
- !SCS2.IsLvalueReference);
+ !SCS2.IsLvalueReference && SCS2.BindsToFunctionLvalue);
}
/// CompareStandardConversionSequences - Compare two standard
@@ -4372,6 +4373,10 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType,
return ICS;
}
+ // A temporary of function type cannot be created; don't even try.
+ if (T1->isFunctionType())
+ return ICS;
+
// -- Otherwise, a temporary of type "cv1 T1" is created and
// initialized from the initializer expression using the
// rules for a non-reference copy initialization (8.5). The
@@ -4433,28 +4438,34 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType,
if (ICS.isStandard()) {
ICS.Standard.ReferenceBinding = true;
ICS.Standard.IsLvalueReference = !isRValRef;
- ICS.Standard.BindsToFunctionLvalue = T2->isFunctionType();
+ ICS.Standard.BindsToFunctionLvalue = false;
ICS.Standard.BindsToRvalue = true;
ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier = false;
ICS.Standard.ObjCLifetimeConversionBinding = false;
} else if (ICS.isUserDefined()) {
- // Don't allow rvalue references to bind to lvalues.
- if (DeclType->isRValueReferenceType()) {
- if (const ReferenceType *RefType =
- ICS.UserDefined.ConversionFunction->getReturnType()
- ->getAs<LValueReferenceType>()) {
- if (!RefType->getPointeeType()->isFunctionType()) {
- ICS.setBad(BadConversionSequence::lvalue_ref_to_rvalue, Init,
- DeclType);
- return ICS;
- }
- }
+ const ReferenceType *LValRefType =
+ ICS.UserDefined.ConversionFunction->getReturnType()
+ ->getAs<LValueReferenceType>();
+
+ // C++ [over.ics.ref]p3:
+ // Except for an implicit object parameter, for which see 13.3.1, a
+ // standard conversion sequence cannot be formed if it requires [...]
+ // binding an rvalue reference to an lvalue other than a function
+ // lvalue.
+ // Note that the function case is not possible here.
+ if (DeclType->isRValueReferenceType() && LValRefType) {
+ // FIXME: This is the wrong BadConversionSequence. The problem is binding
+ // an rvalue reference to a (non-function) lvalue, not binding an lvalue
+ // reference to an rvalue!
+ ICS.setBad(BadConversionSequence::lvalue_ref_to_rvalue, Init, DeclType);
+ return ICS;
}
+
ICS.UserDefined.Before.setAsIdentityConversion();
ICS.UserDefined.After.ReferenceBinding = true;
ICS.UserDefined.After.IsLvalueReference = !isRValRef;
- ICS.UserDefined.After.BindsToFunctionLvalue = T2->isFunctionType();
- ICS.UserDefined.After.BindsToRvalue = true;
+ ICS.UserDefined.After.BindsToFunctionLvalue = false;
+ ICS.UserDefined.After.BindsToRvalue = !LValRefType;
ICS.UserDefined.After.BindsImplicitObjectArgumentWithoutRefQualifier = false;
ICS.UserDefined.After.ObjCLifetimeConversionBinding = false;
}
OpenPOWER on IntegriCloud