From 5edbdcc62098e305cd55654814dcf783a3f3c477 Mon Sep 17 00:00:00 2001 From: Jeffrey Yasskin Date: Fri, 11 Jun 2010 05:57:47 +0000 Subject: [PATCH] Add an option -fshow-overloads=best|all to limit the number of overload candidates printed. We default to 'all'. At the moment, 'best' prints only the first 4 overloads, but we'll improve that over time. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@105815 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/Diagnostic.h | 17 ++++++++++++- include/clang/Basic/DiagnosticSemaKinds.td | 3 +++ include/clang/Driver/CC1Options.td | 3 +++ include/clang/Driver/Options.td | 1 + include/clang/Frontend/DiagnosticOptions.h | 5 ++++ lib/Basic/Diagnostic.cpp | 1 + lib/Driver/Tools.cpp | 3 +++ lib/Frontend/CompilerInvocation.cpp | 13 +++++++++- lib/Frontend/Warnings.cpp | 2 ++ lib/Sema/SemaOverload.cpp | 25 +++++++++++++++---- test/SemaCXX/overloaded-builtin-operators.cpp | 5 ++-- 11 files changed, 69 insertions(+), 9 deletions(-) diff --git a/include/clang/Basic/Diagnostic.h b/include/clang/Basic/Diagnostic.h index 62f06edb77..a4221e0ff4 100644 --- a/include/clang/Basic/Diagnostic.h +++ b/include/clang/Basic/Diagnostic.h @@ -176,7 +176,14 @@ public: ak_nestednamespec, // NestedNameSpecifier * ak_declcontext // DeclContext * }; - + + /// Specifies which overload candidates to display when overload resolution + /// fails. + enum OverloadsShown { + Ovl_All, ///< Show all overloads. + Ovl_Best ///< Show just the "best" overload candidates. + }; + /// ArgumentValue - This typedef represents on argument value, which is a /// union discriminated by ArgumentKind, with a value. typedef std::pair ArgumentValue; @@ -188,6 +195,7 @@ private: bool ErrorsAsFatal; // Treat errors like fatal errors. bool SuppressSystemWarnings; // Suppress warnings in system headers. bool SuppressAllDiagnostics; // Suppress all diagnostics. + OverloadsShown ShowOverloads; // Which overload candidates to show. unsigned ErrorLimit; // Cap of # errors emitted, 0 -> no limit. unsigned TemplateBacktraceLimit; // Cap on depth of template backtrace stack, // 0 -> no limit. @@ -318,6 +326,13 @@ public: } bool getSuppressAllDiagnostics() const { return SuppressAllDiagnostics; } + /// \brief Specify which overload candidates to show when overload resolution + /// fails. By default, we show all candidates. + void setShowOverloads(OverloadsShown Val) { + ShowOverloads = Val; + } + OverloadsShown getShowOverloads() const { return ShowOverloads; } + /// \brief Pretend that the last diagnostic issued was ignored. This can /// be used by clients who suppress diagnostics themselves. void setLastDiagnosticIgnored() { diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 24d72193f1..c272aed7ea 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -1091,6 +1091,9 @@ def err_ovl_ambiguous_member_call : Error< "call to member function %0 is ambiguous">; def err_ovl_deleted_member_call : Error< "call to %select{unavailable|deleted}0 member function %1">; +def note_ovl_too_many_candidates : Note< + "remaining %0 candidate%s0 omitted; " + "pass -fshow-overloads=all to show them">; def note_ovl_candidate : Note<"candidate " "%select{function|function|constructor|" "function |function |constructor |" diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index 59c49301b3..a9e0165b0a 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -184,6 +184,9 @@ def fno_show_column : Flag<"-fno-show-column">, HelpText<"Do not include column number on diagnostics">; def fno_show_source_location : Flag<"-fno-show-source-location">, HelpText<"Do not include source location information with diagnostics">; +def fshow_overloads_EQ : Joined<"-fshow-overloads=">, + HelpText<"Which overload candidates to show when overload resolution fails: " + "best|all; defaults to all">; def fno_caret_diagnostics : Flag<"-fno-caret-diagnostics">, HelpText<"Do not include source line and caret with diagnostics">; def fno_diagnostics_fixit_info : Flag<"-fno-diagnostics-fixit-info">, diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index 8f1346c762..68604aaf71 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -359,6 +359,7 @@ def fsched_interblock : Flag<"-fsched-interblock">, Group def fshort_enums : Flag<"-fshort-enums">, Group; def freorder_blocks : Flag<"-freorder-blocks">, Group; def fshort_wchar : Flag<"-fshort-wchar">, Group; +def fshow_overloads_EQ : Joined<"-fshow-overloads=">, Group; def fshow_source_location : Flag<"-fshow-source-location">, Group; def fsigned_bitfields : Flag<"-fsigned-bitfields">, Group; def fsigned_char : Flag<"-fsigned-char">, Group; diff --git a/include/clang/Frontend/DiagnosticOptions.h b/include/clang/Frontend/DiagnosticOptions.h index 8eb66e57da..516dc67b42 100644 --- a/include/clang/Frontend/DiagnosticOptions.h +++ b/include/clang/Frontend/DiagnosticOptions.h @@ -10,6 +10,8 @@ #ifndef LLVM_CLANG_FRONTEND_DIAGNOSTICOPTIONS_H #define LLVM_CLANG_FRONTEND_DIAGNOSTICOPTIONS_H +#include "clang/Basic/Diagnostic.h" + #include #include @@ -33,6 +35,8 @@ public: unsigned ShowCategories : 2; /// Show categories: 0 -> none, 1 -> Number, /// 2 -> Full Name. unsigned ShowColors : 1; /// Show diagnostics with ANSI color sequences. + unsigned ShowOverloads : 1; /// Overload candidates to show. Values from + /// Diagnostic::OverloadsShown unsigned VerifyDiagnostics: 1; /// Check that diagnostics match the expected /// diagnostics, indicated by markers in the /// input source file. @@ -72,6 +76,7 @@ public: PedanticErrors = 0; ShowCarets = 1; ShowColors = 0; + ShowOverloads = Diagnostic::Ovl_All; ShowColumn = 1; ShowFixits = 1; ShowLocation = 1; diff --git a/lib/Basic/Diagnostic.cpp b/lib/Basic/Diagnostic.cpp index 2fd985f538..a2480b1684 100644 --- a/lib/Basic/Diagnostic.cpp +++ b/lib/Basic/Diagnostic.cpp @@ -250,6 +250,7 @@ Diagnostic::Diagnostic(DiagnosticClient *client) : Client(client) { ErrorsAsFatal = false; SuppressSystemWarnings = false; SuppressAllDiagnostics = false; + ShowOverloads = Ovl_All; ExtBehavior = Ext_Ignore; ErrorOccurred = false; diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp index d45676dda8..d47efbc8e8 100644 --- a/lib/Driver/Tools.cpp +++ b/lib/Driver/Tools.cpp @@ -1381,6 +1381,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, options::OPT_fno_show_source_location)) CmdArgs.push_back("-fno-show-source-location"); + if (Arg *A = Args.getLastArg(options::OPT_fshow_overloads_EQ)) + A->render(Args, CmdArgs); + // -fdollars-in-identifiers default varies depending on platform and // language; only pass if specified. if (Arg *A = Args.getLastArg(options::OPT_fdollars_in_identifiers, diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 9bc8b76de8..b2f1ec6fc0 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -869,7 +869,18 @@ static void ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args, Opts.ShowFixits = !Args.hasArg(OPT_fno_diagnostics_fixit_info); Opts.ShowLocation = !Args.hasArg(OPT_fno_show_source_location); Opts.ShowOptionNames = Args.hasArg(OPT_fdiagnostics_show_option); - + + llvm::StringRef ShowOverloads = + Args.getLastArgValue(OPT_fshow_overloads_EQ, "all"); + if (ShowOverloads == "best") + Opts.ShowOverloads = Diagnostic::Ovl_Best; + else if (ShowOverloads == "all") + Opts.ShowOverloads = Diagnostic::Ovl_All; + else + Diags.Report(diag::err_drv_invalid_value) + << Args.getLastArg(OPT_fshow_overloads_EQ)->getAsString(Args) + << ShowOverloads; + llvm::StringRef ShowCategory = Args.getLastArgValue(OPT_fdiagnostics_show_category, "none"); if (ShowCategory == "none") diff --git a/lib/Frontend/Warnings.cpp b/lib/Frontend/Warnings.cpp index 84c4f5d40f..8cc56168e0 100644 --- a/lib/Frontend/Warnings.cpp +++ b/lib/Frontend/Warnings.cpp @@ -35,6 +35,8 @@ void clang::ProcessWarningOptions(Diagnostic &Diags, const DiagnosticOptions &Opts) { Diags.setSuppressSystemWarnings(true); // Default to -Wno-system-headers Diags.setIgnoreAllWarnings(Opts.IgnoreWarnings); + Diags.setShowOverloads( + static_cast(Opts.ShowOverloads)); // Handle -ferror-limit if (Opts.ErrorLimit) diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 721c68f6c1..eda7e7ad88 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -5689,7 +5689,10 @@ Sema::PrintOverloadCandidates(OverloadCandidateSet& CandidateSet, Cands.push_back(Cand); else if (OCD == OCD_AllCandidates) { CompleteNonViableCandidate(*this, Cand, Args, NumArgs); - Cands.push_back(Cand); + if (Cand->Function || Cand->IsSurrogate) + Cands.push_back(Cand); + // Otherwise, this a non-viable builtin candidate. We do not, in general, + // want to list every possible builtin candidate. } } @@ -5699,17 +5702,26 @@ Sema::PrintOverloadCandidates(OverloadCandidateSet& CandidateSet, bool ReportedAmbiguousConversions = false; llvm::SmallVectorImpl::iterator I, E; + const Diagnostic::OverloadsShown ShowOverloads = Diags.getShowOverloads(); + unsigned CandsShown = 0; for (I = Cands.begin(), E = Cands.end(); I != E; ++I) { OverloadCandidate *Cand = *I; + // Set an arbitrary limit on the number of candidate functions we'll spam + // the user with. FIXME: This limit should depend on details of the + // candidate list. + if (CandsShown >= 4 && ShowOverloads == Diagnostic::Ovl_Best) { + break; + } + ++CandsShown; + if (Cand->Function) NoteFunctionCandidate(*this, Cand, Args, NumArgs); else if (Cand->IsSurrogate) NoteSurrogateCandidate(*this, Cand); - - // This a builtin candidate. We do not, in general, want to list - // every possible builtin candidate. - else if (Cand->Viable) { + else { + assert(Cand->Viable && + "Non-viable built-in candidates are not added to Cands."); // Generally we only see ambiguities including viable builtin // operators if overload resolution got screwed up by an // ambiguous user-defined conversion. @@ -5725,6 +5737,9 @@ Sema::PrintOverloadCandidates(OverloadCandidateSet& CandidateSet, NoteBuiltinOperatorCandidate(*this, Opc, OpLoc, Cand); } } + + if (I != E) + Diag(OpLoc, diag::note_ovl_too_many_candidates) << E - I; } static bool CheckUnresolvedAccess(Sema &S, OverloadExpr *E, DeclAccessPair D) { diff --git a/test/SemaCXX/overloaded-builtin-operators.cpp b/test/SemaCXX/overloaded-builtin-operators.cpp index 1ba9452466..8a49671f1a 100644 --- a/test/SemaCXX/overloaded-builtin-operators.cpp +++ b/test/SemaCXX/overloaded-builtin-operators.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -fshow-overloads=best -verify %s struct yes; struct no; @@ -173,7 +173,8 @@ struct A { void test_dr425(A a) { // FIXME: lots of candidates here! (void)(1.0f * a); // expected-error{{ambiguous}} \ - // expected-note 81{{candidate}} + // expected-note 4{{candidate}} \ + // expected-note {{remaining 77 candidates omitted; pass -fshow-overloads=all to show them}} } // pr5432 -- 2.40.0