aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2016-01-19 14:00:21 -0500
committerJason Merrill <jason@gcc.gnu.org>2016-01-19 14:00:21 -0500
commit33f488425964a50f8bcd847980c02beea8b25956 (patch)
tree5619684f985ef38c0ced0fa21b91f394c85a805c
parenta88d10cb99e33d58fd07a4bad0ae7d523d731135 (diff)
downloadgcc-33f488425964a50f8bcd847980c02beea8b25956.zip
gcc-33f488425964a50f8bcd847980c02beea8b25956.tar.gz
gcc-33f488425964a50f8bcd847980c02beea8b25956.tar.bz2
re PR c++/59759 (internal compiler error: in unify, using std::enable_if on classes)
PR c++/59759 * pt.c (convert_template_argument): Handle VAR_DECL properly. From-SVN: r232580
-rw-r--r--gcc/cp/ChangeLog5
-rw-r--r--gcc/cp/pt.c21
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/temp_default6.C27
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/temp_default7.C27
4 files changed, 74 insertions, 6 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index ac2bbae..45cb0e7 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 6062ebe..ae60f1c 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -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
index 0000000..10cde2d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/temp_default6.C
@@ -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
index 0000000..c517aad
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/temp_default7.C
@@ -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);
+}