aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorPatrick Palka <ppalka@redhat.com>2021-07-09 22:40:07 -0400
committerPatrick Palka <ppalka@redhat.com>2021-07-09 22:40:07 -0400
commitb9119edc09e4660d772dea771578715858f7fbdb (patch)
tree4b3c6fb7575e670996de09c0ae666b7b472a1098 /gcc
parentef2ace642a1ba795235c542b728cb83c73dfce74 (diff)
downloadgcc-b9119edc09e4660d772dea771578715858f7fbdb.zip
gcc-b9119edc09e4660d772dea771578715858f7fbdb.tar.gz
gcc-b9119edc09e4660d772dea771578715858f7fbdb.tar.bz2
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.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/init.c43
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr78765.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-requires27.C10
-rw-r--r--gcc/testsuite/g++.dg/template/sfinae14.C2
4 files changed, 41 insertions, 16 deletions
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 88f6f90..d47e405 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 6b66d26..4c63fdd 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 0000000..99d4500
--- /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 93eba43a..0c59dad 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));