This is the mail archive of the gcc-patches@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]

Patch to pretty print function template intantiation



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



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