Commit 4904b64b by Jason Merrill Committed by Jason Merrill

re PR c++/44609 (Invalid template code causes infinite loop of error messages)

	PR c++/44609
	* cp-tree.h (struct tinst_level): Add errors field.
	* pt.c (neglectable_inst_p, limit_bad_template_recurson): New.
	(push_tinst_level): Don't start another decl in that case.
	(reopen_tinst_level): Adjust errors field.
	* decl2.c (cp_write_global_declarations): Don't complain about
	undefined inline if its template was defined.
	* mangle.c (mangle_decl_string): Handle failure from push_tinst_level.

From-SVN: r176176
parent 848ca96f
2011-07-11 Jason Merrill <jason@redhat.com>
PR c++/44609
* cp-tree.h (struct tinst_level): Add errors field.
* pt.c (neglectable_inst_p, limit_bad_template_recurson): New.
(push_tinst_level): Don't start another decl in that case.
(reopen_tinst_level): Adjust errors field.
* decl2.c (cp_write_global_declarations): Don't complain about
undefined inline if its template was defined.
* mangle.c (mangle_decl_string): Handle failure from push_tinst_level.
2011-07-10 Jason Merrill <jason@redhat.com> 2011-07-10 Jason Merrill <jason@redhat.com>
PR c++/49691 PR c++/49691
......
...@@ -4679,6 +4679,9 @@ struct GTY((chain_next ("%h.next"))) tinst_level { ...@@ -4679,6 +4679,9 @@ struct GTY((chain_next ("%h.next"))) tinst_level {
/* The location where the template is instantiated. */ /* The location where the template is instantiated. */
location_t locus; location_t locus;
/* errorcount+sorrycount when we pushed this level. */
int errors;
/* True if the location is in a system header. */ /* True if the location is in a system header. */
bool in_system_header_p; bool in_system_header_p;
}; };
......
...@@ -3950,10 +3950,10 @@ cp_write_global_declarations (void) ...@@ -3950,10 +3950,10 @@ cp_write_global_declarations (void)
#pragma interface, etc.) we decided not to emit the #pragma interface, etc.) we decided not to emit the
definition here. */ definition here. */
&& !DECL_INITIAL (decl) && !DECL_INITIAL (decl)
/* An explicit instantiation can be used to specify /* Don't complain if the template was defined. */
that the body is in another unit. It will have && !(DECL_TEMPLATE_INSTANTIATION (decl)
already verified there was a definition. */ && DECL_INITIAL (DECL_TEMPLATE_RESULT
&& !DECL_EXPLICIT_INSTANTIATION (decl)) (template_for_substitution (decl)))))
{ {
warning (0, "inline function %q+D used but never defined", decl); warning (0, "inline function %q+D used but never defined", decl);
/* Avoid a duplicate warning from check_global_declaration_1. */ /* Avoid a duplicate warning from check_global_declaration_1. */
......
...@@ -3106,11 +3106,11 @@ mangle_decl_string (const tree decl) ...@@ -3106,11 +3106,11 @@ mangle_decl_string (const tree decl)
if (DECL_LANG_SPECIFIC (decl) && DECL_USE_TEMPLATE (decl)) if (DECL_LANG_SPECIFIC (decl) && DECL_USE_TEMPLATE (decl))
{ {
struct tinst_level *tl = current_instantiation (); struct tinst_level *tl = current_instantiation ();
if (!tl || tl->decl != decl) if ((!tl || tl->decl != decl)
&& push_tinst_level (decl))
{ {
template_p = true; template_p = true;
saved_fn = current_function_decl; saved_fn = current_function_decl;
push_tinst_level (decl);
current_function_decl = NULL_TREE; current_function_decl = NULL_TREE;
} }
} }
......
...@@ -7499,6 +7499,36 @@ uses_template_parms_level (tree t, int level) ...@@ -7499,6 +7499,36 @@ uses_template_parms_level (tree t, int level)
/*include_nondeduced_p=*/true); /*include_nondeduced_p=*/true);
} }
/* Returns TRUE iff INST is an instantiation we don't need to do in an
ill-formed translation unit, i.e. a variable or function that isn't
usable in a constant expression. */
static inline bool
neglectable_inst_p (tree d)
{
return (DECL_P (d)
&& !(TREE_CODE (d) == FUNCTION_DECL ? DECL_DECLARED_CONSTEXPR_P (d)
: decl_maybe_constant_var_p (d)));
}
/* Returns TRUE iff we should refuse to instantiate DECL because it's
neglectable and instantiated from within an erroneous instantiation. */
static bool
limit_bad_template_recurson (tree decl)
{
struct tinst_level *lev = current_tinst_level;
int errs = errorcount + sorrycount;
if (lev == NULL || errs == 0 || !neglectable_inst_p (decl))
return false;
for (; lev; lev = lev->next)
if (neglectable_inst_p (lev->decl))
break;
return (lev && errs > lev->errors);
}
static int tinst_depth; static int tinst_depth;
extern int max_tinst_depth; extern int max_tinst_depth;
#ifdef GATHER_STATISTICS #ifdef GATHER_STATISTICS
...@@ -7532,9 +7562,16 @@ push_tinst_level (tree d) ...@@ -7532,9 +7562,16 @@ push_tinst_level (tree d)
return 0; return 0;
} }
/* If the current instantiation caused problems, don't let it instantiate
anything else. Do allow deduction substitution and decls usable in
constant expressions. */
if (limit_bad_template_recurson (d))
return 0;
new_level = ggc_alloc_tinst_level (); new_level = ggc_alloc_tinst_level ();
new_level->decl = d; new_level->decl = d;
new_level->locus = input_location; new_level->locus = input_location;
new_level->errors = errorcount+sorrycount;
new_level->in_system_header_p = in_system_header; new_level->in_system_header_p = in_system_header;
new_level->next = current_tinst_level; new_level->next = current_tinst_level;
current_tinst_level = new_level; current_tinst_level = new_level;
...@@ -7578,6 +7615,8 @@ reopen_tinst_level (struct tinst_level *level) ...@@ -7578,6 +7615,8 @@ reopen_tinst_level (struct tinst_level *level)
current_tinst_level = level; current_tinst_level = level;
pop_tinst_level (); pop_tinst_level ();
if (current_tinst_level)
current_tinst_level->errors = errorcount+sorrycount;
return level->decl; return level->decl;
} }
......
2011-07-11 Jason Merrill <jason@redhat.com>
PR c++/44609
* g++.dg/template/recurse3.C: New.
2011-07-11 Jakub Jelinek <jakub@redhat.com> 2011-07-11 Jakub Jelinek <jakub@redhat.com>
PR debug/49676 PR debug/49676
......
// PR c++/44609
// { dg-options -ftemplate-depth=10 }
template<int N>
void f()
{
0 = 0; // { dg-error "lvalue required" }
f<N+1>(); // { dg-bogus "instantiation depth" }
}
int main()
{
f<0>();
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment