aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2010-09-12 08:07:23 +0000
committerDouglas Gregor <dgregor@apple.com>2010-09-12 08:07:23 +0000
commit8fcc516a5d5b2fec0023a9dced29285a38b95355 (patch)
treeb23ca737524fdd1cb440bac909b0a14d4cef6b5a
parentc6dbc3fa467e2355b678a6b717534928048efcb2 (diff)
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
-rw-r--r--include/clang/Sema/Overload.h6
-rw-r--r--lib/Sema/SemaInit.cpp15
-rw-r--r--lib/Sema/SemaOverload.cpp18
-rw-r--r--test/SemaCXX/conversion-function.cpp10
4 files changed, 33 insertions, 16 deletions
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<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;
}
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<int> test;
}
+
+namespace PR8034 {
+ struct C {
+ operator int();
+
+ private:
+ template <typename T> operator T();
+ };
+ int x = C().operator int();
+}