On 7/17/24 5:33 PM, Marek Polacek wrote:
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
Hmm, I thought I had replied to this already.
-- >8 --
Unfortunately, my r15-1946 fix broke the attached testcase. In it,
we no longer go into the
/* P1009: Array size deduction in new-expressions. */
block, and instead generate an operator new [] call along with a loop
in build_new_1, which we can't constexpr-evaluate. So this patch
reverts r15-1946 and uses CONSTRUCTOR_IS_PAREN_INIT to distinguish
between () and {} to fix the original testcase (anew7.C).
PR c++/115645
gcc/cp/ChangeLog:
* call.cc (convert_like_internal) <case ck_user>: Don't report errors
about calling an explicit constructor when the constructor was marked
CONSTRUCTOR_IS_PAREN_INIT.
* init.cc (build_new): Revert r15-1946. Set CONSTRUCTOR_IS_PAREN_INIT.
(build_vec_init): Maybe set CONSTRUCTOR_IS_PAREN_INIT.
gcc/testsuite/ChangeLog:
* g++.dg/cpp2a/constexpr-new23.C: New test.
---
gcc/cp/call.cc | 2 ++
gcc/cp/init.cc | 17 ++++-----
gcc/testsuite/g++.dg/cpp2a/constexpr-new23.C | 38 ++++++++++++++++++++
3 files changed, 49 insertions(+), 8 deletions(-)
create mode 100644 gcc/testsuite/g++.dg/cpp2a/constexpr-new23.C
diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index a5d3426b70c..2d94d5e0d07 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -8592,6 +8592,8 @@ convert_like_internal (conversion *convs, tree expr, tree
fn, int argnum,
&& BRACE_ENCLOSED_INITIALIZER_P (expr)
/* Unless this is for direct-list-initialization. */
&& (!CONSTRUCTOR_IS_DIRECT_INIT (expr) || convs->need_temporary_p)
+ /* And it wasn't a ()-init. */
+ && !CONSTRUCTOR_IS_PAREN_INIT (expr)
/* And in C++98 a default constructor can't be explicit. */
&& cxx_dialect >= cxx11)
{
diff --git a/gcc/cp/init.cc b/gcc/cp/init.cc
index e9561c146d7..4138a6077dd 100644
--- a/gcc/cp/init.cc
+++ b/gcc/cp/init.cc
@@ -4005,20 +4005,17 @@ build_new (location_t loc, vec<tree, va_gc>
**placement, tree type,
/* P1009: Array size deduction in new-expressions. */
const bool array_p = TREE_CODE (type) == ARRAY_TYPE;
if (*init
- /* If the array didn't specify its bound, we have to deduce it. */
- && ((array_p && !TYPE_DOMAIN (type))
- /* For C++20 array with parenthesized-init, we have to process
- the parenthesized-list. But don't do it for (), which is
- value-initialization, and INIT should stay empty. */
- || (cxx_dialect >= cxx20
- && (array_p || nelts)
- && !(*init)->is_empty ())))
+ /* If ARRAY_P, we have to deduce the array bound. For C++20 paren-init,
+ we have to process the parenthesized-list. But don't do it for (),
+ which is value-initialization, and INIT should stay empty. */
+ && (array_p || (cxx_dialect >= cxx20 && nelts && !(*init)->is_empty ())))
{
/* This means we have 'new T[]()'. */
if ((*init)->is_empty ())
{
tree ctor = build_constructor (init_list_type_node, NULL);
CONSTRUCTOR_IS_DIRECT_INIT (ctor) = true;
+ CONSTRUCTOR_IS_PAREN_INIT (ctor) = true;
vec_safe_push (*init, ctor);
}
tree &elt = (**init)[0];
@@ -4735,6 +4732,9 @@ build_vec_init (tree base, tree maxindex, tree init,
bool do_static_init = (DECL_P (obase) && TREE_STATIC (obase));
bool empty_list = false;
+ const bool paren_init_p = (init
+ && TREE_CODE (init) == CONSTRUCTOR
+ && CONSTRUCTOR_IS_PAREN_INIT (init));
I think rather than recognizing paren-init in general, we want to
recognize () specifically, and set explicit_value_init_p...
if (init && BRACE_ENCLOSED_INITIALIZER_P (init)
&& CONSTRUCTOR_NELTS (init) == 0)
/* Skip over the handling of non-empty init lists. */
@@ -4927,6 +4927,7 @@ build_vec_init (tree base, tree maxindex, tree init,
|| TREE_CODE (type) == ARRAY_TYPE))
{
init = build_constructor (init_list_type_node, NULL);
+ CONSTRUCTOR_IS_PAREN_INIT (init) = paren_init_p;
}
else
{
...by taking the else branch here. Then we shouldn't need the
convert_like change.
Jason