Skip to content

Commit 1ce52ca

Browse files
committed
Reference binding via user-defined conversion can compute a binding
that is not reference-related (because it requires another implicit conversion to which we can find). Fixes PR6483. llvm-svn: 97922
1 parent 5cdbd70 commit 1ce52ca

File tree

3 files changed

+44
-14
lines changed

3 files changed

+44
-14
lines changed

clang/lib/Sema/SemaDeclCXX.cpp

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4526,20 +4526,23 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType,
45264526
OverloadCandidateSet::iterator Best;
45274527
switch (BestViableFunction(CandidateSet, DeclLoc, Best)) {
45284528
case OR_Success:
4529+
// C++ [over.ics.ref]p1:
4530+
//
4531+
// [...] If the parameter binds directly to the result of
4532+
// applying a conversion function to the argument
4533+
// expression, the implicit conversion sequence is a
4534+
// user-defined conversion sequence (13.3.3.1.2), with the
4535+
// second standard conversion sequence either an identity
4536+
// conversion or, if the conversion function returns an
4537+
// entity of a type that is a derived class of the parameter
4538+
// type, a derived-to-base Conversion.
4539+
if (!Best->FinalConversion.DirectBinding)
4540+
break;
4541+
45294542
// This is a direct binding.
45304543
BindsDirectly = true;
45314544

45324545
if (ICS) {
4533-
// C++ [over.ics.ref]p1:
4534-
//
4535-
// [...] If the parameter binds directly to the result of
4536-
// applying a conversion function to the argument
4537-
// expression, the implicit conversion sequence is a
4538-
// user-defined conversion sequence (13.3.3.1.2), with the
4539-
// second standard conversion sequence either an identity
4540-
// conversion or, if the conversion function returns an
4541-
// entity of a type that is a derived class of the parameter
4542-
// type, a derived-to-base Conversion.
45434546
ICS->setUserDefined();
45444547
ICS->UserDefined.Before = Best->Conversions[0].Standard;
45454548
ICS->UserDefined.After = Best->FinalConversion;

clang/lib/Sema/SemaInit.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2273,10 +2273,17 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
22732273
Sema::ReferenceCompareResult NewRefRelationship
22742274
= S.CompareReferenceRelationship(DeclLoc, T1, T2.getNonReferenceType(),
22752275
NewDerivedToBase);
2276-
assert(NewRefRelationship != Sema::Ref_Incompatible &&
2277-
"Overload resolution picked a bad conversion function");
2278-
(void)NewRefRelationship;
2279-
if (NewDerivedToBase)
2276+
if (NewRefRelationship == Sema::Ref_Incompatible) {
2277+
// If the type we've converted to is not reference-related to the
2278+
// type we're looking for, then there is another conversion step
2279+
// we need to perform to produce a temporary of the right type
2280+
// that we'll be binding to.
2281+
ImplicitConversionSequence ICS;
2282+
ICS.setStandard();
2283+
ICS.Standard = Best->FinalConversion;
2284+
T2 = ICS.Standard.getToType(2);
2285+
Sequence.AddConversionSequenceStep(ICS, T2);
2286+
} else if (NewDerivedToBase)
22802287
Sequence.AddDerivedToBaseCastStep(
22812288
S.Context.getQualifiedType(T1,
22822289
T2.getNonReferenceType().getQualifiers()),

clang/test/SemaCXX/overload-call.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,3 +386,23 @@ namespace DerivedToBase {
386386
float &fr = f0(C());
387387
}
388388
}
389+
390+
namespace PR6483 {
391+
struct X0 {
392+
operator const unsigned int & () const;
393+
};
394+
395+
struct X1 {
396+
operator unsigned int & () const;
397+
};
398+
399+
void f0(const bool &);
400+
void f1(bool &); // expected-note 2{{not viable}}
401+
402+
void g(X0 x0, X1 x1) {
403+
f0(x0);
404+
f1(x0); // expected-error{{no matching function for call}}
405+
f0(x1);
406+
f1(x1); // expected-error{{no matching function for call}}
407+
}
408+
}

0 commit comments

Comments
 (0)