* 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);
}
}