This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

C++ PATCH for c++/59759 (ICE with variable as default template argument)


The comment removed by this patch asserts that we can't see a VAR_DECL in unify, because any use of a variable as a template argument will have been adjusted to be either its constant value or its address. But that isn't actually true when the type of the non-type template parameter depends on a type template argument, so we need to adjust based on what we end up getting.

Tested x86_64-pc-linux-gnu, applying to trunk.
commit fb06c19fb2adc8d69e924db2072437904a4e9c58
Author: Jason Merrill <jason@redhat.com>
Date:   Tue Jan 19 12:09:17 2016 -0500

    	PR c++/59759
    	* pt.c (convert_template_argument): Handle VAR_DECL properly.

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 866b4b1..9305e1d 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -19923,11 +19923,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:
@@ -19960,7 +19969,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);
+}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]