From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1888) id 0370E3857011; Sat, 10 Jul 2021 02:43:38 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 0370E3857011 MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="utf-8" From: Patrick Palka To: gcc-cvs@gcc.gnu.org Subject: [gcc r12-2233] c++: 'new T[N]' and SFINAE [PR82110] X-Act-Checkin: gcc X-Git-Author: Patrick Palka X-Git-Refname: refs/heads/master X-Git-Oldrev: ef2ace642a1ba795235c542b728cb83c73dfce74 X-Git-Newrev: b9119edc09e4660d772dea771578715858f7fbdb Message-Id: <20210710024338.0370E3857011@sourceware.org> Date: Sat, 10 Jul 2021 02:43:38 +0000 (GMT) X-BeenThere: gcc-cvs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 10 Jul 2021 02:43:38 -0000 https://gcc.gnu.org/g:b9119edc09e4660d772dea771578715858f7fbdb commit r12-2233-gb9119edc09e4660d772dea771578715858f7fbdb Author: Patrick Palka Date: Fri Jul 9 22:40:07 2021 -0400 c++: 'new T[N]' and SFINAE [PR82110] Here we're failing to treat 'new T[N]' as erroneous in a SFINAE context when T isn't default constructible because expand_aggr_init_1 doesn't communicate to build_aggr_init (its only SFINAE caller) whether the initialization was actually successful. To fix this, this patch makes expand_aggr_init_1 and its subroutine expand_default_init return true on success, false on failure so that build_aggr_init can properly return error_mark_node on failure. PR c++/82110 gcc/cp/ChangeLog: * init.c (build_aggr_init): Return error_mark_node if expand_aggr_init_1 returns false. (expand_default_init): Change return type to bool. Return false on error, true on success. (expand_aggr_init_1): Likewise. gcc/testsuite/ChangeLog: * g++.dg/cpp0x/pr78765.C: Expect another conversion failure diagnostic. * g++.dg/template/sfinae14.C: Flip incorrect assertion. * g++.dg/cpp2a/concepts-requires27.C: New test. Diff: --- gcc/cp/init.c | 43 ++++++++++++++++-------- gcc/testsuite/g++.dg/cpp0x/pr78765.C | 2 +- gcc/testsuite/g++.dg/cpp2a/concepts-requires27.C | 10 ++++++ gcc/testsuite/g++.dg/template/sfinae14.C | 2 +- 4 files changed, 41 insertions(+), 16 deletions(-) diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 88f6f90a800..d47e405e745 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -39,8 +39,8 @@ along with GCC; see the file COPYING3. If not see static bool begin_init_stmts (tree *, tree *); static tree finish_init_stmts (bool, tree, tree); static void construct_virtual_base (tree, tree); -static void expand_aggr_init_1 (tree, tree, tree, tree, int, tsubst_flags_t); -static void expand_default_init (tree, tree, tree, tree, int, tsubst_flags_t); +static bool expand_aggr_init_1 (tree, tree, tree, tree, int, tsubst_flags_t); +static bool expand_default_init (tree, tree, tree, tree, int, tsubst_flags_t); static void perform_member_init (tree, tree); static int member_init_ok_or_else (tree, tree, tree); static void expand_virtual_init (tree, tree); @@ -1838,12 +1838,14 @@ build_aggr_init (tree exp, tree init, int flags, tsubst_flags_t complain) is_global = begin_init_stmts (&stmt_expr, &compound_stmt); destroy_temps = stmts_are_full_exprs_p (); current_stmt_tree ()->stmts_are_full_exprs_p = 0; - expand_aggr_init_1 (TYPE_BINFO (type), exp, exp, - init, LOOKUP_NORMAL|flags, complain); + bool ok = expand_aggr_init_1 (TYPE_BINFO (type), exp, exp, + init, LOOKUP_NORMAL|flags, complain); stmt_expr = finish_init_stmts (is_global, stmt_expr, compound_stmt); current_stmt_tree ()->stmts_are_full_exprs_p = destroy_temps; TREE_READONLY (exp) = was_const; TREE_THIS_VOLATILE (exp) = was_volatile; + if (!ok) + return error_mark_node; if ((VAR_P (exp) || TREE_CODE (exp) == PARM_DECL) && TREE_SIDE_EFFECTS (stmt_expr) @@ -1854,7 +1856,7 @@ build_aggr_init (tree exp, tree init, int flags, tsubst_flags_t complain) return stmt_expr; } -static void +static bool expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags, tsubst_flags_t complain) { @@ -1889,6 +1891,9 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags, happen for direct-initialization, too. */ init = digest_init (type, init, complain); + if (init == error_mark_node) + return false; + /* A CONSTRUCTOR of the target's type is a previously digested initializer, whether that happened just above or in cp_parser_late_parsing_nsdmi. @@ -1910,7 +1915,7 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags, init = build2 (INIT_EXPR, TREE_TYPE (exp), exp, init); TREE_SIDE_EFFECTS (init) = 1; finish_expr_stmt (init); - return; + return true; } if (init && TREE_CODE (init) != TREE_LIST @@ -1927,8 +1932,12 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags, have already built up the constructor call so we could wrap it in an exception region. */; else - init = ocp_convert (type, init, CONV_IMPLICIT|CONV_FORCE_TEMP, - flags, complain | tf_no_cleanup); + { + init = ocp_convert (type, init, CONV_IMPLICIT|CONV_FORCE_TEMP, + flags, complain | tf_no_cleanup); + if (init == error_mark_node) + return false; + } if (TREE_CODE (init) == MUST_NOT_THROW_EXPR) /* We need to protect the initialization of a catch parm with a @@ -1944,7 +1953,7 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags, init = build2 (INIT_EXPR, TREE_TYPE (exp), exp, init); TREE_SIDE_EFFECTS (init) = 1; finish_expr_stmt (init); - return; + return true; } if (init == NULL_TREE) @@ -1982,6 +1991,8 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags, &parms, binfo, flags, complain); base = fold_build_cleanup_point_expr (void_type_node, base); + if (complete == error_mark_node || base == error_mark_node) + return false; rval = build_if_in_charge (complete, base); } else @@ -1991,6 +2002,8 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags, rval = build_special_member_call (exp, ctor_name, &parms, binfo, flags, complain); + if (rval == error_mark_node) + return false; } if (parms != NULL) @@ -2010,10 +2023,12 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags, /* FIXME put back convert_to_void? */ if (TREE_SIDE_EFFECTS (rval)) finish_expr_stmt (rval); + + return true; } /* This function is responsible for initializing EXP with INIT - (if any). + (if any). Returns true on success, false on failure. BINFO is the binfo of the type for who we are performing the initialization. For example, if W is a virtual base class of A and B, @@ -2032,7 +2047,7 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags, FLAGS is just passed to `build_new_method_call'. See that function for its description. */ -static void +static bool expand_aggr_init_1 (tree binfo, tree true_exp, tree exp, tree init, int flags, tsubst_flags_t complain) { @@ -2058,7 +2073,7 @@ expand_aggr_init_1 (tree binfo, tree true_exp, tree exp, tree init, int flags, if (init) finish_expr_stmt (init); gcc_assert (!cleanups); - return; + return true; } /* List-initialization from {} becomes value-initialization for non-aggregate @@ -2096,7 +2111,7 @@ expand_aggr_init_1 (tree binfo, tree true_exp, tree exp, tree init, int flags, /* If we don't need to mess with the constructor at all, then we're done. */ if (! type_build_ctor_call (type)) - return; + return true; /* Otherwise fall through and call the constructor. */ init = NULL_TREE; @@ -2104,7 +2119,7 @@ expand_aggr_init_1 (tree binfo, tree true_exp, tree exp, tree init, int flags, /* We know that expand_default_init can handle everything we want at this point. */ - expand_default_init (binfo, true_exp, exp, init, flags, complain); + return expand_default_init (binfo, true_exp, exp, init, flags, complain); } /* Report an error if TYPE is not a user-defined, class type. If diff --git a/gcc/testsuite/g++.dg/cpp0x/pr78765.C b/gcc/testsuite/g++.dg/cpp0x/pr78765.C index 6b66d26e549..4c63fddb684 100644 --- a/gcc/testsuite/g++.dg/cpp0x/pr78765.C +++ b/gcc/testsuite/g++.dg/cpp0x/pr78765.C @@ -8,7 +8,7 @@ struct ValueType { int field; }; -static constexpr ValueType var = 0; // { dg-error "conversion" } +static constexpr ValueType var = 0; // { dg-error "conversion|convert" } template class ValueTypeInfo; diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-requires27.C b/gcc/testsuite/g++.dg/cpp2a/concepts-requires27.C new file mode 100644 index 00000000000..99d45001383 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-requires27.C @@ -0,0 +1,10 @@ +// PR c++/82110 +// { dg-do compile { target c++20 } } + +struct X { X() = delete; }; + +template concept C = requires(T t) { new T; }; +template concept D = requires(T t) { new T[1]; }; + +static_assert(!C); +static_assert(!D); diff --git a/gcc/testsuite/g++.dg/template/sfinae14.C b/gcc/testsuite/g++.dg/template/sfinae14.C index 93eba43a08f..0c59dad305d 100644 --- a/gcc/testsuite/g++.dg/template/sfinae14.C +++ b/gcc/testsuite/g++.dg/template/sfinae14.C @@ -76,4 +76,4 @@ STATIC_ASSERT(!(has_new_one_arg::value)); STATIC_ASSERT((has_array_new::value)); STATIC_ASSERT(!(has_array_new::value)); -STATIC_ASSERT((has_array_new::value)); +STATIC_ASSERT(!(has_array_new::value));