c++: explicit spec of constrained member tmpl [PR107522]
When defining a explicit specialization of a constrained member template (of a class template) such as f and g in the below testcase, the DECL_TEMPLATE_PARMS of the corresponding TEMPLATE_DECL are partially instantiated, whereas its associated constraints are carried over from the original template and thus are in terms of the original DECL_TEMPLATE_PARMS. So during normalization for such an explicit specialization we need to consider the (parameters of) the most general template, since that's what the constraints are in terms of and since we always use the full set of template arguments during satisfaction. PR c++/107522 gcc/cp/ChangeLog: * constraint.cc (get_normalized_constraints_from_decl): Use the most general template for an explicit specialization of a member template. gcc/testsuite/ChangeLog: * g++.dg/cpp2a/concepts-explicit-spec7.C: New test. Reviewed-by: Jason Merrill <jason@redhat.com>
This commit is contained in:
parent
d72e5b7be2
commit
62daa81308
2 changed files with 43 additions and 5 deletions
|
@ -701,11 +701,19 @@ get_normalized_constraints_from_decl (tree d, bool diag = false)
|
|||
accepting the latter causes the template parameter level of U
|
||||
to be reduced in a way that makes it overly difficult substitute
|
||||
concrete arguments (i.e., eventually {int, int} during satisfaction. */
|
||||
if (tmpl)
|
||||
{
|
||||
if (DECL_LANG_SPECIFIC (tmpl) && !DECL_TEMPLATE_SPECIALIZATION (tmpl))
|
||||
tmpl = most_general_template (tmpl);
|
||||
}
|
||||
if (tmpl && DECL_LANG_SPECIFIC (tmpl)
|
||||
&& (!DECL_TEMPLATE_SPECIALIZATION (tmpl)
|
||||
/* DECL_TEMPLATE_SPECIALIZATION means TMPL is either a partial
|
||||
specialization, or an explicit specialization of a member
|
||||
template. In the former case all is well: TMPL's constraints
|
||||
are in terms of its parameters. But in the latter case TMPL's
|
||||
parameters are partially instantiated whereas its constraints
|
||||
aren't, so we need to instead use (the parameters of) the most
|
||||
general template. The following test distinguishes between a
|
||||
partial specialization and such an explicit specialization. */
|
||||
|| (TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl))
|
||||
< TMPL_ARGS_DEPTH (DECL_TI_ARGS (tmpl)))))
|
||||
tmpl = most_general_template (tmpl);
|
||||
|
||||
d = tmpl ? tmpl : decl;
|
||||
|
||||
|
|
30
gcc/testsuite/g++.dg/cpp2a/concepts-explicit-spec7.C
Normal file
30
gcc/testsuite/g++.dg/cpp2a/concepts-explicit-spec7.C
Normal file
|
@ -0,0 +1,30 @@
|
|||
// PR c++/107522
|
||||
// { dg-do compile { target c++20 } }
|
||||
|
||||
template<class T>
|
||||
struct A {
|
||||
template<int N>
|
||||
static void f() requires (N == 42);
|
||||
|
||||
template<class U>
|
||||
struct B {
|
||||
template<int N>
|
||||
static void g() requires (T(N) == 42);
|
||||
};
|
||||
};
|
||||
|
||||
template<>
|
||||
template<int N>
|
||||
void A<int>::f() requires (N == 42) { }
|
||||
|
||||
template<>
|
||||
template<>
|
||||
template<int N>
|
||||
void A<int>::B<int>::g() requires (int(N) == 42) { }
|
||||
|
||||
int main() {
|
||||
A<int>::f<42>();
|
||||
A<int>::f<43>(); // { dg-error "no match" }
|
||||
A<int>::B<int>::g<42>();
|
||||
A<int>::B<int>::g<43>(); // { dg-error "no match" }
|
||||
}
|
Loading…
Add table
Reference in a new issue