On Wed, 2 Feb 2022, Jason Merrill wrote: > On 2/2/22 13:21, Patrick Palka wrote: > > On Wed, 2 Feb 2022, Patrick Palka wrote: > > > > > Here we're crashing during satisfaction of the lambda's placeholder type > > > constraints because the constraints depend on the template arguments > > > from the enclosing scope, which aren't a part of the lambda's > > > DECL_TI_ARGS. So when inside a lambda, do_auto_deduction needs to add > > > the "regenerating" template arguments to the set of outer template > > > arguments, like we already do in satisfy_declaration_constraints. > > > > > > Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for > > > trunk and perhaps 11? > > > > > > PR c++/103706 > > > > > > gcc/cp/ChangeLog: > > > > > > * constraint.cc (satisfy_declaration_constraints): Use > > > lambda_regenerating_args instead. > > > * cp-tree.h (lambda_regenerating_args): Declare. > > > * pt.cc (add_to_template_args): Handle NULL_TREE extra_args > > > gracefully. > > > (lambda_regenerating_args): Define, split out from > > > satisfy_declaration_constraints. > > > (do_auto_deduction): Use lambda_regenerating_args to obtain the > > > full set of outer template arguments when checking the > > > constraint on a placeholder type within a lambda. > > > > > > gcc/testsuite/ChangeLog: > > > > > > * g++.dg/cpp2a/concepts-lambda18.C: New test. > > > --- > > > gcc/cp/constraint.cc | 9 +---- > > > gcc/cp/cp-tree.h | 1 + > > > gcc/cp/pt.cc | 37 ++++++++++++++++--- > > > .../g++.dg/cpp2a/concepts-lambda18.C | 14 +++++++ > > > 4 files changed, 48 insertions(+), 13 deletions(-) > > > create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-lambda18.C > > > > > > diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc > > > index cc4df4216ef..c41ee02b910 100644 > > > --- a/gcc/cp/constraint.cc > > > +++ b/gcc/cp/constraint.cc > > > @@ -3148,18 +3148,13 @@ satisfy_declaration_constraints (tree t, sat_info > > > info) > > > args = add_outermost_template_args (args, inh_ctor_targs); > > > } > > > - if (regenerated_lambda_fn_p (t)) > > > + if (LAMBDA_FUNCTION_P (t)) > > > { > > > /* The TI_ARGS of a regenerated lambda contains only the innermost > > > set of template arguments. Augment this with the outer > > > template > > > arguments that were used to regenerate the lambda. */ > > > gcc_assert (!args || TMPL_ARGS_DEPTH (args) == 1); > > > - tree lambda = CLASSTYPE_LAMBDA_EXPR (DECL_CONTEXT (t)); > > > - tree outer_args = TI_ARGS (LAMBDA_EXPR_REGEN_INFO (lambda)); > > > - if (args) > > > - args = add_to_template_args (outer_args, args); > > > - else > > > - args = outer_args; > > > + args = add_to_template_args (lambda_regenerating_args (t), args); > > > } > > > /* If any arguments depend on template parameters, we can't > > > diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h > > > index b9eb71fbc3a..7a7fe5ba599 100644 > > > --- a/gcc/cp/cp-tree.h > > > +++ b/gcc/cp/cp-tree.h > > > @@ -7715,6 +7715,7 @@ extern void finish_lambda_scope > > > (void); > > > extern tree start_lambda_function (tree fn, tree > > > lambda_expr); > > > extern void finish_lambda_function (tree body); > > > extern bool regenerated_lambda_fn_p (tree); > > > +extern tree lambda_regenerating_args (tree); > > > extern tree most_general_lambda (tree); > > > extern tree finish_omp_target (location_t, tree, > > > tree, bool); > > > extern void finish_omp_target_clauses (location_t, tree, > > > tree *); > > > diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc > > > index 6e129da1d05..c919d2de68f 100644 > > > --- a/gcc/cp/pt.cc > > > +++ b/gcc/cp/pt.cc > > > @@ -573,6 +573,9 @@ add_to_template_args (tree args, tree extra_args) > > > if (args == NULL_TREE || extra_args == error_mark_node) > > > return extra_args; > > > + if (extra_args == NULL_TREE) > > > + return args; > > > + > > > > Whoops, this last-minute change to add_to_template_args turned out to > > be a bad idea as some callers apparently rely on add_to_template_args > > treating NULL_TREE extra_args as a depth 1 targ vector (whereas for > > the calls in satisfy_declaration_constraints and do_auto_deduction we > > want NULL_TREE extra_args to be treated as a depth 0 targ vector). > > > > Please consider the below patch instead, which doesn't attempt to change > > the behavior of add_to_template_args: > > > > -- >8 -- > > > > Subject: [PATCH] c++: constrained auto in lambda using outer tparms > > [PR103706] > > > > Here we're crashing during satisfaction of the lambda's placeholder type > > constraints because the constraints depend on the template arguments > > from the enclosing scope, which aren't part of the lambda's DECL_TI_ARGS. > > So when inside a lambda, do_auto_deduction needs to add its > > "regenerating" template arguments to the set of outer template > > arguments, like we already do in satisfy_declaration_constraints. > > > > PR c++/103706 > > > > gcc/cp/ChangeLog: > > > > * constraint.cc (satisfy_declaration_constraints): Use > > lambda_regenerating_args instead. > > * cp-tree.h (lambda_regenerating_args): Declare. > > * pt.cc (lambda_regenerating_args): Define, split out from > > satisfy_declaration_constraints. > > (do_auto_deduction): Use lambda_regenerating_args to obtain the > > full set of outer template arguments for satisfaction. > > > > gcc/testsuite/ChangeLog: > > > > * g++.dg/cpp2a/concepts-lambda18.C: New test. > > --- > > gcc/cp/constraint.cc | 9 ++--- > > gcc/cp/cp-tree.h | 1 + > > gcc/cp/pt.cc | 39 ++++++++++++++++--- > > .../g++.dg/cpp2a/concepts-lambda18.C | 14 +++++++ > > 4 files changed, 52 insertions(+), 11 deletions(-) > > create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-lambda18.C > > > > diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc > > index cc4df4216ef..c0ebe63a0a2 100644 > > --- a/gcc/cp/constraint.cc > > +++ b/gcc/cp/constraint.cc > > @@ -3148,18 +3148,17 @@ satisfy_declaration_constraints (tree t, sat_info > > info) > > args = add_outermost_template_args (args, inh_ctor_targs); > > } > > - if (regenerated_lambda_fn_p (t)) > > + if (LAMBDA_FUNCTION_P (t)) > > I wonder why you changed this test? OK either way. No good reason, it shouldn't make a functional difference so I'll drop this no-op change. > > > { > > /* The TI_ARGS of a regenerated lambda contains only the innermost > > set of template arguments. Augment this with the outer template > > arguments that were used to regenerate the lambda. */ > > gcc_assert (!args || TMPL_ARGS_DEPTH (args) == 1); > > - tree lambda = CLASSTYPE_LAMBDA_EXPR (DECL_CONTEXT (t)); > > - tree outer_args = TI_ARGS (LAMBDA_EXPR_REGEN_INFO (lambda)); > > + tree regen_args = lambda_regenerating_args (t); > > if (args) > > - args = add_to_template_args (outer_args, args); > > + args = add_to_template_args (regen_args, args); > > else > > - args = outer_args; > > + args = regen_args; > > } > > /* If any arguments depend on template parameters, we can't > > diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h > > index b9eb71fbc3a..7a7fe5ba599 100644 > > --- a/gcc/cp/cp-tree.h > > +++ b/gcc/cp/cp-tree.h > > @@ -7715,6 +7715,7 @@ extern void finish_lambda_scope > > (void); > > extern tree start_lambda_function (tree fn, tree lambda_expr); > > extern void finish_lambda_function (tree body); > > extern bool regenerated_lambda_fn_p (tree); > > +extern tree lambda_regenerating_args (tree); > > extern tree most_general_lambda (tree); > > extern tree finish_omp_target (location_t, tree, > > tree, bool); > > extern void finish_omp_target_clauses (location_t, tree, > > tree *); > > diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc > > index 6e129da1d05..46754c611e7 100644 > > --- a/gcc/cp/pt.cc > > +++ b/gcc/cp/pt.cc > > @@ -14442,6 +14442,21 @@ most_general_lambda (tree t) > > return t; > > } > > +/* Return the set of template arguments used to regenerate the lambda T > > + from its most general lambda. */ > > + > > +tree > > +lambda_regenerating_args (tree t) > > +{ > > + if (LAMBDA_FUNCTION_P (t)) > > + t = CLASSTYPE_LAMBDA_EXPR (DECL_CONTEXT (t)); > > + gcc_assert (TREE_CODE (t) == LAMBDA_EXPR); > > + if (tree ti = LAMBDA_EXPR_REGEN_INFO (t)) > > + return TI_ARGS (ti); > > + else > > + return NULL_TREE; > > +} > > + > > /* We're instantiating a variable from template function TCTX. Return the > > corresponding current enclosing scope. We can match them up using > > DECL_SOURCE_LOCATION because lambdas only ever have one source > > location, and > > @@ -30100,12 +30115,24 @@ do_auto_deduction (tree type, tree init, tree > > auto_node, > > return type; > > } > > - if ((context == adc_return_type > > - || context == adc_variable_type > > - || context == adc_decomp_type) > > - && current_function_decl > > - && DECL_TEMPLATE_INFO (current_function_decl)) > > - outer_targs = DECL_TI_ARGS (current_function_decl); > > + if (context == adc_return_type > > + || context == adc_variable_type > > + || context == adc_decomp_type) > > + if (tree fn = current_function_decl) > > + if (DECL_TEMPLATE_INFO (fn) || LAMBDA_FUNCTION_P (fn)) > > + { > > + outer_targs > > + = DECL_TEMPLATE_INFO (fn) ? DECL_TI_ARGS (fn) : NULL_TREE; > > + if (LAMBDA_FUNCTION_P (fn)) > > + { > > + /* As in satisfy_declaration_constraints. */ > > + tree regen_args = lambda_regenerating_args (fn); > > + if (outer_targs) > > + outer_targs = add_to_template_args (regen_args, > > outer_targs); > > + else > > + outer_targs = regen_args; > > + } > > + } > > tree full_targs = add_to_template_args (outer_targs, targs); > > diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-lambda18.C > > b/gcc/testsuite/g++.dg/cpp2a/concepts-lambda18.C > > new file mode 100644 > > index 00000000000..f1058daf317 > > --- /dev/null > > +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-lambda18.C > > @@ -0,0 +1,14 @@ > > +// PR c++/103706 > > +// { dg-do compile { target c++20 } } > > + > > +template<class T, class U> concept C = __is_same(U, int); > > + > > +template<class T> void f() { > > + []() -> C<T> auto { > > + C<T> auto x = T(); // { dg-error "constraints" } > > + return T(); // { dg-error "constraints" } > > + }(); > > +} > > + > > +template void f<int>(); // { dg-bogus "" } > > +template void f<char>(); // { dg-message "required from here" } > >
Re: [PATCH] c++: constrained auto in lambda using outer tparms [PR103706]
Patrick Palka via Gcc-patches Thu, 03 Feb 2022 09:17:29 -0800
- [PATCH] c++: constrained auto in lambda usin... Patrick Palka via Gcc-patches
- Re: [PATCH] c++: constrained auto in la... Patrick Palka via Gcc-patches
- Re: [PATCH] c++: constrained auto i... Jason Merrill via Gcc-patches
- Re: [PATCH] c++: constrained au... Patrick Palka via Gcc-patches