re PR c++/64297 (ICE: canonical types differ for identical types)
authorJason Merrill <jason@redhat.com>
Mon, 15 Dec 2014 20:19:51 +0000 (15:19 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Mon, 15 Dec 2014 20:19:51 +0000 (15:19 -0500)
PR c++/64297
* typeck.c (apply_memfn_quals): Correct wrong TYPE_CANONICAL.

From-SVN: r218763

gcc/cp/ChangeLog
gcc/cp/typeck.c
gcc/testsuite/g++.dg/cpp0x/ref-qual16.C [new file with mode: 0644]

index c14020dafd61d222f95f89c34988a200fd8c6077..afb24839c4256792ef7251235194e5a966e11489 100644 (file)
@@ -1,5 +1,8 @@
 2014-12-15  Jason Merrill  <jason@redhat.com>
 
+       PR c++/64297
+       * typeck.c (apply_memfn_quals): Correct wrong TYPE_CANONICAL.
+
        N3778: Sized Deallocation
        * call.c (non_placement_deallocation_fn_p): A global sized
        operator delete is not a usual deallocation function until C++14.
index 7b39816bdb1f6962fb6ed17cfb4c17cb60d34d57..9368b49b012c167f0effba5fa709a2d64cd8bf9d 100644 (file)
@@ -8945,6 +8945,12 @@ apply_memfn_quals (tree type, cp_cv_quals memfn_quals, cp_ref_qualifier rqual)
   /* This should really have a different TYPE_MAIN_VARIANT, but that gets
      complex.  */
   tree result = build_qualified_type (type, memfn_quals);
+  if (tree canon = TYPE_CANONICAL (result))
+    if (canon != result)
+      /* check_qualified_type doesn't check the ref-qualifier, so make sure
+        TYPE_CANONICAL is correct.  */
+      TYPE_CANONICAL (result)
+       = build_ref_qualified_type (canon, type_memfn_rqual (result));
   result = build_exception_variant (result, TYPE_RAISES_EXCEPTIONS (type));
   return build_ref_qualified_type (result, rqual);
 }
diff --git a/gcc/testsuite/g++.dg/cpp0x/ref-qual16.C b/gcc/testsuite/g++.dg/cpp0x/ref-qual16.C
new file mode 100644 (file)
index 0000000..1d7650b
--- /dev/null
@@ -0,0 +1,12 @@
+// PR c++/64297
+// { dg-do compile { target c++11 } }
+
+struct A {
+  typedef int X;
+  template <int> X m_fn1() const;
+};
+template <typename> struct is_function {};
+is_function<int() const &> i;
+struct D {
+  template <typename Y, typename = is_function<Y>> D(Y);
+} b(&A::m_fn1<0>);