diff options
author | Jason Merrill <jason@redhat.com> | 2011-07-11 14:52:12 -0400 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2011-07-11 14:52:12 -0400 |
commit | 4904b64bf7dc5538b06d2ba01fc1c55231c09bb8 (patch) | |
tree | 3256896a64479248e6b7bfbaeb3af03b35d3636e /gcc/cp/pt.c | |
parent | 848ca96f30746fc6972105de156656ce8c5ee586 (diff) | |
download | gcc-4904b64bf7dc5538b06d2ba01fc1c55231c09bb8.zip gcc-4904b64bf7dc5538b06d2ba01fc1c55231c09bb8.tar.gz gcc-4904b64bf7dc5538b06d2ba01fc1c55231c09bb8.tar.bz2 |
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
Diffstat (limited to 'gcc/cp/pt.c')
-rw-r--r-- | gcc/cp/pt.c | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 2c64dd4..7c735ef 100644 --- a/gcc/cp/pt.c +++ b/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; } |