On Thu, 25 Feb 2021, Jason Merrill wrote: > On 2/25/21 1:37 AM, Patrick Palka wrote: > > In-Reply-To: <20210225063712.3725111-1-ppa...@redhat.com> > > BTW, This patch doesn't seem in any way a reply to your previous patch, so > it's confusing for the mail headers (and thus MUA threading) to say that it > is. Maybe you want git send-email --no-thread or > git config sendemail.thread false ?
Ah, thanks for the heads up. Out of convenience I sent these two unrelated patches via a single "git send-email" command, which unknowingly caused the second patch to get sent as reply to the first. I'll make sure to send unrelated patches via separate send-email commands, or via a single command but with --no-thread. > > > In the three-parameter version of satisfy_declaration_constraints, when > > 't' isn't the most general template, then 't' doesn't correspond with > > the augmented template arguments 'args', and so the instantiation > > context that we push via push_tinst_level isn't quite correct. This > > manifests as misleading diagnostic context lines during satisfaction > > failure as in the testcase below for which without this patch we emit > > In substitution of '... static void A<int>::f<U>() [with U = int]' > > and with this patch we emit > > In substitution of '... static void A<T>::f<U>() [with U = char; T = > > int]'. > > > > This patch fixes this by passing the most general template to > > push_tinst_level. > > > > Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for > > trunk? > > > gcc/cp/ChangeLog: > > > > PR c++/99214 > > * constraint.cc (get_normalized_constraints_from_decl): Fix > > formatting. > > (satisfy_declaration_constraints): Be lazy about augmenting > > 'args'. Pass the most general template to push_tinst_level. > > > > gcc/testsuite/ChangeLog: > > > > PR c++/99214 > > * g++.dg/concepts/diagnostic16.C: New test. > > --- > > gcc/cp/constraint.cc | 16 ++++++++-------- > > gcc/testsuite/g++.dg/concepts/diagnostic16.C | 15 +++++++++++++++ > > 2 files changed, 23 insertions(+), 8 deletions(-) > > create mode 100644 gcc/testsuite/g++.dg/concepts/diagnostic16.C > > > > diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc > > index 31e0fb5079a..88963e687a7 100644 > > --- a/gcc/cp/constraint.cc > > +++ b/gcc/cp/constraint.cc > > @@ -910,11 +910,9 @@ 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)) > > + tmpl = most_general_template (tmpl); > > Can we use template_for_substitution instead of checking > DECL_TEMPLATE_SPECIALIZATION and most_general_template? That seems to be the > semantic we want. That sounds promising. I tried (roughly) diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc index 88963e687a7..1d974c52911 100644 --- a/gcc/cp/constraint.cc +++ b/gcc/cp/constraint.cc @@ -910,9 +910,7 @@ 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 && DECL_LANG_SPECIFIC (tmpl) - && !DECL_TEMPLATE_SPECIALIZATION (tmpl)) - tmpl = most_general_template (tmpl); + tmpl = template_for_substitution (decl); /* If we're not diagnosing errors, use cached constraints, if any. */ if (!diag) which breaks a lot of tests due to trivial reasons (e.g. DECL_LANG_SPECIFIC being empty), but in particular it breaks g++.dg/cpp2a/concepts-partial-spec2.C in a non-trivial way. In this testcase, the TEMPLATE_DECL for the partial specialization template <class T> requires True<T> && (T() == 0) constexpr bool p<T*> = true; has as its DECL_TEMPLATE_RESULT a VAR_DECL whose DECL_TI_TEMPLATE is the TEMPLATE_DECL not for the above partial specialization but for the primary template for p. So in short, when calling get_normalized_constraints_from_decl on the above TEMPLATE_DECL we have tmpl = d decl = DECL_TEMPLATE_RESULT(tmpl) most_general_template(tmpl) == tmpl == the partial specialization template_for_substitution(decl) == decl == the primary template and hence using template_for_substitution instead of most_general_template here would cause us to normalize the wrong constraints. > > > /* If we're not diagnosing errors, use cached constraints, if any. */ > > if (!diag) > > @@ -3157,12 +3155,14 @@ satisfy_declaration_constraints (tree t, tree args, > > sat_info info) > > gcc_assert (TREE_CODE (t) == TEMPLATE_DECL); > > - args = add_outermost_template_args (t, args); > > - > > tree result = boolean_true_node; > > if (tree norm = normalize_template_requirements (t, info.noisy ())) > > { > > - if (!push_tinst_level (t, args)) > > + args = add_outermost_template_args (t, args); > > + tree gen_tmpl = t; > > + if (DECL_LANG_SPECIFIC (t) && !DECL_TEMPLATE_SPECIALIZATION (t)) > > + gen_tmpl = most_general_template (t); > > + if (!push_tinst_level (gen_tmpl, args)) > > return result; > > tree pattern = DECL_TEMPLATE_RESULT (t); > > push_access_scope (pattern); > > diff --git a/gcc/testsuite/g++.dg/concepts/diagnostic16.C > > b/gcc/testsuite/g++.dg/concepts/diagnostic16.C > > new file mode 100644 > > index 00000000000..b8d586e9a21 > > --- /dev/null > > +++ b/gcc/testsuite/g++.dg/concepts/diagnostic16.C > > @@ -0,0 +1,15 @@ > > +// PR c++/99214 > > +// { dg-do compile { target c++20 } } > > + > > +template <class T> > > +struct A { > > + template <class U> static void f() requires ([] { return U::fail; }()); > > // { dg-error "fail" } > > + template <class U> static void f(); > > +}; > > + > > +int main() { > > + A<int>::f<char>(); > > +} > > + > > +// This matches the context line "In substitution of '... [with U = char; T > > = int]'" > > +// { dg-message "U = char; T = int" "" { target *-*-* } 0 } > > > >