* 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.
Index: diagnostic.c
===================================================================
--- diagnostic.c        (revision 213526)
+++ diagnostic.c        (working copy)
@@ -986,6 +986,28 @@ warning_at (location_t location, int opt
   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
Index: diagnostic-core.h
===================================================================
--- diagnostic-core.h   (revision 213526)
+++ diagnostic-core.h   (working copy)
@@ -58,6 +58,8 @@ extern void internal_error (const char *
      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);
Index: ipa-devirt.c
===================================================================
--- ipa-devirt.c        (revision 213526)
+++ ipa-devirt.c        (working copy)
@@ -3279,12 +3279,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);
              }
        }
 
@@ -3299,19 +3318,45 @@ ipa_devirt (void)
            {
              tree decl = decl_warnings_vec[i]->decl;
              int count = decl_warnings_vec[i]->count;
+             long long dyn_count = decl_warnings_vec[i]->dyn_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);
+             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);
            }
        }
        

Reply via email to