This template meta-programming equivalent of an infinite loop ------------------------ template <int N> struct X { static const int value = X<N-1>::value; }; template struct X<1000>; ------------------------ generates inordinately long and un-useful output, namely one line per intermediate class: g/a> /home/bangerth/bin/gcc-3.4-pre/bin/gcc -c x.cc x.cc:2: error: template instantiation depth exceeds maximum of 500 (use -ftemplate-depth-NN to increase the maximum) instantiating `struct X<500>' x.cc:2: instantiated from `X<501>' x.cc:2: instantiated from `X<502>' x.cc:2: instantiated from `X<503>' [...] x.cc:2: instantiated from `X<1000>' x.cc:4: instantiated from here x.cc:2: error: incomplete type `X<500>' does not have member `value' I think this should be cut-down somehow. Since the default value for -ftemplate-depth has been raised from 17 to 500, showing the whole list is no longer useful. On the other hand, this is really a very minor nuisance, so I lowered all priorities for this one. W. Release: unknown Environment: all versions of gcc
State-Changed-From-To: open->analyzed State-Changed-Why: Still true
From: "Giovanni Bajo" <giovannibajo@libero.it> To: <gcc-gnats@gcc.gnu.org>, <gcc-bugs@gcc.gnu.org>, <nobody@gcc.gnu.org>, <bangerth@ticam.utexas.edu>, <gcc-prs@gcc.gnu.org> Cc: Subject: Re: c++/9335: Inordinately long output when maximum template depth is exceeded Date: Fri, 2 May 2003 20:32:27 +0200 http://gcc.gnu.org/cgi-bin/gnatsweb.pl?cmd=view%20audit-trail&database=gcc&pr=9335 For completeness, Comeau's diagnostic is: "pr9335.cpp", line 2: error: excessive recursion at instantiation of class "X<936>" static const int value = X<N-1>::value; ^ detected during: instantiation of class "X<N> [with N=937]" at line 2 instantiation of class "X<N> [with N=938]" at line 2 instantiation of class "X<N> [with N=939]" at line 2 instantiation of class "X<N> [with N=940]" at line 2 instantiation of class "X<N> [with N=941]" at line 2 [ 54 instantiation contexts not shown ] instantiation of class "X<N> [with N=996]" at line 2 instantiation of class "X<N> [with N=997]" at line 2 instantiation of class "X<N> [with N=998]" at line 2 instantiation of class "X<N> [with N=999]" at line 2 instantiation of class "X<N> [with N=1000]" at line 4 Giovanni Bajo
Responsible-Changed-From-To: unassigned->gdr Responsible-Changed-Why: Diagnostic mantainer
*** Bug 23510 has been marked as a duplicate of this bug. ***
*** Bug 43113 has been marked as a duplicate of this bug. ***
The following patch seems to do the trick: Index: gcc/cp/error.c =================================================================== --- gcc/cp/error.c (revision 150311) +++ gcc/cp/error.c (working copy) @@ -2707,31 +2707,83 @@ print_instantiation_full_context (diagno } /* Same as above but less verbose. */ static void print_instantiation_partial_context (diagnostic_context *context, - struct tinst_level *t, location_t loc) + struct tinst_level *t0, location_t loc) { + struct tinst_level *t; expanded_location xloc; const char *str; - for (; ; t = t->next) + int n_total = 0; + int n; + int skip = 0; + + xloc = expand_location (loc); + + for (t = t0; t != NULL; t = t->next) + n_total++; + + t = t0; + + if (n_total >= 12) + { + skip = n_total - 10; + for (n = 0; n < 5; n++) + { + gcc_assert (t != NULL); + str = decl_as_string_translate (t->decl, + TFF_DECL_SPECIFIERS | TFF_RETURN_TYPE); + if (flag_show_column) + pp_verbatim (context->printer, + _("%s:%d:%d: instantiated from %qs\n"), + xloc.file, xloc.line, xloc.column, str); + else + pp_verbatim (context->printer, + _("%s:%d: instantiated from %qs\n"), + xloc.file, xloc.line, str); + loc = t->locus; + xloc = expand_location (loc); + t = t->next; + } + } + + if (skip) + { + if (flag_show_column) + pp_verbatim (context->printer, + _("%s:%d:%d: [ skipping %d instantiation contexts ]\n"), + xloc.file, xloc.line, xloc.column, skip); + else + pp_verbatim (context->printer, + _("%s:%d: [ skipping %d instantiation contexts ]\n"), + xloc.file, xloc.line, skip); + + while (skip-- > 0) + { + loc = t->locus; + xloc = expand_location (loc); + t = t->next; + } + } + + for (; t != NULL; t = t->next) { - xloc = expand_location (loc); - if (t == NULL) - break; str = decl_as_string_translate (t->decl, - TFF_DECL_SPECIFIERS | TFF_RETURN_TYPE); + TFF_DECL_SPECIFIERS | TFF_RETURN_TYPE); if (flag_show_column) pp_verbatim (context->printer, _("%s:%d:%d: instantiated from %qs\n"), xloc.file, xloc.line, xloc.column, str); else pp_verbatim (context->printer, _("%s:%d: instantiated from %qs\n"), xloc.file, xloc.line, str); loc = t->locus; + xloc = expand_location (loc); } + if (flag_show_column) pp_verbatim (context->printer, _("%s:%d:%d: instantiated from here"), xloc.file, xloc.line, xloc.column); else pp_verbatim (context->printer, _("%s:%d: instantiated from here"),
Having this finally fixed would be really great, Manuel!
However, this particular error has gotten much worse and now we iterate over the error: (...skipping a lot of lines...) pr9335.C: In instantiation of ‘const int X<15>::value’: pr9335.C:2:36: instantiated from ‘const int X<16>::value’ pr9335.C:2:36: instantiated from ‘const int X<17>::value’ pr9335.C:2:36: instantiated from ‘const int X<18>::value’ pr9335.C:2:36: instantiated from ‘const int X<19>::value’ pr9335.C:2:36: instantiated from ‘const int X<20>::value’ pr9335.C:4:17: instantiated from here pr9335.C:2:36: error: ‘X<15>::value’ cannot be initialized by a non-constant expression when being declared pr9335.C: In instantiation of ‘const int X<16>::value’: pr9335.C:2:36: instantiated from ‘const int X<17>::value’ pr9335.C:2:36: instantiated from ‘const int X<18>::value’ pr9335.C:2:36: instantiated from ‘const int X<19>::value’ pr9335.C:2:36: instantiated from ‘const int X<20>::value’ pr9335.C:4:17: instantiated from here pr9335.C:2:36: error: ‘X<16>::value’ cannot be initialized by a non-constant expression when being declared pr9335.C: In instantiation of ‘const int X<17>::value’: pr9335.C:2:36: instantiated from ‘const int X<18>::value’ pr9335.C:2:36: instantiated from ‘const int X<19>::value’ pr9335.C:2:36: instantiated from ‘const int X<20>::value’ pr9335.C:4:17: instantiated from here pr9335.C:2:36: error: ‘X<17>::value’ cannot be initialized by a non-constant expression when being declared pr9335.C: In instantiation of ‘const int X<18>::value’: pr9335.C:2:36: instantiated from ‘const int X<19>::value’ pr9335.C:2:36: instantiated from ‘const int X<20>::value’ pr9335.C:4:17: instantiated from here pr9335.C:2:36: error: ‘X<18>::value’ cannot be initialized by a non-constant expression when being declared pr9335.C: In instantiation of ‘const int X<19>::value’: pr9335.C:2:36: instantiated from ‘const int X<20>::value’ pr9335.C:4:17: instantiated from here pr9335.C:2:36: error: ‘X<19>::value’ cannot be initialized by a non-constant expression when being declared pr9335.C: In instantiation of ‘const int X<20>::value’: pr9335.C:4:17: instantiated from here pr9335.C:2:36: error: ‘X<20>::value’ cannot be initialized by a non-constant expression when being declared
Now, I mean a recent GCC (4.5), not my patch. The testcase for 23510 works ok and the output of my patch is: pr9335-2.C:7:3: error: expected unqualified-id before ‘template’ pr9335-2.C: At global scope: pr9335-2.C:4:3: error: template instantiation depth exceeds maximum of 50 (use -ftemplate-depth-NN to increase the maximum) instantiating ‘struct Factorial<4294967251u>’ pr9335-2.C:4:3: instantiated from ‘Factorial<4294967252u>’ pr9335-2.C:4:3: instantiated from ‘Factorial<4294967253u>’ pr9335-2.C:4:3: instantiated from ‘Factorial<4294967254u>’ pr9335-2.C:4:3: instantiated from ‘Factorial<4294967255u>’ pr9335-2.C:4:3: instantiated from ‘Factorial<4294967256u>’ pr9335-2.C:4:3: [ skipping 40 instantiation contexts ] pr9335-2.C:4:3: instantiated from ‘Factorial<1u>’ pr9335-2.C:4:3: instantiated from ‘Factorial<2u>’ pr9335-2.C:4:3: instantiated from ‘Factorial<3u>’ pr9335-2.C:4:3: instantiated from ‘Factorial<4u>’ pr9335-2.C:4:3: instantiated from ‘Factorial<5u>’ pr9335-2.C:17:20: instantiated from here pr9335-2.C:4:3: error: incomplete type ‘Factorial<4294967251u>’ used in nested name specifier So I can ignore this testcase and take the ones from PR23510 and PR43113.
With my patch, the testcase in PR43113 still looks awful because each single line is already too long. Basically, my patch fixes PR23510. The other PRs are different (but related) problems.
Maybe it was a mistake on my part closing PR43113 as duplicate of this one. Unless you can soon manage to fix both at once with a single patch, maybe better separating the PRs again. Anyway, with your draft, PR9335 appears to improve, at least.
The reason why this testcase cannot be solved like bug 23510 is that this testcase produces many repeated: error: template instantiation depth exceeds maximum of 500 (use -ftemplate-depth-NN to increase the maximum) instantiating `struct X<500>' each of them with their own long list of instantiations. In fact, this could have been detected in the testsuite: gcc/testsuite/g++.dg/template/recurse.C but the testsuite does not detect repeated messages. We should give just one error like Comeau does. This is a regression but I don't know in which version this used to work.
I have a patch that prints this: /home/manuel/src/pr9335.C:2:36: error: template instantiation depth exceeds maximum of 1024 (use -ftemplate-depth= to increase the maximum) instantiating ‘struct X<-0x00000000000000018>’ /home/manuel/src/pr9335.C:2:36: recursively instantiated from ‘const int X<1000>::value’ /home/manuel/src/pr9335.C:4:17: instantiated from here /home/manuel/src/pr9335.C:2:36: error: incomplete type ‘X<-0x00000000000000018>’ used in nested name specifier /home/manuel/src/pr9335.C: In instantiation of ‘const int X<-0x00000000000000016>::value’: /home/manuel/src/pr9335.C:2:36: recursively instantiated from ‘const int X<1000>::value’ /home/manuel/src/pr9335.C:4:17: instantiated from here /home/manuel/src/pr9335.C:2:36: error: ‘X<-0x00000000000000016>::value’ cannot be initialized by a non-constant expression when being declared /home/manuel/src/pr9335.C: In instantiation of ‘const int X<-0x00000000000000015>::value’: /home/manuel/src/pr9335.C:2:36: recursively instantiated from ‘const int X<1000>::value’ /home/manuel/src/pr9335.C:4:17: instantiated from here /home/manuel/src/pr9335.C:2:36: error: ‘X<-0x00000000000000015>::value’ cannot be initialized by a non-constant expression when being declared /home/manuel/src/pr9335.C: In instantiation of ‘const int X<-0x00000000000000014>::value’: /home/manuel/src/pr9335.C:2:36: recursively instantiated from ‘const int X<1000>::value’ /home/manuel/src/pr9335.C:4:17: instantiated from here then continues for 4000 lines It is perhaps an improvement but not a fix. @Jason, I see that in pt.c (instantiate_decl), after we get the first error, then init == error_mark_node. However, the parser continues building the declaration as if nothing. And we end up with something like: <var_decl 0x7ffff717bf00 value type <integer_type 0x7ffff7490f18 int readonly type_6 SI size <integer_cst 0x7ffff754d960 constant 32> unit size <integer_cst 0x7ffff754d668 constant 4> align 32 symtab 0 alias set -1 canonical type 0x7ffff7490f18 precision 32 min <integer_cst 0x7ffff754d8e8 -2147483648> max <integer_cst 0x7ffff754d910 2147483647\ >> readonly constant used public static tree_1 tree_2 tree_3 external nonlocal decl_3 decl_6 SI file /home/manuel/src/pr9335.C line 2 col 36 size <integer_cst 0x7ffff75\ 4d960 32> unit size <integer_cst 0x7ffff754d668 4> align 32 context <record_type 0x7ffff717ddc8 X> initial <error_mark 0x7ffff7555ca8> template-info 0x7ffff7177600 chain <type_decl 0x7ffff717e8a0 X>> Couldn't we abort all this earlier?
That sounds like another case where trying to recover from an error by changing a problematic type to 'int' doesn't actually improve matters.
Subject: Re: repeated diagnostic when maximum template depth is exceeded When that happens? I am sorry but your answer does not help me to find how to fix this.
Created attachment 20403 [details] patch to stop error cascade This patch fixes the repeated error; it turns out I was wrong about this being related to default int. Do you want to experiment more with this patch or should I just check it in?
(In reply to comment #16) > Created an attachment (id=20403) [edit] > patch to stop error cascade > > This patch fixes the repeated error; it turns out I was wrong about this being > related to default int. Do you want to experiment more with this patch or > should I just check it in? > I still don't understand why this fixes the problem, but whatever. What is the output with your patch? Do you think that my patch is to emit "recursively instantiated" would still be useful in general? Should I submit it properly?
The output with my patch is wa.C:2:38: error: template instantiation depth exceeds maximum of 1024 (use -ftemplate-depth= to increase the maximum) instantiating ‘struct X<-0x000000018>’ wa.C:2:38: instantiated from ‘const int X<-0x000000017>::value’ wa.C:2:38: instantiated from ‘const int X<-0x000000016>::value’ wa.C:2:38: instantiated from ‘const int X<-0x000000015>::value’ wa.C:2:38: instantiated from ‘const int X<-0x000000014>::value’ wa.C:2:38: instantiated from ‘const int X<-0x000000013>::value’ wa.C:2:38: [ skipping 1014 instantiation contexts ] wa.C:2:38: instantiated from ‘const int X<996>::value’ wa.C:2:38: instantiated from ‘const int X<997>::value’ wa.C:2:38: instantiated from ‘const int X<998>::value’ wa.C:2:38: instantiated from ‘const int X<999>::value’ wa.C:2:38: instantiated from ‘const int X<1000>::value’ wa.C:4:17: instantiated from here wa.C:2:38: error: incomplete type ‘X<-0x000000018>’ used in nested name specifier it avoids the error cascade by avoiding all the non-constant initializer errors. I guess your patch just cuts down the "instantiated from" list to one element? I think the previous change to skip all but 10 is good enough.
(In reply to comment #18) > The output with my patch is > > wa.C:2:38: error: template instantiation depth exceeds maximum of 1024 (use > -ftemplate-depth= to increase the maximum) instantiating �struct > X<-0x000000018>� > wa.C:2:38: instantiated from �const int X<-0x000000017>::value� > wa.C:2:38: instantiated from �const int X<-0x000000016>::value� > wa.C:2:38: instantiated from �const int X<-0x000000015>::value� > wa.C:2:38: instantiated from �const int X<-0x000000014>::value� > wa.C:2:38: instantiated from �const int X<-0x000000013>::value� > wa.C:2:38: [ skipping 1014 instantiation contexts ] > wa.C:2:38: instantiated from �const int X<996>::value� > wa.C:2:38: instantiated from �const int X<997>::value� > wa.C:2:38: instantiated from �const int X<998>::value� > wa.C:2:38: instantiated from �const int X<999>::value� > wa.C:2:38: instantiated from �const int X<1000>::value� > wa.C:4:17: instantiated from here > > wa.C:2:38: error: incomplete type �X<-0x000000018>� used in nested name > specifier > > it avoids the error cascade by avoiding all the non-constant initializer > errors. > > I guess your patch just cuts down the "instantiated from" list to one element? No, to 2 elements, the original instantiation, and the recursive instantiation. /home/manuel/src/pr9335.C:2:36: error: template instantiation depth exceeds maximum of 1024 (use -ftemplate-depth= to increase the maximum) instantiating �struct X<-0x00000000000000018>� /home/manuel/src/pr9335.C:2:36: recursively instantiated from �const int X<1000>::value� /home/manuel/src/pr9335.C:4:17: instantiated from here > I think the previous change to skip all but 10 is good enough. Well, the patch is mostly done, it reduces the output from 11 to 1 lines and it neatly points out where is the recursive instantiation. So I hope you may reconsider, unless you think the 101 lines are useful to the user somehow.
(In reply to comment #19) > Well, the patch is mostly done, it reduces the output from 11 to 1 lines and it > neatly points out where is the recursive instantiation. So I hope you may > reconsider, unless you think the 101 lines are useful to the user somehow. 101 lines? Is that a typo? If this change only applies to the case where all 11 lines would be instantiations of the same template I guess it sounds reasonable, though the 11-line output seems a bit clearer as to where the recursion is happening. Perhaps two instantiation lines in this case so we see the first recursion?
(In reply to comment #20) > (In reply to comment #19) > > Well, the patch is mostly done, it reduces the output from 11 to 1 lines and it > > neatly points out where is the recursive instantiation. So I hope you may > > reconsider, unless you think the 101 lines are useful to the user somehow. > > 101 lines? Is that a typo? Yes, sorry. I meant 11 lines. > If this change only applies to the case where all 11 lines would be > instantiations of the same template I guess it sounds reasonable, though the > 11-line output seems a bit clearer as to where the recursion is happening. > Perhaps two instantiation lines in this case so we see the first recursion? My current patch prints: /home/manuel/src/pr9335.C:2:36: error: template instantiation depth exceeds maximum of 1024 (use -ftemplate-depth= to increase the maximum) instantiating 'struct X<-0x00000000000000018>' /home/manuel/src/pr9335.C:2:36: recursively instantiated from 'const int X<1000>::value' /home/manuel/src/pr9335.C:4:17: instantiated from here Is that ok or you would prefer the following? /home/manuel/src/pr9335.C:2:36: error: template instantiation depth exceeds maximum of 1024 (use -ftemplate-depth= to increase the maximum) instantiating 'struct X<-0x00000000000000018>' /home/manuel/src/pr9335.C:2:36: recursively instantiated from 'const int X<N-1>::value' /home/manuel/src/pr9335.C:2:36: recursively instantiated from 'const int X<1000>::value' /home/manuel/src/pr9335.C:4:17: instantiated from here I think with some tinkering I can reach that output but I don't see which useful information provides, since the location of the extra line is the same as the error line and the recursive instantiation line.
(In reply to comment #21) > Is that ok or you would prefer the following? > > /home/manuel/src/pr9335.C:2:36: error: template instantiation depth exceeds > maximum of 1024 (use -ftemplate-depth= to increase the maximum) instantiating > 'struct X<-0x00000000000000018>' > /home/manuel/src/pr9335.C:2:36: recursively instantiated from 'const int > X<N-1>::value' > /home/manuel/src/pr9335.C:2:36: recursively instantiated from 'const int > X<1000>::value' > /home/manuel/src/pr9335.C:4:17: instantiated from here I was thinking just /home/manuel/src/pr9335.C:2:36: recursively instantiated from 'const int X<999>::value' /home/manuel/src/pr9335.C:2:36: instantiated from 'const int X<1000>::value' I think seeing one iteration would make it clearer.
Oh, that is not very difficult to do. But notice that you will still get the last line: /home/manuel/src/pr9335.C:4:17: instantiated from here so we go from 11 to 3 lines. I think that is ok. So go ahead, commit your patch and I will update mine to produce that.
We didn't get the error cascade in 2.95; we did in 3.4. I don't have any releases in between handy.
Subject: Bug 9335 Author: jason Date: Wed Apr 21 06:06:27 2010 New Revision: 158586 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=158586 Log: PR c++/9335 gcc/cp: * init.c (constant_value_1): Treat error_mark_node as a constant if DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P is set. * cvt.c (ocp_convert): Handle getting error_mark_node from integral_constant_value. * decl.c (compute_array_index_type): Likewise. gcc/testsuite: * lib/prune.exp: Prune "skipping N instantiation contexts". Added: trunk/gcc/testsuite/g++.dg/template/recurse2.C Modified: trunk/gcc/cp/ChangeLog trunk/gcc/cp/cvt.c trunk/gcc/cp/decl.c trunk/gcc/cp/init.c trunk/gcc/testsuite/ChangeLog trunk/gcc/testsuite/g++.dg/init/member1.C trunk/gcc/testsuite/g++.dg/other/fold1.C trunk/gcc/testsuite/g++.dg/parse/crash36.C trunk/gcc/testsuite/lib/prune.exp
Subject: Bug 9335 Author: manu Date: Wed Apr 28 08:34:01 2010 New Revision: 158823 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=158823 Log: 2010-04-28 Manuel López-Ibáñez <manu@gcc.gnu.org> PR c++/9335 cp/ * error.c (print_instantiation_partial_context_line): Handle recursive instantiation. (print_instantiation_partial_context): Likewise. testsuite/ * g++.dg/template/recurse2.C: Update * g++.dg/template/recurse.C: Update. * g++.dg/template/pr23510.C: Update. * lib/prune.exp: Filter out 'recursively instantiated'. Modified: trunk/gcc/cp/ChangeLog trunk/gcc/cp/error.c trunk/gcc/testsuite/ChangeLog trunk/gcc/testsuite/g++.dg/template/pr23510.C trunk/gcc/testsuite/g++.dg/template/recurse.C trunk/gcc/testsuite/g++.dg/template/recurse2.C trunk/gcc/testsuite/lib/prune.exp
The current output is: recurse2.C:5:38: error: template instantiation depth exceeds maximum of 1024 (use -ftemplate-depth= to increase the maximum) instantiating ‘struct X<-0x00000000000000018>’ recurse2.C:5:38: recursively instantiated from ‘const int X<999>::value’ recurse2.C:5:38: instantiated from ‘const int X<1000>::value’ recurse2.C:8:17: instantiated from here recurse2.C:5:38: error: incomplete type ‘X<-0x00000000000000018>’ used in nested name specifier From my point of view this is FIXED. I am not going to backport any patches.
Agreed.