Multiple conversions to the same type are ambiguous but for the

purpose of overload resolution is to be treated as a uner-defined
conversion.

llvm-svn: 83004
This commit is contained in:
Fariborz Jahanian 2009-09-28 19:06:58 +00:00
parent 5ad7c54bb9
commit c9c3917a86
2 changed files with 48 additions and 12 deletions

View File

@ -1511,8 +1511,6 @@ Sema::OverloadingResult Sema::IsUserDefinedConversion(
return OR_Deleted;
case OR_Ambiguous:
// FIXME: See C++ [over.best.ics]p10 for the handling of
// ambiguous conversion sequences.
return OR_Ambiguous;
}
@ -2236,8 +2234,20 @@ Sema::AddOverloadCandidate(FunctionDecl *Function,
/*InOverloadResolution=*/true);
if (Candidate.Conversions[ArgIdx].ConversionKind
== ImplicitConversionSequence::BadConversion) {
Candidate.Viable = false;
break;
// 13.3.3.1-p10 If several different sequences of conversions exist that
// each convert the argument to the parameter type, the implicit conversion
// sequence associated with the parameter is defined to be the unique conversion
// sequence designated the ambiguous conversion sequence. For the purpose of
// ranking implicit conversion sequences as described in 13.3.3.2, the ambiguous
// conversion sequence is treated as a user-defined sequence that is
// indistinguishable from any other user-defined conversion sequence
if (Candidate.Conversions[ArgIdx].ConversionFunctionSet.size() > 0)
Candidate.Conversions[ArgIdx].ConversionKind =
ImplicitConversionSequence::UserDefinedConversion;
else {
Candidate.Viable = false;
break;
}
}
} else {
// (C++ 13.3.2p2): For the purposes of overload resolution, any

View File

@ -1,10 +1,11 @@
// RUN: clang-cc -fsyntax-only -verify %s
// Test1
struct BASE {
operator int &(); // expected-note 4 {{candidate function}}
operator int &(); // expected-note {{candidate function}}
};
struct BASE1 {
operator int &(); // expected-note 4 {{candidate function}}
operator int &(); // expected-note {{candidate function}}
};
struct B : public BASE, BASE1 {
@ -14,13 +15,38 @@ struct B : public BASE, BASE1 {
extern B f();
B b1;
void func(const int ci, const char cc); // expected-note {{function not viable because of ambiguity in conversion of argument 1}}
void func(const char ci, const B b); // expected-note {{function not viable because of ambiguity in conversion of argument 1}}
void func(const B b, const int ci); // expected-note {{function not viable because of ambiguity in conversion of argument 2}}
void func(const int ci, const char cc); // expected-note {{candidate function}}
void func(const char ci, const B b); // expected-note {{candidate function}}
void func(const B b, const int ci); // expected-note {{candidate function}}
const int main() {
func(b1, f()); // expected-error {{no matching function for call to 'func'}}
const int Test1() {
func(b1, f()); // expected-error {{call to 'func' is ambiguous}}
return f(); // expected-error {{conversion from 'struct B' to 'int const' is ambiguous}}
}
// Test2
struct E;
struct A {
A (E&);
};
struct E {
operator A ();
};
struct C {
C (E&);
};
void f1(A); // expected-note {{candidate function}}
void f1(C); // expected-note {{candidate function}}
void Test2()
{
E b;
f1(b); // expected-error {{call to 'f1' is ambiguous}}
// ambiguous because b -> C via constructor and
// b → A via constructor or conversion function.
}