This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Support %N$/*N$ style format arguments in GCC diagnostics
- From: Jakub Jelinek <jakub at redhat dot com>
- To: "Joseph S. Myers" <joseph at codesourcery dot com>, Zack Weinberg <zack at codesourcery dot com>, Gabriel Dos Reis <gdr at integrable-solutions dot net>
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Fri, 20 May 2005 15:37:40 -0400
- Subject: [PATCH] Support %N$/*N$ style format arguments in GCC diagnostics
- References: <20050517113757.GD4930@devserv.devel.redhat.com> <Pine.LNX.4.61.0505171343560.27091@digraph.polyomino.org.uk> <20050518170635.GB22344@sunsite.mff.cuni.cz> <Pine.LNX.4.61.0505181726490.9991@digraph.polyomino.org.uk>
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
On Wed, May 18, 2005 at 05:34:52PM +0000, Joseph S. Myers wrote:
> > BTW, shouldn't we implement %n$ style arguments in addition to % ones?
> > It seems e.g. several turkish translations relied on this...
>
> Chiaki Ishikawa had a long patch series attempting to implement them but I
> don't think they ever got in reviewable form or were following an approach
> Zack liked.
Seeing that the last po commit added a big number of %N$ arguments, I wrote
following patch.
I tried to make the requirements match POSIX *printf requirements.
pp_base_format_text works in 3 phases, first it scans the format string
and records the arguments, then, with optional help of a hook stores
the arguments into a union and finally prints them as it used to print them
before, only instead of va_arg directly it uses that union.
I'm not sure what to do about the special case for %H/%J at the beginning
of (some of) the format strings. The patch below doesn't take them into
account at all, so those must be really %H resp. %J with no
modifiers/position specification etc., and as their argument is eaten by the
time we reach pp_base_format_text, %J%2$d%1$d, this is the hidden tree argument
and then 2 integers after it. Not sure if this would not confuse
translators. So alternatively we could perhaps cooperate with
pp_base_prepare_to_format, if using positional arguments the initial
%H would need to be %1$H (resp. %1$J for %J) and other arguments would
count from 2. What do you think?
Tested with make check and printing a couple of weirdo warning calls
I wrote just to test it out.
2005-05-20 Jakub Jelinek <jakub@redhat.com>
* pretty-print.h (pp_fmt_arg): New type.
(PP_NL_ARGMAX): Define.
(arg_fetch_fn): New function type.
(printer_fn): Add pp_fmt_arg * argument.
(struct pretty_print_info): Add format_arg_fetch field.
* pretty-print.c (pp_base_format_text): Add support for numbered
arguments (%N$ resp. *N$ notation) and %.Ns.
(pp_integer_with_precision): Adjust.
* diagnostic.h (diagnostic_format_arg_fetch): Define.
* toplev.c (default_tree_arg_fetch): New function.
(default_tree_printer): Add ARG argument. Fetch value from
ARG->data union rather than from va_arg.
(general_init): Initialize pp_format_arg_fetch.
* c-objc-common.c (c_tree_arg_fetch): New function.
(c_tree_printer): Add ARG argument. Fetch value from
ARG->data union rather than from va_arg.
(c_objc_common_init): Initialize diagnostic_format_arg_fetch.
* error.c (cp_arg_fetch): New function.
(cp_printer): Add ARG argument. Fetch value from ARG->data
union rather than from va_arg.
(init_error): Initialize diagnostic_format_arg_fetch.
--- gcc/pretty-print.h.jj 2004-11-11 10:37:33.000000000 +0100
+++ gcc/pretty-print.h 2005-05-20 18:05:54.000000000 +0200
@@ -1,5 +1,5 @@
/* Various declarations for language-independent pretty-print subroutines.
- Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
Contributed by Gabriel Dos Reis <gdr@integrable-solutions.net>
This file is part of GCC.
@@ -72,13 +72,40 @@ typedef enum
pp_none, pp_before, pp_after
} pp_padding;
+typedef struct
+{
+ unsigned char code;
+ union
+ {
+ int pp_d_int;
+ unsigned pp_d_uint;
+ long int pp_d_long;
+ unsigned long int pp_d_ulong;
+ long long int pp_d_longlong;
+ unsigned long long int pp_d_ulonglong;
+ HOST_WIDE_INT pp_d_hwi;
+ unsigned HOST_WIDE_INT pp_d_uhwi;
+ const char *pp_d_string;
+ void *pp_d_ptr;
+ location_t *pp_d_locus;
+ tree pp_d_tree;
+ } data;
+} pp_fmt_arg;
+
+/* Maximum number of format string arguments. */
+#define PP_NL_ARGMAX 30
+
/* The type of a hook that formats client-specific data onto a pretty_pinter.
A client-supplied formatter returns true if everything goes well,
otherwise it returns false. */
typedef struct pretty_print_info pretty_printer;
-typedef bool (*printer_fn) (pretty_printer *, text_info *);
+typedef bool (*arg_fetch_fn) (pretty_printer *, text_info *, pp_fmt_arg *);
+typedef bool (*printer_fn) (pretty_printer *, text_info *, pp_fmt_arg *);
+
+/* Client supplied function used to fetch format arguments. */
+#define pp_format_arg_fetch(PP) pp_base (PP)->format_arg_fetch
-/* Client supplied function used to decode formats. */
+/* Client supplied function used to decode and print formats. */
#define pp_format_decoder(PP) pp_base (PP)->format_decoder
/* TRUE if a newline character needs to be added before further
@@ -126,10 +153,16 @@ struct pretty_print_info
/* Current prefixing rule. */
diagnostic_prefixing_rule_t prefixing_rule;
+ /* If non-NULL, this function should fetch argument for format argument
+ in ARG->code from *TEXT->args_pts using VA_ARG and store it into
+ ARG->data union. */
+ arg_fetch_fn format_arg_fetch;
+
/* If non-NULL, this function formats a TEXT into the BUFFER. When called,
TEXT->format_spec points to a format code. FORMAT_DECODER should call
pp_string (and related functions) to add data to the BUFFER.
- FORMAT_DECODER can read arguments from *TEXT->args_pts using VA_ARG.
+ FORMAT_DECODER can use argument previously fetched by FORMAT_ARG_FETCH
+ into ARG->data union.
If the BUFFER needs additional characters from the format string, it
should advance the TEXT->format_spec as it goes. When FORMAT_DECODER
returns, TEXT->format_spec should point to the last character processed.
--- gcc/pretty-print.c.jj 2005-04-29 09:18:04.000000000 +0200
+++ gcc/pretty-print.c 2005-05-20 21:17:38.000000000 +0200
@@ -35,28 +35,28 @@ Software Foundation, 59 Temple Place - S
#define pp_formatted_text_data(PP) \
((const char *) obstack_base (&pp_base (PP)->buffer->obstack))
-/* Format an integer given by va_arg (ARG, type-specifier T) where
+/* Format an integer given by ARG[I].data.T where
type-specifier is a precision modifier as indicated by PREC. F is
a string used to construct the appropriate format-specifier. */
-#define pp_integer_with_precision(PP, ARG, PREC, T, F) \
- do \
- switch (PREC) \
- { \
- case 0: \
- pp_scalar (PP, "%" F, va_arg (ARG, T)); \
- break; \
- \
- case 1: \
- pp_scalar (PP, "%l" F, va_arg (ARG, long T)); \
- break; \
- \
- case 2: \
- pp_scalar (PP, "%ll" F, va_arg (ARG, long long T)); \
- break; \
- \
- default: \
- break; \
- } \
+#define pp_integer_with_precision(PP, ARG, I, PREC, T, F) \
+ do \
+ switch (PREC) \
+ { \
+ case 0: \
+ pp_scalar (PP, "%" F, ARG[I].data.T##int); \
+ break; \
+ \
+ case 1: \
+ pp_scalar (PP, "%l" F, ARG[I].data.T##long); \
+ break; \
+ \
+ case 2: \
+ pp_scalar (PP, "%ll" F, ARG[I].data.T##longlong); \
+ break; \
+ \
+ default: \
+ break; \
+ } \
while (0)
@@ -218,33 +218,228 @@ pp_base_prepare_to_format (pretty_printe
%>: closing quote.
%': apostrophe (should only be used in untranslated messages;
translations should use appropriate punctuation directly).
- %.*s: a substring the length of which is specified by an integer.
+ %.*s: a substring the length of which is specified by an argument
+ integer.
+ %Ns: likewise, but length specified as constant in the format string.
%H: location_t.
- Flag 'q': quote formatted text (must come immediately after '%'). */
+ Flag 'q': quote formatted text (must come immediately after '%').
+ Arguments can be used sequentially, or through %N$ resp. *N$ notation
+ Nth argument after the format string (and optional argument matching
+ initial %H resp. %J in the format string handled in
+ pp_base_prepare_to_format). If %N$/*N$ notation is used, it must
+ be used for all arguments, except %m, %%, %<, %> and %' where either
+ form can be used. The format string must have conversion specifiers
+ with argument numbers 1 up to highest argument. A format string
+ can have at most 30 arguments. */
void
pp_base_format_text (pretty_printer *pp, text_info *text)
{
- for (; *text->format_spec; ++text->format_spec)
+ pp_fmt_arg args[PP_NL_ARGMAX];
+ const char *p = text->format_spec;
+ unsigned int curarg = 0;
+ bool any_numbered = false, any_unnumbered = false;
+ unsigned int argno;
+
+ /* First phase. Scan the format string to see if % or %N$ style
+ specifiers are used, record them in the ARGS array. */
+ memset (args, 0, sizeof (args));
+ for (p = text->format_spec; *p; )
+ if (*p++ == '%')
+ {
+ unsigned int n;
+ unsigned char code;
+ int precision = 0;
+ bool numbered = false;
+
+ if (*p >= '0' && *p <= '9')
+ {
+ char *end;
+ n = strtoul (p, &end, 10) - 1;
+ gcc_assert (*end == '$');
+ p = (const char *) (end + 1);
+ numbered = true;
+ }
+ else
+ n = curarg;
+
+ if (*p == 'q')
+ ++p;
+ switch (*p)
+ {
+ case 'w':
+ precision = 3;
+ ++p;
+ break;
+
+ case 'l':
+ do
+ ++precision;
+ while (*++p == 'l');
+ /* We don't support precision beyond that of "long long". */
+ gcc_assert (precision <= 2);
+ break;
+
+ default:
+ break;
+ }
+
+ /* %%, %m, %<, %>, %' don't use arguments, so can be used with
+ both These specifiers don't need any arguments. */
+ if (strchr ("%m<>'", *p) == NULL)
+ {
+ if (numbered)
+ {
+ any_numbered = true;
+ gcc_assert (! any_unnumbered);
+ }
+ else
+ {
+ any_unnumbered = true;
+ gcc_assert (! any_numbered);
+ ++curarg;
+ }
+ }
+ else if (!numbered)
+ {
+ ++p;
+ continue;
+ }
+
+ gcc_assert (n < PP_NL_ARGMAX);
+ if (*p == '+')
+ ++p;
+ if (*p == '#')
+ ++p;
+ switch (*p)
+ {
+ case '%':
+ case 'm':
+ case '<':
+ case '>':
+ case '\'':
+ code = '%';
+ break;
+ /* These take {,long,long long,HOST_WIDE_INT} int. */
+ case 'd':
+ case 'i':
+ code = '0' + precision;
+ break;
+ /* These take unsigned {,long,long long,HOST_WIDE_INT} int. */
+ case 'o':
+ case 'u':
+ case 'x':
+ code = '5' + precision;
+ break;
+ /* We handle '%.Ns' and '%.*s' or '%M$.*N$s' (where M and N are
+ small unsigned decimal numbers). */
+ case '.':
+ if (p[1] >= '0' && p[1] <= '9')
+ for (p += 2; *p >= '0' && *p <= '9'; ++p);
+ else
+ {
+ unsigned int pn;
+
+ gcc_assert (p[1] == '*');
+ p += 2;
+ if (numbered)
+ {
+ char *end;
+
+ pn = strtoul (p, &end, 10) - 1;
+ gcc_assert (p != end && *end == '$');
+ p = (const char *) (end + 1);
+ }
+ else
+ {
+ pn = n;
+ n = curarg++;
+ gcc_assert (n < PP_NL_ARGMAX);
+ }
+
+ gcc_assert (args[pn].code == '\0' || args[pn].code == '0');
+ args[pn].code = '0';
+ }
+ gcc_assert (*p == 's');
+ code = 's';
+ break;
+ default:
+ code = *p;
+ break;
+ }
+
+ gcc_assert (args[n].code == '\0' || args[n].code == code);
+ args[n].code = code;
+ ++p;
+ }
+
+ /* Second phase. Fetch the arguments from *text->args_ptr va_list. */
+ for (argno = 0; argno < PP_NL_ARGMAX; ++argno)
+ {
+ if (args[argno].code == '\0')
+ continue;
+ gcc_assert (argno == 0 || args[argno - 1].code != '\0');
+ switch (args[argno].code)
+ {
+ case '%':
+ break;
+#define pp_arg_fetch(code, field, type) \
+ case code: \
+ args[argno].data.pp_d_##field = va_arg (*text->args_ptr, type); \
+ break
+ pp_arg_fetch ('0', int, int);
+ pp_arg_fetch ('1', long, long int);
+ pp_arg_fetch ('2', longlong, long long int);
+ pp_arg_fetch ('3', hwi, HOST_WIDE_INT);
+ pp_arg_fetch ('5', uint, unsigned int);
+ pp_arg_fetch ('6', ulong, unsigned long int);
+ pp_arg_fetch ('7', ulonglong, unsigned long long int);
+ pp_arg_fetch ('8', uhwi, unsigned HOST_WIDE_INT);
+ pp_arg_fetch ('c', int, int);
+ pp_arg_fetch ('p', ptr, void *);
+ pp_arg_fetch ('s', string, const char *);
+ pp_arg_fetch ('H', locus, location_t *);
+#undef pp_arg_fetch
+ default:
+ {
+ bool ok;
+
+ gcc_assert (pp_format_arg_fetch (pp));
+ ok = pp_format_arg_fetch (pp) (pp, text, &args[argno]);
+ gcc_assert (ok);
+ break;
+ }
+ }
+ }
+
+ /* Third phase. Actually print it. */
+ for (curarg = 0; *text->format_spec; ++text->format_spec, ++curarg)
{
int precision = 0;
bool wide = false;
bool quoted = false;
/* Ignore text. */
- {
- const char *p = text->format_spec;
- while (*p && *p != '%')
- ++p;
- pp_wrap_text (pp, text->format_spec, p);
- text->format_spec = p;
- }
+ p = text->format_spec;
+ while (*p && *p != '%')
+ ++p;
+ pp_wrap_text (pp, text->format_spec, p);
+ text->format_spec = p;
if (*text->format_spec == '\0')
break;
- /* We got a '%'. Check for 'q', then parse precision modifiers,
- if any. */
- if (*++text->format_spec == 'q')
+ /* We got a '%'. First check for 'N$'. */
+ ++text->format_spec;
+ if (*text->format_spec >= '0' && *text->format_spec <= '9')
+ {
+ char *end;
+ curarg = strtoul (text->format_spec, &end, 10) - 1;
+ gcc_assert (*end == '$');
+ text->format_spec = (const char *) (end + 1);
+ }
+
+ /* Check for 'q', then parse precision modifiers, if any. */
+ if (*text->format_spec == 'q')
{
quoted = true;
++text->format_spec;
@@ -273,73 +468,81 @@ pp_base_format_text (pretty_printer *pp,
switch (*text->format_spec)
{
case 'c':
- pp_character (pp, va_arg (*text->args_ptr, int));
+ pp_character (pp, args[curarg].data.pp_d_int);
break;
case 'd':
case 'i':
- if (wide)
- pp_wide_integer (pp, va_arg (*text->args_ptr, HOST_WIDE_INT));
- else
- pp_integer_with_precision
- (pp, *text->args_ptr, precision, int, "d");
+ if (wide)
+ pp_wide_integer (pp, args[curarg].data.pp_d_hwi);
+ else
+ pp_integer_with_precision
+ (pp, args, curarg, precision, pp_d_, "d");
break;
case 'o':
- if (wide)
- pp_scalar (pp, "%" HOST_WIDE_INT_PRINT "o",
- va_arg (*text->args_ptr, unsigned HOST_WIDE_INT));
- else
- pp_integer_with_precision
- (pp, *text->args_ptr, precision, unsigned, "u");
+ if (wide)
+ pp_scalar (pp, "%" HOST_WIDE_INT_PRINT "o",
+ args[curarg].data.pp_d_uhwi);
+ else
+ pp_integer_with_precision
+ (pp, args, curarg, precision, pp_d_u, "o");
break;
case 's':
- pp_string (pp, va_arg (*text->args_ptr, const char *));
+ pp_string (pp, args[curarg].data.pp_d_string);
break;
- case 'p':
- pp_pointer (pp, va_arg (*text->args_ptr, void *));
- break;
+ case 'p':
+ pp_pointer (pp, args[curarg].data.pp_d_ptr);
+ break;
case 'u':
- if (wide)
- pp_scalar (pp, HOST_WIDE_INT_PRINT_UNSIGNED,
- va_arg (*text->args_ptr, unsigned HOST_WIDE_INT));
- else
- pp_integer_with_precision
- (pp, *text->args_ptr, precision, unsigned, "u");
+ if (wide)
+ pp_scalar (pp, HOST_WIDE_INT_PRINT_UNSIGNED,
+ args[curarg].data.pp_d_uhwi);
+ else
+ pp_integer_with_precision
+ (pp, args, curarg, precision, pp_d_u, "u");
break;
case 'x':
- if (wide)
- pp_scalar (pp, HOST_WIDE_INT_PRINT_HEX,
- va_arg (*text->args_ptr, unsigned HOST_WIDE_INT));
- else
- pp_integer_with_precision
- (pp, *text->args_ptr, precision, unsigned, "x");
+ if (wide)
+ pp_scalar (pp, HOST_WIDE_INT_PRINT_HEX,
+ args[curarg].data.pp_d_uhwi);
+ else
+ pp_integer_with_precision
+ (pp, args, curarg, precision, pp_d_u, "x");
break;
case 'm':
pp_string (pp, xstrerror (text->err_no));
+ /* Undo ++curarg done by for, as m takes no argument. */
+ --curarg;
break;
case '%':
pp_character (pp, '%');
+ /* Undo ++curarg done by for, as % takes no argument. */
+ --curarg;
break;
case '<':
pp_string (pp, open_quote);
+ /* Undo ++curarg done by for, as < takes no argument. */
+ --curarg;
break;
case '>':
case '\'':
pp_string (pp, close_quote);
+ /* Undo ++curarg done by for, as >' take no argument. */
+ --curarg;
break;
case 'H':
{
- location_t *locus = va_arg (*text->args_ptr, location_t *);
+ location_t *locus = args[curarg].data.pp_d_locus;
expanded_location s = expand_location (*locus);
pp_string (pp, "file '");
pp_string (pp, s.file);
@@ -352,14 +555,32 @@ pp_base_format_text (pretty_printer *pp,
{
int n;
const char *s;
+ char *end;
/* We handle no precision specifier but '%.*s'. */
++text->format_spec;
- gcc_assert (*text->format_spec == '*');
- ++text->format_spec;
+ if (*text->format_spec >= '0' && *text->format_spec <= '9')
+ {
+ n = strtoul (text->format_spec, &end, 10);
+ text->format_spec = (const char *) end;
+ }
+ else
+ {
+ gcc_assert (*text->format_spec == '*');
+ ++text->format_spec;
+ if (*text->format_spec >= '0' && *text->format_spec <= '9')
+ {
+ n = strtoul (text->format_spec, &end, 10) - 1;
+ gcc_assert (n >= 0 && n < PP_NL_ARGMAX);
+ gcc_assert (*end == '$');
+ text->format_spec = (const char *) (end + 1);
+ n = args[n].data.pp_d_int;
+ }
+ else
+ n = args[curarg++].data.pp_d_int;
+ }
gcc_assert (*text->format_spec == 's');
- n = va_arg (*text->args_ptr, int);
- s = va_arg (*text->args_ptr, const char *);
+ s = args[curarg].data.pp_d_string;
pp_append_text (pp, s, s + n);
}
break;
@@ -369,7 +590,7 @@ pp_base_format_text (pretty_printer *pp,
bool ok;
gcc_assert (pp_format_decoder (pp));
- ok = pp_format_decoder (pp) (pp, text);
+ ok = pp_format_decoder (pp) (pp, text, &args[curarg]);
gcc_assert (ok);
}
}
--- gcc/diagnostic.h.jj 2005-05-06 09:58:26.000000000 +0200
+++ gcc/diagnostic.h 2005-05-20 17:58:28.000000000 +0200
@@ -116,6 +116,9 @@ struct diagnostic_context
/* Extension hook for client. */
#define diagnostic_auxiliary_data(DC) (DC)->x_data
+/* Same as pp_format_arg_fetch. Works on 'diagnostic_context *'. */
+#define diagnostic_format_arg_fetch(DC) ((DC)->printer->format_arg_fetch)
+
/* Same as pp_format_decoder. Works on 'diagnostic_context *'. */
#define diagnostic_format_decoder(DC) ((DC)->printer->format_decoder)
--- gcc/toplev.c.jj 2005-05-06 09:58:28.000000000 +0200
+++ gcc/toplev.c 2005-05-20 18:18:31.000000000 +0200
@@ -1565,23 +1565,41 @@ default_pch_valid_p (const void *data_p,
}
}
+/* Default tree format argument fetcher. Handles declarations only. */
+static bool
+default_tree_arg_fetch (pretty_printer *pp ATTRIBUTE_UNUSED, text_info *text,
+ pp_fmt_arg *arg)
+{
+ switch (arg->code)
+ {
+ case 'D':
+ case 'F':
+ case 'T':
+ arg->data.pp_d_tree = va_arg (*text->args_ptr, tree);
+ return true;
+
+ default:
+ return false;
+ }
+}
+
/* Default tree printer. Handles declarations only. */
static bool
-default_tree_printer (pretty_printer * pp, text_info *text)
+default_tree_printer (pretty_printer *pp, text_info *text, pp_fmt_arg *arg)
{
tree t;
switch (*text->format_spec)
{
case 'D':
- t = va_arg (*text->args_ptr, tree);
+ t = arg->data.pp_d_tree;
if (DECL_DEBUG_EXPR (t) && DECL_DEBUG_EXPR_IS_FROM (t))
t = DECL_DEBUG_EXPR (t);
break;
case 'F':
case 'T':
- t = va_arg (*text->args_ptr, tree);
+ t = arg->data.pp_d_tree;
break;
default:
@@ -1626,8 +1644,9 @@ general_init (const char *argv0)
/* Initialize the diagnostics reporting machinery, so option parsing
can give warnings and errors. */
diagnostic_initialize (global_dc);
- /* Set a default printer. Language specific initializations will
- override it later. */
+ /* Set a default printer and format arg fetcher. Language specific
+ initializations will override it later. */
+ pp_format_arg_fetch (global_dc->printer) = &default_tree_arg_fetch;
pp_format_decoder (global_dc->printer) = &default_tree_printer;
/* Trap fatal signals, e.g. SIGSEGV, and convert them to ICE messages. */
--- gcc/c-objc-common.c.jj 2005-04-29 09:17:42.000000000 +0200
+++ gcc/c-objc-common.c 2005-05-20 18:18:31.000000000 +0200
@@ -40,7 +40,8 @@ Software Foundation, 59 Temple Place - S
#include "target.h"
#include "c-objc-common.h"
-static bool c_tree_printer (pretty_printer *, text_info *);
+static bool c_tree_arg_fetch (pretty_printer *, text_info *, pp_fmt_arg *);
+static bool c_tree_printer (pretty_printer *, text_info *, pp_fmt_arg *);
bool
c_missing_noreturn_ok_p (tree decl)
@@ -132,6 +133,7 @@ c_objc_common_init (void)
/* These were not defined in the Objective-C front end, but I'm
putting them here anyway. The diagnostic format decoder might
want an enhanced ObjC implementation. */
+ diagnostic_format_arg_fetch (global_dc) = &c_tree_arg_fetch;
diagnostic_format_decoder (global_dc) = &c_tree_printer;
/* If still unspecified, make it match -std=c99
@@ -160,9 +162,26 @@ c_objc_common_init (void)
Please notice when called, the `%' part was already skipped by the
diagnostic machinery. */
static bool
-c_tree_printer (pretty_printer *pp, text_info *text)
+c_tree_arg_fetch (pretty_printer *pp ATTRIBUTE_UNUSED, text_info *text,
+ pp_fmt_arg *arg)
{
- tree t = va_arg (*text->args_ptr, tree);
+ switch (arg->code)
+ {
+ case 'D':
+ case 'E':
+ case 'F':
+ case 'T':
+ arg->data.pp_d_tree = va_arg (*text->args_ptr, tree);
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool
+c_tree_printer (pretty_printer *pp, text_info *text, pp_fmt_arg *arg)
+{
+ tree t = arg->data.pp_d_tree;
tree name;
const char *n = "({anonymous})";
c_pretty_printer *cpp = (c_pretty_printer *) pp;
--- gcc/cp/error.c.jj 2005-03-25 11:37:25.000000000 +0100
+++ gcc/cp/error.c 2005-05-20 18:18:31.000000000 +0200
@@ -86,7 +86,8 @@ static void cp_diagnostic_starter (diagn
static void cp_diagnostic_finalizer (diagnostic_context *, diagnostic_info *);
static void cp_print_error_function (diagnostic_context *, diagnostic_info *);
-static bool cp_printer (pretty_printer *, text_info *);
+static bool cp_arg_fetch (pretty_printer *, text_info *, pp_fmt_arg *);
+static bool cp_printer (pretty_printer *, text_info *, pp_fmt_arg *);
static tree locate_error (const char *, va_list);
static location_t location_of (tree);
@@ -95,6 +96,7 @@ init_error (void)
{
diagnostic_starter (global_dc) = cp_diagnostic_starter;
diagnostic_finalizer (global_dc) = cp_diagnostic_finalizer;
+ diagnostic_format_arg_fetch (global_dc) = cp_arg_fetch;
diagnostic_format_decoder (global_dc) = cp_printer;
pp_construct (pp_base (cxx_pp), NULL, 0);
@@ -2272,14 +2274,48 @@ print_instantiation_context (void)
%T type.
%V cv-qualifier. */
static bool
-cp_printer (pretty_printer *pp, text_info *text)
+cp_arg_fetch (pretty_printer *pp ATTRIBUTE_UNUSED, text_info *text,
+ pp_fmt_arg *arg)
+{
+#define next_tree arg->data.pp_d_tree = va_arg (*text->args_ptr, tree)
+#define next_tcode arg->data.pp_d_int \
+ = (int) va_arg (*text->args_ptr, enum tree_code)
+#define next_lang arg->data.pp_d_int \
+ = (int) va_arg (*text->args_ptr, enum languages)
+#define next_int arg->data.pp_d_int = va_arg (*text->args_ptr, int)
+
+ switch (arg->code)
+ {
+ case 'A': next_tree; break;
+ case 'C': next_tcode; break;
+ case 'D': next_tree; break;
+ case 'E': next_tree; break;
+ case 'F': next_tree; break;
+ case 'L': next_lang; break;
+ case 'O': next_tcode; break;
+ case 'P': next_int; break;
+ case 'Q': next_tcode; break;
+ case 'T': next_tree; break;
+ case 'V': next_tree; break;
+ default:
+ return false;
+ }
+ return true;
+#undef next_tree
+#undef next_tcode
+#undef next_lang
+#undef next_int
+}
+
+static bool
+cp_printer (pretty_printer *pp, text_info *text, pp_fmt_arg *arg)
{
int verbose = 0;
const char *result;
-#define next_tree va_arg (*text->args_ptr, tree)
-#define next_tcode va_arg (*text->args_ptr, enum tree_code)
-#define next_lang va_arg (*text->args_ptr, enum languages)
-#define next_int va_arg (*text->args_ptr, int)
+#define next_tree arg->data.pp_d_tree
+#define next_tcode ((enum tree_code) arg->data.pp_d_int)
+#define next_lang ((enum languages) arg->data.pp_d_int)
+#define next_int arg->data.pp_d_int
if (*text->format_spec == '+')
++text->format_spec;
Jakub