public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
From: Jason Merrill <jason@gcc.gnu.org>
To: gcc-cvs@gcc.gnu.org
Subject: [gcc r13-4712] c++: fix initializer_list transformation [PR108071]
Date: Thu, 15 Dec 2022 05:26:19 +0000 (GMT)	[thread overview]
Message-ID: <20221215052619.D85523883F2F@sourceware.org> (raw)

https://gcc.gnu.org/g:4ef521bbc63f8a3883d507a8b6c1f95f442df3fe

commit r13-4712-g4ef521bbc63f8a3883d507a8b6c1f95f442df3fe
Author: Jason Merrill <jason@redhat.com>
Date:   Wed Dec 14 17:42:52 2022 -0500

    c++: fix initializer_list transformation [PR108071]
    
    In these testcases, we weren't adequately verifying that constructing the
    element type from an array element would have the same effect as
    constructing it from one of the initializers.
    
            PR c++/108071
            PR c++/105838
    
    gcc/cp/ChangeLog:
    
            * call.cc (struct conversion_obstack_sentinel): New.
            (maybe_init_list_as_array): Compare conversion of dummy argument.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/cpp0x/initlist131.C: New test.
            * g++.dg/cpp0x/initlist132.C: New test.
            * g++.dg/cpp0x/initlist133.C: New test.

Diff:
---
 gcc/cp/call.cc                           | 35 ++++++++++++++++++++++++++------
 gcc/testsuite/g++.dg/cpp0x/initlist131.C | 14 +++++++++++++
 gcc/testsuite/g++.dg/cpp0x/initlist132.C | 30 +++++++++++++++++++++++++++
 gcc/testsuite/g++.dg/cpp0x/initlist133.C | 25 +++++++++++++++++++++++
 4 files changed, 98 insertions(+), 6 deletions(-)

diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index 33b5e7f87f5..c25df174280 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -622,6 +622,15 @@ conversion_obstack_alloc (size_t n)
   return p;
 }
 
+/* RAII class to discard anything added to conversion_obstack.  */
+
+struct conversion_obstack_sentinel
+{
+  void *p;
+  conversion_obstack_sentinel (): p (conversion_obstack_alloc (0)) {}
+  ~conversion_obstack_sentinel () { obstack_free (&conversion_obstack, p); }
+};
+
 /* Allocate rejection reasons.  */
 
 static struct rejection_reason *
@@ -4219,18 +4228,32 @@ static tree
 maybe_init_list_as_array (tree elttype, tree init)
 {
   /* Only do this if the array can go in rodata but not once converted.  */
-  if (!CLASS_TYPE_P (elttype))
+  if (!TYPE_NON_AGGREGATE_CLASS (elttype))
     return NULL_TREE;
   tree init_elttype = braced_init_element_type (init);
   if (!init_elttype || !SCALAR_TYPE_P (init_elttype) || !TREE_CONSTANT (init))
     return NULL_TREE;
 
+  /* Check with a stub expression to weed out special cases, and check whether
+     we call the same function for direct-init as copy-list-init.  */
+  conversion_obstack_sentinel cos;
+  tree arg = build_stub_object (init_elttype);
+  conversion *c = implicit_conversion (elttype, init_elttype, arg, false,
+				       LOOKUP_NORMAL, tf_none);
+  if (c && c->kind == ck_rvalue)
+    c = next_conversion (c);
+  if (!c || c->kind != ck_user)
+    return NULL_TREE;
+
   tree first = CONSTRUCTOR_ELT (init, 0)->value;
-  if (TREE_CODE (init_elttype) == INTEGER_TYPE && null_ptr_cst_p (first))
-    /* Avoid confusion from treating 0 as a null pointer constant.  */
-    first = build1 (UNARY_PLUS_EXPR, init_elttype, first);
-  first = (perform_implicit_conversion_flags
-	   (elttype, first, tf_none, LOOKUP_IMPLICIT|LOOKUP_NO_NARROWING));
+  conversion *fc = implicit_conversion (elttype, init_elttype, first, false,
+					LOOKUP_IMPLICIT|LOOKUP_NO_NARROWING,
+					tf_none);
+  if (fc && fc->kind == ck_rvalue)
+    fc = next_conversion (fc);
+  if (!fc || fc->kind != ck_user || fc->cand->fn != c->cand->fn)
+    return NULL_TREE;
+  first = convert_like (fc, first, tf_none);
   if (first == error_mark_node)
     /* Let the normal code give the error.  */
     return NULL_TREE;
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist131.C b/gcc/testsuite/g++.dg/cpp0x/initlist131.C
new file mode 100644
index 00000000000..a714215219a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist131.C
@@ -0,0 +1,14 @@
+// PR c++/108071
+// { dg-do compile { target c++11 } }
+
+#include <initializer_list>
+
+struct OptSpecifier {
+  explicit OptSpecifier(bool);
+  OptSpecifier(unsigned);
+};
+void f (std::initializer_list<OptSpecifier>);
+int main()
+{
+  f({1});
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist132.C b/gcc/testsuite/g++.dg/cpp0x/initlist132.C
new file mode 100644
index 00000000000..34e0307cbbc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist132.C
@@ -0,0 +1,30 @@
+// PR c++/108071
+// { dg-do compile { target c++11 } }
+
+#include <initializer_list>
+
+template< typename T1, typename T2 = void >
+struct ConstCharArrayDetector
+{
+    static const bool ok = false;
+};
+template< std::size_t N, typename T >
+struct ConstCharArrayDetector< const char[ N ], T >
+{
+    typedef T Type;
+};
+
+struct Dummy { };
+
+struct OUString
+{
+  template<typename T>
+    OUString(T&, typename ConstCharArrayDetector<T, Dummy>::Type = Dummy())
+    { }
+};
+
+struct Sequence {
+  Sequence(std::initializer_list<OUString>);
+};
+
+Sequence s = {""};
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist133.C b/gcc/testsuite/g++.dg/cpp0x/initlist133.C
new file mode 100644
index 00000000000..08da5bebd0b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist133.C
@@ -0,0 +1,25 @@
+// PR c++/108071
+// { dg-do compile { target c++14 } }
+
+#include <initializer_list>
+
+template<bool> struct enable_if { };
+template<> struct enable_if<true> { using type = void; };
+
+template<typename T> constexpr bool is_array_v = false;
+template<typename T, std::size_t N> constexpr bool is_array_v<T[N]> = true;
+
+struct OUString
+{
+  template<typename T, typename = typename enable_if<is_array_v<T>>::type>
+  OUString(T&) { }
+};
+
+struct vector
+{
+  vector(std::initializer_list<OUString>) { }
+  template<typename Iter>
+  vector(Iter i, Iter j) { if (i != j) OUString(*i); }
+};
+
+vector v = { "" };

                 reply	other threads:[~2022-12-15  5:26 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

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=20221215052619.D85523883F2F@sourceware.org \
    --to=jason@gcc.gnu.org \
    --cc=gcc-cvs@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).