http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51635
--- Comment #11 from Richard Guenther <rguenth at gcc dot gnu.org> 2011-12-21 10:56:01 UTC --- One issue we still hit is that we for example merge in stl_iterator_base_types.h template<typename _Iterator> struct iterator_traits { typedef typename _Iterator::iterator_category iterator_category; typedef typename _Iterator::value_type value_type; typedef typename _Iterator::difference_type difference_type; typedef typename _Iterator::pointer pointer; typedef typename _Iterator::reference reference; }; and template<typename _Tp> struct iterator_traits<const _Tp*> { typedef random_access_iterator_tag iterator_category; typedef _Tp value_type; typedef ptrdiff_t difference_type; typedef const _Tp* pointer; typedef const _Tp& reference; }; and so end up attaching the same TYPE_DECL to both iterator_category typedefs. An extreme idea was to only merge if the TYPE_DECLs source location was the same (but not sure if that works reliably without expensive location expansion). The above merging causes us to infinitely recurse in modified_type_die through DECL_ORIGINAL_TYPE which forms a typedef cycle. You probably hit a similar bug. A non-optimial patch for the above is (non-optimal because it does not include hashing) Index: gcc/gimple.c =================================================================== --- gcc/gimple.c (revision 182525) +++ gcc/gimple.c (working copy) @@ -3318,28 +3318,35 @@ compare_type_names_p (tree t1, tree t2) tree name1 = TYPE_NAME (t1); tree name2 = TYPE_NAME (t2); + if (name1 == name2) + return true; + 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); + { + expanded_location loc1, loc2; - if (TREE_CODE (name2) == TYPE_DECL) - name2 = DECL_NAME (name2); - gcc_checking_assert (!name2 || TREE_CODE (name2) == IDENTIFIER_NODE); + if (DECL_NAME (name1) != DECL_NAME (name2)) + return false; - /* Identifiers can be compared with pointer equality rather - than a string comparison. */ - if (name1 == name2) - return true; + if (DECL_SOURCE_LOCATION (name1) == DECL_SOURCE_LOCATION (name2)) + return true; + + loc1 = expand_location (DECL_SOURCE_LOCATION (name1)); + loc2 = expand_location (DECL_SOURCE_LOCATION (name2)); + if (loc1.line != loc2.line + || loc1.column != loc2.column + || strcmp (loc1.file, loc2.file) != 0) + return false; + + return true; + } return false; }