From: Jason Merrill <jason@redhat.com>
To: Patrick Palka <ppalka@redhat.com>, gcc-patches@gcc.gnu.org
Subject: Re: [PATCH] c++: detecting copy-init context during CTAD [PR102137]
Date: Fri, 4 Mar 2022 17:34:30 -0500 [thread overview]
Message-ID: <e7aa6013-6337-d30a-ac45-4852610e1449@redhat.com> (raw)
In-Reply-To: <20220304182436.122498-1-ppalka@redhat.com>
On 3/4/22 14:24, Patrick Palka wrote:
> Here we're failing to communicate to cp_finish_decl from tsubst_expr
> that we're in a copy-initialization context (via the LOOKUP_ONLYCONVERTING
> flag), which causes do_class_deduction to always consider explicit
> deduction guides when performing CTAD for a templated variable initializer.
>
> We could fix this by passing LOOKUP_ONLYCONVERTING appropriately when
> calling cp_finish_decl from tsubst_expr, but it seems do_class_deduction
> can determine if we're in a copy-init context by simply inspecting the
> initializer, and thus render its flags parameter unnecessary, which is
> what this patch implements. (If we were to fix this in tsubst_expr
> instead, I think we'd have to inspect the initializer in the same way
> in order to detect a copy-init context?)
Hmm, does this affect conversions as well?
Looks like it does:
struct A
{
explicit operator int();
};
template <class T> void f()
{
T t = A();
}
int main()
{
f<int>(); // wrongly accepted
}
The reverse, initializing via an explicit constructor, is caught by code
in build_aggr_init much like the code your patch adds to
do_auto_deduction; perhaps we should move/copy that code to cp_finish_decl?
> Bootstrapped and regtestd on x86_64-pc-linux-gnu, does this look OK for
> trunk?
>
> PR c++/102137
>
> gcc/cp/ChangeLog:
>
> * cp-tree.h (do_auto_deduction): Remove flags parameter.
> * decl.cc (cp_finish_decl): Adjust call to do_auto_deduction.
> * pt.cc (convert_template_argument): Likewise.
> (do_class_deduction): Remove flags parameter and instead
> determine if we're in a copy-init context by inspecting the
> initializer.
> (do_auto_deduction): Adjust call to do_class_deduction.
>
> gcc/testsuite/ChangeLog:
>
> * g++.dg/cpp1z/class-deduction108.C: New test.
> ---
> gcc/cp/cp-tree.h | 3 +-
> gcc/cp/decl.cc | 2 +-
> gcc/cp/pt.cc | 23 +++++++------
> .../g++.dg/cpp1z/class-deduction108.C | 32 +++++++++++++++++++
> 4 files changed, 48 insertions(+), 12 deletions(-)
> create mode 100644 gcc/testsuite/g++.dg/cpp1z/class-deduction108.C
>
> diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
> index ac723901098..c2ef6544389 100644
> --- a/gcc/cp/cp-tree.h
> +++ b/gcc/cp/cp-tree.h
> @@ -7279,8 +7279,7 @@ extern tree do_auto_deduction (tree, tree, tree,
> = tf_warning_or_error,
> auto_deduction_context
> = adc_unspecified,
> - tree = NULL_TREE,
> - 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/decl.cc b/gcc/cp/decl.cc
> index 199ac768d43..152f657e9f2 100644
> --- a/gcc/cp/decl.cc
> +++ b/gcc/cp/decl.cc
> @@ -8039,7 +8039,7 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
> outer_targs = DECL_TI_ARGS (decl);
> type = TREE_TYPE (decl) = do_auto_deduction (type, d_init, auto_node,
> tf_warning_or_error, adc,
> - outer_targs, flags);
> + outer_targs);
> if (type == error_mark_node)
> return;
> if (TREE_CODE (type) == FUNCTION_TYPE)
> diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
> index d94d4538faa..66fc8cacdc6 100644
> --- a/gcc/cp/pt.cc
> +++ b/gcc/cp/pt.cc
> @@ -8567,8 +8567,7 @@ convert_template_argument (tree parm,
> can happen in the context of -fnew-ttp-matching. */;
> else if (tree a = type_uses_auto (t))
> {
> - t = do_auto_deduction (t, arg, a, complain, adc_unify, args,
> - LOOKUP_IMPLICIT);
> + t = do_auto_deduction (t, arg, a, complain, adc_unify, args);
> if (t == error_mark_node)
> return error_mark_node;
> }
> @@ -29832,8 +29831,7 @@ ctad_template_p (tree tmpl)
> type. */
>
> static tree
> -do_class_deduction (tree ptype, tree tmpl, tree init,
> - int flags, tsubst_flags_t complain)
> +do_class_deduction (tree ptype, tree tmpl, tree init, tsubst_flags_t complain)
> {
> /* We should have handled this in the caller. */
> if (DECL_TEMPLATE_TEMPLATE_PARM_P (tmpl))
> @@ -29881,6 +29879,13 @@ do_class_deduction (tree ptype, tree tmpl, tree init,
> if (type_dependent_expression_p (init))
> return ptype;
>
> + bool copy_init_p = true;
> + if (!init
> + || TREE_CODE (init) == TREE_LIST
> + || (BRACE_ENCLOSED_INITIALIZER_P (init)
> + && CONSTRUCTOR_IS_DIRECT_INIT (init)))
> + copy_init_p = false;
> +
> tree type = TREE_TYPE (tmpl);
>
> bool try_list_ctor = false;
> @@ -29929,7 +29934,7 @@ do_class_deduction (tree ptype, tree tmpl, tree init,
> /* Prune explicit deduction guides in copy-initialization context (but
> not copy-list-initialization). */
> bool elided = false;
> - if (!list_init_p && (flags & LOOKUP_ONLYCONVERTING))
> + if (!list_init_p && copy_init_p)
> {
> for (lkp_iterator iter (cands); !elided && iter; ++iter)
> if (DECL_NONCONVERTING_P (STRIP_TEMPLATE (*iter)))
> @@ -30007,7 +30012,7 @@ do_class_deduction (tree ptype, tree tmpl, tree init,
> }
> /* [over.match.list]/1: In copy-list-initialization, if an explicit
> constructor is chosen, the initialization is ill-formed. */
> - else if (flags & LOOKUP_ONLYCONVERTING)
> + else if (copy_init_p)
> {
> if (DECL_NONCONVERTING_P (fndecl))
> {
> @@ -30045,7 +30050,7 @@ do_class_deduction (tree ptype, tree tmpl, tree init,
> /* Replace occurrences of 'auto' in TYPE with the appropriate type deduced
> from INIT. AUTO_NODE is the TEMPLATE_TYPE_PARM used for 'auto' in TYPE.
> The CONTEXT determines the context in which auto deduction is performed
> - and is used to control error diagnostics. FLAGS are the LOOKUP_* flags.
> + and is used to control error diagnostics.
>
> OUTER_TARGS is used during template argument deduction (context == adc_unify)
> to properly substitute the result. It's also used in the adc_unify and
> @@ -30058,7 +30063,7 @@ do_class_deduction (tree ptype, tree tmpl, tree init,
> tree
> do_auto_deduction (tree type, tree init, tree auto_node,
> tsubst_flags_t complain, auto_deduction_context context,
> - tree outer_targs, int flags)
> + tree outer_targs)
> {
> if (init == error_mark_node)
> return error_mark_node;
> @@ -30079,7 +30084,7 @@ do_auto_deduction (tree type, tree init, tree auto_node,
>
> if (tree tmpl = CLASS_PLACEHOLDER_TEMPLATE (auto_node))
> /* C++17 class template argument deduction. */
> - return do_class_deduction (type, tmpl, init, flags, complain);
> + return do_class_deduction (type, tmpl, init, complain);
>
> if (init == NULL_TREE || TREE_TYPE (init) == NULL_TREE)
> /* Nothing we can do with this, even in deduction context. */
> diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction108.C b/gcc/testsuite/g++.dg/cpp1z/class-deduction108.C
> new file mode 100644
> index 00000000000..f76671c287a
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction108.C
> @@ -0,0 +1,32 @@
> +// PR c++/102137
> +// { dg-do compile { target c++17 } }
> +
> +template<class T>
> +struct A {
> + A();
> + A(int);
> +};
> +
> +explicit A(int) -> A<int>;
> +explicit A() -> A<int>;
> +
> +template<template<class> class T>
> +void f() {
> + T x1 = 0; // { dg-error "deduction|no match" }
> + T x2 = {0}; // { dg-error "explicit deduction guide" }
> + T x3(0);
> + T x4{0};
> + T x5;
> +}
> +
> +template<class T>
> +void g(T t) {
> + A a1 = t; // { dg-error "deduction|no match" }
> + A a2 = {t}; // { dg-error "explicit deduction guide" }
> + A a3(t);
> + A a4{t};
> + A a5;
> +}
> +
> +template void f<A>();
> +template void g(int);
next prev parent reply other threads:[~2022-03-04 22:34 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-03-04 18:24 Patrick Palka
2022-03-04 22:34 ` Jason Merrill [this message]
2022-03-07 14:47 ` Patrick Palka
2022-03-07 19:14 ` Jason Merrill
2022-03-08 15:36 ` Patrick Palka
2022-03-08 16:24 ` Jason Merrill
2022-03-08 18:38 ` Patrick Palka
2022-03-08 20:07 ` Jason Merrill
2022-03-08 21:17 ` Patrick Palka
2022-03-08 22:26 ` Jason Merrill
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=e7aa6013-6337-d30a-ac45-4852610e1449@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).