Patchwork C++ PATCH to print missing template instantiation context

login
register
mail settings
Submitter Jason Merrill
Date April 22, 2013, 8:41 p.m.
Message ID <5175A06C.2040504@redhat.com>
Download mbox | patch
Permalink /patch/238663/
State New
Headers show

Comments

Jason Merrill - April 22, 2013, 8:41 p.m.
While looking at another issue, I noticed that we were missing some 
template instantiation context when a class instantiation was triggered 
by instantiation of a default template argument to a function; we got 
the information that the default argument was involved, but nothing 
about the call that necessitated the default argument.

This patch makes us push the subst level around the call to 
type_unification_real when we aren't in the middle of explaining why the 
call failed.

Tested x86_64-pc-linux-gnu, applying to trunk.

Patch

commit 4c44bea1d8228188db87478e418df7e10921b7c8
Author: Jason Merrill <jason@redhat.com>
Date:   Fri Apr 12 09:58:39 2013 -0400

    gcc/cp/
    	* pt.c (fn_type_unification): Push tinst level around
    	type_unification_real if we aren't explaining.
    	* cp-tree.h (TFF_NO_TEMPLATE_BINDINGS): New.
    	* error.c (dump_function_decl): Respect it.
    	(subst_to_string): Pass it.
    libstdc++-v3/
    	* testsuite/lib/prune.exp (libstdc++-dg-prune): Also ignore "In
    	substitution" lines.

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index a5c7548..d96340a 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4636,7 +4636,9 @@  enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, TYPENAME_FLAG };
    TFF_UNQUALIFIED_NAME: do not print the qualifying scope of the
        top-level entity.
    TFF_NO_OMIT_DEFAULT_TEMPLATE_ARGUMENTS: do not omit template arguments
-       identical to their defaults.  */
+       identical to their defaults.
+   TFF_NO_TEMPLATE_BINDINGS: do not print information about the template
+       arguments for a function template specialization.  */
 
 #define TFF_PLAIN_IDENTIFIER			(0)
 #define TFF_SCOPE				(1)
@@ -4652,6 +4654,7 @@  enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, TYPENAME_FLAG };
 #define TFF_NO_FUNCTION_ARGUMENTS		(1 << 10)
 #define TFF_UNQUALIFIED_NAME			(1 << 11)
 #define TFF_NO_OMIT_DEFAULT_TEMPLATE_ARGUMENTS	(1 << 12)
+#define TFF_NO_TEMPLATE_BINDINGS		(1 << 13)
 
 /* Returns the TEMPLATE_DECL associated to a TEMPLATE_TEMPLATE_PARM
    node.  */
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index 3206342..7a8c0bc 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -1451,7 +1451,8 @@  dump_function_decl (tree t, int flags)
 	dump_type_suffix (TREE_TYPE (fntype), flags);
 
       /* If T is a template instantiation, dump the parameter binding.  */
-      if (template_parms != NULL_TREE && template_args != NULL_TREE)
+      if (template_parms != NULL_TREE && template_args != NULL_TREE
+	  && !(flags & TFF_NO_TEMPLATE_BINDINGS))
 	{
 	  pp_cxx_whitespace (cxx_pp);
 	  pp_cxx_left_bracket (cxx_pp);
@@ -2889,7 +2890,8 @@  subst_to_string (tree p)
   tree decl = TREE_PURPOSE (p);
   tree targs = TREE_VALUE (p);
   tree tparms = DECL_TEMPLATE_PARMS (decl);
-  int flags = TFF_DECL_SPECIFIERS|TFF_TEMPLATE_HEADER;
+  int flags = (TFF_DECL_SPECIFIERS|TFF_TEMPLATE_HEADER
+	       |TFF_NO_TEMPLATE_BINDINGS);
 
   if (p == NULL_TREE)
     return "";
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 6ce2770..855c1f7 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -15125,9 +15125,21 @@  fn_type_unification (tree fn,
      callers must be ready to deal with unification failures in any
      event.  */
 
+  TREE_VALUE (tinst) = targs;
+  /* If we aren't explaining yet, push tinst context so we can see where
+     any errors (e.g. from class instantiations triggered by instantiation
+     of default template arguments) come from.  If we are explaining, this
+     context is redundant.  */
+  if (!explain_p && !push_tinst_level (tinst))
+    {
+      excessive_deduction_depth = true;
+      goto fail;
+    }
   ok = !type_unification_real (DECL_INNERMOST_TEMPLATE_PARMS (fn),
 			       targs, parms, args, nargs, /*subr=*/0,
 			       strict, flags, explain_p);
+  if (!explain_p)
+    pop_tinst_level ();
   if (!ok)
     goto fail;
 
diff --git a/gcc/testsuite/g++.dg/cpp0x/fntmpdefarg5.C b/gcc/testsuite/g++.dg/cpp0x/fntmpdefarg5.C
new file mode 100644
index 0000000..0821fc0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/fntmpdefarg5.C
@@ -0,0 +1,17 @@ 
+// Only print template subst context when it isn't redundant.
+// { dg-require-effective-target c++11 }
+// { dg-prune-output "error" }
+
+template<class T> struct A { typedef typename T::type type; };
+
+template <class T, class U = typename A<T>::type>
+void f(T);
+
+template <class T, class U = typename T::type>
+void g(T);
+
+int main()
+{
+  f(1);				// { dg-message "required from here" }
+  g(1);				// { dg-bogus "required from here" }
+}
diff --git a/libstdc++-v3/testsuite/lib/prune.exp b/libstdc++-v3/testsuite/lib/prune.exp
index b17fa00..6ed3efb 100644
--- a/libstdc++-v3/testsuite/lib/prune.exp
+++ b/libstdc++-v3/testsuite/lib/prune.exp
@@ -42,7 +42,7 @@  proc libstdc++-dg-prune { system text } {
 
     # Remove parts of warnings that refer to location of previous
     # definitions, etc as these confuse dejagnu
-    regsub -all "(^|\n)(\[^\n\]*: )?In ((static member |lambda )?function|member|method|(copy )?constructor|destructor|instantiation|program|subroutine|block-data)\[^\n\]*" $text "" text
+    regsub -all "(^|\n)(\[^\n\]*: )?In ((static member |lambda )?function|member|method|(copy )?constructor|destructor|instantiation|substitution|program|subroutine|block-data)\[^\n\]*" $text "" text
     regsub -all "(^|\n)\[^\n\]*(: )?At (top level|global scope):\[^\n\]*" $text "" text
     regsub -all "(^|\n)\[^\n\]*:   (recursively )?required \[^\n\]*" $text "" text
     regsub -all "(^|\n)\[^\n\]*:   . skipping \[0-9\]* instantiation contexts \[^\n\]*" $text "" text