]> gcc.gnu.org Git - gcc.git/commitdiff
c++: non-dep array new-expr size [PR111929]
authorPatrick Palka <ppalka@redhat.com>
Tue, 24 Oct 2023 22:03:17 +0000 (18:03 -0400)
committerPatrick Palka <ppalka@redhat.com>
Tue, 24 Oct 2023 22:03:17 +0000 (18:03 -0400)
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.

gcc/cp/init.cc
gcc/testsuite/g++.dg/template/non-dependent28.C [new file with mode: 0644]

index d48bb16c7c5e13451ccf5eff07412f3d087c616c..65d37c3c0c764e0752e7d2813e4ebb94b524daa6 100644 (file)
@@ -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 (file)
index 0000000..f7f31d9
--- /dev/null
@@ -0,0 +1,6 @@
+// PR c++/111929
+
+template<class>
+void f(char x) {
+  new int[x + 42];
+}
This page took 0.07495 seconds and 5 git commands to generate.