]> granicus.if.org Git - clang/commitdiff
Add an option -fshow-overloads=best|all to limit the number of overload
authorJeffrey Yasskin <jyasskin@google.com>
Fri, 11 Jun 2010 05:57:47 +0000 (05:57 +0000)
committerJeffrey Yasskin <jyasskin@google.com>
Fri, 11 Jun 2010 05:57:47 +0000 (05:57 +0000)
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
include/clang/Basic/DiagnosticSemaKinds.td
include/clang/Driver/CC1Options.td
include/clang/Driver/Options.td
include/clang/Frontend/DiagnosticOptions.h
lib/Basic/Diagnostic.cpp
lib/Driver/Tools.cpp
lib/Frontend/CompilerInvocation.cpp
lib/Frontend/Warnings.cpp
lib/Sema/SemaOverload.cpp
test/SemaCXX/overloaded-builtin-operators.cpp

index 62f06edb7785f13803d13c2b0f56f3484afc3796..a4221e0ff4417fbac61a063b4393394b595b7877 100644 (file)
@@ -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<ArgumentKind, intptr_t> 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() {
index 24d72193f1308acdda12e623ebbdaa7b65325109..c272aed7eaa5e913327d13502f28bc84927ccfbd 100644 (file)
@@ -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 |"
index 59c49301b32584cb1408d628a49c9c493d9a05f5..a9e0165b0afc0b3e7666c8cd5fd5d79b2263e338 100644 (file)
@@ -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">,
index 8f1346c7625d9714bc91d4942cdd1ef63f37bbe3..68604aaf7119493e68667deb0e96f75f6892629a 100644 (file)
@@ -359,6 +359,7 @@ def fsched_interblock : Flag<"-fsched-interblock">, Group<clang_ignored_f_Group>
 def fshort_enums : Flag<"-fshort-enums">, Group<clang_ignored_f_Group>;
 def freorder_blocks : Flag<"-freorder-blocks">, Group<clang_ignored_f_Group>;
 def fshort_wchar : Flag<"-fshort-wchar">, Group<f_Group>;
+def fshow_overloads_EQ : Joined<"-fshow-overloads=">, Group<f_Group>;
 def fshow_source_location : Flag<"-fshow-source-location">, Group<f_Group>;
 def fsigned_bitfields : Flag<"-fsigned-bitfields">, Group<f_Group>;
 def fsigned_char : Flag<"-fsigned-char">, Group<f_Group>;
index 8eb66e57da923b24db2ec0bec5f5271c4b3e433c..516dc67b425d443f8bf5a30c0960e69ab744195f 100644 (file)
@@ -10,6 +10,8 @@
 #ifndef LLVM_CLANG_FRONTEND_DIAGNOSTICOPTIONS_H
 #define LLVM_CLANG_FRONTEND_DIAGNOSTICOPTIONS_H
 
+#include "clang/Basic/Diagnostic.h"
+
 #include <string>
 #include <vector>
 
@@ -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;
index 2fd985f538036a1f31178cf701189edcf870ff70..a2480b16843195484351019ac67f498c85285e4b 100644 (file)
@@ -250,6 +250,7 @@ Diagnostic::Diagnostic(DiagnosticClient *client) : Client(client) {
   ErrorsAsFatal = false;
   SuppressSystemWarnings = false;
   SuppressAllDiagnostics = false;
+  ShowOverloads = Ovl_All;
   ExtBehavior = Ext_Ignore;
 
   ErrorOccurred = false;
index d45676dda8e1e46d0a1bb9b650e4f8bd140ed403..d47efbc8e8411132e741a5ba8044d82fc4147517 100644 (file)
@@ -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,
index 9bc8b76de8941a012622c0e72744222ee26850d1..b2f1ec6fc0857375dbb5cb8bcafefb693ff59e75 100644 (file)
@@ -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")
index 84c4f5d40faf1c702efb095c63341bc7a52e3863..8cc56168e0f8fa2a8084a9b1130498660ba0042f 100644 (file)
@@ -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<Diagnostic::OverloadsShown>(Opts.ShowOverloads));
   
   // Handle -ferror-limit
   if (Opts.ErrorLimit)
index 721c68f6c1dbd8be34d2712e3cbf0f796f712b9e..eda7e7ad885d3a06574b864a33e49ff89d97113f 100644 (file)
@@ -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<OverloadCandidate*>::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) {
index 1ba945246663aea235990e64ae4229c873dd886b..8a49671f1ab898c744ba4b5aded21572f1917c10 100644 (file)
@@ -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