Hi! While looking into another PR, I've noticed that in two spots the parser->type_definition_forbidden_message messages are untranslatable, we construct them at runtime from 3 strings using concat.
The following patch fixes it by adding a const char * member to the parser structure and passing that as another argument to error, in the more usual case where the argument string only contains %< and %> and not %qs added in this patch it will be just ignored. I believe this patch is more friendly to the translators (as well as less expensive at compile time because it doesn't have to concat/allocate anything). Another possibility would be to just use in cp_parser_has_attribute_expression G_("types may not be defined in %<__builtin_has_attribute%> expressions") and in cp_parser_sizeof_operand use a switch based on the 3 possible keyword values and use G_("types may not be defined in %<sizeof%> expressions") G_("types may not be defined in %<__alignof__%> expressions") G_("types may not be defined in %<alignof%> expressions") G_("types may not be defined in %<typeof%> expressions") depending on that (and C++ mode which determines which alignof spelling is in ridpointers). We wouldn't need to add an extra member, on the other side the translators would need to translate 5 messages instead of just one. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2019-04-11 Jakub Jelinek <ja...@redhat.com> PR translation/90035 * parser.h (struct cp_parser): Add type_definition_forbidden_message_arg member. * parser.c (cp_debug_parser): Print it. (cp_parser_check_type_definition): Pass parser->type_definition_forbidden_message_arg as second argument to error. (cp_parser_has_attribute_expression, cp_parser_sizeof_operand): Set parser->type_definition_forbidden_message_arg and use G_() with %qs for parser->type_definition_forbidden_message instead of building untranslatable message using concat. --- gcc/cp/parser.h.jj 2019-01-08 22:33:34.255713665 +0100 +++ gcc/cp/parser.h 2019-04-10 15:19:37.672814432 +0200 @@ -350,6 +350,9 @@ struct GTY(()) cp_parser { issued as an error message if a type is defined. */ const char *type_definition_forbidden_message; + /* Argument for type_definition_forbidden_message if needed. */ + const char *type_definition_forbidden_message_arg; + /* A stack used for member functions of local classes. The lists contained in an individual entry can only be processed once the outermost class being defined is complete. */ --- gcc/cp/parser.c.jj 2019-03-27 21:19:39.000045746 +0100 +++ gcc/cp/parser.c 2019-04-10 15:34:28.201322120 +0200 @@ -570,8 +570,10 @@ cp_debug_parser (FILE *file, cp_parser * cp_debug_print_flag (file, "Colon doesn't start a class definition", parser->colon_doesnt_start_class_def_p); if (parser->type_definition_forbidden_message) - fprintf (file, "Error message for forbidden type definitions: %s\n", - parser->type_definition_forbidden_message); + fprintf (file, "Error message for forbidden type definitions: %s %s\n", + parser->type_definition_forbidden_message, + parser->type_definition_forbidden_message_arg + ? parser->type_definition_forbidden_message_arg : "<none>"); cp_debug_print_unparsed_queues (file, parser->unparsed_queues); fprintf (file, "Number of class definitions in progress: %u\n", parser->num_classes_being_defined); @@ -3054,8 +3056,9 @@ cp_parser_check_type_definition (cp_pars if (parser->type_definition_forbidden_message) { /* Don't use `%s' to print the string, because quotations (`%<', `%>') - in the message need to be interpreted. */ - error (parser->type_definition_forbidden_message); + or %qs in the message need to be interpreted. */ + error (parser->type_definition_forbidden_message, + parser->type_definition_forbidden_message_arg); return false; } return true; @@ -8518,12 +8521,12 @@ cp_parser_has_attribute_expression (cp_p /* Types cannot be defined in a `sizeof' expression. Save away the old message. */ const char *saved_message = parser->type_definition_forbidden_message; - /* And create the new one. */ - const int kwd = RID_BUILTIN_HAS_ATTRIBUTE; - char *tmp = concat ("types may not be defined in %<", - IDENTIFIER_POINTER (ridpointers[kwd]), - "%> expressions", NULL); - parser->type_definition_forbidden_message = tmp; + const char *saved_message_arg + = parser->type_definition_forbidden_message_arg; + parser->type_definition_forbidden_message + = G_("types may not be defined in %qs expressions"); + parser->type_definition_forbidden_message_arg + = IDENTIFIER_POINTER (ridpointers[RID_BUILTIN_HAS_ATTRIBUTE]); /* The restrictions on constant-expressions do not apply inside sizeof expressions. */ @@ -8562,10 +8565,9 @@ cp_parser_has_attribute_expression (cp_p --cp_unevaluated_operand; --c_inhibit_evaluation_warnings; - /* Free the message we created. */ - free (tmp); /* And restore the old one. */ parser->type_definition_forbidden_message = saved_message; + parser->type_definition_forbidden_message_arg = saved_message_arg; parser->integral_constant_expression_p = saved_integral_constant_expression_p; parser->non_integral_constant_expression_p @@ -28928,7 +28930,7 @@ cp_parser_sizeof_operand (cp_parser* par { tree expr = NULL_TREE; const char *saved_message; - char *tmp; + const char *saved_message_arg; bool saved_integral_constant_expression_p; bool saved_non_integral_constant_expression_p; @@ -28941,11 +28943,11 @@ cp_parser_sizeof_operand (cp_parser* par /* Types cannot be defined in a `sizeof' expression. Save away the old message. */ saved_message = parser->type_definition_forbidden_message; - /* And create the new one. */ - tmp = concat ("types may not be defined in %<", - IDENTIFIER_POINTER (ridpointers[keyword]), - "%> expressions", NULL); - parser->type_definition_forbidden_message = tmp; + saved_message_arg = parser->type_definition_forbidden_message_arg; + parser->type_definition_forbidden_message + = G_("types may not be defined in %qs expressions"); + parser->type_definition_forbidden_message_arg + = IDENTIFIER_POINTER (ridpointers[keyword]); /* The restrictions on constant-expressions do not apply inside sizeof expressions. */ @@ -29002,10 +29004,9 @@ cp_parser_sizeof_operand (cp_parser* par --cp_unevaluated_operand; --c_inhibit_evaluation_warnings; - /* Free the message we created. */ - free (tmp); /* And restore the old one. */ parser->type_definition_forbidden_message = saved_message; + parser->type_definition_forbidden_message_arg = saved_message_arg; parser->integral_constant_expression_p = saved_integral_constant_expression_p; parser->non_integral_constant_expression_p Jakub