From 26e82579383ea5d8fcf2149eaba65708893f58dc Mon Sep 17 00:00:00 2001
From: Jan Hubicka <hubicka@ucw.cz>
Date: Sat, 20 Sep 2014 05:06:26 +0200
Subject: [PATCH] diagnostic.c (warning_n): New function.

	* diagnostic.c (warning_n): New function.
	* diagnostic-core.h (warning_n): Declare.
	* ipa-devirt.c (ipa_devirt): Handle singulars correctly;
	output dynamic counts when available.

From-SVN: r215416
---
 gcc/ChangeLog         |  7 ++++
 gcc/diagnostic-core.h |  2 ++
 gcc/diagnostic.c      | 22 ++++++++++++
 gcc/ipa-devirt.c      | 83 +++++++++++++++++++++++++++++++++----------
 4 files changed, 95 insertions(+), 19 deletions(-)

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index ad435363e08d..4c03408368fe 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2014-09-19  Jan Hubicka  <hubicka@ucw.cz>
+
+	* diagnostic.c (warning_n): New function.
+	* diagnostic-core.h (warning_n): Declare.
+	* ipa-devirt.c (ipa_devirt): Handle singulars correctly;
+	output dynamic counts when available.
+
 2014-09-19  Jan Hubicka  <hubicka@ucw.cz>
 
 	PR tree-optimization/63255
diff --git a/gcc/diagnostic-core.h b/gcc/diagnostic-core.h
index 2ff840492ecf..a8245de8985c 100644
--- a/gcc/diagnostic-core.h
+++ b/gcc/diagnostic-core.h
@@ -58,6 +58,8 @@ extern void internal_error (const char *, ...) ATTRIBUTE_GCC_DIAG(1,2)
      ATTRIBUTE_NORETURN;
 /* Pass one of the OPT_W* from options.h as the first parameter.  */
 extern bool warning (int, const char *, ...) ATTRIBUTE_GCC_DIAG(2,3);
+extern bool warning_n (location_t, int, int, const char *, const char *, ...)
+    ATTRIBUTE_GCC_DIAG(4,6) ATTRIBUTE_GCC_DIAG(5,6);
 extern bool warning_at (location_t, int, const char *, ...)
     ATTRIBUTE_GCC_DIAG(3,4);
 extern void error (const char *, ...) ATTRIBUTE_GCC_DIAG(1,2);
diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c
index 73666d62fc7b..881da0b80455 100644
--- a/gcc/diagnostic.c
+++ b/gcc/diagnostic.c
@@ -997,6 +997,28 @@ warning_at (location_t location, int opt, const char *gmsgid, ...)
   return ret;
 }
 
+/* A warning at LOCATION.  Use this for code which is correct according to the
+   relevant language specification but is likely to be buggy anyway.
+   Returns true if the warning was printed, false if it was inhibited.  */
+
+bool
+warning_n (location_t location, int opt, int n, const char *singular_gmsgid,
+	   const char *plural_gmsgid, ...)
+{
+  diagnostic_info diagnostic;
+  va_list ap;
+  bool ret;
+
+  va_start (ap, plural_gmsgid);
+  diagnostic_set_info_translated (&diagnostic,
+                                  ngettext (singular_gmsgid, plural_gmsgid, n),
+                                  &ap, location, DK_WARNING);
+  diagnostic.option_index = opt;
+  ret = report_diagnostic (&diagnostic);
+  va_end (ap);
+  return ret;
+}
+
 /* A "pedantic" warning at LOCATION: issues a warning unless
    -pedantic-errors was given on the command line, in which case it
    issues an error.  Use this for diagnostics required by the relevant
diff --git a/gcc/ipa-devirt.c b/gcc/ipa-devirt.c
index 61e87e80240c..774275b22690 100644
--- a/gcc/ipa-devirt.c
+++ b/gcc/ipa-devirt.c
@@ -4137,12 +4137,31 @@ ipa_devirt (void)
 	    if (final_warning_records->type_warnings[i].count)
 	      {
 	        tree type = final_warning_records->type_warnings[i].type;
-		warning_at (DECL_SOURCE_LOCATION (TYPE_NAME (type)),
-			    OPT_Wsuggest_final_types,
-			    "Declaring type %qD final "
-			    "would enable devirtualization of %i calls",
-			    type,
-			    final_warning_records->type_warnings[i].count);
+	        int count = final_warning_records->type_warnings[i].count;
+	        long long dyn_count
+		  = final_warning_records->type_warnings[i].dyn_count;
+
+		if (!dyn_count)
+		  warning_n (DECL_SOURCE_LOCATION (TYPE_NAME (type)),
+			     OPT_Wsuggest_final_types, count,
+			     "Declaring type %qD final "
+			     "would enable devirtualization of %i call",
+			     "Declaring type %qD final "
+			     "would enable devirtualization of %i calls",
+			     type,
+			     count);
+		else
+		  warning_n (DECL_SOURCE_LOCATION (TYPE_NAME (type)),
+			     OPT_Wsuggest_final_types, count,
+			     "Declaring type %qD final "
+			     "would enable devirtualization of %i call "
+			     "executed %lli times",
+			     "Declaring type %qD final "
+			     "would enable devirtualization of %i calls "
+			     "executed %lli times",
+			     type,
+			     count,
+			     dyn_count);
 	      }
 	}
 
@@ -4157,19 +4176,45 @@ ipa_devirt (void)
 	    {
 	      tree decl = decl_warnings_vec[i]->decl;
 	      int count = decl_warnings_vec[i]->count;
-
-	      if (DECL_CXX_DESTRUCTOR_P (decl))
-		warning_at (DECL_SOURCE_LOCATION (decl),
-			    OPT_Wsuggest_final_methods,
-			    "Declaring virtual destructor of %qD final "
-			    "would enable devirtualization of %i calls",
-			    DECL_CONTEXT (decl), count);
-	      else
-		warning_at (DECL_SOURCE_LOCATION (decl),
-			    OPT_Wsuggest_final_methods,
-			    "Declaring method %qD final "
-			    "would enable devirtualization of %i calls",
-			    decl, count);
+	      long long dyn_count = decl_warnings_vec[i]->dyn_count;
+
+	      if (!dyn_count)
+		if (DECL_CXX_DESTRUCTOR_P (decl))
+		  warning_n (DECL_SOURCE_LOCATION (decl),
+			      OPT_Wsuggest_final_methods, count,
+			      "Declaring virtual destructor of %qD final "
+			      "would enable devirtualization of %i call",
+			      "Declaring virtual destructor of %qD final "
+			      "would enable devirtualization of %i calls",
+			      DECL_CONTEXT (decl), count);
+		else
+		  warning_n (DECL_SOURCE_LOCATION (decl),
+			      OPT_Wsuggest_final_methods, count,
+			      "Declaring method %qD final "
+			      "would enable devirtualization of %i call",
+			      "Declaring method %qD final "
+			      "would enable devirtualization of %i calls",
+			      decl, count);
+	       else if (DECL_CXX_DESTRUCTOR_P (decl))
+		  warning_n (DECL_SOURCE_LOCATION (decl),
+			      OPT_Wsuggest_final_methods, count,
+			      "Declaring virtual destructor of %qD final "
+			      "would enable devirtualization of %i call "
+			      "executed %lli times",
+			      "Declaring virtual destructor of %qD final "
+			      "would enable devirtualization of %i calls "
+			      "executed %lli times",
+			      DECL_CONTEXT (decl), count, dyn_count);
+		else
+		  warning_n (DECL_SOURCE_LOCATION (decl),
+			      OPT_Wsuggest_final_methods, count,
+			      "Declaring method %qD final "
+			      "would enable devirtualization of %i call "
+			      "executed %lli times",
+			      "Declaring method %qD final "
+			      "would enable devirtualization of %i calls "
+			      "executed %lli times",
+			      decl, count, dyn_count);
 	    }
 	}
 	
-- 
GitLab