public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc(refs/users/marxin/heads/PR94314-fix-new-delete-pair-deletion-part-3)] c++: Fix wrong paren-init of aggregates interference [PR93790]
@ 2020-04-14 6:35 Martin Liska
0 siblings, 0 replies; only message in thread
From: Martin Liska @ 2020-04-14 6:35 UTC (permalink / raw)
To: gcc-cvs
https://gcc.gnu.org/g:830c572428758f134bd001e699a08e622e2452c3
commit 830c572428758f134bd001e699a08e622e2452c3
Author: Marek Polacek <polacek@redhat.com>
Date: Wed Apr 8 17:03:53 2020 -0400
c++: Fix wrong paren-init of aggregates interference [PR93790]
This PR points out that we are rejecting valid code in C++20. The
problem is that we were surreptitiously transforming
T& t(e)
into
T& t{e}
which is wrong, because the type of e had a conversion function to T,
while aggregate initialization of t from e doesn't work. Therefore, I
was violating a design principle of P0960, which says that any existing
meaning of A(b) should not change. So I think we should only attempt to
aggregate-initialize if the original expression was ill-formed.
Another design principle is that () should work where {} works, so this:
struct S { int i; };
const S& s(1);
has to keep working. Thus the special handling for paren-lists with one
element. (A paren-list with more than one element would give you "error:
expression list treated as compound expression in initializer" C++17.)
PR c++/93790
* call.c (initialize_reference): If the reference binding failed, maybe
try initializing from { }.
* decl.c (grok_reference_init): For T& t(e), set
LOOKUP_AGGREGATE_PAREN_INIT but don't build up a constructor yet.
* g++.dg/cpp2a/paren-init23.C: New test.
* g++.dg/init/aggr14.C: New test.
Diff:
---
gcc/cp/ChangeLog | 8 ++++++++
gcc/cp/call.c | 14 ++++++++++++++
gcc/cp/decl.c | 19 ++++++++++++++++---
gcc/testsuite/ChangeLog | 6 ++++++
gcc/testsuite/g++.dg/cpp2a/paren-init23.C | 19 +++++++++++++++++++
gcc/testsuite/g++.dg/init/aggr14.C | 14 ++++++++++++++
6 files changed, 77 insertions(+), 3 deletions(-)
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index e63f30bf3c1..cdd9b52915a 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,11 @@
+2020-04-09 Marek Polacek <polacek@redhat.com>
+
+ PR c++/93790
+ * call.c (initialize_reference): If the reference binding failed, maybe
+ try initializing from { }.
+ * decl.c (grok_reference_init): For T& t(e), set
+ LOOKUP_AGGREGATE_PAREN_INIT but don't build up a constructor yet.
+
2020-04-08 Iain Sandoe <iain@sandoe.co.uk>
Jun Ma <JunMa@linux.alibaba.com>
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 02220ffb3a1..1f3d9d23b5b 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -12196,6 +12196,20 @@ initialize_reference (tree type, tree expr,
conv = reference_binding (type, TREE_TYPE (expr), expr, /*c_cast_p=*/false,
flags, complain);
+ /* If this conversion failed, we're in C++20, and we have something like
+ A& a(b) where A is an aggregate, try again, this time as A& a{b}. */
+ if ((!conv || conv->bad_p)
+ && (flags & LOOKUP_AGGREGATE_PAREN_INIT))
+ {
+ tree e = build_constructor_single (init_list_type_node, NULL_TREE, expr);
+ CONSTRUCTOR_IS_DIRECT_INIT (e) = true;
+ CONSTRUCTOR_IS_PAREN_INIT (e) = true;
+ conversion *c = reference_binding (type, TREE_TYPE (e), e,
+ /*c_cast_p=*/false, flags, complain);
+ /* If this worked, use it. */
+ if (c && !c->bad_p)
+ expr = e, conv = c;
+ }
if (!conv || conv->bad_p)
{
if (complain & tf_error)
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index a6a1340e631..1447b89e692 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -5568,9 +5568,22 @@ grok_reference_init (tree decl, tree type, tree init, int flags)
&& !DECL_DECOMPOSITION_P (decl)
&& (cxx_dialect >= cxx2a))
{
- init = build_constructor_from_list (init_list_type_node, init);
- CONSTRUCTOR_IS_DIRECT_INIT (init) = true;
- CONSTRUCTOR_IS_PAREN_INIT (init) = true;
+ /* We don't know yet if we should treat const A& r(1) as
+ const A& r{1}. */
+ if (list_length (init) == 1)
+ {
+ flags |= LOOKUP_AGGREGATE_PAREN_INIT;
+ init = build_x_compound_expr_from_list (init, ELK_INIT,
+ tf_warning_or_error);
+ }
+ /* If the list had more than one element, the code is ill-formed
+ pre-C++20, so we can build a constructor right away. */
+ else
+ {
+ init = build_constructor_from_list (init_list_type_node, init);
+ CONSTRUCTOR_IS_DIRECT_INIT (init) = true;
+ CONSTRUCTOR_IS_PAREN_INIT (init) = true;
+ }
}
else
init = build_x_compound_expr_from_list (init, ELK_INIT,
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 6a972217610..a5bd5614e5a 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2020-04-09 Marek Polacek <polacek@redhat.com>
+
+ PR c++/93790
+ * g++.dg/cpp2a/paren-init23.C: New test.
+ * g++.dg/init/aggr14.C: New test.
+
2020-04-09 Jan Hubicka <hubicka@ucw.cz>
PR tree-optimization/91322
diff --git a/gcc/testsuite/g++.dg/cpp2a/paren-init23.C b/gcc/testsuite/g++.dg/cpp2a/paren-init23.C
new file mode 100644
index 00000000000..6038f63be5a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/paren-init23.C
@@ -0,0 +1,19 @@
+// PR c++/93790 - wrong paren-init of aggregates interference.
+// { dg-do compile { target c++2a } }
+
+struct S {
+ int i;
+};
+const S& s(1);
+
+struct A {
+ int i;
+ A(int);
+};
+const A& a(1);
+
+struct B {
+ int i;
+ B(int) = delete;
+};
+const B& b(1); // { dg-error "use of deleted function" }
diff --git a/gcc/testsuite/g++.dg/init/aggr14.C b/gcc/testsuite/g++.dg/init/aggr14.C
new file mode 100644
index 00000000000..538b467d467
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/aggr14.C
@@ -0,0 +1,14 @@
+// PR c++/93790 - wrong paren-init of aggregates interference.
+// { dg-do compile }
+
+struct S {};
+class S_refwrap {
+ S& Sref_;
+public:
+ S_refwrap(S& Sref) : Sref_(Sref) {}
+ operator S&() { return Sref_; }
+};
+
+S s;
+S_refwrap r(s);
+S& s2(r);
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2020-04-14 6:35 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-04-14 6:35 [gcc(refs/users/marxin/heads/PR94314-fix-new-delete-pair-deletion-part-3)] c++: Fix wrong paren-init of aggregates interference [PR93790] Martin Liska
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).