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++/14912 (omitting default template args in error messages)


This patch has been kicking around for years, without ever actually making it into G++. I'm not sure why, exactly; I guess Giovanni lost interest in it due to controversy over future directions. The current patch omits defaulted template arguments when dumping a class template specialization, i.e. vector<int> rather than vector<int, allocator<int> >. It does not remove defaulted template arguments from the pretty-printing of function template specializations, which will still look like (say)

void std::vector<_Tp, _Alloc>::_M_initialize_dispatch(_InputIterator,
_InputIterator, std::__false_type)
[with _InputIterator = double, _Tp = std::vector<std::vector<int> >,
 _Alloc = std::allocator<std::vector<std::vector<int> > >]

Because _Alloc shows up in the template signature, I think we need to list what that name means even if it's defaulted. But because dumping the binding itself uses the normal type mechanisms, we omit the default arguments there so we avoid the combinatorial explosion problem that we previously got with nested containers.

Tested x86_64-pc-linux-gnu, applied to trunk.
2009-04-05  Giovanni Bajo <giovannibajo@libero.it>
	    Jason Merrill  <jason@redhat.com>

	PR c++/14912
	* error.c (count_non_default_template_args): New fn.
	(dump_template_parms): Call it.
	(dump_template_argument_list): Call it.  Add parms parm.
	(dump_template_argument): Adjust call to dump_template_argument_list.
	(dump_type, dump_decl): Likewise.
	(dump_template_bindings): Refactor logic.

diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index 8b31980..a97017a 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -73,12 +73,14 @@ static void dump_global_iord (tree);
 static void dump_parameters (tree, int);
 static void dump_exception_spec (tree, int);
 static void dump_template_argument (tree, int);
-static void dump_template_argument_list (tree, int);
+static void dump_template_argument_list (tree, 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);
 
+static int count_non_default_template_args (tree, tree);
+
 static const char *function_category (tree);
 static void maybe_print_instantiation_context (diagnostic_context *);
 static void print_instantiation_full_context (diagnostic_context *);
@@ -140,7 +142,7 @@ static void
 dump_template_argument (tree arg, int flags)
 {
   if (ARGUMENT_PACK_P (arg))
-    dump_template_argument_list (ARGUMENT_PACK_ARGS (arg), flags);
+    dump_template_argument_list (ARGUMENT_PACK_ARGS (arg), NULL_TREE, flags);
   else if (TYPE_P (arg) || TREE_CODE (arg) == TEMPLATE_DECL)
     dump_type (arg, flags & ~TFF_CLASS_KEY_OR_ENUM);
   else
@@ -152,17 +154,49 @@ dump_template_argument (tree arg, int flags)
     }
 }
 
+/* Count the number of template arguments ARGS whose value does not
+   match the (optional) default template parameter in PARAMS  */
+
+static int
+count_non_default_template_args (tree args, tree params)
+{
+  int n = TREE_VEC_LENGTH (args);
+  int last;
+
+  if (params == NULL_TREE)
+    return n;
+
+  for (last = n - 1; last >= 0; --last)
+    {
+      tree param = TREE_VEC_ELT (params, last);
+      tree def = TREE_PURPOSE (param);
+
+      if (!def)
+        break;
+      if (uses_template_parms (def))
+	{
+	  ++processing_template_decl;
+	  def = tsubst_copy_and_build (def, args, tf_none, NULL_TREE, false, true);
+	  --processing_template_decl;
+	}
+      if (!cp_tree_equal (TREE_VEC_ELT (args, last), def))
+        break;
+    }
+
+  return last + 1;
+}
+
 /* Dump a template-argument-list ARGS (always a TREE_VEC) under control
    of FLAGS.  */
 
 static void
-dump_template_argument_list (tree args, int flags)
+dump_template_argument_list (tree args, tree parms, int flags)
 {
-  int n = TREE_VEC_LENGTH (args);
+  int n = count_non_default_template_args (args, parms);
   int need_comma = 0;
   int i;
 
-  for (i = 0; i< n; ++i)
+  for (i = 0; i < n; ++i)
     {
       tree arg = TREE_VEC_ELT (args, i);
 
@@ -240,18 +274,19 @@ dump_template_bindings (tree parms, tree args, VEC(tree,gc)* typenames)
       int lvl = TMPL_PARMS_DEPTH (parms);
       int arg_idx = 0;
       int i;
+      tree lvl_args = NULL_TREE;
+
+      /* Don't crash if we had an invalid argument list.  */
+      if (TMPL_ARGS_DEPTH (args) >= lvl)
+	lvl_args = TMPL_ARGS_LEVEL (args, lvl);
 
       for (i = 0; i < TREE_VEC_LENGTH (p); ++i)
 	{
 	  tree arg = NULL_TREE;
 
 	  /* Don't crash if we had an invalid argument list.  */
-	  if (TMPL_ARGS_DEPTH (args) >= lvl)
-	    {
-	      tree lvl_args = TMPL_ARGS_LEVEL (args, lvl);
-	      if (NUM_TMPL_ARGS (lvl_args) > arg_idx)
-		arg = TREE_VEC_ELT (lvl_args, arg_idx);
-	    }
+	  if (lvl_args && NUM_TMPL_ARGS (lvl_args) > arg_idx)
+	    arg = TREE_VEC_ELT (lvl_args, arg_idx);
 
 	  if (need_comma)
 	    pp_separate_with_comma (cxx_pp);
@@ -365,7 +400,7 @@ dump_type (tree t, int flags)
 	pp_cxx_cv_qualifier_seq (cxx_pp, t);
 	pp_cxx_tree_identifier (cxx_pp, TYPE_IDENTIFIER (t));
 	pp_cxx_begin_template_argument_list (cxx_pp);
-	dump_template_argument_list (args, flags);
+	dump_template_argument_list (args, NULL_TREE, flags);
 	pp_cxx_end_template_argument_list (cxx_pp);
       }
       break;
@@ -959,7 +994,7 @@ dump_decl (tree t, int flags)
 	dump_decl (name, flags);
 	pp_cxx_begin_template_argument_list (cxx_pp);
 	if (TREE_OPERAND (t, 1))
-	  dump_template_argument_list (TREE_OPERAND (t, 1), flags);
+	  dump_template_argument_list (TREE_OPERAND (t, 1), NULL_TREE, flags);
 	pp_cxx_end_template_argument_list (cxx_pp);
       }
       break;
@@ -1389,11 +1424,15 @@ dump_template_parms (tree info, int primary, int flags)
   if (args && !primary)
     {
       int len, ix;
+      /* We don't know the parms for a friend template specialization.  */
+      tree params = (TREE_CODE (TI_TEMPLATE (info)) == TEMPLATE_DECL
+		     ? DECL_INNERMOST_TEMPLATE_PARMS (TI_TEMPLATE (info))
+		     : NULL_TREE);
 
       if (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (args))
 	args = TREE_VEC_ELT (args, TREE_VEC_LENGTH (args) - 1);
 
-      len = TREE_VEC_LENGTH (args);
+      len = count_non_default_template_args (args, params);
 
       for (ix = 0; ix != len; ix++)
 	{
diff --git a/gcc/testsuite/g++.dg/template/error39.C b/gcc/testsuite/g++.dg/template/error39.C
new file mode 100644
index 0000000..49faa36
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/error39.C
@@ -0,0 +1,11 @@
+// PR c++/14912
+
+template <class T, int N=0, int X=1>
+struct A
+{
+};
+
+void foo(void)
+{
+  A<void> a = 0;		// { dg-error "A<void>" }
+}

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