aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Sema/SemaDeclCXX.cpp23
-rw-r--r--lib/Sema/SemaInit.cpp15
-rw-r--r--test/SemaCXX/overload-call.cpp20
3 files changed, 44 insertions, 14 deletions
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 0708d4176a..b959202b88 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -4526,20 +4526,23 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType,
OverloadCandidateSet::iterator Best;
switch (BestViableFunction(CandidateSet, DeclLoc, Best)) {
case OR_Success:
+ // C++ [over.ics.ref]p1:
+ //
+ // [...] If the parameter binds directly to the result of
+ // applying a conversion function to the argument
+ // expression, the implicit conversion sequence is a
+ // user-defined conversion sequence (13.3.3.1.2), with the
+ // second standard conversion sequence either an identity
+ // conversion or, if the conversion function returns an
+ // entity of a type that is a derived class of the parameter
+ // type, a derived-to-base Conversion.
+ if (!Best->FinalConversion.DirectBinding)
+ break;
+
// This is a direct binding.
BindsDirectly = true;
if (ICS) {
- // C++ [over.ics.ref]p1:
- //
- // [...] If the parameter binds directly to the result of
- // applying a conversion function to the argument
- // expression, the implicit conversion sequence is a
- // user-defined conversion sequence (13.3.3.1.2), with the
- // second standard conversion sequence either an identity
- // conversion or, if the conversion function returns an
- // entity of a type that is a derived class of the parameter
- // type, a derived-to-base Conversion.
ICS->setUserDefined();
ICS->UserDefined.Before = Best->Conversions[0].Standard;
ICS->UserDefined.After = Best->FinalConversion;
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
index 98db60854f..3540cd02e6 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/lib/Sema/SemaInit.cpp
@@ -2273,10 +2273,17 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
Sema::ReferenceCompareResult NewRefRelationship
= S.CompareReferenceRelationship(DeclLoc, T1, T2.getNonReferenceType(),
NewDerivedToBase);
- assert(NewRefRelationship != Sema::Ref_Incompatible &&
- "Overload resolution picked a bad conversion function");
- (void)NewRefRelationship;
- if (NewDerivedToBase)
+ if (NewRefRelationship == Sema::Ref_Incompatible) {
+ // If the type we've converted to is not reference-related to the
+ // type we're looking for, then there is another conversion step
+ // we need to perform to produce a temporary of the right type
+ // that we'll be binding to.
+ ImplicitConversionSequence ICS;
+ ICS.setStandard();
+ ICS.Standard = Best->FinalConversion;
+ T2 = ICS.Standard.getToType(2);
+ Sequence.AddConversionSequenceStep(ICS, T2);
+ } else if (NewDerivedToBase)
Sequence.AddDerivedToBaseCastStep(
S.Context.getQualifiedType(T1,
T2.getNonReferenceType().getQualifiers()),
diff --git a/test/SemaCXX/overload-call.cpp b/test/SemaCXX/overload-call.cpp
index 77e0908ef4..c286028c29 100644
--- a/test/SemaCXX/overload-call.cpp
+++ b/test/SemaCXX/overload-call.cpp
@@ -386,3 +386,23 @@ namespace DerivedToBase {
float &fr = f0(C());
}
}
+
+namespace PR6483 {
+ struct X0 {
+ operator const unsigned int & () const;
+ };
+
+ struct X1 {
+ operator unsigned int & () const;
+ };
+
+ void f0(const bool &);
+ void f1(bool &); // expected-note 2{{not viable}}
+
+ void g(X0 x0, X1 x1) {
+ f0(x0);
+ f1(x0); // expected-error{{no matching function for call}}
+ f0(x1);
+ f1(x1); // expected-error{{no matching function for call}}
+ }
+}