Bug 37920 - ICE (segv) with typename typeof in local struct
Summary: ICE (segv) with typename typeof in local struct
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.3.1
: P3 normal
Target Milestone: 4.5.0
Assignee: Jason Merrill
Keywords: ice-on-valid-code
Depends on:
Reported: 2008-10-26 17:35 UTC by Keith Reynolds
Modified: 2009-11-08 23:11 UTC (History)
3 users (show)

See Also:
Host: i486-linux-gnu
Target: i486-linux-gnu
Build: i486-linux-gnu
Known to work:
Known to fail:
Last reconfirmed: 2009-11-08 04:13:17

preprocessed source file that triggers the ICE (29.08 KB, text/plain)
2008-10-26 17:36 UTC, Keith Reynolds

Note You need to log in before you can comment on or make changes to this bug.
Description Keith Reynolds 2008-10-26 17:35:40 UTC
When compiling the attached code, I get an ICE:

$ /usr/lib/gcc-snapshot/bin/g++ -v -Q -save-temps -c ice.cpp
Using built-in specs.
Target: i486-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 20080404-0ubuntu1' --with-bugurl=file:///usr/share/doc/gcc-snapshot/README.Bugs --enable-languages=c,c++,java,fortran,objc,obj-c++,ada --prefix=/usr/lib/gcc-snapshot --enable-shared --with-system-zlib --disable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-java-awt=gtk --enable-gtk-cairo --disable-plugin --with-java-home=/usr/lib/gcc-snapshot/jre --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-mpfr --enable-targets=all --disable-werror --build=i486-linux-gnu --host=i486-linux-gnu --target=i486-linux-gnu
Thread model: posix
gcc version 4.3.1 20080404 (prerelease) [gcc-4_3-branch revision 133917] (Ubuntu 20080404-0ubuntu1)
COLLECT_GCC_OPTIONS='-v' '-Q' '-save-temps' '-c' '-shared-libgcc' '-mtune=generic'
 /usr/lib/gcc-snapshot/libexec/gcc/i486-linux-gnu/4.3.1/cc1plus -E -v -D_GNU_SOURCE ice.cpp -mtune=generic -fpch-preprocess -o ice.ii
ignoring nonexistent directory "/usr/local/include/i486-linux-gnu"
ignoring nonexistent directory "/usr/lib/gcc-snapshot/lib/gcc/i486-linux-gnu/4.3.1/../../../../i486-linux-gnu/include"
ignoring nonexistent directory "/usr/include/i486-linux-gnu"
#include "..." search starts here:
#include <...> search starts here:
End of search list.

Execution times (seconds)
 TOTAL                 :   0.17             0.02             0.20               3835 kB
COLLECT_GCC_OPTIONS='-v' '-Q' '-save-temps' '-c' '-shared-libgcc' '-mtune=generic'
 /usr/lib/gcc-snapshot/libexec/gcc/i486-linux-gnu/4.3.1/cc1plus -fpreprocessed ice.ii -dumpbase ice.cpp -mtune=generic -auxbase ice -version -o ice.s
GNU C++ (Ubuntu 20080404-0ubuntu1) version 4.3.1 20080404 (prerelease) [gcc-4_3-branch revision 133917] (i486-linux-gnu)
        compiled by GNU C version 4.3.1 20080404 (prerelease) [gcc-4_3-branch revision 133917], GMP version 4.2.2, MPFR version 2.3.1.
GGC heuristics: --param ggc-min-expand=98 --param ggc-min-heapsize=128223
options passed:  -fpreprocessed ice.ii -mtune=generic
options enabled:  -falign-loops -fargument-alias -fauto-inc-dec
 -fbranch-count-reg -fcommon -fearly-inlining
 -feliminate-unused-debug-types -fexceptions -ffunction-cse -fgcse-lm
 -fident -fivopts -fkeep-static-consts -fleading-underscore -fmath-errno
 -fmerge-debug-strings -fmove-loop-invariants -fpcc-struct-return
 -fpeephole -fsched-interblock -fsched-spec -fsched-stalled-insns-dep
 -fsigned-zeros -fsplit-ivs-in-unroller -ftoplevel-reorder -ftrapping-math
 -ftree-cselim -ftree-loop-im -ftree-loop-ivcanon -ftree-loop-optimize
 -ftree-parallelize-loops= -ftree-reassoc -ftree-scev-cprop
 -ftree-vect-loop-version -fvar-tracking -fvect-cost-model
 -fzero-initialized-in-bss -m32 -m80387 -m96bit-long-double
 -maccumulate-outgoing-args -malign-stringops -mfancy-math-387
 -mfp-ret-in-387 -mfused-madd -mglibc -mieee-fp -mno-red-zone -mno-sse4
 -mpush-args -msahf -mtls-direct-seg-refs
Compiler executable checksum: dd9fb97039947d8c4927d069b05a68b5
 bool std::rel_ops::operator!=(const _Tp&, const _Tp&) bool std::rel_ops::operator>(const _Tp&, const _Tp&) bool std::rel_ops::operator<=(const _Tp&, const _Tp&) bool std::rel_ops::operator>=(const _Tp&, const _Tp&) void std::swap(_Tp&, _Tp&) std::pair<_T1, _T2>::pair() std::pair<_T1, _T2>::pair(const _T1&, const _T2&) std::pair<_T1, _T2>::pair(const std::pair<_U1, _U2>&) bool std::operator==(const std::pair<_T1, _T2>&, const std::pair<_T1, _T2>&) bool std::operator<(const std::pair<_T1, _T2>&, const std::pair<_T1, _T2>&) bool std::operator!=(const std::pair<_T1, _T2>&, const std::pair<_T1, _T2>&) bool std::operator>(const std::pair<_T1, _T2>&, const std::pair<_T1, _T2>&) bool std::operator<=(const std::pair<_T1, _T2>&, const std::pair<_T1, _T2>&) bool std::operator>=(const std::pair<_T1, _T2>&, const std::pair<_T1, _T2>&) std::pair<_T1, _T2> std::make_pair(_T1, _T2) long int std::abs(long int) ldiv_t std::div(long int, long int) long long int __gnu_cxx::abs(long long int) lldiv_t __gnu_cxx::div(long long int, long long int) mpl_::int_<N>::operator int() const mpl_::bool_<C_>::operator bool() const mpl_::integral_c<T, N>::operator T() const mpl_::integral_c<bool, C>::operator bool() const mpl_::size_t<N>::operator size_t() const boost::aligned_storage<size_, alignment_>::aligned_storage() boost::aligned_storage<size_, alignment_>::~aligned_storage() void* boost::aligned_storage<size_, alignment_>::address() const void* boost::aligned_storage<size_, alignment_>::address() const void func1(int&) func1(int&)::_scope_exit_9::_scope_exit_9(int&) func1(int&)::_scope_exit_9::_scope_exit_9(int&) func1(int&)::_scope_exit_9::_scope_exit_9(int&) func1(int&)::_scope_exit_9::~_scope_exit_9() func1(int&)::_scope_exit_9::~_scope_exit_9() func1(int&)::_scope_exit_9::~_scope_exit_9() void func2(T&) func2(T&)::_scope_exit_17::_scope_exit_17(typename __typeof__ (boost::type_of::ensure_obj(scope_exit::wrap_type(t)))::type&) func2(T&)::_scope_exit_17::~_scope_exit_17() int main() void func2(T&) [with T = double]
ice.cpp: In constructor 'func2(T&)::_scope_exit_17::_scope_exit_17(typename __typeof__ (boost::type_of::ensure_obj(scope_exit::wrap_type(t)))::type&) [with T = double]':
ice.cpp:15:   instantiated from 'void func2(T&) [with T = double]'
ice.cpp:29:   instantiated from here
ice.cpp:15: internal compiler error: in tsubst_copy, at cp/pt.c:9723

The same code, but used within a non-template function (func1 in the attached file) and therefore without the typename keyword, does not cause an ICE.

This also happens with the other versions of gcc on my machine:

$ gcc -v
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 --with-gxx-include-dir=/usr/include/c++/4.2 --program-suffix=-4.2 --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --enable-mpfr --enable-targets=all --enable-checking=release --build=i486-linux-gnu --host=i486-linux-gnu --target=i486-linux-gnu
Thread model: posix
gcc version 4.2.4 (Ubuntu 4.2.4-1ubuntu3)

$ gcc-4.1 -v
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 --with-gxx-include-dir=/usr/include/c++/4.1.3 --program-suffix=-4.1 --enable-__cxa_atexit --enable-clocale=gnu --enable-libstdcxx-debug --enable-mpfr --enable-checking=release i486-linux-gnu
Thread model: posix
gcc version 4.1.3 20080308 (prerelease) (Ubuntu 4.1.2-21ubuntu1)
Comment 1 Keith Reynolds 2008-10-26 17:36:35 UTC
Created attachment 16552 [details]
preprocessed source file that triggers the ICE
Comment 2 Andrew Pinski 2008-10-27 00:26:23 UTC
Reducing ...
Comment 3 Andrew Pinski 2008-10-27 01:32:09 UTC
Reduced testcase:
template<typename T> T& ensure_obj(const T&);
template <typename T>
void func2(T& t)
  typedef __typeof__(ensure_obj(t)) ttt;
  struct ttt1 
    ttt1( ttt arg0 ){}
  }  tttt ( t );
  double d = 5;

---- CUT ----
If I use decltype (which is part of the C++0x standard), it works ....
Comment 4 Andrew Pinski 2008-10-27 02:00:13 UTC
3.3 did not ICE but did give the wrong error message:
t.cc: In instantiation of `func2(T&) [with T = double]::ttt1':
t.cc:10:   instantiated from `void func2(T&) [with T = double]'
t.cc:15:   instantiated from here
t.cc:8: error: `t' was not declared in this scope
t.cc: In function `void func2(T&) [with T = double]':
t.cc:15:   instantiated from here
t.cc:10: error: no matching function for call to `func2(T&) [with T = 
t.cc:9: error: candidates are: func2(T&) [with T = double]::ttt1::ttt1(const 
   func2(T&) [with T = double]::ttt1&)

There is no use of t really at line 8 of my reduced testcase, only the use of the typedef.
Comment 5 Michael Barrientos 2009-08-28 05:12:58 UTC
I just ran into this bug too. Before I found this bug report, I did some more investigation to characterize the bug a little more. I am including my version of the reduced test case, with more commentary inline.
// Cause: Use of __typeof__ on a templated type (dependent upon template arguments of outer function/class) as the type of an argument for any function in a locally defined class crashes g++. Since this successfully typechecks, I suspect that during symbol lookup in some IR generating phase, for arguments to a function of a local class, if a __typeof__ is involved, g++ does not properly lookup symbols in the outer function/class symbol table.

template<typename ImplList> struct VertexData;

template<typename LM> void init() {            // Making non-templated function eliminates ICE. (Also ICEs for non-templated member function in a templated class.)
    VertexData<LM>* v0;                        // Making this non-template eliminates ICE. Changing LM to int eliminates ICE.
    typedef __typeof__(v0) v0_type_;           // Using VertexData<LM> instead of __typeof__(v0) eliminates ICE.  Using __decltype(v0) still causes ICE in GCC 4.3.4, but eliminates ICE in GCC 4.4
    struct MeshConditionalInit {               // Removing body of struct eliminates ICE.
        MeshConditionalInit(v0_type_& v0) { }  // Removing argument eliminates ICE. Using v0_type_ only in body and not as argument eliminates ICE.
    };                                         // ICE still occurs when used as function argument instead of constructor argument.
    MeshConditionalInit bar138(v0);

int main(int argn, char ** argv) {
ICE occurs with no special compile flags in the following standard distribution packages of GCC:
4.1.3, 4.2.4, and 4.3.3 on Ubuntu 9.04
4.0.1 and 4.2.1 on Mac OS X 10.5 (the versions with XCode)
4.4.0 on Mac OS X 10.5 (MacPorts build)

And because I got bored, here's a 140-character twitterable version of an even smaller test case (inlines the typeof into the constructor's argument, removing the typedef, which may not be legal, but definitely still causes an ICE in GCC):
/*GCC Instacrash*/ template<class T> class C;template<class U> void f() {C<U>* i;struct S{S(__typeof__(i)& i){}}s(i);}int main(){f<int>();}
Comment 6 Jason Merrill 2009-11-08 23:11:13 UTC
Fixed for 4.5.