My patch for 58606 was incomplete; there were other places that needed
to change to handle dereferencing reference non-type template parameters.
Tested x86_64-pc-linux-gnu, applying to trunk. I reverted the earlier
58606 patch on the 4.8 branch.
commit 7b1bb4515ae768ca44e192442d2578ea46c16f96
Author: Jason Merrill <ja...@redhat.com>
Date: Thu Feb 20 23:22:21 2014 -0500
PR c++/60167
PR c++/60222
PR c++/58606
* parser.c (cp_parser_template_argument): Restore dereference.
* pt.c (template_parm_to_arg): Dereference non-pack expansions too.
(process_partial_specialization): Handle deref.
(unify): Likewise.
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 4673f78..d8ccd2b 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -13937,6 +13937,7 @@ cp_parser_template_argument (cp_parser* parser)
if (INDIRECT_REF_P (argument))
{
+ /* Strip the dereference temporarily. */
gcc_assert (REFERENCE_REF_P (argument));
argument = TREE_OPERAND (argument, 0);
}
@@ -13975,6 +13976,8 @@ cp_parser_template_argument (cp_parser* parser)
if (address_p)
argument = build_x_unary_op (loc, ADDR_EXPR, argument,
tf_warning_or_error);
+ else
+ argument = convert_from_reference (argument);
return argument;
}
}
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 6477fce..4cf387a 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -3861,6 +3861,8 @@ template_parm_to_arg (tree t)
SET_ARGUMENT_PACK_ARGS (t, vec);
TREE_TYPE (t) = type;
}
+ else
+ t = convert_from_reference (t);
}
return t;
}
@@ -4218,10 +4220,12 @@ process_partial_specialization (tree decl)
if (/* These first two lines are the `non-type' bit. */
!TYPE_P (arg)
&& TREE_CODE (arg) != TEMPLATE_DECL
- /* This next line is the `argument expression is not just a
+ /* This next two lines are the `argument expression is not just a
simple identifier' condition and also the `specialized
non-type argument' bit. */
- && TREE_CODE (arg) != TEMPLATE_PARM_INDEX)
+ && TREE_CODE (arg) != TEMPLATE_PARM_INDEX
+ && !(REFERENCE_REF_P (arg)
+ && TREE_CODE (TREE_OPERAND (arg, 0)) == TEMPLATE_PARM_INDEX))
{
if ((!packed_args && tpd.arg_uses_template_parms[i])
|| (packed_args && uses_template_parms (arg)))
@@ -17893,6 +17897,12 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict,
/* Unification fails if we hit an error node. */
return unify_invalid (explain_p);
+ case INDIRECT_REF:
+ if (REFERENCE_REF_P (parm))
+ return unify (tparms, targs, TREE_OPERAND (parm, 0), arg,
+ strict, explain_p);
+ /* FALLTHRU */
+
default:
/* An unresolved overload is a nondeduced context. */
if (is_overloaded_fn (parm) || type_unknown_p (parm))
diff --git a/gcc/testsuite/g++.dg/template/ref7.C b/gcc/testsuite/g++.dg/template/ref7.C
new file mode 100644
index 0000000..f6395e2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/ref7.C
@@ -0,0 +1,10 @@
+// PR c++/60167
+
+template <int& F>
+struct Foo {
+ typedef int Bar;
+
+ static Bar cache;
+};
+
+template <int& F> typename Foo<F>::Bar Foo<F>::cache;
diff --git a/gcc/testsuite/g++.dg/template/ref8.C b/gcc/testsuite/g++.dg/template/ref8.C
new file mode 100644
index 0000000..a2fc847
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/ref8.C
@@ -0,0 +1,8 @@
+// PR c++/60222
+
+template<int&> struct A
+{
+ template<typename> struct B;
+
+ template<typename T> struct B<T*> {};
+};