When performing overload resolution, only compare the final conversion

sequences for two conversion functions when in fact we are in the text
of initialization by a user-defined conversion sequences. Fixes PR8034.

llvm-svn: 113724
This commit is contained in:
Douglas Gregor 2010-09-12 08:07:23 +00:00
parent 6162334ce0
commit d5b730c9d5
4 changed files with 33 additions and 16 deletions

View File

@ -630,7 +630,8 @@ namespace clang {
/// Find the best viable function on this overload set, if it exists.
OverloadingResult BestViableFunction(Sema &S, SourceLocation Loc,
OverloadCandidateSet::iterator& Best);
OverloadCandidateSet::iterator& Best,
bool UserDefinedConversion = false);
void NoteCandidates(Sema &S,
OverloadCandidateDisplayKind OCD,
@ -642,7 +643,8 @@ namespace clang {
bool isBetterOverloadCandidate(Sema &S,
const OverloadCandidate& Cand1,
const OverloadCandidate& Cand2,
SourceLocation Loc);
SourceLocation Loc,
bool UserDefinedConversion = false);
} // end namespace clang
#endif // LLVM_CLANG_SEMA_OVERLOAD_H

View File

@ -2389,7 +2389,7 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
// Perform overload resolution. If it fails, return the failed result.
OverloadCandidateSet::iterator Best;
if (OverloadingResult Result
= CandidateSet.BestViableFunction(S, DeclLoc, Best))
= CandidateSet.BestViableFunction(S, DeclLoc, Best, true))
return Result;
FunctionDecl *Function = Best->Function;
@ -2981,7 +2981,7 @@ static void TryUserDefinedConversion(Sema &S,
// Perform overload resolution. If it fails, return the failed result.
OverloadCandidateSet::iterator Best;
if (OverloadingResult Result
= CandidateSet.BestViableFunction(S, DeclLoc, Best)) {
= CandidateSet.BestViableFunction(S, DeclLoc, Best, true)) {
Sequence.SetOverloadFailure(
InitializationSequence::FK_UserConversionOverloadFailed,
Result);
@ -3276,10 +3276,10 @@ static bool shouldDestroyTemporary(const InitializedEntity &Entity) {
/// a temporary object, or an error expression if a copy could not be
/// created.
static ExprResult CopyObject(Sema &S,
QualType T,
const InitializedEntity &Entity,
ExprResult CurInit,
bool IsExtraneousCopy) {
QualType T,
const InitializedEntity &Entity,
ExprResult CurInit,
bool IsExtraneousCopy) {
// Determine which class type we're copying to.
Expr *CurInitExpr = (Expr *)CurInit.get();
CXXRecordDecl *Class = 0;
@ -4033,7 +4033,8 @@ bool InitializationSequence::Diagnose(Sema &S,
<< Args[0]->getSourceRange();
OverloadCandidateSet::iterator Best;
OverloadingResult Ovl
= FailedCandidateSet.BestViableFunction(S, Kind.getLocation(), Best);
= FailedCandidateSet.BestViableFunction(S, Kind.getLocation(), Best,
true);
if (Ovl == OR_Deleted) {
S.Diag(Best->Function->getLocation(), diag::note_unavailable_here)
<< Best->Function->isDeleted();

View File

@ -2041,7 +2041,7 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
}
OverloadCandidateSet::iterator Best;
switch (CandidateSet.BestViableFunction(S, From->getLocStart(), Best)) {
switch (CandidateSet.BestViableFunction(S, From->getLocStart(), Best, true)) {
case OR_Success:
// Record the standard conversion we used and the conversion function.
if (CXXConstructorDecl *Constructor
@ -2769,7 +2769,7 @@ FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS,
}
OverloadCandidateSet::iterator Best;
switch (CandidateSet.BestViableFunction(S, DeclLoc, Best)) {
switch (CandidateSet.BestViableFunction(S, DeclLoc, Best, true)) {
case OR_Success:
// C++ [over.ics.ref]p1:
//
@ -5329,7 +5329,8 @@ bool
isBetterOverloadCandidate(Sema &S,
const OverloadCandidate& Cand1,
const OverloadCandidate& Cand2,
SourceLocation Loc) {
SourceLocation Loc,
bool UserDefinedConversion) {
// Define viable functions to be better candidates than non-viable
// functions.
if (!Cand2.Viable)
@ -5404,7 +5405,7 @@ isBetterOverloadCandidate(Sema &S,
// the type of the entity being initialized) is a better
// conversion sequence than the standard conversion sequence
// from the return type of F2 to the destination type.
if (Cand1.Function && Cand2.Function &&
if (UserDefinedConversion && Cand1.Function && Cand2.Function &&
isa<CXXConversionDecl>(Cand1.Function) &&
isa<CXXConversionDecl>(Cand2.Function)) {
switch (CompareStandardConversionSequences(S,
@ -5441,12 +5442,14 @@ isBetterOverloadCandidate(Sema &S,
/// \returns The result of overload resolution.
OverloadingResult
OverloadCandidateSet::BestViableFunction(Sema &S, SourceLocation Loc,
iterator& Best) {
iterator& Best,
bool UserDefinedConversion) {
// Find the best viable function.
Best = end();
for (iterator Cand = begin(); Cand != end(); ++Cand) {
if (Cand->Viable)
if (Best == end() || isBetterOverloadCandidate(S, *Cand, *Best, Loc))
if (Best == end() || isBetterOverloadCandidate(S, *Cand, *Best, Loc,
UserDefinedConversion))
Best = Cand;
}
@ -5459,7 +5462,8 @@ OverloadCandidateSet::BestViableFunction(Sema &S, SourceLocation Loc,
for (iterator Cand = begin(); Cand != end(); ++Cand) {
if (Cand->Viable &&
Cand != Best &&
!isBetterOverloadCandidate(S, *Best, *Cand, Loc)) {
!isBetterOverloadCandidate(S, *Best, *Cand, Loc,
UserDefinedConversion)) {
Best = end();
return OR_Ambiguous;
}

View File

@ -343,3 +343,13 @@ namespace PR8065 {
Container<int> test;
}
namespace PR8034 {
struct C {
operator int();
private:
template <typename T> operator T();
};
int x = C().operator int();
}