This fixes PR51567 - we are incorrectly merging the two 'iterator' types in
class _Deque_base { public: typedef _Deque_iterator iterator; iterator _M_impl; }; class deque : public _Deque_base { public: typedef _Deque_base::iterator iterator; }; which results in dwarf2out.c being confused. The following patch fixes that, which results in SPEC 2k6 to build fine with LTO and debug info enabled (finally!). LTO bootstrapped on x86_64-unknown-linux-gnu, testing in progress. I'll apply this once the testing finished. Honza, now is a good time to test if Mozilla is happy with -flto -g (and maybe also watch how (bad) memory usage and diskspace usage got). Thanks, Richard. 2011-12-15 Richard Guenther <rguent...@suse.de> PR lto/51567 * gimple.c (compare_type_names_p): Also compare the TREE_CODE. (iterative_hash_name): Also hash the TREE_CODE. (gimple_types_compatible_p_1): For types with a TYPE_DECL name and a type DECL_CONTEXT recurse to that type. (iterative_hash_gimple_type): Likewise. * g++.dg/lto/pr51567-1_0.C: New testcase. Index: gcc/gimple.c =================================================================== --- gcc/gimple.c (revision 182366) +++ gcc/gimple.c (working copy) @@ -3318,11 +3318,21 @@ compare_type_names_p (tree t1, tree t2) tree name1 = TYPE_NAME (t1); tree name2 = TYPE_NAME (t2); - if (name1 && TREE_CODE (name1) == TYPE_DECL) + if ((name1 != NULL_TREE) != (name2 != NULL_TREE)) + return false; + + if (name1 == NULL_TREE) + return true; + + /* Either both should be a TYPE_DECL or both an IDENTIFIER_NODE. */ + if (TREE_CODE (name1) != TREE_CODE (name2)) + return false; + + if (TREE_CODE (name1) == TYPE_DECL) name1 = DECL_NAME (name1); gcc_checking_assert (!name1 || TREE_CODE (name1) == IDENTIFIER_NODE); - if (name2 && TREE_CODE (name2) == TYPE_DECL) + if (TREE_CODE (name2) == TYPE_DECL) name2 = DECL_NAME (name2); gcc_checking_assert (!name2 || TREE_CODE (name2) == IDENTIFIER_NODE); @@ -3537,6 +3547,19 @@ gimple_types_compatible_p_1 (tree t1, tr if (!compare_type_names_p (t1, t2)) goto different_types; + /* We may not merge typedef types to the same type in different + contexts. */ + if (TYPE_NAME (t1) + && TREE_CODE (TYPE_NAME (t1)) == TYPE_DECL + && DECL_CONTEXT (TYPE_NAME (t1)) + && TYPE_P (DECL_CONTEXT (TYPE_NAME (t1)))) + { + if (!gtc_visit (DECL_CONTEXT (TYPE_NAME (t1)), + DECL_CONTEXT (TYPE_NAME (t2)), + state, sccstack, sccstate, sccstate_obstack)) + goto different_types; + } + /* If their attributes are not the same they can't be the same type. */ if (!attribute_list_equal (TYPE_ATTRIBUTES (t1), TYPE_ATTRIBUTES (t2))) goto different_types; @@ -3980,6 +4003,7 @@ iterative_hash_name (tree name, hashval_ { if (!name) return v; + v = iterative_hash_hashval_t (TREE_CODE (name), v); if (TREE_CODE (name) == TYPE_DECL) name = DECL_NAME (name); if (!name) @@ -4046,6 +4070,12 @@ iterative_hash_gimple_type (tree type, h only existing types having the same features as the new type will be checked. */ v = iterative_hash_name (TYPE_NAME (type), 0); + if (TYPE_NAME (type) + && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL + && DECL_CONTEXT (TYPE_NAME (type)) + && TYPE_P (DECL_CONTEXT (TYPE_NAME (type)))) + v = visit (DECL_CONTEXT (TYPE_NAME (type)), state, v, + sccstack, sccstate, sccstate_obstack); v = iterative_hash_hashval_t (TREE_CODE (type), v); v = iterative_hash_hashval_t (TYPE_QUALS (type), v); v = iterative_hash_hashval_t (TREE_ADDRESSABLE (type), v); Index: gcc/testsuite/g++.dg/lto/pr51567-1_0.C =================================================================== --- gcc/testsuite/g++.dg/lto/pr51567-1_0.C (revision 0) +++ gcc/testsuite/g++.dg/lto/pr51567-1_0.C (revision 0) @@ -0,0 +1,27 @@ +// { dg-lto-do link } +// { dg-lto-options { { -flto -g } } } + +struct _Deque_iterator { + int* _M_cur; + void foo() {} +}; +class _Deque_base { +public: + typedef _Deque_iterator iterator; + iterator _M_impl; +}; +class deque : public _Deque_base { +public: + typedef _Deque_base::iterator iterator; +}; +class OutputContextStack { +public: + deque m_stack; + deque::iterator m_stackPosition; +}; +int main() +{ + OutputContextStack s; + s.m_stackPosition.foo(); +} +