Hi! On the following testcase we ICE, because now that clone_tree_hash inserts elements into decl_table hash table, if the hash table is expanded during that, storing into *slot might either store it at a wrong spot, or in completely unrelated memory.
Fixed by storing into the hash table immediately when we have the DIE's copy, before the clone_tree_hash loop. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk/4.6? 2012-02-16 Jakub Jelinek <ja...@redhat.com> PR debug/52260 * dwarf2out.c (copy_decls_walk): Fill in *slot before traversing children with clone_tree_hash, not after it. * g++.dg/debug/dwarf2/pr52260.C: New test. --- gcc/dwarf2out.c.jj 2012-02-15 07:35:11.000000000 +0100 +++ gcc/dwarf2out.c 2012-02-15 20:30:00.845071676 +0100 @@ -7471,14 +7471,6 @@ copy_decls_walk (dw_die_ref unit, dw_die dw_die_ref parent = unit; dw_die_ref copy = clone_die (targ); - FOR_EACH_CHILD (targ, c, - add_child_die (copy, - clone_tree_hash (c, decl_table))); - - /* Make sure the cloned tree is marked as part of the - type unit. */ - mark_dies (copy); - /* Record in DECL_TABLE that TARG has been copied. Need to do this now, before the recursive call, because DECL_TABLE may be expanded and SLOT @@ -7488,6 +7480,14 @@ copy_decls_walk (dw_die_ref unit, dw_die entry->copy = copy; *slot = entry; + FOR_EACH_CHILD (targ, c, + add_child_die (copy, + clone_tree_hash (c, decl_table))); + + /* Make sure the cloned tree is marked as part of the + type unit. */ + mark_dies (copy); + /* If TARG has surrounding context, copy its ancestor tree into the new type unit. */ if (targ->die_parent != NULL --- gcc/testsuite/g++.dg/debug/dwarf2/pr52260.C.jj 2012-02-16 00:22:11.632188858 +0100 +++ gcc/testsuite/g++.dg/debug/dwarf2/pr52260.C 2012-02-16 00:21:51.000000000 +0100 @@ -0,0 +1,133 @@ +// PR debug/52260 +// { dg-do compile } +// { dg-options "-gdwarf-4 -std=c++0x" } + +namespace { typedef decltype (nullptr) T1; } +struct B {}; +namespace A +{ + template <typename T, T __v> + struct C { static constexpr T value = __v; }; + typedef C <bool, false> D; + template <typename> + struct E : D {}; + template <typename T> + struct F : C <bool, (E <T>::value)> {}; + template <bool, typename T = void> + struct G { typedef T t; }; +} +template <typename T> +struct H {}; +namespace A +{ + template <typename T> + struct I : H <T> {}; + template <typename ...> struct J; + template <typename> struct K; + struct L + { + template <typename B2> + struct M + { + template <typename T> static bool m2 (T) { return false; } + }; + }; + template <typename, typename> struct N; + template <typename T, typename B2, typename ... B4> + struct N <T (B4 ...), B2> : L::M <B2> {}; + template <typename T, typename ... B4> + struct K <T (B4 ...)> :J <,>, L + { + typedef T O (B4 ...); + struct P {}; + template <typename B2> K (B2, typename G <!F <B2>::value, P>::t = P ()); + }; + template <typename T, typename ... B1> + template <typename B2> + K <T (B1 ...)>::K (B2 __f, typename G <!F < B2>::value, P>::t) + { + typedef N <O, B2> Q; + Q::m2 (__f); + }; +} +enum R { r1 }; +const R r2 = r1; +namespace A +{ + template <typename> + struct S {}; + template <typename T, typename _Dp = S <T>> + struct U {}; + template <typename T, R _Lp = r2> + struct V { T *operator -> (); }; + template <typename T> + struct W : V <T> + { + W (const W &); + W (T1) {} + W & operator= (W) {} + }; + template <typename> struct Z; + struct AA + { + struct AB + { + struct AC { void operator () () {} }; + }; + template <typename T> using AD = U <T, AB::AC>; + struct AE + { + typedef AD <AB> AZ; + virtual ~AE (); + void o3 (K <AZ ()>, bool = false) {} + template <typename, typename _Arg> struct AY; + struct C1 {}; + template <typename T> struct AY <T, C1> + { + AZ operator () () { return AZ (); } + Z <T> _M_Z; + }; + template <typename T> + static AY <T, C1> _s1 (B, Z <T> *); + }; + }; + template <> + struct Z <void> + { + typedef AA::AE AF; + W <AF> o4; + void foo (B __p) + { + auto _s1 = AF::_s1 (__p, this); + o4->o3 (_s1); + } + }; + template <typename T, typename _Alloc> + struct AG {}; + template <typename T, typename D1 = A::I <T>> + struct AH : AG <T, D1> + { + void bar (T) { baz (); } + template <typename ... _Args> + void baz (_Args && ...); + }; + template <typename T, typename D1> + template <typename ... _Args> + void AH <T, D1>::baz (_Args && ...) {} + namespace + { + typedef A::K <void ()> AI; + struct AF + { + int v2; + AI v1; + AF (int, unsigned, AI __t) : v2 (), v1 (__t) {} + }; + struct D3 : A::AH <AF> + { + typedef AF AFT; + void v3 (AI __t) { bar (AFT (4, v4, __t)); } + int v4; + }; + } +} Jakub