This fixes some issues with constrained variable templates: * Constraints aren't checked when explicitly specializing a variable template * Constraints aren't attached to a static data member template at parse time * Constraints aren't propagated when (partially) instantiating a static data member template
Bootstrapped and regtested on x86_64-pc-linux-gnu, and also tested on cmcstl2 and range-v3, does this look OK for trunk and perhaps 11? PR c++/98486 gcc/cp/ChangeLog: * decl.c (grokdeclarator): Set constraints on a static data member template. * pt.c (determine_specialization): Check constraints on a variable template. (tsubst_decl) <case VAR_DECL>: Propagate constraints on a static data member template. gcc/testsuite/ChangeLog: * g++.dg/cpp2a/concepts-var-templ1.C: New test. * g++.dg/cpp2a/concepts-var-templ1a.C: New test. * g++.dg/cpp2a/concepts-var-templ1b.C: New test. --- gcc/cp/decl.c | 11 +++++++++++ gcc/cp/pt.c | 8 +++++++- gcc/testsuite/g++.dg/cpp2a/concepts-var-templ1.C | 9 +++++++++ gcc/testsuite/g++.dg/cpp2a/concepts-var-templ1a.C | 14 ++++++++++++++ gcc/testsuite/g++.dg/cpp2a/concepts-var-templ1b.C | 15 +++++++++++++++ 5 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-var-templ1.C create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-var-templ1a.C create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-var-templ1b.C diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index c0f1496636f..7beac79ec25 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -13980,6 +13980,17 @@ grokdeclarator (const cp_declarator *declarator, if (declspecs->gnu_thread_keyword_p) SET_DECL_GNU_TLS_P (decl); } + + /* Set the constraints on declaration. */ + bool memtmpl = (processing_template_decl + > template_class_depth (current_class_type)); + if (memtmpl) + { + tree tmpl_reqs + = TEMPLATE_PARMS_CONSTRAINTS (current_template_parms); + tree ci = build_constraints (tmpl_reqs, NULL_TREE); + set_constraints (decl, ci); + } } else { diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 224dd9ebd2b..613d87f2637 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -2218,7 +2218,8 @@ determine_specialization (tree template_id, targs = coerce_template_parms (parms, explicit_targs, fns, tf_warning_or_error, /*req_all*/true, /*use_defarg*/true); - if (targs != error_mark_node) + if (targs != error_mark_node + && constraints_satisfied_p (fns, targs)) templates = tree_cons (targs, fns, templates); } else for (lkp_iterator iter (fns); iter; ++iter) @@ -14920,6 +14921,11 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) if (DECL_NAMESPACE_SCOPE_P (t)) DECL_NOT_REALLY_EXTERN (r) = 1; + /* Propagate the declaration's constraints. */ + if (VAR_P (r) && DECL_CLASS_SCOPE_P (r)) + if (tree ci = get_constraints (t)) + set_constraints (r, ci); + DECL_TEMPLATE_INFO (r) = build_template_info (tmpl, argvec); SET_DECL_IMPLICIT_INSTANTIATION (r); if (!error_operand_p (r) || (complain & tf_error)) diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-var-templ1.C b/gcc/testsuite/g++.dg/cpp2a/concepts-var-templ1.C new file mode 100644 index 00000000000..80b48ba3a3d --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-var-templ1.C @@ -0,0 +1,9 @@ +// PR c++/98486 +// { dg-do compile { target c++20 } } + +template<class T, class U> concept C = __is_same(T, U); + +template<C<int>> int v; + +template<> int v<int>; +template<> int v<char>; // { dg-error "match" } diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-var-templ1a.C b/gcc/testsuite/g++.dg/cpp2a/concepts-var-templ1a.C new file mode 100644 index 00000000000..b12d37d8b7e --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-var-templ1a.C @@ -0,0 +1,14 @@ +// PR c++/98486 +// { dg-do compile { target c++20 } } + +template<class T, class U> concept C = __is_same(T, U); + +struct A { + template<C<int>> static int v; +}; + +template<> int A::v<int>; +template<> int A::v<char>; // { dg-error "match" } + +int x = A::v<int>; +int y = A::v<char>; // { dg-error "invalid" } diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-var-templ1b.C b/gcc/testsuite/g++.dg/cpp2a/concepts-var-templ1b.C new file mode 100644 index 00000000000..37d7f0fc654 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-var-templ1b.C @@ -0,0 +1,15 @@ +// PR c++/98486 +// { dg-do compile { target c++20 } } + +template<class T, class U> concept C = __is_same(T, U); + +template<class T> +struct A { + template<C<T>> static int v; +}; + +template<> template<> int A<int>::v<int>; +template<> template<> int A<int>::v<char>; // { dg-error "match" } + +int x = A<int>::v<int>; +int y = A<int>::v<char>; // { dg-error "invalid" } -- 2.33.0.363.g4c719308ce