public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Jason Merrill <jason@redhat.com>
To: Patrick Palka <ppalka@redhat.com>, gcc-patches@gcc.gnu.org
Subject: Re: [PATCH] c++: NTTP constraint depending on outer args [PR109160]
Date: Wed, 29 Mar 2023 16:28:00 -0400	[thread overview]
Message-ID: <a07656e7-2c98-0162-5db4-ccfc55c17c71@redhat.com> (raw)
In-Reply-To: <20230317152629.3944138-1-ppalka@redhat.com>

On 3/17/23 11:26, Patrick Palka wrote:
> Here we're crashing during satisfaction for the NTTP 'C<B> auto' from
> do_auto_deduction ultimately because convert_template_argument / unify
> don't pass all outer template arguments to do_auto_deduction, and during
> satisfaction we need to know all arguments.  While these callers do
> pass some outer arguments, they are only sufficient to properly
> substitute the 'auto' and are not necessarily the complete set.
> 
> Fortunately it seems it's possible to obtain the full set of outer
> arguments from these callers via convert_template_argument's IN_DECL
> parameter and unify's TPARMS parameter.  So this patch adds a TMPL
> parameter to do_auto_deduction, used only during adc_unify deduction,
> which contains the (partially instantiated) template corresponding to
> this auto and from which we can obtain all outer template arguments for
> satisfaction.
> 
> This patch also adjusts the IN_DECL argument passed to
> coerce_template_parms from tsubst_decl so that we could in turn safely
> assume convert_template_argument's IN_DECL is always a TEMPLATE_DECL,
> and thus could pass it as-is to do_auto_deduction.  (tsubst_decl seems
> to be the only caller that passes a non-empty non-template IN_DECL to
> coerce_template_parms.)
> 
> Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
> trunk/12?
> 
> 	PR c++/109160
> 
> gcc/cp/ChangeLog:
> 
> 	* cp-tree.h (do_auto_deduction): Add defaulted TMPL parameter.
> 	* pt.cc (convert_template_argument): Pass IN_DECL as TMPL to
> 	do_auto_deduction.
> 	(tsubst_decl) <case VAR_/TYPE_DECL>: Pass TMPL instead of T as
> 	IN_DECL to coerce_template_parms.
> 	(unify) <case TEMPLATE_PARM_INDEX>: Pass the corresponding
> 	template as TMPL to do_auto_deduction.
> 	(do_auto_deduction): Document default arguments.  Use TMPL
> 	to obtain a full set of template arguments for satisfaction
> 	in the adc_unify case.
> 
> gcc/testsuite/ChangeLog:
> 
> 	* g++.dg/cpp2a/concepts-placeholder12.C: New test.
> ---
>   gcc/cp/cp-tree.h                              |  3 +-
>   gcc/cp/pt.cc                                  | 30 ++++++++++++++-----
>   .../g++.dg/cpp2a/concepts-placeholder12.C     | 29 ++++++++++++++++++
>   3 files changed, 53 insertions(+), 9 deletions(-)
>   create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-placeholder12.C
> 
> diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
> index dfc1c845768..e7190c5cc62 100644
> --- a/gcc/cp/cp-tree.h
> +++ b/gcc/cp/cp-tree.h
> @@ -7324,7 +7324,8 @@ extern tree do_auto_deduction                   (tree, tree, tree,
>                                                    auto_deduction_context
>   						 = adc_unspecified,
>   						 tree = NULL_TREE,
> -						 int = LOOKUP_NORMAL);
> +						 int = LOOKUP_NORMAL,
> +						 tree = NULL_TREE);
>   extern tree type_uses_auto			(tree);
>   extern tree type_uses_auto_or_concept		(tree);
>   extern void append_type_to_template_for_access_check (tree, tree, tree,
> diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
> index ddbd73371b9..6400b686a58 100644
> --- a/gcc/cp/pt.cc
> +++ b/gcc/cp/pt.cc
> @@ -8638,7 +8638,7 @@ convert_template_argument (tree parm,
>         else if (tree a = type_uses_auto (t))
>   	{
>   	  t = do_auto_deduction (t, arg, a, complain, adc_unify, args,
> -				 LOOKUP_IMPLICIT);
> +				 LOOKUP_IMPLICIT, in_decl);
>   	  if (t == error_mark_node)
>   	    return error_mark_node;
>   	}
> @@ -15243,7 +15243,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
>   		     the template.  */
>   		  argvec = (coerce_template_parms
>   			    (DECL_TEMPLATE_PARMS (gen_tmpl),
> -			     argvec, t, complain));
> +			     argvec, tmpl, complain));
>   		if (argvec == error_mark_node)
>   		  RETURN (error_mark_node);
>   		hash = spec_hasher::hash (gen_tmpl, argvec);
> @@ -24655,7 +24655,9 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict,
>   	  if (tree a = type_uses_auto (tparm))
>   	    {
>   	      tparm = do_auto_deduction (tparm, arg, a,
> -					 complain, adc_unify, targs);
> +					 complain, adc_unify, targs,
> +					 LOOKUP_NORMAL,
> +					 TPARMS_PRIMARY_TEMPLATE (tparms)); >   	      if (tparm == error_mark_node)
>   		return 1;
>   	    }
> @@ -30643,13 +30645,20 @@ unparenthesized_id_or_class_member_access_p (tree init)
>      adc_requirement contexts to communicate the necessary template arguments
>      to satisfaction.  OUTER_TARGS is ignored in other contexts.
>   
> -   For partial-concept-ids, extra args may be appended to the list of deduced
> -   template arguments prior to determining constraint satisfaction.  */
> +   Additionally for adc_unify contexts TMPL is the template for which this
> +   auto is a template parameter type.
> +
> +   For partial-concept-ids, extra args from OUTER_TARGS, TMPL and the current
> +   scope may be appended to the list of deduced template arguments prior to
> +   determining constraint satisfaction as appropriate.  */
>   
>   tree
>   do_auto_deduction (tree type, tree init, tree auto_node,
> -                   tsubst_flags_t complain, auto_deduction_context context,
> -		   tree outer_targs, int flags)
> +		   tsubst_flags_t complain /* = tf_warning_or_error */,
> +		   auto_deduction_context context /* = adc_unspecified */,
> +		   tree outer_targs /* = NULL_TREE */,
> +		   int flags /* = LOOKUP_NORMAL */,
> +		   tree tmpl /* = NULL_TREE */)
>   {
>     if (init == error_mark_node)
>       return error_mark_node;
> @@ -30839,7 +30848,12 @@ do_auto_deduction (tree type, tree init, tree auto_node,
>   		}
>   	    }
>   
> -      tree full_targs = add_to_template_args (outer_targs, targs);
> +      tree full_targs = outer_targs;
> +
> +      if (context == adc_unify)
> +	full_targs = add_outermost_template_args (tmpl, full_targs);

I recently noticed that sometimes TPARMS_PRIMARY_TEMPLATE isn't set 
properly for partially instantiated template template parameters, so 
let's make this more robust by only doing this if tmpl is non-null, 
maybe with a checking_assert that it is.  OK with that change.

> +      full_targs = add_to_template_args (full_targs, targs);
>   
>         /* HACK: Compensate for callers not always communicating all levels of
>   	 outer template arguments by filling in the outermost missing levels
> diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder12.C b/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder12.C
> new file mode 100644
> index 00000000000..3d4d138720e
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder12.C
> @@ -0,0 +1,29 @@
> +// PR c++/109160
> +// { dg-do compile { target c++20 } }
> +
> +template<class T, bool B>
> +concept C = B;
> +
> +template<int> struct X { };
> +
> +template<bool B>
> +struct A {
> +  template<C<B> auto V> static void f();
> +  template<C<B> auto V> static void g(X<V>);
> +  template<C<B> auto V> static inline int value = V;
> +  template<C<B> auto V> struct D { };
> +};
> +
> +int main() {
> +  A<true>::f<0>();
> +  A<false>::f<0>(); // { dg-error "no match|constraints" }
> +
> +  A<true>::g(X<0>{});
> +  A<false>::g(X<0>{}); // { dg-error "no match|constraints" }
> +
> +  bool v1 = A<true>::value<0>;
> +  bool v2 = A<false>::value<0>;  // { dg-error "constraints" }
> +
> +  A<true>::D<0> d1;
> +  A<false>::D<0> d2; // { dg-error "constraints" }
> +}


  parent reply	other threads:[~2023-03-29 20:28 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-03-17 15:26 Patrick Palka
2023-03-17 15:44 ` Patrick Palka
2023-03-27 17:54 ` Patrick Palka
2023-03-29 20:28 ` Jason Merrill [this message]
2023-04-01 16:04   ` Patrick Palka

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=a07656e7-2c98-0162-5db4-ccfc55c17c71@redhat.com \
    --to=jason@redhat.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=ppalka@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).