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
diff --git a/lib/Basic/Diagnostic.cpp b/lib/Basic/Diagnostic.cpp
index 2fd985f..a2480b1 100644
--- a/lib/Basic/Diagnostic.cpp
+++ b/lib/Basic/Diagnostic.cpp
@@ -250,6 +250,7 @@
   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 d45676d..d47efbc 100644
--- a/lib/Driver/Tools.cpp
+++ b/lib/Driver/Tools.cpp
@@ -1381,6 +1381,9 @@
                     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 9bc8b76..b2f1ec6 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -869,7 +869,18 @@
   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 84c4f5d..8cc5616 100644
--- a/lib/Frontend/Warnings.cpp
+++ b/lib/Frontend/Warnings.cpp
@@ -35,6 +35,8 @@
                                   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)
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 721c68f..eda7e7a 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -5689,7 +5689,10 @@
       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 @@
   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 @@
       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) {