public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Patrick Palka <ppalka@redhat.com>
To: gcc-patches@gcc.gnu.org
Subject: [PATCH] c++: detecting copy-init context during CTAD [PR102137]
Date: Fri,  4 Mar 2022 13:24:36 -0500	[thread overview]
Message-ID: <20220304182436.122498-1-ppalka@redhat.com> (raw)

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?)

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);
-- 
2.35.1.354.g715d08a9e5


             reply	other threads:[~2022-03-04 18:25 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-03-04 18:24 Patrick Palka [this message]
2022-03-04 22:34 ` Jason Merrill
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=20220304182436.122498-1-ppalka@redhat.com \
    --to=ppalka@redhat.com \
    --cc=gcc-patches@gcc.gnu.org \
    /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).