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.
commit 4c44bea1d8228188db87478e418df7e10921b7c8
Author: Jason Merrill <ja...@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