PATCH:g++ error formatting

Nathan Sidwell nathan@acm.org
Wed Mar 10 02:52:00 GMT 1999


Hi,
Here's a patch to cp/error.c which tidies up some overloading of the verbose
flag and enables the dumping of exception specifications.

Currently dump_type_real uses the verbose flag to a) print 'struct A' rather
than plain 'A', and b) print default argument values on a parameter list. This
means it's not possible to print a function declaration showing default
arguments, without also being verbose about the types. I.e. '%#D' can be rather
verbose!
There's also duplicate code dealing with function parameters scattered around
error.c. What I've done is moved the code from dump_type_real which printed the
inner parts of an argument list to a new static function, dump_parameters. This
allows other parts of error.c to be tidied up. dump_parameters uses its verbose
flag to show default values. It does not pass the verbose flag through to
printing out its parameter types.

In line with this, I altered the code which deals with printing pointers to
functions. Here I inhibit the printing of default parameters, as function
pointers have to match exactly. (This is possibly a little excessive on my
part.)

Here's an example program showing old and new behaviour
void fn(void (*)(int = 0) = 0);
void fn(int (*)(int = 0) = 0);
struct A;
typedef struct A B;

void foo(A *, B *);
void foo(A *, A *);
void foo(A *, B *, int = 0);
void foo(A *, B *, float = 0);
void f()
{
  fn();
  foo(0, 0);
}
-- old behaviour
foo.cc: In function `void f()':
foo.cc:12: call of overloaded `fn ()' is ambiguous
foo.cc:1: candidates are: void fn(void (*)(int = 0) = 0)
foo.cc:2:                 void fn(int (*)(int = 0) = 0)
foo.cc:13: call of overloaded `foo (int, int)' is ambiguous
foo.cc:7: candidates are: void foo(struct A *, struct A *)
foo.cc:8:                 void foo(struct A *, struct B *, int = 0)
foo.cc:9:                 void foo(struct A *, struct B *, float = 0)
-- patched behaviour
foo.cc: In function `void f()':
foo.cc:12: call of overloaded `fn ()' is ambiguous
foo.cc:1: candidates are: void fn(void (*)(int) = 0)
foo.cc:2:                 void fn(int (*)(int) = 0)
foo.cc:13: call of overloaded `foo (int, int)' is ambiguous
foo.cc:7: candidates are: void foo(A *, A *)
foo.cc:8:                 void foo(A *, B *, int = 0)
foo.cc:9:                 void foo(A *, B *, float = 0)

As preparatory work for checking of exception specifiers, I've added a new
static function, dump_exception_spec, which does what its name suggests. I've
added calls to this from dump_function_decl, and from dumping pointers to
functions. (So it'll work when we grok those.) Now that gives rather a lot of
options to how dump_function_decl should behave. It would be inappropriate to
always dump the exception specs. Although I've extended the meaning of its
verbose flag, the meanings of the old values (-ve, 0, 1) remain unchanged. Two
new values (2, 3) indicate whether throw specifiers should be printed with or
without default argument values. I believe the possible actions of
dump_function_decl to be sensible.

Finally to get cp_error to print a function decl with throw specifiers I've
added a '%F' format specifier. With the '#' modifier this will print default
argument values too. The behaviour of '%D' and '%#D' remains unaltered in this
respect. I intend to use this when moaning about throw specifiers mismatching.

A minor change to sig.c, is that it wasn't taking advantage of cp_error's
formatting escapes.

There were no changes in the regression behaviour of the g++ testsuite with
this patch.

Enjoy,
nathan
-- 
Dr Nathan Sidwell :: Computer Science Department :: Bristol University
      You can up the bandwidth, but you can't up the speed of light      
nathan@acm.org  http://www.cs.bris.ac.uk/~nathan/  nathan@cs.bris.ac.uk
egcs/gcc/cp/ChangeLog:
Wed Mar 10 09:46:08 GMT 1999  Nathan Sidwell  <nathan@acm.org>

	* error.c (cp_printers): Add 'F' escape character.
	(dump_type_real): Remove TREE_LIST (fnargs) printing.
	Functionality moved to dump_parameters.
	(dump_type_suffix): Use dump_parameters and dump_exception_spec.
	(dump_function_decl): Extend meaning of V parameter. Use
	dump_parameters and dump_exception_spec.
	(dump_parameters): New static function.
	(dump_exception_spec): New static function.
	(fndecl_as_string): Change argument semantics. Use
	dump_function_decl directly.
	
	* sig.c (build_signature_table_constructor): Use cp_error.
	
Index: egcs/gcc/cp/error.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/error.c,v
retrieving revision 1.67
diff -c -3 -p -r1.67 error.c
*** error.c	1999/01/21 14:29:28	1.67
--- error.c	1999/03/10 09:50:56
*************** typedef char* cp_printer ();
*** 32,37 ****
--- 32,38 ----
  #define C code_as_string
  #define D decl_as_string
  #define E expr_as_string
+ #define F fndecl_as_string
  #define L language_as_string
  #define O op_as_string
  #define P parm_as_string
*************** cp_printer * cp_printers[256] =
*** 47,53 ****
    o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, /* 0x10 */
    o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, /* 0x20 */
    o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, /* 0x30 */
!   o, A, o, C, D, E, o, o, o, o, o, o, L, o, o, O, /* 0x40 */
    P, Q, o, o, T, o, V, o, o, o, o, o, o, o, o, o, /* 0x50 */
    o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, /* 0x60 */
    o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, /* 0x70 */
--- 48,54 ----
    o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, /* 0x10 */
    o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, /* 0x20 */
    o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, /* 0x30 */
!   o, A, o, C, D, E, F, o, o, o, o, o, L, o, o, O, /* 0x40 */
    P, Q, o, o, T, o, V, o, o, o, o, o, o, o, o, o, /* 0x50 */
    o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, /* 0x60 */
    o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, /* 0x70 */
*************** cp_printer * cp_printers[256] =
*** 55,60 ****
--- 56,62 ----
  #undef C
  #undef D
  #undef E
+ #undef F
  #undef L
  #undef O
  #undef P
*************** static void dump_expr_list PROTO((tree))
*** 104,109 ****
--- 106,113 ----
  static void dump_global_iord PROTO((tree));
  static void dump_qualifiers PROTO((tree, enum pad));
  static void dump_char PROTO((int));
+ static void dump_parameters PROTO((tree, int, int));
+ static void dump_exception_spec PROTO((tree, int));
  static char *aggr_variety PROTO((tree));
  static tree ident_fndecl PROTO((tree));
  
*************** dump_type_real (t, v, canonical_name)
*** 201,229 ****
        OB_PUTS ("{unknown type}");
        break;
  
-     case TREE_LIST:
-       /* i.e. function taking no arguments */
-       if (t != void_list_node)
- 	{
- 	  dump_type_real (TREE_VALUE (t), v, canonical_name);
- 	  /* Can this happen other than for default arguments? */
- 	  if (TREE_PURPOSE (t) && v)
- 	    {
- 	      OB_PUTS (" = ");
- 	      dump_expr (TREE_PURPOSE (t), 0);
- 	    }
- 	  if (TREE_CHAIN (t))
- 	    {
- 	      if (TREE_CHAIN (t) != void_list_node)
- 		{
- 		  OB_PUTC2 (',', ' ');
- 		  dump_type_real (TREE_CHAIN (t), v, canonical_name);
- 		}
- 	    }
- 	  else OB_PUTS (" ...");
- 	}
-       break;
- 
      case IDENTIFIER_NODE:
        OB_PUTID (t);
        break;
--- 205,210 ----
*************** dump_type_suffix (t, v, canonical_name)
*** 569,588 ****
      case METHOD_TYPE:
        {
  	tree arg;
! 	OB_PUTC2 (')', '(');
  	arg = TYPE_ARG_TYPES (t);
  	if (TREE_CODE (t) == METHOD_TYPE)
  	  arg = TREE_CHAIN (arg);
! 
! 	if (arg)
! 	  dump_type (arg, v);
! 	else
! 	  OB_PUTS ("...");
! 	OB_PUTC (')');
  	if (TREE_CODE (t) == METHOD_TYPE)
  	  dump_qualifiers
  	    (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t))), before);
  	dump_type_suffix (TREE_TYPE (t), v, canonical_name);
  	break;
        }
  
--- 550,565 ----
      case METHOD_TYPE:
        {
  	tree arg;
! 	OB_PUTC (')');
  	arg = TYPE_ARG_TYPES (t);
  	if (TREE_CODE (t) == METHOD_TYPE)
  	  arg = TREE_CHAIN (arg);
! 	dump_parameters (arg, 0, canonical_name); /* no default args on fptr */
  	if (TREE_CODE (t) == METHOD_TYPE)
  	  dump_qualifiers
  	    (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t))), before);
  	dump_type_suffix (TREE_TYPE (t), v, canonical_name);
+ 	dump_exception_spec (TYPE_RAISES_EXCEPTIONS (t), canonical_name);
  	break;
        }
  
*************** dump_decl (t, v)
*** 957,966 ****
      }
  }
  
! /* Pretty printing for announce_function.  T is the declaration of the
!    function we are interested in seeing.  If V is zero, we print the
!    argument types.  If V is positive, we also print the return types.
!    If V is negative, we do not even print the argument types.  */
  
  static void
  dump_function_decl (t, v)
--- 934,948 ----
      }
  }
  
! /* Pretty print a function decl. There are several ways we want to print a
!    function declaration. We use V to tell us what.
!      V    - 01 23
!    args   - ++ ++
!    retval - -+ ++
!    default- -+ -+
!    throw  - -- ++
!    As cp_error can only apply the '#' flag once to give 0 and 1 for V, there
!    is %D which doesn't print the throw specs, and %F which does. */
  
  static void
  dump_function_decl (t, v)
*************** dump_function_decl (t, v)
*** 1026,1041 ****
    /* If V is negative, we don't print the argument types.  */
    if (v < 0)
      return;
- 
-   OB_PUTC ('(');
  
!   if (parmtypes)
!     dump_type (parmtypes, v);
!   else
!     OB_PUTS ("...");
! 
!   OB_PUTC (')');
! 
    if (v && ! DECL_CONV_FN_P (t))
      dump_type_suffix (TREE_TYPE (fntype), 1, 0);
  
--- 1008,1016 ----
    /* If V is negative, we don't print the argument types.  */
    if (v < 0)
      return;
  
!   dump_parameters (parmtypes, v & 1, 0);
!   
    if (v && ! DECL_CONV_FN_P (t))
      dump_type_suffix (TREE_TYPE (fntype), 1, 0);
  
*************** dump_function_decl (t, v)
*** 1049,1056 ****
--- 1024,1093 ----
  	dump_qualifiers
  	  (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (fntype))), before);
      }
+   
+   if (v >= 2)
+     dump_exception_spec (TYPE_RAISES_EXCEPTIONS (fntype), 0);
  }
  
+ /* Print a parameter list. V indicates if we show default values or not. If
+    these are for a member function, the member object ptr
+    (and any other hidden args) should have already been removed. */
+ 
+ static void
+ dump_parameters (parmtypes, v, canonical_name)
+      tree parmtypes;
+      int v;
+      int canonical_name;
+ {
+   int first;
+   OB_PUTC ('(');
+ 
+   for (first = 1; parmtypes != void_list_node;
+        parmtypes = TREE_CHAIN (parmtypes))
+     {
+       if (!first)
+         OB_PUTC2 (',', ' ');
+       first = 0;
+       if (!parmtypes)
+         {
+           OB_PUTS ("...");
+           break;
+         }
+       dump_type_real (TREE_VALUE (parmtypes), 0, canonical_name);
+       
+       if (TREE_PURPOSE (parmtypes) && v)
+         {
+           OB_PUTS (" = ");
+           dump_expr (TREE_PURPOSE (parmtypes), 0);
+         }
+     }
+ 
+   OB_PUTC (')');
+ }
+ 
+ /* Print an exception specification. T is the exception specification. */
+ 
+ static void
+ dump_exception_spec (t, canonical_name)
+      tree t;
+      int canonical_name;
+ {
+   if (t)
+     {
+       OB_PUTS (" throw (");
+       if (TREE_VALUE (t) != NULL_TREE)
+         while (1)
+           {
+             dump_type_real (TREE_VALUE (t), 0, canonical_name);
+             t = TREE_CHAIN (t);
+             if (!t)
+               break;
+             OB_PUTC2 (',', ' ');
+           }
+       OB_PUTC (')');
+     }
+ }
+ 
  /* Handle the function name for a FUNCTION_DECL node, grokking operators
     and destructors properly.  */
  
*************** dump_unary_op (opstring, t, nop)
*** 1758,1769 ****
    if (!nop) OB_PUTC (')');
  }
  
  char *
! fndecl_as_string (fndecl, print_ret_type_p)
       tree fndecl;
!      int print_ret_type_p;
  {
!   return decl_as_string (fndecl, print_ret_type_p);
  }
  
  /* Same, but handle a _TYPE.
--- 1795,1814 ----
    if (!nop) OB_PUTC (')');
  }
  
+ /* Print a function decl with exception specification included. */
+ 
  char *
! fndecl_as_string (fndecl, print_default_args_p)
       tree fndecl;
!      int print_default_args_p;
  {
!   OB_INIT ();
! 
!   dump_function_decl (fndecl, 2 + print_default_args_p);
!   
!   OB_FINISH ();
! 
!   return (char *)obstack_base (&scratch_obstack);
  }
  
  /* Same, but handle a _TYPE.
Index: egcs/gcc/cp/sig.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/sig.c,v
retrieving revision 1.18
diff -c -3 -p -r1.18 sig.c
*** sig.c	1998/12/16 21:16:10	1.18
--- sig.c	1999/03/10 09:50:57
*************** build_signature_table_constructor (sig_t
*** 551,559 ****
  	      || (compute_access (basetypes, rhs_method)
  		  != access_public_node))
  	    {
! 	      error ("class `%s' does not contain a method conforming to `%s'",
! 		     TYPE_NAME_STRING (rhstype),
! 		     fndecl_as_string (sig_method, 1));
  	      undo_casts (sig_ty);
  	      return error_mark_node;
  	    }
--- 551,558 ----
  	      || (compute_access (basetypes, rhs_method)
  		  != access_public_node))
  	    {
! 	      cp_error ("`%T' does not contain a method conforming to `%#D'",
! 		     rhstype, sig_method);
  	      undo_casts (sig_ty);
  	      return error_mark_node;
  	    }


More information about the Gcc-patches mailing list