From 99d6c445cc968bdf08c53a6bd4e9044bde43bdd1 Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Mon, 28 Sep 2009 19:06:58 +0000 Subject: [PATCH] Multiple conversions to the same type are ambiguous but for the purpose of overload resolution is to be treated as a uner-defined conversion. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@83004 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaOverload.cpp | 18 ++++++-- .../ambig-user-defined-conversions.cpp | 42 +++++++++++++++---- 2 files changed, 48 insertions(+), 12 deletions(-) diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 793041b9b7..885f59c5aa 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -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 diff --git a/test/SemaCXX/ambig-user-defined-conversions.cpp b/test/SemaCXX/ambig-user-defined-conversions.cpp index 1117253d36..94598f0e8e 100644 --- a/test/SemaCXX/ambig-user-defined-conversions.cpp +++ b/test/SemaCXX/ambig-user-defined-conversions.cpp @@ -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. +} + -- 2.40.0