[PATCH] c++: Fix ICE during constexpr virtual call evaluation [PR93633]
Jason Merrill
jason@redhat.com
Sun Feb 9 11:26:00 GMT 2020
On 2/9/20 2:27 AM, Jakub Jelinek wrote:
> Hi!
>
> The first (valid) testcase ICEs because for
> A *a = new B ();
> a->foo (); // virtual method call
> we actually see &heap and the "heap " objects don't have the class or
> whatever else type was used in new expression, but an array type containing
> one (or more of those for array new) and so when using TYPE_BINFO (objtype)
> on it we ICE.
> This patch handles this special case, and otherwise punts (as shown e.g. in
> the second testcase, where because the heap object is already deleted,
> we don't really want to allow it to be used.
>
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
OK.
> 2020-02-08 Jakub Jelinek <jakub@redhat.com>
>
> PR c++/93633
> * constexpr.c (cxx_eval_constant_expression): If obj is heap var with
> ARRAY_TYPE, use the element type. Punt if objtype after that is not
> a class type.
>
> * g++.dg/cpp2a/constexpr-new11.C: New test.
> * g++.dg/cpp2a/constexpr-new12.C: New test.
> * g++.dg/cpp2a/constexpr-new13.C: New test.
>
> --- gcc/cp/constexpr.c.jj 2020-02-08 10:58:15.434064005 +0100
> +++ gcc/cp/constexpr.c 2020-02-08 14:15:55.356768622 +0100
> @@ -6027,6 +6027,17 @@ cxx_eval_constant_expression (const cons
> && DECL_FIELD_IS_BASE (TREE_OPERAND (obj, 1)))
> obj = TREE_OPERAND (obj, 0);
> tree objtype = TREE_TYPE (obj);
> + if (VAR_P (obj)
> + && DECL_NAME (obj) == heap_identifier
> + && TREE_CODE (objtype) == ARRAY_TYPE)
> + objtype = TREE_TYPE (objtype);
> + if (!CLASS_TYPE_P (objtype))
> + {
> + if (!ctx->quiet)
> + error_at (loc, "expression %qE is not a constant expression", t);
> + *non_constant_p = true;
> + return t;
> + }
> /* Find the function decl in the virtual functions list. TOKEN is
> the DECL_VINDEX that says which function we're looking for. */
> tree virtuals = BINFO_VIRTUALS (TYPE_BINFO (objtype));
> --- gcc/testsuite/g++.dg/cpp2a/constexpr-new11.C.jj 2020-02-08 14:22:34.740789172 +0100
> +++ gcc/testsuite/g++.dg/cpp2a/constexpr-new11.C 2020-02-08 14:21:50.689448695 +0100
> @@ -0,0 +1,31 @@
> +// PR c++/93633
> +// { dg-do compile { target c++2a } }
> +
> +struct A {
> + constexpr A () : a (0) {}
> + constexpr virtual int foo () { return 1 + a * 4; }
> + int a;
> +};
> +
> +struct B : A {
> + constexpr B () : b (0) {}
> + constexpr virtual int foo () { return 0 + b * 4; }
> + int b;
> +};
> +
> +constexpr int
> +foo ()
> +{
> + A *a = new B ();
> + a->a = 4;
> + int r = a->foo ();
> + delete a;
> + return r;
> +}
> +
> +int
> +main ()
> +{
> + constexpr auto a = foo ();
> + static_assert (a == 0);
> +}
> --- gcc/testsuite/g++.dg/cpp2a/constexpr-new12.C.jj 2020-02-08 14:22:38.043739717 +0100
> +++ gcc/testsuite/g++.dg/cpp2a/constexpr-new12.C 2020-02-08 14:24:04.119451025 +0100
> @@ -0,0 +1,26 @@
> +// PR c++/93633
> +// { dg-do compile { target c++2a } }
> +
> +struct A {
> + constexpr A () : a (0) {}
> + constexpr virtual int foo () { return 1 + a * 4; }
> + int a;
> +};
> +
> +struct B : A {
> + constexpr B () : b (0) {}
> + constexpr virtual int foo () { return 0 + b * 4; }
> + int b;
> +};
> +
> +constexpr int
> +foo ()
> +{
> + A *a = new B ();
> + a->a = 4;
> + delete a;
> + int r = a->foo ();
> + return r;
> +}
> +
> +constexpr auto a = foo (); // { dg-error "is not a constant expression" }
> --- gcc/testsuite/g++.dg/cpp2a/constexpr-new13.C.jj 2020-02-08 14:22:41.060694553 +0100
> +++ gcc/testsuite/g++.dg/cpp2a/constexpr-new13.C 2020-02-08 14:25:38.783033750 +0100
> @@ -0,0 +1,26 @@
> +// PR c++/93633
> +// { dg-do compile { target c++2a } }
> +
> +struct A {
> + constexpr A () : a (0) {}
> + virtual int foo () { return 1 + a * 4; }
> + int a;
> +};
> +
> +struct B : A {
> + constexpr B () : b (0) {}
> + virtual int foo () { return 0 + b * 4; } // { dg-message "declared here" }
> + int b;
> +};
> +
> +constexpr int
> +foo ()
> +{
> + A *a = new B ();
> + a->a = 4;
> + int r = a->foo (); // { dg-error "call to non-.constexpr. function" }
> + delete a;
> + return r;
> +}
> +
> +constexpr auto a = foo ();
>
> Jakub
>
More information about the Gcc-patches
mailing list