Bug 65042 - gcc5 has a template depth problem that was fine in gcc4
Summary: gcc5 has a template depth problem that was fine in gcc4
Status: WAITING
Alias: None
Product: gcc
Classification: Unclassified
Component: libstdc++ (show other bugs)
Version: 5.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2015-02-12 14:30 UTC by karl kleinpaste
Modified: 2017-12-13 11:16 UTC (History)
4 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2017-12-12 00:00:00


Attachments
class description employing layered string- and int-indexed maps-within-maps (2.50 KB, text/x-c++hdr)
2015-02-12 14:30 UTC, karl kleinpaste
Details
preprocessed file (350.81 KB, application/x-gz)
2015-02-12 18:05 UTC, Matěj Cepl
Details

Note You need to log in before you can comment on or make changes to this bug.
Description karl kleinpaste 2015-02-12 14:30:44 UTC
Created attachment 34740 [details]
class description employing layered string- and int-indexed maps-within-maps

Attached is modulecache.hh, part of Xiphos, which was recently involved in a Fedora gcc5 mass rebuild test for upcoming Fedora 22.  This file exhibits a template complaint regarding nested std::map usage.  The nesting provides an intuitive access to data content by allowing subscripting at any map level to obtain all subordinate content.

The plain fact is that this code has been compiling in gcc4 since approximately 2008.  It was then found that using -ftemplate-depth=128 makes the gcc5 compilation survive, but I don't see why this should be necessary, considering that the code has been fine for 7 years preceding, without use of any such modifiers.  Has the default depth limit changed in gcc5?

FYI recommended to file this report by an involved Fedora engineer; I am Xiphos project admin.

In file included from /usr/include/c++/5.0.0/map:60:0,
                 from ../src/main/modulecache.hh:45,
                 from ../src/main/modulecache.cc:30:
/usr/include/c++/5.0.0/bits/stl_tree.h: In instantiation of 'void std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_destroy_node(std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type) [with _Key = int; _Val = std::pair<const int, ModuleCache::CacheVerse>; _KeyOfValue = std::_Select1st<std::pair<const int, ModuleCache::CacheVerse> >; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, ModuleCache::CacheVerse> >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type = std::_Rb_tree_node<std::pair<const int, ModuleCache::CacheVerse> >*]':
/usr/include/c++/5.0.0/bits/stl_tree.h:562:17:   required from 'void std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_drop_node(std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type) [with _Key = int; _Val = std::pair<const int, ModuleCache::CacheVerse>; _KeyOfValue = std::_Select1st<std::pair<const int, ModuleCache::CacheVerse> >; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, ModuleCache::CacheVerse> >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type = std::_Rb_tree_node<std::pair<const int, ModuleCache::CacheVerse> >*]'
/usr/include/c++/5.0.0/bits/stl_tree.h:1493:16:   required from 'void std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_erase(std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type) [with _Key = int; _Val = std::pair<const int, ModuleCache::CacheVerse>; _KeyOfValue = std::_Select1st<std::pair<const int, ModuleCache::CacheVerse> >; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, ModuleCache::CacheVerse> >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type = std::_Rb_tree_node<std::pair<const int, ModuleCache::CacheVerse> >*]'
/usr/include/c++/5.0.0/bits/stl_tree.h:859:17:   required from 'std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::~_Rb_tree() [with _Key = int; _Val = std::pair<const int, ModuleCache::CacheVerse>; _KeyOfValue = std::_Select1st<std::pair<const int, ModuleCache::CacheVerse> >; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, ModuleCache::CacheVerse> >]'
/usr/include/c++/5.0.0/bits/stl_map.h:96:11:   required from 'void __gnu_cxx::new_allocator<_Tp>::destroy(__gnu_cxx::new_allocator<_Tp>::pointer) [with _Tp = std::pair<const int, std::map<int, ModuleCache::CacheVerse> >; __gnu_cxx::new_allocator<_Tp>::pointer = std::pair<const int, std::map<int, ModuleCache::CacheVerse> >*]'
/usr/include/c++/5.0.0/bits/stl_tree.h:521:9:   required from 'void std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_destroy_node(std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type) [with _Key = int; _Val = std::pair<const int, std::map<int, ModuleCache::CacheVerse> >; _KeyOfValue = std::_Select1st<std::pair<const int, std::map<int, ModuleCache::CacheVerse> > >; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, std::map<int, ModuleCache::CacheVerse> > >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type = std::_Rb_tree_node<std::pair<const int, std::map<int, ModuleCache::CacheVerse> > >*]'
/usr/include/c++/5.0.0/bits/stl_tree.h:562:17:   [ skipping 14 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
/usr/include/c++/5.0.0/bits/stl_tree.h:521:9:   required from 'void std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_destroy_node(std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type) [with _Key = const std::basic_string<char>; _Val = std::pair<const std::basic_string<char>, std::map<int, std::map<int, std::map<int, std::map<int, ModuleCache::CacheVerse> > > > >; _KeyOfValue = std::_Select1st<std::pair<const std::basic_string<char>, std::map<int, std::map<int, std::map<int, std::map<int, ModuleCache::CacheVerse> > > > > >; _Compare = std::less<const std::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::basic_string<char>, std::map<int, std::map<int, std::map<int, std::map<int, ModuleCache::CacheVerse> > > > > >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type = std::_Rb_tree_node<std::pair<const std::basic_string<char>, std::map<int, std::map<int, std::map<int, std::map<int, ModuleCache::CacheVerse> > > > > >*]'
/usr/include/c++/5.0.0/bits/stl_tree.h:562:17:   required from 'void std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_drop_node(std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type) [with _Key = const std::basic_string<char>; _Val = std::pair<const std::basic_string<char>, std::map<int, std::map<int, std::map<int, std::map<int, ModuleCache::CacheVerse> > > > >; _KeyOfValue = std::_Select1st<std::pair<const std::basic_string<char>, std::map<int, std::map<int, std::map<int, std::map<int, ModuleCache::CacheVerse> > > > > >; _Compare = std::less<const std::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::basic_string<char>, std::map<int, std::map<int, std::map<int, std::map<int, ModuleCache::CacheVerse> > > > > >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type = std::_Rb_tree_node<std::pair<const std::basic_string<char>, std::map<int, std::map<int, std::map<int, std::map<int, ModuleCache::CacheVerse> > > > > >*]'
/usr/include/c++/5.0.0/bits/stl_tree.h:1493:16:   required from 'void std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_erase(std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type) [with _Key = const std::basic_string<char>; _Val = std::pair<const std::basic_string<char>, std::map<int, std::map<int, std::map<int, std::map<int, ModuleCache::CacheVerse> > > > >; _KeyOfValue = std::_Select1st<std::pair<const std::basic_string<char>, std::map<int, std::map<int, std::map<int, std::map<int, ModuleCache::CacheVerse> > > > > >; _Compare = std::less<const std::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::basic_string<char>, std::map<int, std::map<int, std::map<int, std::map<int, ModuleCache::CacheVerse> > > > > >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type = std::_Rb_tree_node<std::pair<const std::basic_string<char>, std::map<int, std::map<int, std::map<int, std::map<int, ModuleCache::CacheVerse> > > > > >*]'
/usr/include/c++/5.0.0/bits/stl_tree.h:859:17:   required from 'std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::~_Rb_tree() [with _Key = const std::basic_string<char>; _Val = std::pair<const std::basic_string<char>, std::map<int, std::map<int, std::map<int, std::map<int, ModuleCache::CacheVerse> > > > >; _KeyOfValue = std::_Select1st<std::pair<const std::basic_string<char>, std::map<int, std::map<int, std::map<int, std::map<int, ModuleCache::CacheVerse> > > > > >; _Compare = std::less<const std::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::basic_string<char>, std::map<int, std::map<int, std::map<int, std::map<int, ModuleCache::CacheVerse> > > > > >]'
/usr/include/c++/5.0.0/bits/stl_map.h:163:14:   required from 'std::map<_Key, _Tp, _Compare, _Alloc>::map() [with _Key = const std::basic_string<char>; _Tp = std::map<int, std::map<int, std::map<int, std::map<int, ModuleCache::CacheVerse> > > >; _Compare = std::less<const std::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::basic_string<char>, std::map<int, std::map<int, std::map<int, std::map<int, ModuleCache::CacheVerse> > > > > >]'
../src/main/modulecache.cc:34:23:   required from here
/usr/include/c++/5.0.0/bits/stl_tree.h:521:22: fatal error: template instantiation depth exceeds maximum of 25 (use -ftemplate-depth= to increase the maximum)
       { get_allocator().destroy(__p->_M_valptr()); }
                      ^
Comment 1 Jakub Jelinek 2015-02-12 15:15:57 UTC
Please provide preprocessed source (see http://gcc.gnu.org/bugs/ for details how).
Comment 2 Matěj Cepl 2015-02-12 18:05:58 UTC
Created attachment 34741 [details]
preprocessed file
Comment 3 Marek Polacek 2015-02-12 18:15:05 UTC
Note that the package explicitly uses -ftemplate-depth=25 (without that the .ii files compiles fine).  So maybe just some changes in libstdc++ that trigger the limit?
Comment 4 Jakub Jelinek 2015-02-12 18:17:47 UTC
What command line options are used?
With explicit -ftemplate-depth=25 (or even 27) it indeed fails, succeeds with 28, but the default is 900 AFAIK.  Have those command line options changed in any way since the compilation with the older g++?
Comment 5 Jakub Jelinek 2015-02-12 18:24:29 UTC
Verified that even with 2.5 years old cc1plus we still trigger the instantiation limit, so it indeed is some changes in libstdc++.  Guess you can try -ftemplate-depth=20 etc. in 4.9 to see how close to the limit you were before.
Comment 6 Marek Polacek 2015-02-12 18:28:40 UTC
Yeah, the default is 900.   (C++11 recommends 1024 AFAIK.)

From what I can see they used
/usr/lib64/ccache/g++ -v -save-temps -g3 -O0 -DDEBUG -ftemplate-depth-25 -DHAVE_CONFIG_H -pthread -Idefault/src/main -I../src/main -Idefault -I.. -Idefault/src -I../src -I/usr/include/dbus-1.0 -I/usr/lib64/dbus-1.0/include -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include -I/usr/include/gconf/2 -I/usr/include/libgsf-1 -I/usr/include/libglade-2.0 -I/usr/include/webkitgtk-1.0 -I/usr/include/libsoup-2.4 -I/usr/include/libxml2 -I/usr/include/gtk-2.0 -I/usr/lib64/gtk-2.0/include -I/usr/include/pango-1.0 -I/usr/include/atk-1.0 -I/usr/include/cairo -I/usr/include/pixman-1 -I/usr/include/libdrm -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/libpng16 -I/usr/include/harfbuzz -I/usr/include/freetype2 -I/usr/include/sword -I/usr/include/biblesync/bibleysnc -I/usr/include/uuid ../src/main/modulecache.cc -c -o default/src/main/modulecache_1.o

I don't know if those command-line options have changed.
Comment 7 Jonathan Wakely 2015-02-13 11:40:33 UTC
Trying to use the standard library with such a tiny limit is simply not going to work. If it worked previously you got lucky, but if you need to raise the limit now then that's what you need to do.

What's the purpose of enforcing such a tiny limit anyway?
Comment 8 Jonathan Wakely 2017-12-12 18:32:40 UTC
As I said, it's not reasonable to use libstdc++ with such tiny limits.

(In reply to Jonathan Wakely from comment #7)
> What's the purpose of enforcing such a tiny limit anyway?

Changing status to WAITING, and the bug will be closed if no answer is forthcoming.