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
This commit is contained in:
parent
848ca96f30
commit
4904b64bf7
|
@ -1,3 +1,14 @@
|
|||
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>
|
||||
|
||||
PR c++/49691
|
||||
|
|
|
@ -4679,6 +4679,9 @@ struct GTY((chain_next ("%h.next"))) tinst_level {
|
|||
/* The location where the template is instantiated. */
|
||||
location_t locus;
|
||||
|
||||
/* errorcount+sorrycount when we pushed this level. */
|
||||
int errors;
|
||||
|
||||
/* True if the location is in a system header. */
|
||||
bool in_system_header_p;
|
||||
};
|
||||
|
|
|
@ -3950,10 +3950,10 @@ cp_write_global_declarations (void)
|
|||
#pragma interface, etc.) we decided not to emit the
|
||||
definition here. */
|
||||
&& !DECL_INITIAL (decl)
|
||||
/* An explicit instantiation can be used to specify
|
||||
that the body is in another unit. It will have
|
||||
already verified there was a definition. */
|
||||
&& !DECL_EXPLICIT_INSTANTIATION (decl))
|
||||
/* Don't complain if the template was defined. */
|
||||
&& !(DECL_TEMPLATE_INSTANTIATION (decl)
|
||||
&& DECL_INITIAL (DECL_TEMPLATE_RESULT
|
||||
(template_for_substitution (decl)))))
|
||||
{
|
||||
warning (0, "inline function %q+D used but never defined", decl);
|
||||
/* Avoid a duplicate warning from check_global_declaration_1. */
|
||||
|
|
|
@ -3106,11 +3106,11 @@ mangle_decl_string (const tree decl)
|
|||
if (DECL_LANG_SPECIFIC (decl) && DECL_USE_TEMPLATE (decl))
|
||||
{
|
||||
struct tinst_level *tl = current_instantiation ();
|
||||
if (!tl || tl->decl != decl)
|
||||
if ((!tl || tl->decl != decl)
|
||||
&& push_tinst_level (decl))
|
||||
{
|
||||
template_p = true;
|
||||
saved_fn = current_function_decl;
|
||||
push_tinst_level (decl);
|
||||
current_function_decl = NULL_TREE;
|
||||
}
|
||||
}
|
||||
|
|
39
gcc/cp/pt.c
39
gcc/cp/pt.c
|
@ -7499,6 +7499,36 @@ uses_template_parms_level (tree t, int level)
|
|||
/*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;
|
||||
extern int max_tinst_depth;
|
||||
#ifdef GATHER_STATISTICS
|
||||
|
@ -7532,9 +7562,16 @@ push_tinst_level (tree d)
|
|||
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->decl = d;
|
||||
new_level->locus = input_location;
|
||||
new_level->errors = errorcount+sorrycount;
|
||||
new_level->in_system_header_p = in_system_header;
|
||||
new_level->next = current_tinst_level;
|
||||
current_tinst_level = new_level;
|
||||
|
@ -7578,6 +7615,8 @@ reopen_tinst_level (struct tinst_level *level)
|
|||
|
||||
current_tinst_level = level;
|
||||
pop_tinst_level ();
|
||||
if (current_tinst_level)
|
||||
current_tinst_level->errors = errorcount+sorrycount;
|
||||
return level->decl;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
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>
|
||||
|
||||
PR debug/49676
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
// 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>();
|
||||
}
|
Loading…
Reference in New Issue