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

Reply via email to