[PATCH] c++: dependent constraint on placeholder return type [PR96443]

Patrick Palka ppalka@redhat.com
Thu Aug 6 13:47:49 GMT 2020


On Wed, 5 Aug 2020, Jason Merrill wrote:

> On 8/4/20 8:00 PM, Patrick Palka wrote:
> > On Tue, 4 Aug 2020, Patrick Palka wrote:
> > 
> > > In the testcase below, we never substitute function-template arguments
> > > into f15<int>'s placeholder-return-type constraint, which leads to us
> > > incorrectly rejecting this instantiation in do_auto_deduction due to
> > > satisfaction failure (of the constraint SameAs<int, decltype(x)>).
> > > 
> > > The fact that we incorrectly reject this testcase is masked by the
> > > other instantiation f15<char>, which we correctly reject and diagnose
> > > (by accident).
> > > 
> > > A good place to do this missing substitution seems to be during
> > > TEMPLATE_TYPE_PARM level lowering.  So this patch adds a call to
> > > tsubst_constraint there, and also adds dg-bogus directives to this
> > > testcase wherever we expect instantiation to succeed. (So without the
> > > substitution fix, this last dg-bogus would FAIL).
> 
> > > Successfully tested on x86_64-pc-linux-gnu, and also on the cmcstl2 and
> > > range-v3 projects.  Does this look OK to commit?
> > > 
> > > gcc/cp/ChangeLog:
> > > 
> > > 	PR c++/96443
> > > 	* pt.c (tsubst) <case TEMPLATE_TYPE_PARM>: Substitute into
> > > 	the constraints on a placeholder type when its level.
> > > 
> > > gcc/testsuite/ChangeLog:
> > > 
> > > 	PR c++/96443
> > > 	* g++.dg/cpp2a/concepts-ts1.C: Add dg-bogus wherever we expect
> > > 	instantiation to succeed.
> > 
> > Looking back at this patch with fresh eyes, I realized that the commit
> > message is not the best.  I rewrote the commit message to hopefully be
> > more coherent below:
> > 
> > -- >8 --
> > 
> > Subject: [PATCH] c++: dependent constraint on placeholder return type
> >   [PR96443]
> > 
> > In the testcase concepts-ts1.C, we're incorrectly rejecting the call to
> > 'f15(0)' due to satisfaction failure of the function's
> > placeholder-return-type constraint.
> > 
> > The testcase doesn't spot this rejection because the error we emit for
> > the constraint failure points to f15's return statement instead of the
> > call site, and we already have a dg-error at the return statement to
> > verify the (correct) rejection of the call f15('a').  So in order to
> > verify that we indeed accept the call 'f15(0)', we need to add a
> > dg-bogus directive at the call site to look for the "required from here"
> > diagnostic line that generally accompanies an instantiation failure.
> > 
> > As for why satisfaction failure occurs, it turns out that we never
> > substitute the template arguments of a function template specialization
> > in to its placeholder-return-type constraint.  So in this case during
> > do_auto_deduction, we end up checking satisfaction of the still-dependent
> > constraint SameAs<int, decltype(x)> from do_auto_deduction, which fails
> > because it's dependent.
> > 
> > A good place to do this missing substitution seems to be during
> > TEMPLATE_TYPE_PARM level lowering; so this patch adds a call to
> > tsubst_constraint there.
> 
> Doing substitution seems like the wrong approach here; requirements should
> never be substituted except as part of satisfaction calculation (or, rarely,
> for declaration matching).  If we aren't communicating all the necessary
> template arguments to the later satisfaction, that's what we need to fix.

Ah okay, that makes sense.

It also looks like the question of perform a single full substitution
(during auto deduction) vs two substitutions may also be a correctness
issue in light of SFINAE.  Consider the following testcase:

    template<typename T, typename U>
    concept C = true;

    auto f(auto x) -> C<decltype(x.fail())> auto { return 0; }
    auto f(auto x, ...) { return 1; }

    int a = f(0);

If we do a single substitution, then the substitution failure is a hard
error and we'll reject this testcase.  If we do two substitutions, then
it's a SFINAE error and we select the second overload.  Would we be
correct to issue a hard error here?

> 
> > Successfully tested on x86_64-pc-linux-gnu, and also on the cmcstl2 and
> > range-v3 projects.  Does this look OK to commit?
> > 
> > gcc/cp/ChangeLog:
> > 
> > 	PR c++/96443
> > 	* pt.c (tsubst) <case TEMPLATE_TYPE_PARM>: Substitute into
> > 	the constraints on a placeholder type when reducing its level.
> > 
> > gcc/testsuite/ChangeLog:
> > 
> > 	PR c++/96443
> > 	* g++.dg/cpp2a/concepts-ts1.C: Add dg-bogus to the call to f15
> > 	that we expect to accept.
> > ---
> >   gcc/cp/pt.c                               | 7 ++++---
> >   gcc/testsuite/g++.dg/cpp2a/concepts-ts1.C | 2 +-
> >   2 files changed, 5 insertions(+), 4 deletions(-)
> > 
> > diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
> > index e7496002c1c..9f3426f8249 100644
> > --- a/gcc/cp/pt.c
> > +++ b/gcc/cp/pt.c
> > @@ -15524,10 +15524,11 @@ tsubst (tree t, tree args, tsubst_flags_t
> > complain, tree in_decl)
> >                     if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
> >   		  {
> > -		    /* Propagate constraints on placeholders since they are
> > -		       only instantiated during satisfaction.  */
> > +		    /* Substitute constraints on placeholders when reducing
> > +		       their level.  */
> >   		    if (tree constr = PLACEHOLDER_TYPE_CONSTRAINTS (t))
> > -		      PLACEHOLDER_TYPE_CONSTRAINTS (r) = constr;
> > +		      PLACEHOLDER_TYPE_CONSTRAINTS (r)
> > +			= tsubst_constraint (constr, args, complain, in_decl);
> >   		    else if (tree pl = CLASS_PLACEHOLDER_TEMPLATE (t))
> >   		      {
> >   			pl = tsubst_copy (pl, args, complain, in_decl);
> > diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-ts1.C
> > b/gcc/testsuite/g++.dg/cpp2a/concepts-ts1.C
> > index 1cefe3b243f..a116cac4ea4 100644
> > --- a/gcc/testsuite/g++.dg/cpp2a/concepts-ts1.C
> > +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-ts1.C
> > @@ -40,7 +40,7 @@ void driver()
> >     f3('a'); // { dg-error "" }
> >     f4(0, 0);
> >     f4(0, 'a'); // { dg-error "" }
> > -  f15(0);
> > +  f15(0); // { dg-bogus "" }
> >     f15('a'); // { dg-message "" }
> >   }
> >   
> 
> 



More information about the Gcc-patches mailing list