Error also occurs in g++4.3 in 20071026 snapshot. In that snapshot, the ice occurred on line 6651 which is a gcc_assert preceded by comment: /* We should never instantiate a nested class before its enclosing class; we need to look up the nested class by name before we can instantiate it, and that lookup should instantiate the enclosing class. */ I will attach the output from make showing the error and the .ii file (once I figure how to do that).
I was unable to create attachment; so, here's the source (no #includes). <-- cut here -- //Purpose: // Reproduce, with simplified code, the error: /* main.cpp:1675: instantiated from here main.cpp:1277: internal compiler error: in instantiate_class_template, at cp/pt.c:6651 */ //reported in main.cpp.log on line 767 which occured during //compile of main.cpp with gcc-4.3-20071026 on: // Tue Oct 30 08:45:37 //The same error occurred with gcc-4.1, but not gcc-3.4. // template < typename Variables > struct gram_tree { typedef Variables vars ; struct defn_variable { public: typedef defn_variable my_type ; defn_variable(void) {} defn_variable(my_type const& a_copy) ; template < typename Rhs > defn_variable(Rhs const& a_rhs) ; my_type const& operator=(my_type const& a_var) ; template < typename Rhs > my_type const& operator=(Rhs const& a_rhs) ; };//end defn_variable struct struct productions { productions(void) ; defn_variable& operator[](typename vars::symb_enum) ; };//end productions struct //begin: Composite expressions struct expr_sequence { template < typename Left , typename Right > struct node { node(Left const& a_left, Right const& a_right) ; }; }; template < typename Left , typename Right > friend expr_sequence::node<Left,Right> operator>>(Left const& a_left, Right const& a_right) ; //end: Composite expressions };//end gram_tree<Variables> struct struct vars { enum symb_enum { e }; };//exit vars struct int main(void) { typedef gram_tree<vars> gt; gt::productions prods; prods[vars::e]=prods[vars::e] >> prods[vars::e] ; return 0; } >-- cut here -- and here's the make output <-- cut here -- cd /home/evansl/prog_dev/boost-svn/ro/trunk/sandbox/lje/libs/grammar_pipeline/test/spirit_proto/ make -f Makefile.imk bugrept /usr/bin/g++-4.1 -c -Wall -ftemplate-depth-100 -O0 -fno-inline -v -save-temps main-pt-c-ice.cpp -o bugrept Using built-in specs. Target: i486-linux-gnu Configured with: ../src/configure -v --enable-languages=c,c++,fortran,objc,obj-c++,treelang --prefix=/usr --enable-shared --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --enable-nls --program-suffix=-4.1 --enable-__cxa_atexit --enable-clocale=gnu --enable-libstdcxx-debug --enable-mpfr --with-tune=i686 --enable-checking=release i486-linux-gnu Thread model: posix gcc version 4.1.2 20061115 (prerelease) (Debian 4.1.1-21) /usr/lib/gcc/i486-linux-gnu/4.1.2/cc1plus -E -quiet -v -D_GNU_SOURCE main-pt-c-ice.cpp -mtune=i686 -Wall -ftemplate-depth-100 -fno-inline -O0 -fpch-preprocess -o main-pt-c-ice.ii ignoring nonexistent directory "/usr/local/include/i486-linux-gnu" ignoring nonexistent directory "/usr/lib/gcc/i486-linux-gnu/4.1.2/../../../../i486-linux-gnu/include" ignoring nonexistent directory "/usr/include/i486-linux-gnu" #include "..." search starts here: #include <...> search starts here: /usr/lib/gcc/i486-linux-gnu/4.1.2/../../../../include/c++/4.1.2 /usr/lib/gcc/i486-linux-gnu/4.1.2/../../../../include/c++/4.1.2/i486-linux-gnu /usr/lib/gcc/i486-linux-gnu/4.1.2/../../../../include/c++/4.1.2/backward /usr/local/include /usr/lib/gcc/i486-linux-gnu/4.1.2/include /usr/include End of search list. /usr/lib/gcc/i486-linux-gnu/4.1.2/cc1plus -fpreprocessed main-pt-c-ice.ii -quiet -dumpbase main-pt-c-ice.cpp -mtune=i686 -auxbase-strip bugrept -O0 -Wall -version -ftemplate-depth-100 -fno-inline -o main-pt-c-ice.s GNU C++ version 4.1.2 20061115 (prerelease) (Debian 4.1.1-21) (i486-linux-gnu) compiled by GNU C version 4.1.2 20061115 (prerelease) (Debian 4.1.1-21). GGC heuristics: --param ggc-min-expand=55 --param ggc-min-heapsize=48218 Compiler executable checksum: 183d42a838ed2b7313bffcb8f2f2fda7 main-pt-c-ice.cpp: In instantiation of 'gram_tree<vars>::expr_sequence::node<gram_tree<vars>::defn_variable, gram_tree<vars>::defn_variable>': main-pt-c-ice.cpp:109: instantiated from here main-pt-c-ice.cpp:74: internal compiler error: in instantiate_class_template, at cp/pt.c:5652 Please submit a full bug report, with preprocessed source if appropriate. See <URL:http://gcc.gnu.org/bugs.html> for instructions. For Debian GNU/Linux specific bug reporting instructions, see <URL:file:///usr/share/doc/gcc-4.1/README.Bugs>. Preprocessed source stored into /tmp/ccITi2V4.out file, please attach this to your bugreport. make: *** [bugrept] Error 1 Compilation exited abnormally with code 2 at Wed Oct 31 09:20:49 >-- cut here --
Confirmed.
When that following main is used instead of the one posted earlier, the error no longer occurs. <-- cut here -- int main(void) { typedef gram_tree<vars> gt; gt::productions prods; #define INST_SEQ #ifdef INST_SEQ gt::expr_sequence inst_seq; #endif prods[vars::e]=prods[vars::e] >> #ifdef INST_SEQ inst_seq #else prods[vars::e] #endif ; return 0; } >-- cut here -- IOW, the pt.c insource comment mentioned in my first post really means what it says, i.e. the above code instantiates the outer class, expr_sequence, and the ice no longer occurs. Maybe the gcc_assert that's in pt.c on line 6651 and that was mentioned in my first post should be removed?
The reason version 3.4.6 doesn't have similar ice is that the corresponding check is surrounded by: #ifdef ENABLE_CHECKING ... #endif
Created attachment 14459 [details] testcase Several macros to enable exploring reasons for ice.
Created attachment 14460 [details] testcase Several macros to enable exploring reasons for ice.
Please ignore 1st attachment. I selected auto-detect thinking it would auto-detect it as text/plain. When #define INST_GT, the friend operator>> is instantiated and this give the ice. OTOH, when #undef INST_GT, apparently the fried operator>> is not instantiated and compiler gives: main-pt-c-ice.cpp:68: error: no match for 'operator>>' in 'a_arg >> a_arg' So maybe the compiler is right about having to instantiate enclosing class. Maybe what I really need is a templated namespace, as mentioned here: http://groups.google.com/group/comp.std.c++/browse_thread/thread/4baec3f90675a166/6eb713e7bb143b09?lnk=gst&q=namespace+template#6eb713e7bb143b09
Simplified testcase: template <typename T> struct A { struct C { template <typename U> struct D {}; }; template <typename U> friend C::D<U> operator* (U const &); }; struct E {}; int main () { A<E> a; E e; *e; } A<E>::C wasn't instantiated, because during cp_parser_nested_name_specifier_opt where it normally would be instantiated it was dependent type: /* If it is a class scope, try to complete it; we are about to be looking up names inside the class. */ if (TYPE_P (new_scope) /* Since checking types for dependency can be expensive, avoid doing it if the type is already complete. */ && !COMPLETE_TYPE_P (new_scope) /* Do not try to complete dependent types. */ && !dependent_type_p (new_scope)) { new_scope = complete_type (new_scope); and then just build_x_indirect_ref -> build_new_op -> build_{over,cxx}_call -> require_complete_type ... -> instantiate_class_template instantiates the return type without completing the scopes. Another testcase that fails similarly is template <typename T> struct A { struct C { template <typename U> struct D {}; }; template <typename S> static C::D<S> bar (S const &); }; struct E {}; int main () { E e; A<E>::bar (e); } so it is not just friend related. One fix would be just remove the assertion and instead call complete_type_or_else on the scope.
Or tsubst on types could for TYPE_CLASS_SCOPE_P (t) call complete_type on TYPE_CONTEXT (t). That works for this testcase, but not sure if it would generally. Jason/Mark, ideas?
Subject: Bug 33959 Author: jason Date: Tue Jan 22 14:48:05 2008 New Revision: 131724 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=131724 Log: PR c++/33959 * pt.c (tsubst_aggr_type): Make sure our context is complete. PR c++/34573 * pt.c (retrieve_local_specialization): Robustify. (tsubst_pack_expansion, tsubst_decl): Remove redundant checks. PR c++/34846 * pt.c (tsubst): Only call retrieve_local_specialization if the original typedef was in a function template. Added: trunk/gcc/testsuite/g++.dg/template/nested5.C trunk/gcc/testsuite/g++.dg/template/typedef10.C trunk/gcc/testsuite/g++.dg/template/typedef9.C Modified: trunk/gcc/cp/ChangeLog trunk/gcc/cp/pt.c
Fixed on the trunk.
Subject: Bug 33959 Author: jason Date: Tue Jan 22 15:59:57 2008 New Revision: 131725 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=131725 Log: PR c++/33959 * pt.c (tsubst_aggr_type): Make sure our context is complete. Added: branches/gcc-4_2-branch/gcc/testsuite/g++.dg/template/nested5.C Modified: branches/gcc-4_2-branch/gcc/cp/ChangeLog branches/gcc-4_2-branch/gcc/cp/pt.c
Subject: Bug 33959 Author: jason Date: Mon Jan 28 16:27:17 2008 New Revision: 131907 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=131907 Log: PR c++/27177 * class.c (build_base_path): Fix previous change. PR c++/27177 * class.c (build_base_path): Don't mess with virtual access if skip_evaluation. * call.c (standard_conversion): Don't check whether source type is complete. PR c++/33959 * pt.c (tsubst_aggr_type): Make sure our context is complete. Modified: branches/gcc-4_1-branch/gcc/cp/ChangeLog branches/gcc-4_1-branch/gcc/cp/call.c branches/gcc-4_1-branch/gcc/cp/class.c branches/gcc-4_1-branch/gcc/cp/pt.c
Fixed in all open branches.