This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Patch to pretty print function template intantiation
- To: egcs-patches at egcs dot cygnus dot com
- Subject: Patch to pretty print function template intantiation
- From: gdr at codesourcery dot com
- Date: 29 Sep 1999 03:34:17 +0200
- Organization: CodeSourcery, LLC
- Reply-To: gdr at codesourcery dot com
I checked in the following patch (approved my Mark). Basically, it
attemps to pretty print template instantiations (implicit or
explicit), mostly in diagnostic messages.
Consider the following (erronous) program:
template<typename T> struct vector {};
template<typename T> struct list {};
template<typename T> struct stack {};
template<typename T>
T f (T, const list<T>* = 0, T = T())
{
T& t;
return t;
}
void g()
{
stack<vector<double> > svd;
f(svd);
}
int main()
{
g();
}
Right now, G++ used to say:
1.C: In function `stack<vector<double> > f<stack<vector<double> > >(stack<vector<double> >, const list<stack<vector<double> > > *, stack<vector<double> >)':
1.C:17: instantiated from here
1.C:10: `t' declared as reference but not initialized
An understandable message but really hard to read. With my patch, we
get a small improvement:
1.C: In function `T f (T, const list<T> *, T) [with T = stack<vector<double> >]':
1.C:17: instantiated from here
1.C:10: `t' declared as reference but not initialized
something less messier to read, still understandable. I guess
libstdc++-v3 folks will find that helpful. Future patches will
supply automatic line wrapping.
Comments/advice are welcome.
-- Gaby
999-09-28 Gabriel Dos Reis <gdr@codesourcery.com>
* pt.c (most_general_template): Adjust declaration.
* cp-tree.h: (most_general_template): Declare.
* error.c (dump_template_value): Rename to ...
(dump_template_argument): This.
(dump_template_argument_list): New function.
(dump_type): Use it.
(dump_template_parameter): New function.
(dump_template_decl): Use it.
(dump_template_bindings): New function.
(dump_function_decl): Use it. Pretty print function template
instantiations.
Index: cp/error.c
===================================================================
RCS file: /cvs/egcs/egcs/gcc/cp/error.c,v
retrieving revision 1.91
diff -p -r1.91 error.c
*** error.c 1999/09/27 08:25:59 1.91
--- error.c 1999/09/29 01:02:04
*************** static void dump_parameters PROTO((tree,
*** 89,95 ****
static void dump_exception_spec PROTO((tree, enum tree_string_flags));
static const char *aggr_variety PROTO((tree));
static tree ident_fndecl PROTO((tree));
! static void dump_template_value PROTO((tree, enum tree_string_flags));
static void dump_scope PROTO((tree, enum tree_string_flags));
static void dump_template_parms PROTO((tree, int, enum tree_string_flags));
--- 89,98 ----
static void dump_exception_spec PROTO((tree, enum tree_string_flags));
static const char *aggr_variety PROTO((tree));
static tree ident_fndecl PROTO((tree));
! static void dump_template_argument PROTO((tree, enum tree_string_flags));
! static void dump_template_argument_list PROTO((tree, enum tree_string_flags));
! static void dump_template_parameter PROTO((tree, enum tree_string_flags));
! static void dump_template_bindings PROTO((tree, tree, enum tree_string_flags));
static void dump_scope PROTO((tree, enum tree_string_flags));
static void dump_template_parms PROTO((tree, int, enum tree_string_flags));
*************** dump_qualifiers (t, p)
*** 211,231 ****
value. */
static char digit_buffer[128];
! /* Dump a template parameter or template argument VALUE under
! control of FLAGS. */
static void
! dump_template_value (value, flags)
! tree value;
enum tree_string_flags flags;
{
! if (TREE_CODE_CLASS (TREE_CODE (value)) == 't'
! || TREE_CODE (value) == TEMPLATE_DECL)
! dump_type (value, flags & ~TS_AGGR_TAGS);
else
! dump_expr (value, (flags | TS_EXPR_PARENS) & ~TS_AGGR_TAGS);
}
/* Dump into the obstack a human-readable equivalent of TYPE. FLAGS
controls the format. */
--- 214,333 ----
value. */
static char digit_buffer[128];
! /* Dump the template ARGument under control of FLAGS. */
static void
! dump_template_argument (arg, flags)
! tree arg;
enum tree_string_flags flags;
{
! if (TREE_CODE_CLASS (TREE_CODE (arg)) == 't'
! || TREE_CODE (arg) == TEMPLATE_DECL)
! dump_type (arg, flags & ~TS_AGGR_TAGS);
else
! dump_expr (arg, (flags | TS_EXPR_PARENS) & ~TS_AGGR_TAGS);
}
+ /* Dump a template-argument-list ARGS (always a TREE_VEC) under control
+ of FLAGS. */
+
+ static void
+ dump_template_argument_list (args, flags)
+ tree args;
+ enum tree_string_flags flags;
+ {
+ int n = TREE_VEC_LENGTH (args);
+ int need_comma = 0;
+ int i;
+
+ for (i = 0; i< n; ++i)
+ {
+ if (need_comma)
+ OB_PUTS (", ");
+ dump_template_argument (TREE_VEC_ELT (args, i), flags);
+ need_comma = 1;
+ }
+ }
+
+ /* Dump a template parameter PARM (a TREE_LIST) under control of FLAGS. */
+
+ static void
+ dump_template_parameter (parm, flags)
+ tree parm;
+ enum tree_string_flags flags;
+ {
+ tree p = TREE_VALUE (parm);
+ tree a = TREE_PURPOSE (parm);
+
+ if (TREE_CODE (p) == TYPE_DECL)
+ {
+ if (flags & TS_DECL_TYPE)
+ {
+ OB_PUTS ("class");
+ if (DECL_NAME (p))
+ {
+ OB_PUTC (' ');
+ OB_PUTID (DECL_NAME (p));
+ }
+ }
+ else if (DECL_NAME (p))
+ OB_PUTID (DECL_NAME (p));
+ else
+ OB_PUTS ("{template default argument error}");
+ }
+ else
+ dump_decl (p, flags | TS_DECL_TYPE);
+
+ if ((flags & TS_PARM_DEFAULTS) && a != NULL_TREE)
+ {
+ OB_PUTS (" = ");
+ if (TREE_CODE (a) == TYPE_DECL || TREE_CODE (a) == TEMPLATE_DECL)
+ dump_type (a, flags & ~TS_CHASE_TYPEDEFS);
+ else
+ dump_expr (a, flags | TS_EXPR_PARENS);
+ }
+ }
+
+ /* Dump, under control of FLAGS, a template-parameter-list binding.
+ PARMS is a TREE_LIST of TREE_VEC of TREE_LIST and ARGS is a
+ TREE_VEC. */
+
+ static void
+ dump_template_bindings (parms, args, flags)
+ tree parms, args;
+ enum tree_string_flags flags;
+ {
+ int arg_idx = 0;
+ int need_comma = 0;
+
+ while (parms)
+ {
+ tree p = TREE_VALUE (parms);
+ int i;
+
+ for (i = 0; i < TREE_VEC_LENGTH (p); ++i)
+ {
+ tree arg = TREE_VEC_ELT (args, arg_idx);
+
+ if (need_comma)
+ OB_PUTS (", ");
+ dump_template_parameter (TREE_VEC_ELT (p, i), TS_PLAIN);
+ OB_PUTS (" = ");
+ if (arg)
+ dump_template_argument (arg, TS_PLAIN);
+ else
+ OB_PUTS ("{missing}");
+
+ ++arg_idx;
+ need_comma = 1;
+ }
+
+ parms = TREE_CHAIN (parms);
+ }
+ }
+
+
+
/* Dump into the obstack a human-readable equivalent of TYPE. FLAGS
controls the format. */
*************** dump_type (t, flags)
*** 315,335 ****
if (TYPE_IDENTIFIER (t))
OB_PUTID (TYPE_IDENTIFIER (t));
else
! OB_PUTS ("{anonymous template template parm}");
}
else
{
- int i;
tree args = TYPE_TI_ARGS (t);
OB_PUTID (TYPE_IDENTIFIER (t));
OB_PUTC ('<');
! for (i = 0; i < TREE_VEC_LENGTH (args); i++)
! {
! tree arg = TREE_VEC_ELT (args, i);
! if (i)
! OB_PUTS (", ");
! dump_template_value (arg, flags);
! }
OB_END_TEMPLATE_ID ();
}
break;
--- 417,430 ----
if (TYPE_IDENTIFIER (t))
OB_PUTID (TYPE_IDENTIFIER (t));
else
! OB_PUTS ("{anonymous template template parameter}");
}
else
{
tree args = TYPE_TI_ARGS (t);
OB_PUTID (TYPE_IDENTIFIER (t));
OB_PUTC ('<');
! dump_template_argument_list (args, flags);
OB_END_TEMPLATE_ID ();
}
break;
*************** dump_type (t, flags)
*** 339,345 ****
if (TYPE_IDENTIFIER (t))
OB_PUTID (TYPE_IDENTIFIER (t));
else
! OB_PUTS ("{anonymous template type parm}");
break;
/* This is not always necessary for pointers and such, but doing this
--- 434,440 ----
if (TYPE_IDENTIFIER (t))
OB_PUTID (TYPE_IDENTIFIER (t));
else
! OB_PUTS ("{anonymous template type parameter}");
break;
/* This is not always necessary for pointers and such, but doing this
*************** dump_type (t, flags)
*** 375,381 ****
/* Fall through to error. */
case ERROR_MARK:
! OB_PUTS ("{typeerror}");
break;
}
}
--- 470,476 ----
/* Fall through to error. */
case ERROR_MARK:
! OB_PUTS ("{type error}");
break;
}
}
*************** dump_simple_decl (t, type, flags)
*** 742,748 ****
if (DECL_NAME (t))
dump_decl (DECL_NAME (t), flags);
else
! OB_PUTS ("{anon}");
if (flags & TS_DECL_TYPE)
dump_type_suffix (type, flags);
}
--- 837,843 ----
if (DECL_NAME (t))
dump_decl (DECL_NAME (t), flags);
else
! OB_PUTS ("{anonymous}");
if (flags & TS_DECL_TYPE)
dump_type_suffix (type, flags);
}
*************** dump_decl (t, flags)
*** 802,808 ****
case NAMESPACE_DECL:
dump_scope (CP_DECL_CONTEXT (t), flags);
if (DECL_NAME (t) == anonymous_namespace_name)
! OB_PUTS ("{anonymous}");
else
OB_PUTID (DECL_NAME (t));
break;
--- 897,903 ----
case NAMESPACE_DECL:
dump_scope (CP_DECL_CONTEXT (t), flags);
if (DECL_NAME (t) == anonymous_namespace_name)
! OB_PUTS ("{unnamed}");
else
OB_PUTID (DECL_NAME (t));
break;
*************** dump_decl (t, flags)
*** 892,898 ****
OB_PUTC ('<');
for (args = TREE_OPERAND (t, 1); args; args = TREE_CHAIN (args))
{
! dump_template_value (TREE_VALUE (args), flags);
if (TREE_CHAIN (args))
OB_PUTS (", ");
}
--- 987,993 ----
OB_PUTC ('<');
for (args = TREE_OPERAND (t, 1); args; args = TREE_CHAIN (args))
{
! dump_template_argument (TREE_VALUE (args), flags);
if (TREE_CHAIN (args))
OB_PUTS (", ");
}
*************** dump_decl (t, flags)
*** 934,940 ****
/* Fallthrough to error. */
case ERROR_MARK:
! OB_PUTS ("{declerror}");
break;
}
}
--- 1029,1035 ----
/* Fallthrough to error. */
case ERROR_MARK:
! OB_PUTS ("{declaration error}");
break;
}
}
*************** dump_template_decl (t, flags)
*** 962,994 ****
OB_PUTS ("template <");
for (i = 0; i < len; i++)
{
- tree arg = TREE_VEC_ELT (TREE_VALUE (args), i);
- tree defval = TREE_PURPOSE (arg);
- arg = TREE_VALUE (arg);
if (i)
OB_PUTS (", ");
! if (TREE_CODE (arg) == TYPE_DECL)
! {
! if (DECL_NAME (arg))
! {
! OB_PUTS ("class ");
! OB_PUTID (DECL_NAME (arg));
! }
! else
! OB_PUTS ("class");
! }
! else
! dump_decl (arg, flags | TS_DECL_TYPE);
!
! if (defval)
! {
! OB_PUTS (" = ");
! if (TREE_CODE (arg) == TYPE_DECL
! || TREE_CODE (arg) == TEMPLATE_DECL)
! dump_type (defval, flags);
! else
! dump_expr (defval, flags | TS_EXPR_PARENS);
! }
}
OB_END_TEMPLATE_ID ();
OB_PUTC (' ');
--- 1057,1065 ----
OB_PUTS ("template <");
for (i = 0; i < len; i++)
{
if (i)
OB_PUTS (", ");
! dump_template_parameter (TREE_VEC_ELT (args, i), flags);
}
OB_END_TEMPLATE_ID ();
OB_PUTC (' ');
*************** dump_function_decl (t, flags)
*** 1034,1044 ****
--- 1105,1125 ----
tree fntype;
tree parmtypes;
tree cname = NULL_TREE;
+ tree template_args = NULL_TREE;
+ tree template_parms = NULL_TREE;
int show_return = !(flags & TS_FUNC_NORETURN) && (flags & TS_DECL_TYPE);
if (TREE_CODE (t) == TEMPLATE_DECL)
t = DECL_TEMPLATE_RESULT (t);
+ /* Pretty print template instantiations only. */
+ if (DECL_USE_TEMPLATE (t) == 1 || DECL_USE_TEMPLATE (t) == 3)
+ {
+ template_args = DECL_TI_ARGS (t);
+ t = most_general_template (t);
+ template_parms = DECL_TEMPLATE_PARMS (t);
+ }
+
fntype = TREE_TYPE (t);
parmtypes = TYPE_ARG_TYPES (fntype);
*************** dump_function_decl (t, flags)
*** 1098,1103 ****
--- 1179,1192 ----
if (flags & TS_FUNC_THROW)
dump_exception_spec (TYPE_RAISES_EXCEPTIONS (fntype), flags);
+
+ /* If T is a template instantiation, dump the parameter binding. */
+ if (template_parms != NULL_TREE && template_args != NULL_TREE)
+ {
+ OB_PUTS (" [with ");
+ dump_template_bindings (template_parms, template_args, flags);
+ OB_PUTC (']');
+ }
}
/* Print a parameter list. If this is for a member function, the
*************** dump_template_parms (info, primary, flag
*** 1255,1263 ****
OB_PUTS (", ");
if (!arg)
! OB_PUTS ("{tplparmerror}");
else
! dump_template_value (arg, flags);
need_comma = 1;
}
}
--- 1344,1352 ----
OB_PUTS (", ");
if (!arg)
! OB_PUTS ("{template parameter error}");
else
! dump_template_argument (arg, flags);
need_comma = 1;
}
}
*************** dump_expr (t, flags)
*** 1956,1962 ****
/* fall through to ERROR_MARK... */
case ERROR_MARK:
! OB_PUTCP ("{exprerror}");
break;
}
}
--- 2045,2051 ----
/* fall through to ERROR_MARK... */
case ERROR_MARK:
! OB_PUTCP ("{expression error}");
break;
}
}
Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/egcs/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.320
diff -p -r1.320 cp-tree.h
*** cp-tree.h 1999/09/27 08:25:58 1.320
--- cp-tree.h 1999/09/29 01:02:05
*************** extern tree most_specialized_instantiati
*** 3644,3649 ****
--- 3644,3650 ----
extern void print_candidates PROTO((tree));
extern int instantiate_pending_templates PROTO((void));
extern tree tsubst_default_argument PROTO((tree, tree, tree));
+ extern tree most_general_template PROTO((tree));
extern int processing_template_parmlist;
Index: cp/pt.c
===================================================================
RCS file: /cvs/egcs/egcs/gcc/cp/pt.c,v
retrieving revision 1.365
diff -p -r1.365 pt.c
*** pt.c 1999/09/27 08:26:00 1.365
--- pt.c 1999/09/29 01:02:05
*************** static tree tsubst_template_parms PROTO(
*** 136,142 ****
static void regenerate_decl_from_template PROTO((tree, tree));
static tree most_specialized PROTO((tree, tree, tree));
static tree most_specialized_class PROTO((tree, tree));
- static tree most_general_template PROTO((tree));
static void set_mangled_name_for_template_decl PROTO((tree));
static int template_class_depth_real PROTO((tree, int));
static tree tsubst_aggr_type PROTO((tree, tree, int, tree, int));
--- 136,141 ----
*************** most_specialized (fns, decl, explicit_ar
*** 9088,9094 ****
if TMPL is `template <class U> void S<int*>::f(U)' this will return
`template <class T> template <class U> S<T*>::f(U)'. */
! static tree
most_general_template (decl)
tree decl;
{
--- 9087,9093 ----
if TMPL is `template <class U> void S<int*>::f(U)' this will return
`template <class T> template <class U> S<T*>::f(U)'. */
! tree
most_general_template (decl)
tree decl;
{