Created attachment 37706 [details] Pre-processed source (*.ii) triggering the bug The two attached source files both instantiate a same std::map<F, A>. However, when compiled with -std=gnu++11, code emitted for std::_Rb_tree_iterator<...> std::_Rb_tree<...>::_M_emplace_hint_unique<...> (std::_Rb_tree_const_iterator<std::pair<F const, A> >, std::piecewise_construct_t const&, std::tuple<F&&>&&, std::tuple<>&&) differs in the two resulting object files: _ZNSt8_Rb_treeI1FSt4pairIKS0_1AESt10_Select1stIS4_ESt4lessIS0_ESaIS4_EE22_M_emplace_hint_uniqueIJRKSt21piecewise_construct_tSt5tupleIJOS0_EESF_IJEEEEESt17_Rb_tree_iteratorIS4_ESt23_Rb_tree_const_iteratorIS4_EDpOT_: .fnstart -.LFB1874: - @ args = 4, pretend = 0, frame = 8 +.LFB1860: + @ args = 8, pretend = 0, frame = 8 @ frame_needed = 0, uses_anonymous_args = 0 strd r4, [sp, #-36]! .save {r4, r5, r6, r7, r8, r9, r10, fp, lr} - mov r5, r3 strd r6, [sp, #8] mov r6, r0 mov r0, #32 strd r8, [sp, #16] add r9, r6, #4 strd r10, [sp, #24] - mov r10, r1 + mov r10, r2 str lr, [sp, #32] .pad #12 sub sp, sp, #12 + ldr r5, [sp, #48] bl _Znwj - ldr r3, [r5] mov r4, r0 mov r1, #0 mov r0, #0 cmp r9, r10 + ldr r3, [r5] add fp, r4, #16 ldr r7, [r3] str r7, [r4, #16] strd r0, [r4, #24] Namely, the layout of call arguments seems to differ. Linking the two together results in one of the calls to _M_emplace_hint_unique in the target binary having mismatched arguments and execution causes a SEGV. Tested on GCC 5.2.1 and 5.3.1, as shipped with openSUSE Tumbleweed, as well as vanilla 5.3.0 compiled from sources. System type is armv7hl-suse-linux-gnueabi gcc -v: Using built-in specs. COLLECT_GCC=gcc COLLECT_LTO_WRAPPER=/usr/lib/gcc/armv7hl-suse-linux-gnueabi/5/lto-wrapper Target: armv7hl-suse-linux-gnueabi Configured with: ../configure --prefix=/usr --infodir=/usr/share/info --mandir=/usr/share/man --libdir=/usr/lib --libexecdir=/usr/lib --enable-languages=c,c++,objc,fortran,obj-c++,java,go --enable-checking=release --with-gxx-include-dir=/usr/include/c++/5 --enable-ssp --disable-libssp --disable-libvtv --disable-plugin --with-bugurl=http://bugs.opensuse.org/ --with-pkgversion='SUSE Linux' --disable-libgcj --with-slibdir=/lib --with-system-zlib --enable-__cxa_atexit --enable-libstdcxx-allocator=new --disable-libstdcxx-pch --enable-version-specific-runtime-libs --enable-linker-build-id --enable-linux-futex --program-suffix=-5 --without-system-libunwind --with-arch=armv7-a --with-tune=cortex-a15 --with-float=hard --with-abi=aapcs-linux --with-fpu=vfpv3-d16 --disable-sjlj-exceptions --build=armv7hl-suse-linux-gnueabi --host=armv7hl-suse-linux-gnueabi Thread model: posix gcc version 5.3.1 20151207 [gcc-5-branch revision 231355] (SUSE Linux) Steps to compile / reproduce: g++ -O2 -Wall -std=gnu++11 -c f1.cpp g++ -O2 -Wall -std=gnu++11 -c f2.cpp g++ -O2 -Wall -std=gnu++11 -o f f1.o f2.o ./f Segmentation fault (core dumped) Code works as expected in -O0 or -std=gnu++98 Not sure if specific to arm, but I'm filing initially under 'target'
Confirmed, I'm trying to figure out what is going wrong.
At the heart of the problem, the compiler has decided that the second parameter to this templated function has an overaligned member (64-byte aligned in f2, 8-byte aligned in f1). This gives different parameter passing rules, and you get the code difference above. I haven't figured out what causes the alignment to differ between the two TUs, or why the compiler feels it is safe to propagate the alignment information without specializing the function name. I'll take the bug while I look deeper.
I'm still confused by this. After coming out of the front end I checked the DECL_ALIGN for each field of each of the parameters being passed to this function. I see: ---- f1.ii std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_emplace_hint_unique(std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::const_iterator, _Args&& ...) (struct _Rb_tree * const this (decl alignment: 32), struct const_iterator __pos Fields: _M_node (decl alignment: 32) _Rb_tree_const_iterator (decl alignment: 8) value_type (decl alignment: 8) reference (decl alignment: 32) pointer (decl alignment: 32) iterator (decl alignment: 8) iterator_category (decl alignment: 8) difference_type (decl alignment: 32) _Self (decl alignment: 8) _Base_ptr (decl alignment: 32) _Link_type (decl alignment: 32) (decl alignment: 32, max field alignment: 32), const struct piecewise_construct_t & __args#0 (decl alignment: 32), struct tuple & __args#1 (decl alignment: 32), struct tuple & __args#2 (decl alignment: 32)) f2.ii std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_emplace_hint_unique(std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::const_iterator, _Args&& ...) (struct _Rb_tree * const this (decl alignment: 32), struct const_iterator __pos Fields: _M_node (decl alignment: 32) _Rb_tree_const_iterator (decl alignment: 8) value_type (decl alignment: 64) reference (decl alignment: 32) pointer (decl alignment: 32) iterator (decl alignment: 32) iterator_category (decl alignment: 8) difference_type (decl alignment: 32) _Self (decl alignment: 8) _Base_ptr (decl alignment: 32) _Link_type (decl alignment: 32) (decl alignment: 32, max field alignment: 64), const struct piecewise_construct_t & __args#0 (decl alignment: 32), struct tuple & __args#1 (decl alignment: 32), struct tuple & __args#2 (decl alignment: 32)) --- That is to say, after gimplification we've already decided that the alignment of the value_type field of the std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::const_iterator parameter to std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_emplace_hint_unique in f2.ii is 64, whereas in f1.ii we don't have any extra alignment information. I know nothing about the C++ front-end and how we could end up in this situation. I can understand why, given this, we would generate the code we do for ARM.
Goes away on trunk after r223301 Author: jason <jason@138bc75d-0d04-0410-961f-82ee72b054a4> Date: Mon May 18 17:14:11 2015 +0000 DR 1391 * pt.c (type_unification_real): Check convertibility here. (unify_one_argument): Not here. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@223301 After which the DECL_ALIGN in both TUs is 64, fixing the bug.
I don't know enough about the C++ standard to know whether this patch is reasonable to backport to GCC 5. Jason, do you have an opinion?
*ping*
(In reply to James Greenhalgh from comment #5) > I don't know enough about the C++ standard to know whether this patch is > reasonable to backport to GCC 5. Jason, do you have an opinion? I'd be pretty nervous about packporting that patch, as changes to that behavior tend to have unexpected side-effects. And it seems likely to have just made this bug latent, rather than actually fixed it.
Looks like a dup of 77728. At O1 or lower we get the new ABI change warning with a trunk compiler. Presumably at higher levels of optimization the prolematic code gets optimized away. *** This bug has been marked as a duplicate of bug 77728 ***