From: Fariborz Jahanian Date: Mon, 12 Oct 2009 20:11:40 +0000 (+0000) Subject: Handle built-in unary operators when reporting ambiguities. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2ebe7ebb1d6149a1845dd3169009f99b78e91bc9;p=clang Handle built-in unary operators when reporting ambiguities. wip - To prune excessive reporting. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@83889 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index b81278f037..252cfd2718 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -786,7 +786,10 @@ def err_ovl_template_candidate : Note< "candidate function template specialization %0">; def err_ovl_candidate_deleted : Note< "candidate function has been explicitly %select{made unavailable|deleted}0">; -def err_ovl_builtin_candidate : Note<"built-in candidate operator %2 (%0, %1)">; +def err_ovl_builtin_binary_candidate : Note< + "built-in candidate operator %0 (%1, %2)">; +def err_ovl_builtin_unary_candidate : Note< + "built-in candidate operator %0 (%1)">; def err_ovl_no_viable_function_in_init : Error< "no matching constructor for initialization of %0">; def err_ovl_ambiguous_init : Error<"call to constructor of %0 is ambiguous">; diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index a889eeefe8..7b6fa47e28 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -916,7 +916,7 @@ public: OverloadCandidateSet::iterator& Best); void PrintOverloadCandidates(OverloadCandidateSet& CandidateSet, bool OnlyViable, - BinaryOperator::Opcode Opc=(BinaryOperator::Opcode)0, + const char *Opc=0, SourceLocation Loc=SourceLocation()); FunctionDecl *ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType, diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 27d34ef434..7744ae7c59 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -3973,7 +3973,7 @@ Sema::BestViableFunction(OverloadCandidateSet& CandidateSet, void Sema::PrintOverloadCandidates(OverloadCandidateSet& CandidateSet, bool OnlyViable, - BinaryOperator::Opcode Opc, + const char *Opc, SourceLocation OpLoc) { OverloadCandidateSet::iterator Cand = CandidateSet.begin(), LastCand = CandidateSet.end(); @@ -4048,20 +4048,22 @@ Sema::PrintOverloadCandidates(OverloadCandidateSet& CandidateSet, Diag(Cand->Surrogate->getLocation(), diag::err_ovl_surrogate_cand) << FnType; } else if (OnlyViable) { - assert(Cand->Conversions.size() == 2 && + assert(Cand->Conversions.size() <= 2 && "builtin-binary-operator-not-binary"); - Diag(OpLoc, diag::err_ovl_builtin_candidate) - << Cand->BuiltinTypes.ParamTypes[0] - << Cand->BuiltinTypes.ParamTypes[1] - << BinaryOperator::getOpcodeStr(Opc); + if (Cand->Conversions.size() == 1) + Diag(OpLoc, diag::err_ovl_builtin_unary_candidate) + << Opc << Cand->BuiltinTypes.ParamTypes[0]; + else + Diag(OpLoc, diag::err_ovl_builtin_binary_candidate) + << Opc << Cand->BuiltinTypes.ParamTypes[0] + << Cand->BuiltinTypes.ParamTypes[1]; } 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) { + unsigned NoOperands = Cand->Conversions.size(); + for (unsigned ArgIdx = 0; ArgIdx < NoOperands; ++ArgIdx) { const ImplicitConversionSequence &ICS = Cand->Conversions[ArgIdx]; if (ICS.ConversionKind != ImplicitConversionSequence::BadConversion || ICS.ConversionFunctionSet.empty()) @@ -4559,7 +4561,8 @@ Sema::OwningExprResult Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, Diag(OpLoc, diag::err_ovl_ambiguous_oper) << UnaryOperator::getOpcodeStr(Opc) << Input->getSourceRange(); - PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true); + PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true, + UnaryOperator::getOpcodeStr(Opc), OpLoc); return ExprError(); case OR_Deleted: @@ -4733,7 +4736,8 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, assert(Result.isInvalid() && "C++ binary operator overloading is missing candidates!"); if (Result.isInvalid()) - PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/false, Opc, OpLoc); + PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/false, + BinaryOperator::getOpcodeStr(Opc), OpLoc); return move(Result); } @@ -4741,7 +4745,8 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, Diag(OpLoc, diag::err_ovl_ambiguous_oper) << BinaryOperator::getOpcodeStr(Opc) << Args[0]->getSourceRange() << Args[1]->getSourceRange(); - PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true, Opc, OpLoc); + PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true, + BinaryOperator::getOpcodeStr(Opc), OpLoc); return ExprError(); case OR_Deleted: diff --git a/test/SemaCXX/ambiguous-builtin-unary-operator.cpp b/test/SemaCXX/ambiguous-builtin-unary-operator.cpp new file mode 100644 index 0000000000..042546af69 --- /dev/null +++ b/test/SemaCXX/ambiguous-builtin-unary-operator.cpp @@ -0,0 +1,18 @@ +// RUN: clang-cc -fsyntax-only -verify %s -std=c++0x + +struct A { + operator int&(); +}; + +struct B { + operator long&(); +}; + +struct C : B, A { }; + +void test(C c) { + ++c; // expected-error {{use of overloaded operator '++' is ambiguous}}\ + // expected-note 4 {{built-in candidate operator ++ (}} +} + +