This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: Diagnostics formatting...


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

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]