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