Hello,

in this PR, we end up with 3 types A, B and C such that TYPE_CANONICAL(A)=B and TYPE_CANONICAL(B)=C. I don't think that is supposed to happen. Here, build_qualified_type fills in TYPE_CANONICAL(A) by calling build_qualified_type (so get_qualified_type), which afaics isn't guaranteed to return a canonical type.

I doubt the patch can be wrong, but it may be that this is a situation that is not supposed to happen and should be fixed elsewhere?

Bootstrap+testsuite on x86_64-linux-gnu.

2014-06-09  Marc Glisse  <marc.gli...@inria.fr>

        PR c++/54442
gcc/
        * tree.c (build_qualified_type): Use a canonical type for
        TYPE_CANONICAL.
gcc/testsuite/
        * g++.dg/pr54442.C: New file.

--
Marc Glisse
Index: gcc/testsuite/g++.dg/pr54442.C
===================================================================
--- gcc/testsuite/g++.dg/pr54442.C      (revision 0)
+++ gcc/testsuite/g++.dg/pr54442.C      (working copy)
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+
+struct S
+{
+  void s (int) const throw ();
+  void s (int) throw ();
+};
+
+typedef int index_t;
+
+void (S::*f) (index_t)       = &S::s;
+void (S::*g) (index_t) const = &S::s;
Index: gcc/tree.c
===================================================================
--- gcc/tree.c  (revision 211374)
+++ gcc/tree.c  (working copy)
@@ -6319,22 +6319,25 @@ build_qualified_type (tree type, int typ
                TYPE_ALIGN (t) = TYPE_ALIGN (atomic_type);
            }
        }
 
       if (TYPE_STRUCTURAL_EQUALITY_P (type))
        /* Propagate structural equality. */
        SET_TYPE_STRUCTURAL_EQUALITY (t);
       else if (TYPE_CANONICAL (type) != type)
        /* Build the underlying canonical type, since it is different
           from TYPE. */
-       TYPE_CANONICAL (t) = build_qualified_type (TYPE_CANONICAL (type),
-                                                  type_quals);
+       {
+         tree c = build_qualified_type (TYPE_CANONICAL (type),
+                                        type_quals);
+         TYPE_CANONICAL (t) = TYPE_CANONICAL (c);
+       }
       else
        /* T is its own canonical type. */
        TYPE_CANONICAL (t) = t;
 
     }
 
   return t;
 }
 
 /* Create a variant of type T with alignment ALIGN.  */

Reply via email to