PR c++/92150 - partial specialization with class NTTP.
authorJason Merrill <jason@redhat.com>
Thu, 7 Nov 2019 00:31:52 +0000 (19:31 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Thu, 7 Nov 2019 00:31:52 +0000 (19:31 -0500)
Here unify was getting confused by the VIEW_CONVERT_EXPR we add in
finish_id_expression_1 to make class NTTP const when they're used in an
expression.

Tested x86_64-pc-linux-gnu, applying to trunk.

* pt.c (unify): Handle VIEW_CONVERT_EXPR.

From-SVN: r277901

gcc/cp/ChangeLog
gcc/cp/pt.c
gcc/testsuite/g++.dg/cpp2a/nontype-class24.C [new file with mode: 0644]

index cf3e00a843c043177c10b05de087bd9ed7a8d86c..8f6a71a8b6ad1069cd7db7113f02364a31e4b5f1 100644 (file)
@@ -1,5 +1,8 @@
 2019-11-06  Jason Merrill  <jason@redhat.com>
 
+       PR c++/92150 - partial specialization with class NTTP.
+       * pt.c (unify): Handle VIEW_CONVERT_EXPR.
+
        * pt.c (use_pack_expansion_extra_args_p): Still do substitution if
        all packs are simple pack expansions.
        (add_extra_args): Check that the extra args aren't dependent.
index c8df1d090bc251d0109e94619c9b48a7f120021e..061a92c9db09416adb247883f4be8a5369823cf6 100644 (file)
@@ -22571,8 +22571,9 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict,
   /* I don't think this will do the right thing with respect to types.
      But the only case I've seen it in so far has been array bounds, where
      signedness is the only information lost, and I think that will be
-     okay.  */
-  while (CONVERT_EXPR_P (parm))
+     okay.  VIEW_CONVERT_EXPR can appear with class NTTP, thanks to
+     finish_id_expression_1, and are also OK.  */
+  while (CONVERT_EXPR_P (parm) || TREE_CODE (parm) == VIEW_CONVERT_EXPR)
     parm = TREE_OPERAND (parm, 0);
 
   if (arg == error_mark_node)
diff --git a/gcc/testsuite/g++.dg/cpp2a/nontype-class24.C b/gcc/testsuite/g++.dg/cpp2a/nontype-class24.C
new file mode 100644 (file)
index 0000000..aa96de3
--- /dev/null
@@ -0,0 +1,19 @@
+// PR c++/92150
+// { dg-do compile { target c++2a } }
+
+struct X {
+  int value;
+  // auto operator==(const X&) = default;
+};
+
+template<typename T, X N>
+struct b;
+
+template<typename T>
+inline constexpr bool is_b = false;
+
+template<typename T, X N>
+inline constexpr bool is_b<b<T, N>> = true;
+
+using my_b = b<int, X{1}>;
+static_assert(is_b<my_b>);