aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorPatrick Palka <ppalka@redhat.com>2023-10-24 18:03:17 -0400
committerPatrick Palka <ppalka@redhat.com>2023-10-24 18:03:17 -0400
commitd80a26cca025877b7657fa355570bc301223b50b (patch)
tree56306d3e0dd6a08f6175269cbbc3cb140f016f7c /gcc
parent51f164f76212feaf896d65616f60877d3217b701 (diff)
downloadgcc-d80a26cca025877b7657fa355570bc301223b50b.zip
gcc-d80a26cca025877b7657fa355570bc301223b50b.tar.gz
gcc-d80a26cca025877b7657fa355570bc301223b50b.tar.bz2
c++: non-dep array new-expr size [PR111929]
This PR is another instance of NON_DEPENDENT_EXPR having acted as an "analysis barrier" for middle-end routines, and now that it's gone we're more prone to passing weird templated trees (that have a generic tree code) to middle-end routines which end up ICEing on such trees. In the testcase below the non-dependent array new-expr size 'x + 42' is expressed as an ordinary PLUS_EXPR, but whose operands have different types (since templated trees encode just the syntactic form of an expression devoid of e.g. implicit conversions). This type incoherency triggers an ICE from size_binop in build_new_1 due to a wide_int assert that expects the operand types to have the same precision. This patch fixes this by replacing our piecemeal folding of 'size' in build_new_1 with a single call to cp_fully_fold (which is a no-op in a template context) once 'size' is built up. PR c++/111929 gcc/cp/ChangeLog: * init.cc (build_new_1): Use convert, build2, build3 and cp_fully_fold instead of fold_convert, size_binop and fold_build3 when building up 'size'. gcc/testsuite/ChangeLog: * g++.dg/template/non-dependent28.C: New test.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/init.cc9
-rw-r--r--gcc/testsuite/g++.dg/template/non-dependent28.C6
2 files changed, 11 insertions, 4 deletions
diff --git a/gcc/cp/init.cc b/gcc/cp/init.cc
index d48bb16..65d37c3 100644
--- a/gcc/cp/init.cc
+++ b/gcc/cp/init.cc
@@ -3261,7 +3261,7 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
max_outer_nelts = wi::udiv_trunc (max_size, inner_size);
max_outer_nelts_tree = wide_int_to_tree (sizetype, max_outer_nelts);
- size = size_binop (MULT_EXPR, size, fold_convert (sizetype, nelts));
+ size = build2 (MULT_EXPR, sizetype, size, convert (sizetype, nelts));
if (TREE_CODE (cst_outer_nelts) == INTEGER_CST)
{
@@ -3344,7 +3344,7 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
/* Use a class-specific operator new. */
/* If a cookie is required, add some extra space. */
if (array_p && TYPE_VEC_NEW_USES_COOKIE (elt_type))
- size = size_binop (PLUS_EXPR, size, cookie_size);
+ size = build2 (PLUS_EXPR, sizetype, size, cookie_size);
else
{
cookie_size = NULL_TREE;
@@ -3358,8 +3358,8 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
if (cxx_dialect >= cxx11 && flag_exceptions)
errval = throw_bad_array_new_length ();
if (outer_nelts_check != NULL_TREE)
- size = fold_build3 (COND_EXPR, sizetype, outer_nelts_check,
- size, errval);
+ size = build3 (COND_EXPR, sizetype, outer_nelts_check, size, errval);
+ size = cp_fully_fold (size);
/* Create the argument list. */
vec_safe_insert (*placement, 0, size);
/* Do name-lookup to find the appropriate operator. */
@@ -3415,6 +3415,7 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
outer_nelts_check = NULL_TREE;
}
+ size = cp_fully_fold (size);
/* If size is zero e.g. due to type having zero size, try to
preserve outer_nelts for constant expression evaluation
purposes. */
diff --git a/gcc/testsuite/g++.dg/template/non-dependent28.C b/gcc/testsuite/g++.dg/template/non-dependent28.C
new file mode 100644
index 0000000..f7f31d9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/non-dependent28.C
@@ -0,0 +1,6 @@
+// PR c++/111929
+
+template<class>
+void f(char x) {
+ new int[x + 42];
+}