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;
}