re PR c++/59759 (internal compiler error: in unify, using std::enable_if on classes)
authorJason Merrill <jason@redhat.com>
Tue, 19 Jan 2016 19:00:21 +0000 (14:00 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Tue, 19 Jan 2016 19:00:21 +0000 (14:00 -0500)
PR c++/59759
* pt.c (convert_template_argument): Handle VAR_DECL properly.

From-SVN: r232580

gcc/cp/ChangeLog
gcc/cp/pt.c
gcc/testsuite/g++.dg/cpp0x/temp_default6.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/temp_default7.C [new file with mode: 0644]

index ac2bbae430f1c39eb50ed3acc6324b83eb54213f..45cb0e72a4c6abf3ca101e51739bf3b4cbbaddc1 100644 (file)
@@ -1,3 +1,8 @@
+2016-01-19  Jason Merrill  <jason@redhat.com>
+
+       PR c++/59759
+       * pt.c (convert_template_argument): Handle VAR_DECL properly.
+
 2016-01-19  Marek Polacek  <polacek@redhat.com>
 
        PR c++/68586
index 6062ebe50a6e262ca5405dd8526e487f194b6509..ae60f1c2d0a667d29b8617e97f5baf3462374ab0 100644 (file)
@@ -19928,11 +19928,20 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict,
       return unify_template_argument_mismatch (explain_p, parm, arg);
 
     case VAR_DECL:
-      /* A non-type template parameter that is a variable should be a
-        an integral constant, in which case, it whould have been
-        folded into its (constant) value. So we should not be getting
-        a variable here.  */
-      gcc_unreachable ();
+      /* We might get a variable as a non-type template argument in parm if the
+        corresponding parameter is type-dependent.  Make any necessary
+        adjustments based on whether arg is a reference.  */
+      if (CONSTANT_CLASS_P (arg))
+       parm = fold_non_dependent_expr (parm);
+      else if (REFERENCE_REF_P (arg))
+       {
+         tree sub = TREE_OPERAND (arg, 0);
+         STRIP_NOPS (sub);
+         if (TREE_CODE (sub) == ADDR_EXPR)
+           arg = TREE_OPERAND (sub, 0);
+       }
+      /* Now use the normal expression code to check whether they match.  */
+      goto expr;
 
     case TYPE_ARGUMENT_PACK:
     case NONTYPE_ARGUMENT_PACK:
@@ -19965,7 +19974,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict,
       if (is_overloaded_fn (parm) || type_unknown_p (parm))
        return unify_success (explain_p);
       gcc_assert (EXPR_P (parm));
-
+    expr:
       /* We must be looking at an expression.  This can happen with
         something like:
 
diff --git a/gcc/testsuite/g++.dg/cpp0x/temp_default6.C b/gcc/testsuite/g++.dg/cpp0x/temp_default6.C
new file mode 100644 (file)
index 0000000..10cde2d
--- /dev/null
@@ -0,0 +1,27 @@
+// PR c++/59759
+// { dg-do compile { target c++11 } }
+
+namespace std {
+template <typename _Tp>
+struct B {
+  static constexpr _Tp value = 0;
+};
+typedef B<int> false_type;
+struct C : false_type {};
+template <typename>
+struct is_integral : C {};
+template <int, typename _Tp>
+struct enable_if {
+  typedef _Tp type;
+};
+}
+enum class enabled;
+extern constexpr enabled dummy{};
+template <typename T, typename std::enable_if<std::is_integral<T>::value,
+                                              T>::type = dummy>
+class A;
+template <typename T>
+void f(A<const T&>*) {
+  A<const enabled&>* map;
+  f(map);
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/temp_default7.C b/gcc/testsuite/g++.dg/cpp0x/temp_default7.C
new file mode 100644 (file)
index 0000000..c517aad
--- /dev/null
@@ -0,0 +1,27 @@
+// PR c++/59759
+// { dg-do compile { target c++11 } }
+
+namespace std {
+template <typename _Tp>
+struct B {
+  static constexpr _Tp value = 0;
+};
+typedef B<int> false_type;
+struct C : false_type {};
+template <typename>
+struct is_integral : C {};
+template <int, typename _Tp>
+struct enable_if {
+  typedef _Tp type;
+};
+}
+enum class enabled;
+constexpr enabled dummy{};
+template <typename T, typename std::enable_if<std::is_integral<T>::value,
+                                              enabled>::type = dummy>
+class A;
+template <typename T>
+void f(A<T>*) {
+  A<int>* map;
+  f(map);
+}