At the Lenexa C++ meeting Walter pointed me at a variable template
testcase that was breaking, which turned out to be because we were
failing to strip aliases consistently in variable template arguments,
leading to mismatches between, in the first testcase, V<float> and V<fl>.
Tested x86_64-pc-linux-gnu, applying to trunk and concepts branch.
commit 87ca1bec448edb74cd531d5b2691a9d58ba17326
Author: Jason Merrill <ja...@redhat.com>
Date: Sat May 9 15:50:40 2015 -0500
* pt.c (tsubst_decl) [VAR_DECL]: Call coerce_innermost_template_parms.
(determine_specialization): Call coerce_template_parms.
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 2cd36c9..2166f5f 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -1919,7 +1919,13 @@ determine_specialization (tree template_id,
++header_count;
if (variable_template_p (fns))
- templates = tree_cons (explicit_targs, fns, templates);
+ {
+ tree parms = INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (fns));
+ targs = coerce_template_parms (parms, explicit_targs, fns,
+ tf_warning_or_error,
+ /*req_all*/true, /*use_defarg*/true);
+ templates = tree_cons (targs, fns, templates);
+ }
else for (; fns; fns = OVL_NEXT (fns))
{
tree fn = OVL_CURRENT (fns);
@@ -11265,6 +11271,11 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
tmpl = DECL_TI_TEMPLATE (t);
gen_tmpl = most_general_template (tmpl);
argvec = tsubst (DECL_TI_ARGS (t), args, complain, in_decl);
+ if (argvec != error_mark_node)
+ argvec = (coerce_innermost_template_parms
+ (DECL_TEMPLATE_PARMS (gen_tmpl),
+ argvec, t, complain,
+ /*all*/true, /*defarg*/true));
if (argvec == error_mark_node)
RETURN (error_mark_node);
hash = hash_tmpl_and_args (gen_tmpl, argvec);
diff --git a/gcc/testsuite/g++.dg/cpp1y/var-templ25.C b/gcc/testsuite/g++.dg/cpp1y/var-templ25.C
new file mode 100644
index 0000000..8253eac
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/var-templ25.C
@@ -0,0 +1,8 @@
+// { dg-do compile { target c++14 } }
+
+using fl = float;
+
+template<class T> const int V = 0;
+template<> const int V<fl> = 42;
+
+static_assert(V<float> == 42, "");
diff --git a/gcc/testsuite/g++.dg/cpp1y/var-templ26.C b/gcc/testsuite/g++.dg/cpp1y/var-templ26.C
new file mode 100644
index 0000000..9ac0777
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/var-templ26.C
@@ -0,0 +1,19 @@
+// { dg-do compile { target c++14 } }
+
+template <class T> const int V = 0;
+template <> const int V<char> = 42;
+
+template <class T>
+struct A
+{
+ using N = T;
+};
+
+#define SA(X) static_assert((X),#X)
+template <class T>
+struct B
+{
+ SA(V<typename A<T>::N> == 42);
+};
+
+B<char> b;
commit c1e703a6f795ea63609098607b4484e4b516af41
Author: Jason Merrill <ja...@redhat.com>
Date: Wed May 13 15:57:00 2015 -0400
* pt.c (retrieve_specialization): Make sure our arguments have
gone through strip_typedefs.
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 2166f5f..60f3958 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -1058,6 +1058,14 @@ retrieve_specialization (tree tmpl, tree args, hashval_t hash)
? TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl))
: template_class_depth (DECL_CONTEXT (tmpl))));
+#ifdef ENABLE_CHECKING
+ /* We should have gone through coerce_template_parms by now. */
+ ++processing_template_decl;
+ if (!any_dependent_template_arguments_p (args))
+ gcc_assert (strip_typedefs_expr (args, NULL) == args);
+ --processing_template_decl;
+#endif
+
if (optimize_specialization_lookup_p (tmpl))
{
tree class_template;