I can understand why this code has problems - it is recursive, I need to find a way to make it not be so ! But the compiler spits out an "internal compiler error" that probably needs a look at. template <typename T, T N> struct bit_count_templ { static const T bit_count; }; template <typename T, T N> const T bit_count_templ<T,N>::bit_count = 1 + ( N == 0 ? 0 : bit_count_templ<T, N & ( N -1 ) >::bit_count ); #include <iostream> int main() { std::cout << bit_count_templ<long,0x256500LL>::bit_count; } g++ -Wreturn-type -W -Wpointer-arith -pipe -ggdb3 -fcheck-new -fPIC -D_POSIX_THREADS -D_POSIX_THREAD_SAFE_FUNCTIONS -D_REENTRANT templ_bitcount.cpp -o templ_bitcount templ_bitcount.cpp: In instantiation of `const long int bit_count_templ<long int, 0>::bit_count': templ_bitcount.cpp:10: instantiated from `const long int bit_count_templ<long int, 0>::bit_count' templ_bitcount.cpp:10: instantiated from `const long int bit_count_templ<long int, 2097152>::bit_count' templ_bitcount.cpp:10: instantiated from `const long int bit_count_templ<long int, 2359296>::bit_count' templ_bitcount.cpp:10: instantiated from `const long int bit_count_templ<long int, 2424832>::bit_count' templ_bitcount.cpp:10: instantiated from `const long int bit_count_templ<long int, 2441216>::bit_count' templ_bitcount.cpp:10: instantiated from `const long int bit_count_templ<long int, 2449408>::bit_count' templ_bitcount.cpp:10: instantiated from `const long int bit_count_templ<long int, 2450432>::bit_count' templ_bitcount.cpp:10: instantiated from `const long int bit_count_templ<long int, 2450688>::bit_count' templ_bitcount.cpp:17: instantiated from here templ_bitcount.cpp:10: internal compiler error: in regenerate_decl_from_template, at cp/pt.c:10131 Please submit a full bug report, with preprocessed source if appropriate. See <URL:http://gcc.gnu.org/bugs.html> for instructions.
Confirmed. Since it's an ICE after error, it gets low priority. The funny thing is: gcc 3.2.3 silently accepts the code, whereas 2.95 gets all confused and generates really nonsensical error messages :-) This all means, though, that this is also not a regression. W.
This is somewhat simpler to understand: ------------------------ template <int N> struct S { static const int C; }; template <int N> const int S<N>::C = S<(N+1)%2>::C; template struct S<1>; ------------------------- g/x> /home/bangerth/bin/gcc-3.4-pre/bin/c++ -c x.cc x.cc: In instantiation of `const int S<1>::C': x.cc:6: instantiated from `const int S<0>::C' x.cc:6: instantiated from `const int S<1>::C' x.cc:8: instantiated from here x.cc:6: internal compiler error: in regenerate_decl_from_template, at cp/ pt.c:10771
First, here's a slightly different example that triggers the ICE: ============================================================== template <int> struct A { static const int i; }; template <int N> const int A<N>::i = ( N ? A<N&0>::i : 0 ); int j=A<1>::i; ============================================================== x.cc: In instantiation of `const int A<0>::i': x.cc:10: instantiated from `const int A<0>::i' x.cc:10: instantiated from `const int A<1>::i' x.cc:12: instantiated from here x.cc:10: internal compiler error: in regenerate_decl_from_template, at cp/pt.c:10771 Please submit a full bug report, [etc.] If I replace "N&0" by "0" in the example above, I get the following error message: x.cc:10: error: template instantiation depth exceeds maximum of 500 (use -ftemplate-depth-NN to increase the maximum) instantiating `A<0>::i' x.cc:10: instantiated from `const int A<0>::i' [repeated ~1000 times] x.cc:12: instantiated from here Second, I don't agree with Wolfgang. This code looks valid to me (and is accepted by gcc 3.0 - 3.2.3 as well as icc 7 and Comeau). Thus, we have a regression here and therefore severity "critical".
The code I gave is certainly not valid, since it involves a recursive dependence on templates. For your code, one may argue that it is only valid if the compiler is allowed to skip evaluating the unused arm of a conditional expression. When you write A<N>::i = (N ? A<N&0> : 0) then - if N==0: the code is recursive if we try to evaluate the first part of the conditional, since it again involves A<0>::i, which we are about to initialize - if N!=0, then we get into the N==0 case on the next iteration. I'm not sure if we are allowed to skip evaluation. Someone will be able to point to the right place in the standard, though, I guess. In either case, I don't care too much: raising the priority increases chances to have the bug fixed, which I believe is always good :-) W.
Working on a patch.
Patch submitted: http://gcc.gnu.org/ml/gcc-patches/2003-12/msg02046.html For 3.3.3 this is a complete fix. There is an additional regression to deal with in GCC 3.4 so it's only a partial bugfix there.
Subject: Bug 13289 CVSROOT: /cvs/gcc Module name: gcc Changes by: lerdsuwa@gcc.gnu.org 2003-12-29 11:00:36 Modified files: gcc/cp : ChangeLog semantics.c gcc/testsuite : ChangeLog Added files: gcc/testsuite/g++.dg/parse: nontype1.C Log message: PR c++/13289 * semantics.c (finish_id_expression): Only check if the type of a template argument is integral or enumeration when it is not dependent. * g++.dg/parse/nontype1.C: New test. Patches: http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/ChangeLog.diff?cvsroot=gcc&r1=1.3839&r2=1.3840 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/semantics.c.diff?cvsroot=gcc&r1=1.379&r2=1.380 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/ChangeLog.diff?cvsroot=gcc&r1=1.3317&r2=1.3318 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/parse/nontype1.C.diff?cvsroot=gcc&r1=NONE&r2=1.1
The extra regression in 3.4 is fixed. Now we only have the original problem left together with the patch (still waiting for an approval): http://gcc.gnu.org/ml/gcc-patches/2003-12/msg02046.html
Subject: Bug 13289 CVSROOT: /cvs/gcc Module name: gcc Changes by: pinskia@gcc.gnu.org 2004-01-12 20:10:20 Modified files: gcc/cp : ChangeLog pt.c gcc/testsuite : ChangeLog Added files: gcc/testsuite/g++.dg/template: instantiate6.C Log message: 2004-01-12 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net> PR c++/13289 * pt.c (instantiate_decl): Set DECL_TEMPLATE_INSTANTIATED before calling regenerate_decl_from_template. 2004-01-12 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net> PR c++/13289 * g++.dg/template/instantiate6.C: New test. Patches: http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/ChangeLog.diff?cvsroot=gcc&r1=1.3869&r2=1.3870 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/pt.c.diff?cvsroot=gcc&r1=1.811&r2=1.812 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/ChangeLog.diff?cvsroot=gcc&r1=1.3365&r2=1.3366 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/template/instantiate6.C.diff?cvsroot=gcc&r1=NONE&r2=1.1
Fixed for 3.4 at least.
Subject: Bug 13289 CVSROOT: /cvs/gcc Module name: gcc Branch: gcc-3_3-branch Changes by: gdr@gcc.gnu.org 2004-01-21 03:26:07 Modified files: gcc/cp : ChangeLog pt.c Added files: gcc/testsuite/g++.dg/template: instantiate6.C Log message: 2004-01-20 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net> PR c++/13289 * pt.c (instantiate_decl): Set DECL_TEMPLATE_INSTANTIATED before calling regenerate_decl_from_template. Patches: http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/ChangeLog.diff?cvsroot=gcc&only_with_tag=gcc-3_3-branch&r1=1.3076.2.237&r2=1.3076.2.238 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/pt.c.diff?cvsroot=gcc&only_with_tag=gcc-3_3-branch&r1=1.635.2.40&r2=1.635.2.41 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/template/instantiate6.C.diff?cvsroot=gcc&only_with_tag=gcc-3_3-branch&r1=NONE&r2=1.1.8.1
Fixed with http://gcc.gnu.org/ml/gcc-patches/2003-12/msg02046.html