On 02/27/2018 04:44 PM, Jakub Jelinek wrote:
On Mon, Feb 26, 2018 at 09:19:56PM -0700, Martin Sebor wrote:
+  /* Put together a list of the black listed attributes that the primary
+     template is declared with that the specialization is not, in case
+     it's not apparent from the most recent declaration of the primary.  */
+  unsigned nattrs = 0;
+  std::string str;
+
+  for (unsigned i = 0; i != sizeof blacklist / sizeof *blacklist; ++i)
+    {
+      for (unsigned j = 0; j != 2; ++j)
+       {
+         if (!lookup_attribute (blacklist[i], tmpl_attrs[j]))
+           continue;
+
+         for (unsigned k = 0; k != 1 + !!spec_attrs[1]; ++k)
+           {
+             if (lookup_attribute (blacklist[i], spec_attrs[k]))
+               break;
+
+             if (str.size ())
+               str += ", ";
+             str += "%<";
+             str += blacklist[i];
+             str += "%>";
+             ++nattrs;
+           }
+       }
+    }
+
+  if (!nattrs)
+    return;
+
+  if (warning_at (DECL_SOURCE_LOCATION (spec), OPT_Wmissing_attributes,
+                 "explicit specialization %q#D may be missing attributes",
+                 spec))
+    {
+      if (nattrs > 1)
+       str = G_("missing primary template attributes ") + str;
+      else
+       str = G_("missing primary template attribute ") + str;
+
+      inform (DECL_SOURCE_LOCATION (tmpl), str.c_str ());

This is broken for multiple reasons:
1) it should be inform_n rather than inform
2) you really can't do what you're doing for translations;
   G_(...) marks the string for translations, but what actually is
   translated is not that string, but rather what is passed to inform,
   i.e. str.c_str (), so it will be likely never translated
3) as others have mentioned, the #include <string> you are doing is
   wrong
4) I don't see justification to use std::string here

What you IMHO should use instead is use
  pretty_printer str;
instead, and the pp_* APIs to add stuff in there, including
pp_begin_quote (&str, pp_show_color (global_dc->printer))
and
pp_end_quote (&str, pp_show_color (global_dc->printer))
when you want to add what %< or %> expand to,
and finally
  inform_n (DECL_SOURCE_LOCATION (tmpl), nattrs,
            "missing primary template attribute %s",
            "missing primary template attributes %s",
            pp_formatted_text (&str));
That way it should be properly translatable.

Using inform_n() would not be correct here.  What's being
translated is one of exactly two forms: singular and plural.
It doesn't matter how many things the plural form refers to
because the number doesn't appear in the message.  Let's ask
Google to translate the message above to a language with more
than two plural forms, such as Czech:

there are missing attributes:
https://translate.google.com/?tl=cs#auto/cs/there%20are%20missing%20attributes

vs there are 5 missing attributes:
https://translate.google.com/?tl=cs#auto/cs/there%20are%205%20missing%20attributes

Only the first form is correct when the exact number isn't
mentioned.

There are many places in the C++ front-end where a string
enclosed in G_() is assigned to a pointer and later used
in a diagnostic call.  Is there something different about
the usage I introduced that makes it unsuitable for
translation?

std::string is used in a number of places in GCC.  Why does
using it here need any special justification?

Using the pretty printer as you suggest also sounds
complicated to me and so prone to error but I will defer
to Jason's opinion to decide if any changes are necessary.

Martin

PS What I do think would be helpful (and what I'd like to
look into adding in stage 1) is a directive to format
attribute lists.  But I'm not sure the directive will help
with cases like this one.

Reply via email to