From 574de2c5a4f025808eda36c55f871f78d585dc96 Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Mon, 12 Oct 2009 17:51:19 +0000 Subject: If built-in operators could not be selected because of ambiguity in user-defined type conversions, issue list of ambiguites in addition to the diagnostic. So, clang now issues the following: b.cpp:19:19: error: left hand operand to ->* must be a pointer to class compatible with the right hand operand, but is 'struct C1' int i = c1->*pmf; ~~^ b.cpp:19:19: note: because of ambiguity in conversion of 'struct C1' to 'struct E *' b.cpp:5:5: note: candidate function operator E*(); ^ b.cpp:11:5: note: candidate function operator E*(); ^ llvm-svn: 83862 --- clang/lib/Sema/SemaOverload.cpp | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) (limited to 'clang/lib/Sema/SemaOverload.cpp') diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 30ac59e4ca7..27d34ef4345 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -464,7 +464,8 @@ Sema::TryImplicitConversion(Expr* From, QualType ToType, if (UserDefResult == OR_Ambiguous) { for (OverloadCandidateSet::iterator Cand = Conversions.begin(); Cand != Conversions.end(); ++Cand) - ICS.ConversionFunctionSet.push_back(Cand->Function); + if (Cand->Viable) + ICS.ConversionFunctionSet.push_back(Cand->Function); } } @@ -3976,6 +3977,7 @@ Sema::PrintOverloadCandidates(OverloadCandidateSet& CandidateSet, SourceLocation OpLoc) { OverloadCandidateSet::iterator Cand = CandidateSet.begin(), LastCand = CandidateSet.end(); + bool Reported = false; for (; Cand != LastCand; ++Cand) { if (Cand->Viable || !OnlyViable) { if (Cand->Function) { @@ -4053,6 +4055,33 @@ Sema::PrintOverloadCandidates(OverloadCandidateSet& CandidateSet, << Cand->BuiltinTypes.ParamTypes[1] << BinaryOperator::getOpcodeStr(Opc); } + else if (!Cand->Viable && !Reported) { + // Non-viability might be due to ambiguous user-defined conversions, + // needed for built-in operators. Report them as well, but only once + // as we have typically many built-in candidates. + assert(Cand->Conversions.size() == 2 && + "builtin-binary-operator-not-binary"); + for (unsigned ArgIdx = 0; ArgIdx < 2; ++ArgIdx) { + const ImplicitConversionSequence &ICS = Cand->Conversions[ArgIdx]; + if (ICS.ConversionKind != ImplicitConversionSequence::BadConversion || + ICS.ConversionFunctionSet.empty()) + continue; + if (CXXConversionDecl *Func = dyn_cast( + Cand->Conversions[ArgIdx].ConversionFunctionSet[0])) { + QualType FromTy = + QualType( + static_cast(ICS.UserDefined.Before.FromTypePtr),0); + Diag(OpLoc,diag::note_ambiguous_type_conversion) + << FromTy << Func->getConversionType(); + } + for (unsigned j = 0; j < ICS.ConversionFunctionSet.size(); j++) { + FunctionDecl *Func = + Cand->Conversions[ArgIdx].ConversionFunctionSet[j]; + Diag(Func->getLocation(),diag::err_ovl_candidate); + } + } + Reported = true; + } } } } @@ -4704,7 +4733,7 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, assert(Result.isInvalid() && "C++ binary operator overloading is missing candidates!"); if (Result.isInvalid()) - PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/false); + PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/false, Opc, OpLoc); return move(Result); } -- cgit v1.2.3