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]
Other format: [Raw text]

C++ PATCH for c++/25185 (unhelpful diagnostics)


The problem in 25185 is that when the signature for a function template uses typename, pretty-printing the template signature followed by the template arguments doesn't help the user to know what the typename means, which can be important when trying to figure out what the problem in their code is. This patch changes template pretty-printing to also print the meaning of any typenames that appear in the signature.

Tested x86_64-pc-linux-gnu, applied to trunk.
2009-04-02  Jason Merrill  <jason@redhat.com>

	PR c++/25185
	* error.c (find_typenames, find_typenames_r): New fns.
	(dump_function_decl): Call find_typenames.
	(dump_template_bindings): Print typenames as well.
	* pt.c (tsubst): Non-static.
	* cp-tree.h: Declare it.

Index: cp/error.c
===================================================================
*** cp/error.c	(revision 145475)
--- cp/error.c	(working copy)
*************** along with GCC; see the file COPYING3.  
*** 30,35 ****
--- 30,36 ----
  #include "diagnostic.h"
  #include "langhooks-def.h"
  #include "cxx-pretty-print.h"
+ #include "pointer-set.h"
  
  #define pp_separate_with_comma(PP) pp_cxx_separate_with (PP, ',')
  
*************** static void dump_exception_spec (tree, i
*** 74,80 ****
  static void dump_template_argument (tree, int);
  static void dump_template_argument_list (tree, int);
  static void dump_template_parameter (tree, int);
! static void dump_template_bindings (tree, tree);
  static void dump_scope (tree, int);
  static void dump_template_parms (tree, int, int);
  
--- 75,81 ----
  static void dump_template_argument (tree, int);
  static void dump_template_argument_list (tree, int);
  static void dump_template_parameter (tree, int);
! static void dump_template_bindings (tree, tree, VEC(tree,gc) *);
  static void dump_scope (tree, int);
  static void dump_template_parms (tree, int, int);
  
*************** dump_template_parameter (tree parm, int 
*** 227,235 ****
     TREE_VEC.  */
  
  static void
! dump_template_bindings (tree parms, tree args)
  {
    int need_comma = 0;
  
    while (parms)
      {
--- 228,238 ----
     TREE_VEC.  */
  
  static void
! dump_template_bindings (tree parms, tree args, VEC(tree,gc)* typenames)
  {
    int need_comma = 0;
+   int i;
+   tree t;
  
    while (parms)
      {
*************** dump_template_bindings (tree parms, tree
*** 267,272 ****
--- 270,286 ----
  
        parms = TREE_CHAIN (parms);
      }
+ 
+   for (i = 0; VEC_iterate (tree, typenames, i, t); ++i)
+     {
+       if (need_comma)
+ 	pp_separate_with_comma (cxx_pp);
+       dump_type (t, 0);
+       pp_cxx_whitespace (cxx_pp);
+       pp_equal (cxx_pp);
+       pp_cxx_whitespace (cxx_pp);
+       dump_type (tsubst (t, args, tf_none, NULL_TREE), 0);
+     }
  }
  
  /* Dump a human-readable equivalent of TYPE.  FLAGS controls the
*************** dump_template_decl (tree t, int flags)
*** 1074,1079 ****
--- 1088,1138 ----
      }
  }
  
+ /* find_typenames looks through the type of the function template T
+    and returns a VEC containing any TYPENAME_TYPEs it finds.  */
+ 
+ struct find_typenames_t
+ {
+   struct pointer_set_t *p_set;
+   VEC (tree,gc) *typenames;
+ };
+ 
+ static tree
+ find_typenames_r (tree *tp, int *walk_subtrees, void *data)
+ {
+   struct find_typenames_t *d = (struct find_typenames_t *)data;
+ 
+   if (TREE_CODE (*tp) == TYPENAME_TYPE)
+     {
+       /* Discard any cv-qualifiers.  */
+       tree mv = TYPE_MAIN_VARIANT (*tp);
+       if (mv == *tp || !pointer_set_insert (d->p_set, mv))
+ 	VEC_safe_push (tree, gc, d->typenames, mv);
+       *walk_subtrees = 0;
+     }
+   /* Search into class template arguments, which cp_walk_subtrees
+      doesn't do.  */
+   else if (CLASS_TYPE_P (*tp) && CLASSTYPE_TEMPLATE_INFO (*tp))
+     {
+       cp_walk_tree (&CLASSTYPE_TI_ARGS (*tp), find_typenames_r,
+ 		    data, d->p_set);
+       *walk_subtrees = 0;
+     }
+   return NULL_TREE;
+ }
+ 
+ static VEC(tree,gc) *
+ find_typenames (tree t)
+ {
+   struct find_typenames_t ft;
+   ft.p_set = pointer_set_create ();
+   ft.typenames = NULL;
+   cp_walk_tree (&TREE_TYPE (DECL_TEMPLATE_RESULT (t)),
+ 		find_typenames_r, &ft, ft.p_set);
+   pointer_set_destroy (ft.p_set);
+   return ft.typenames;
+ }
+ 
  /* Pretty print a function decl. There are several ways we want to print a
     function declaration. The TFF_ bits in FLAGS tells us how to behave.
     As error can only apply the '#' flag once to give 0 and 1 for V, there
*************** dump_function_decl (tree t, int flags)
*** 1090,1095 ****
--- 1149,1155 ----
    int show_return = flags & TFF_RETURN_TYPE || flags & TFF_DECL_SPECIFIERS;
    int do_outer_scope = ! (flags & TFF_UNQUALIFIED_NAME);
    tree exceptions;
+   VEC(tree,gc) *typenames = NULL;
  
    flags &= ~TFF_UNQUALIFIED_NAME;
    if (TREE_CODE (t) == TEMPLATE_DECL)
*************** dump_function_decl (tree t, int flags)
*** 1110,1115 ****
--- 1170,1176 ----
  	{
  	  template_parms = DECL_TEMPLATE_PARMS (tmpl);
  	  t = tmpl;
+ 	  typenames = find_typenames (t);
  	}
      }
  
*************** dump_function_decl (tree t, int flags)
*** 1177,1183 ****
        pp_cxx_left_bracket (cxx_pp);
        pp_cxx_identifier (cxx_pp, "with");
        pp_cxx_whitespace (cxx_pp);
!       dump_template_bindings (template_parms, template_args);
        pp_cxx_right_bracket (cxx_pp);
      }
  }
--- 1238,1244 ----
        pp_cxx_left_bracket (cxx_pp);
        pp_cxx_identifier (cxx_pp, "with");
        pp_cxx_whitespace (cxx_pp);
!       dump_template_bindings (template_parms, template_args, typenames);
        pp_cxx_right_bracket (cxx_pp);
      }
  }
Index: cp/pt.c
===================================================================
*** cp/pt.c	(revision 145475)
--- cp/pt.c	(working copy)
*************** static int eq_local_specializations (con
*** 170,176 ****
  static bool dependent_template_arg_p (tree);
  static bool any_template_arguments_need_structural_equality_p (tree);
  static bool dependent_type_p_r (tree);
- static tree tsubst (tree, tree, tsubst_flags_t, tree);
  static tree tsubst_expr	(tree, tree, tsubst_flags_t, tree, bool);
  static tree tsubst_copy	(tree, tree, tsubst_flags_t, tree);
  static tree tsubst_pack_expansion (tree, tree, tsubst_flags_t, tree);
--- 170,175 ----
*************** tsubst_exception_specification (tree fnt
*** 9079,9085 ****
     This function is used for dealing with types, decls and the like;
     for expressions, use tsubst_expr or tsubst_copy.  */
  
! static tree
  tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
  {
    tree type, r;
--- 9078,9084 ----
     This function is used for dealing with types, decls and the like;
     for expressions, use tsubst_expr or tsubst_copy.  */
  
! tree
  tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
  {
    tree type, r;
Index: cp/cp-tree.h
===================================================================
*** cp/cp-tree.h	(revision 145475)
--- cp/cp-tree.h	(working copy)
*************** extern tree most_specialized_instantiati
*** 4593,4598 ****
--- 4593,4599 ----
  extern void print_candidates			(tree);
  extern void instantiate_pending_templates	(int);
  extern tree tsubst_default_argument		(tree, tree, tree);
+ extern tree tsubst (tree, tree, tsubst_flags_t, tree);
  extern tree tsubst_copy_and_build		(tree, tree, tsubst_flags_t,
  						 tree, bool, bool);
  extern tree most_general_template		(tree);
Index: testsuite/g++.dg/template/error38.C
===================================================================
*** testsuite/g++.dg/template/error38.C	(revision 0)
--- testsuite/g++.dg/template/error38.C	(revision 0)
***************
*** 0 ****
--- 1,19 ----
+ // Testcase for printing typename bindings as well as template args
+ // in diagnostics (PR c++/25185)
+ 
+ template <class T>
+ struct A {
+   typename T::type f();		// { dg-message "typename T::type = void*" }
+   void f(int i = 0);		// { dg-message "" }
+ };
+ 
+ struct B
+ {
+   typedef void* type;
+ };
+ 
+ int main()
+ {
+   A<B> a;
+   a.f();			// { dg-error "" }
+ }

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