Hi,
this is, IMHO, a rather interesting issue. I was working on PR 54080,
where currently with ICE pretty badly for Error reporting routines
re-entered without producing any sensible error message. Figured out
that the core of the issue are the error messages in push_tinst_level
about template instantiation depth exceeded. Drafted the attached, the
error message is great with no ICE:
54080.C: In instantiation of ‘decltype (foo<template<class T> class
vector>(foo(input, func1), funcrest)) foo(const vector<int>&, const
Func1&, FuncRest) [with OutType = vector; Func1 = int; FuncRest = int;
decltype (foo<vector>(foo(input, func1), funcrest)) = vector<int>]’:
54080.C:25:22: required from here
54080.C:19:2: error: return-statement with no value, in function
returning ‘vector<int>’ [-fpermissive]
return;
when I ran the testsuite, I found something (tidied):
FAIL: g++.dg/cpp0x/decltype26.C (test for errors, line 6)
FAIL: g++.dg/cpp0x/decltype26.C (test for excess errors)
FAIL: g++.dg/cpp0x/decltype28.C (test for errors, line 11)
FAIL: g++.dg/cpp0x/decltype28.C (test for warnings, line 15)
FAIL: g++.dg/cpp0x/decltype29.C (test for errors, line 12)
FAIL: g++.dg/cpp0x/decltype29.C (test for excess errors)
the really interesting one is decltype28.C, which we don't reject
anymore, we simply accept it. What is happening is that the overload
which leads to excessive template instantiation depth is SFINAE-ed away
and the other one "wins"! Thus, this is the core of my message: it seems
that we behave wrt this issue - SFINAE vs template instantiation depth -
in a different way vs current clang++ and icc: we produce hard error
messages in SFINAE contexts. Is that intended? I find the issue
interesting, arguably a template instantiation depth exceeded isn't just
like any other error.
With the attached draft we handle quite a few other testcases I have
seen around in a different way, for example c++/52875 is automatically
fixed (assuming we want to behave like clang++ and icc).
Thanks!
Paolo.
Index: cp-tree.h
===================================================================
--- cp-tree.h (revision 201588)
+++ cp-tree.h (working copy)
@@ -5541,7 +5541,7 @@ extern tree fold_non_dependent_expr_sfinae (tree,
extern bool alias_type_or_template_p (tree);
extern bool alias_template_specialization_p (const_tree);
extern bool explicit_class_specialization_p (tree);
-extern int push_tinst_level (tree);
+extern int push_tinst_level (tree, tsubst_flags_t);
extern void pop_tinst_level (void);
extern struct tinst_level *outermost_tinst_level(void);
extern void init_template_processing (void);
Index: mangle.c
===================================================================
--- mangle.c (revision 201588)
+++ mangle.c (working copy)
@@ -3429,7 +3429,7 @@ mangle_decl_string (const tree decl)
{
struct tinst_level *tl = current_instantiation ();
if ((!tl || tl->decl != decl)
- && push_tinst_level (decl))
+ && push_tinst_level (decl, tf_warning_or_error))
{
template_p = true;
saved_fn = current_function_decl;
Index: pt.c
===================================================================
--- pt.c (revision 201588)
+++ pt.c (working copy)
@@ -6995,7 +6995,7 @@ add_pending_template (tree d)
level = !current_tinst_level || current_tinst_level->decl != d;
if (level)
- push_tinst_level (d);
+ push_tinst_level (d, tf_warning_or_error);
pt = ggc_alloc_pending_template ();
pt->next = NULL;
@@ -8021,24 +8021,28 @@ static GTY(()) struct tinst_level *last_error_tins
for diagnostics and to restore it later. */
int
-push_tinst_level (tree d)
+push_tinst_level (tree d, tsubst_flags_t complain)
{
struct tinst_level *new_level;
if (tinst_depth >= max_tinst_depth)
{
last_error_tinst_level = current_tinst_level;
- if (TREE_CODE (d) == TREE_LIST)
- error ("template instantiation depth exceeds maximum of %d (use "
- "-ftemplate-depth= to increase the maximum) substituting %qS",
- max_tinst_depth, d);
- else
- error ("template instantiation depth exceeds maximum of %d (use "
- "-ftemplate-depth= to increase the maximum) instantiating %qD",
- max_tinst_depth, d);
- print_instantiation_context ();
+ if (complain & tf_error)
+ {
+ if (TREE_CODE (d) == TREE_LIST)
+ error ("template instantiation depth exceeds maximum of %d (use "
+ "-ftemplate-depth= to increase the maximum) "
+ "substituting %qS", max_tinst_depth, d);
+ else
+ error ("template instantiation depth exceeds maximum of %d (use "
+ "-ftemplate-depth= to increase the maximum) "
+ "instantiating %qD", max_tinst_depth, d);
+ print_instantiation_context ();
+ }
+
return 0;
}
@@ -8691,7 +8695,7 @@ instantiate_class_template_1 (tree type)
return type;
/* If we've recursively instantiated too many templates, stop. */
- if (! push_tinst_level (type))
+ if (! push_tinst_level (type, tf_warning_or_error))
return type;
/* Now we're really doing the instantiation. Mark the type as in
@@ -15005,7 +15009,7 @@ instantiate_alias_template (tree tmpl, tree args,
if (tmpl == error_mark_node || args == error_mark_node)
return error_mark_node;
tree tinst = build_tree_list (tmpl, args);
- if (!push_tinst_level (tinst))
+ if (!push_tinst_level (tinst, complain))
{
ggc_free (tinst);
return error_mark_node;
@@ -15219,7 +15223,7 @@ fn_type_unification (tree fn,
}
TREE_VALUE (tinst) = explicit_targs;
- if (!push_tinst_level (tinst))
+ if (!push_tinst_level (tinst, complain))
{
excessive_deduction_depth = true;
goto fail;
@@ -15270,7 +15274,7 @@ fn_type_unification (tree fn,
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))
+ if (!explain_p && !push_tinst_level (tinst, complain))
{
excessive_deduction_depth = true;
goto fail;
@@ -15327,7 +15331,7 @@ fn_type_unification (tree fn,
substitution results in an invalid type, as described above,
type deduction fails. */
TREE_VALUE (tinst) = targs;
- if (!push_tinst_level (tinst))
+ if (!push_tinst_level (tinst, complain))
{
excessive_deduction_depth = true;
goto fail;
@@ -18876,7 +18880,7 @@ maybe_instantiate_noexcept (tree fn)
if (TREE_CODE (noex) == DEFERRED_NOEXCEPT)
{
- if (push_tinst_level (fn))
+ if (push_tinst_level (fn, tf_warning_or_error))
{
push_access_scope (fn);
push_deferring_access_checks (dk_no_deferred);
@@ -19000,7 +19004,7 @@ instantiate_decl (tree d, int defer_ok,
|| spec == NULL_TREE);
/* This needs to happen before any tsubsting. */
- if (! push_tinst_level (d))
+ if (! push_tinst_level (d, tf_warning_or_error))
return d;
timevar_push (TV_TEMPLATE_INST);
Index: typeck2.c
===================================================================
--- typeck2.c (revision 201588)
+++ typeck2.c (working copy)
@@ -1564,7 +1564,7 @@ build_x_arrow (location_t loc, tree expr, tsubst_f
return error_mark_node;
if (fn && DECL_USE_TEMPLATE (fn))
- push_tinst_level (fn);
+ push_tinst_level (fn, complain);
fn = NULL;
if (vec_member (TREE_TYPE (expr), types_memoized))