Commit 81958cd6 by Jakub Jelinek

c++: Fix ICE during constexpr virtual call evaluation [PR93633]

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.

2020-02-09  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.
parent 9bc3b95d
2020-02-09 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.
2020-02-08 Jason Merrill <jason@redhat.com>
PR c++/90691
......
......@@ -6063,6 +6063,17 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
&& 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));
......
2020-02-09 Jakub Jelinek <jakub@redhat.com>
PR c++/93633
* g++.dg/cpp2a/constexpr-new11.C: New test.
* g++.dg/cpp2a/constexpr-new12.C: New test.
* g++.dg/cpp2a/constexpr-new13.C: New test.
2020-02-08 Andrew Pinski <apinski@marvel.com>
PR target/91927
......
// 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);
}
// 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" }
// 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 ();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment