This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [C++ PATCH] Fix constexpr OBJ_TYPE_REF handling on array elts (PR c++/87398)
- From: Jakub Jelinek <jakub at redhat dot com>
- To: Jason Merrill <jason at redhat dot com>
- Cc: Marek Polacek <polacek at redhat dot com>, gcc-patches List <gcc-patches at gcc dot gnu dot org>
- Date: Tue, 25 Sep 2018 16:57:23 +0200
- Subject: Re: [C++ PATCH] Fix constexpr OBJ_TYPE_REF handling on array elts (PR c++/87398)
- References: <20180925071754.GX8250@tucnak> <CADzB+2nc+62ioqFcPNJY7SKxsfQBMuXC=Xi-45V_P6zoWDBHbQ@mail.gmail.com>
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
On Tue, Sep 25, 2018 at 10:42:08AM -0400, Jason Merrill wrote:
> On Tue, Sep 25, 2018 at 3:17 AM, Jakub Jelinek <jakub@redhat.com> wrote:
> > ARRAY_REF is a handled component, so when a virtual call is on an array
> > element (or some component thereof), the loop to look through handled
> > components will look through the ARRAY_REFs too and then TREE_TYPE (obj)
> > might be an ARRAY_TYPE. The code wants to look at the class type instead
> > though.
>
> Yeah, I think looping through handled components is wrong here; given
> something like
>
> struct A
> {
> virtual void f();
> };
>
> struct B
> {
> A a;
> } b;
>
> int main()
> {
> b.a.f();
> }
>
> Looking through all handled components would give us "b", which has no
> virtual functions.
You're right. So like this (only look through COMPONENT_REFs where the
FIELD_DECL is DECL_FIELD_IS_BASE)?
Only checked
make check-c++-all RUNTESTFLAGS="dg.exp='constexpr-virt* pr87398*'"
so far, but it also fixes the PR87425 testcase and doesn't regress anything.
2018-09-25 Jakub Jelinek <jakub@redhat.com>
PR c++/87398
* constexpr.c (cxx_eval_constant_expression) <case OBJ_TYPE_REF>: Only
look through COMPONENT_REFs with DECL_FIELD_IS_BASE FIELD_DECLs.
* g++.dg/other/pr87398.C: New test.
* g++.dg/cpp2a/constexpr-virtual10.C: New test.
--- gcc/cp/constexpr.c.jj 2018-09-25 15:14:36.335386401 +0200
+++ gcc/cp/constexpr.c 2018-09-25 16:50:38.085334475 +0200
@@ -4812,7 +4812,8 @@ cxx_eval_constant_expression (const cons
return t;
}
obj = TREE_OPERAND (obj, 0);
- while (handled_component_p (obj))
+ while (TREE_CODE (obj) == COMPONENT_REF
+ && DECL_FIELD_IS_BASE (TREE_OPERAND (obj, 1)))
obj = TREE_OPERAND (obj, 0);
tree objtype = TREE_TYPE (obj);
/* Find the function decl in the virtual functions list. TOKEN is
--- gcc/testsuite/g++.dg/other/pr87398.C.jj 2018-09-25 16:49:40.458304980 +0200
+++ gcc/testsuite/g++.dg/other/pr87398.C 2018-09-25 16:49:40.458304980 +0200
@@ -0,0 +1,12 @@
+// PR c++/87398
+// { dg-do compile }
+
+struct A { virtual int foo (); };
+
+int
+bar (int x)
+{
+ A e[5][2];
+ int f = e[4][x].foo ();
+ return f;
+}
--- gcc/testsuite/g++.dg/cpp2a/constexpr-virtual10.C.jj 2018-09-25 16:49:40.458304980 +0200
+++ gcc/testsuite/g++.dg/cpp2a/constexpr-virtual10.C 2018-09-25 16:49:40.458304980 +0200
@@ -0,0 +1,18 @@
+// P1064R0
+// { dg-do compile }
+// { dg-options "-std=c++2a" }
+
+struct X
+{
+ constexpr virtual int f() const { return 1; };
+};
+
+struct Y : public X
+{
+ constexpr virtual int f() const { return 2; };
+};
+
+constexpr X a[2][1][3];
+constexpr Y b[3][12];
+static_assert (a[1][0][1].f() == 1);
+static_assert (b[2][11].f() == 2);
Jakub