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: Expect new X[5] is ill-formed
since X is not default constructible.
* g++.dg/cpp2a/concepts-requires27.C: New test.
---
gcc/cp/init.c | 41 +++++++++++++------
gcc/testsuite/g++.dg/cpp0x/pr78765.C | 2 +-
.../g++.dg/cpp2a/concepts-requires27.C | 10 +++++
gcc/testsuite/g++.dg/template/sfinae14.C | 2 +-
4 files changed, 40 insertions(+), 15 deletions(-)
create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-requires27.C
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 88f6f90a800..1d863ed8538 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,6 +2023,8 @@ 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
@@ -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 <int> 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<class T> concept C = requires(T t) { new T; };
+template<class T> concept D = requires(T t) { new T[1]; };
+
+static_assert(!C<X>);
+static_assert(!D<X>);
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<X, int X::*>::value));
STATIC_ASSERT((has_array_new<Y, int, 5>::value));
STATIC_ASSERT(!(has_array_new<X, int Y::*, &Y::foo>::value));
-STATIC_ASSERT((has_array_new<X, int, 5>::value));
+STATIC_ASSERT(!(has_array_new<X, int, 5>::value));