From: Douglas Gregor Date: Sun, 12 Sep 2010 08:07:23 +0000 (+0000) Subject: When performing overload resolution, only compare the final conversion X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=8fcc516a5d5b2fec0023a9dced29285a38b95355;p=clang 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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@113724 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Sema/Overload.h b/include/clang/Sema/Overload.h index 851d68ac4d..404d895756 100644 --- a/include/clang/Sema/Overload.h +++ b/include/clang/Sema/Overload.h @@ -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 diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index fe10422935..60d2acec07 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -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(); diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 7fa35269f9..cf67f0bdd0 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -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(Cand1.Function) && isa(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; } diff --git a/test/SemaCXX/conversion-function.cpp b/test/SemaCXX/conversion-function.cpp index 8d5e01039c..61c8ada62f 100644 --- a/test/SemaCXX/conversion-function.cpp +++ b/test/SemaCXX/conversion-function.cpp @@ -343,3 +343,13 @@ namespace PR8065 { Container test; } + +namespace PR8034 { + struct C { + operator int(); + + private: + template operator T(); + }; + int x = C().operator int(); +}