This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: Diagnostics formatting...
- To: Eric Weiss <eweiss at apple dot com>
- Subject: Re: Diagnostics formatting...
- From: Nathan Sidwell <nathan at codesourcery dot com>
- Date: Tue, 05 Jun 2001 09:34:32 +0100
- CC: Gabriel Dos Reis <gdr at codesourcery dot com>, gcc at gcc dot gnu dot org
- Organization: Codesourcery LLC
- References: <200106042147.OAA04401@scv1.apple.com> <flwv6rs65f.fsf@sel.cmla.ens-cachan.fr>
Gabriel Dos Reis wrote:
> A good start point is diagnostic.[ch]. There are lots of duplicate
> code there, and they should go away. Next is cp/error.c.
> Eventually, pointer hackering in cp/errfn.c should go.
Another error reporting thing that would be nice is the ability to
push an error reporting scope onto some kind of stack, so that context
information can be given if an error occurs. What I mean is we'd like
to be able to do
push_diag_scope (some_callback_fn, &some_state);
... call something that might issue a diagnostic
pop_diag_scope ();
void some_callback_fn (....whatever)
{
diagprint ("in arg %d of call to %D", state->argnum, state->fn);
}
The 'in arg ...' stuff would be formatted and appended to the diagnostic
text (and properly word wrapped etc).
Currently in g++, we have to pass extra parameters around, or
explicitly check error_count for this, which is icky. I attach a
diff, which I started working on some time back, but it's waiting
for the cp/error.c functions to be properly hooked into the
diagnostic.c stuff.
The attached diff is just a work in progress, and probably doesn't apply
cleanly anymore. We can discuss this on/off line later, when you've got
your head around the other diagnostic machinery, Eric.
Please keep me in the loop on this. Thanks.
nathan
--
Dr Nathan Sidwell :: http://www.codesourcery.com :: CodeSourcery LLC
'But that's a lie.' - 'Yes it is. What's your point?'
nathan@codesourcery.com : http://www.cs.bris.ac.uk/~nathan/ : nathan@acm.org
Index: diagnostic.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/diagnostic.c,v
retrieving revision 1.35
diff -c -3 -p -r1.35 diagnostic.c
*** diagnostic.c 2000/09/06 18:43:35 1.35
--- diagnostic.c 2000/09/11 14:07:23
*************** static void default_diagnostic_finalizer
*** 103,108 ****
--- 103,110 ----
static void error_recursion PARAMS ((void)) ATTRIBUTE_NORETURN;
static const char *trim_filename PARAMS ((const char *));
+ static void diagnostic_scope_string PARAMS ((output_buffer *, void *));
+ static void diagnostic_scope_output PARAMS ((output_buffer *));
extern int rtl_dump_and_exit;
extern int inhibit_warnings;
*************** static int current_prefixing_rule;
*** 151,156 ****
--- 153,168 ----
/* Prevent recursion into the error handler. */
static int diagnostic_lock;
+ /* One frame of the diagnostic stack. */
+ struct diagnostic_scope {
+ diagnostic_scope_fn fn;
+ void *data;
+ struct diagnostic_scope *chain;
+ };
+
+ /* Stack of diagnostic scopes. */
+ static struct diagnostic_scope *diagnostic_scopes;
+
/* Return truthvalue if current input file is different from the most recent
file involved in a diagnostic message. */
*************** output_to_stream (buffer, file)
*** 640,645 ****
--- 652,684 ----
clear_text_info (buffer);
}
+ void
+ diagnostic_printf VPARAMS ((output_buffer *buffer, const char *format, ...))
+ {
+ #ifndef ANSI_PROTOTYPES
+ output_buffer *buffer;
+ const char *format;
+ #endif
+ va_list ap;
+ const char *old_format;
+ va_list *old_args;
+
+ VA_START (ap, format);
+ #ifndef ANSI_PROTOTYPES
+ buffer = va_arg (ap, output_buffer *);
+ format = va_arg (ap, const char *);
+ #endif
+ old_format = output_buffer_text_cursor (buffer);
+ old_args = output_buffer_ptr_to_format_args (buffer);
+ output_buffer_text_cursor (buffer) = format;
+ output_buffer_ptr_to_format_args (buffer) = ≈
+ output_format (buffer);
+ output_buffer_text_cursor (buffer) = old_format;
+ output_buffer_ptr_to_format_args (buffer) = old_args;
+
+ va_end (ap);
+ }
+
/* Format a message pointed to by output_buffer_text_cursor (BUFFER) using
output_buffer_format_args (BUFFER) as appropriate. The following format
specifiers are recognized as being language independent:
*************** output_printf VPARAMS ((struct output_bu
*** 877,882 ****
--- 916,978 ----
va_end (ap);
}
+ /* Nest a diagnostic scope. When issuing a diagnostic, FN will be called
+ with the output buffer, and DATA. It should indicate the current
+ scope. If FN is NULL, then DATA should be a string, which will
+ be output verbatim. */
+
+ void
+ push_diagnostic_scope (fn, data)
+ diagnostic_scope_fn fn;
+ void *data;
+ {
+ struct diagnostic_scope *frame = xmalloc (sizeof (struct diagnostic_scope));
+
+ frame->fn = fn ? fn : diagnostic_scope_string;
+ frame->data = data;
+ frame->chain = diagnostic_scopes;
+
+ diagnostic_scopes = frame;
+ }
+
+ /* Unnest the current diagnostic scope. Returns the DATA originally
+ nested, in case that needs freeing. */
+
+ void *
+ pop_diagnostic_scope ()
+ {
+ struct diagnostic_scope *frame = diagnostic_scopes;
+ void *data = frame->data;
+
+ diagnostic_scopes = frame->chain;
+ free (frame);
+
+ return data;
+ }
+
+ /* Output a context string verbatim. */
+
+ static void
+ diagnostic_scope_string (buffer, data)
+ output_buffer *buffer;
+ void *data;
+ {
+ output_add_string (buffer, (char const *) data);
+ }
+
+ static void
+ diagnostic_scope_output (buffer)
+ output_buffer *buffer;
+ {
+ struct diagnostic_scope *frame;
+
+ for (frame = diagnostic_scopes; frame; frame = frame->chain)
+ {
+ output_add_string (buffer, ", ");
+ frame->fn (buffer, frame->data);
+ }
+ }
+
/* Print the message MSGID in FILE. */
static void
*************** report_diagnostic (dc)
*** 1598,1603 ****
--- 1694,1700 ----
diagnostic_args = diagnostic_argument_list (dc);
(*diagnostic_starter (dc)) (diagnostic_buffer, dc);
output_format (diagnostic_buffer);
+ diagnostic_scope_output (diagnostic_buffer);
(*diagnostic_finalizer (dc)) (diagnostic_buffer, dc);
finish_diagnostic ();
output_buffer_state (diagnostic_buffer) = os;
Index: diagnostic.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/diagnostic.h,v
retrieving revision 1.15
diff -c -3 -p -r1.15 diagnostic.h
*** diagnostic.h 2000/09/06 18:43:35 1.15
--- diagnostic.h 2000/09/11 14:07:23
*************** typedef diagnostic_starter_fn diagnostic
*** 40,45 ****
--- 40,49 ----
everything goes well. */
typedef int (*printer_fn) PARAMS ((output_buffer *));
+ /* The type of a context printer function. A context specific hook which is
+ called during printing a diagnostic to provide more information. */
+ typedef void (*diagnostic_scope_fn) PARAMS ((output_buffer *, void *));
+
/* This data structure encapulates an output_buffer's state. */
typedef struct
{
*************** void record_last_error_module PARAMS (
*** 203,207 ****
--- 207,215 ----
int error_function_changed PARAMS ((void));
void record_last_error_function PARAMS ((void));
void report_problematic_module PARAMS ((output_buffer *));
+
+ void push_diagnostic_scope PARAMS ((diagnostic_scope_fn, void *));
+ void *pop_diagnostic_scope PARAMS ((void));
+ void diagnostic_printf PARAMS ((output_buffer *, char const *, ...));
#endif /* __GCC_DIAGNOSTIC_H__ */
Index: cp/typeck.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/typeck.c,v
retrieving revision 1.310
diff -c -3 -p -r1.310 typeck.c
*** typeck.c 2000/09/10 21:34:41 1.310
--- typeck.c 2000/09/11 14:07:26
*************** Boston, MA 02111-1307, USA. */
*** 41,46 ****
--- 41,47 ----
#include "expr.h"
#include "toplev.h"
#include "defaults.h"
+ #include "diagnostic.h"
static tree convert_for_assignment PARAMS ((tree, tree, const char *, tree,
int));
*************** convert_for_assignment (type, rhs, errty
*** 6470,6475 ****
--- 6471,6492 ----
return perform_implicit_conversion (strip_top_quals (type), rhs);
}
+ struct convert_for_init_frame {
+ tree fn;
+ int parmnum;
+ };
+
+ static void
+ convert_for_init_scope (buffer, data)
+ output_buffer *buffer;
+ void *data;
+ {
+ struct convert_for_init_frame *frame = data;
+
+ diagnostic_printf (buffer, "in passing argument %P of `%+D'",
+ frame->parmnum, frame->fn);
+ }
+
/* Convert RHS to be of type TYPE.
If EXP is non-zero, it is the target of the initialization.
ERRTYPE is a string to use in error messages.
*************** convert_for_initialization (exp, type, r
*** 6541,6559 ****
if (codel == REFERENCE_TYPE)
{
/* This should eventually happen in convert_arguments. */
! extern int warningcount, errorcount;
! int savew = 0, savee = 0;
!
if (fndecl)
! savew = warningcount, savee = errorcount;
rhs = initialize_reference (type, rhs);
if (fndecl)
! {
! if (warningcount > savew)
! cp_warning_at ("in passing argument %P of `%+D'", parmnum, fndecl);
! else if (errorcount > savee)
! cp_error_at ("in passing argument %P of `%+D'", parmnum, fndecl);
! }
return rhs;
}
--- 6558,6572 ----
if (codel == REFERENCE_TYPE)
{
/* This should eventually happen in convert_arguments. */
! struct convert_for_init_frame frame;
!
! frame.fn = fndecl;
! frame.parmnum = parmnum;
if (fndecl)
! push_diagnostic_scope (convert_for_init_scope, &frame);
rhs = initialize_reference (type, rhs);
if (fndecl)
! pop_diagnostic_scope ();
return rhs;
}