From: Jakub Jelinek <jakub@redhat.com>
To: Jason Merrill <jason@redhat.com>
Cc: Andreas Schwab <schwab@suse.de>,
Marek Polacek <polacek@redhat.com>,
GCC Patches <gcc-patches@gcc.gnu.org>
Subject: [C++ PATCH] FIx constexpr virtual function call handling on ia64 (PR c++/87861)
Date: Sat, 08 Dec 2018 09:07:00 -0000 [thread overview]
Message-ID: <20181208090715.GS12380@tucnak> (raw)
In-Reply-To: <CADzB+2mVErikeJfPEFuAi9iiBRXqXgkM75CaRV7VT0sh3Mwtmg@mail.gmail.com>
On Thu, Sep 27, 2018 at 01:15:46AM -0400, Jason Merrill wrote:
> >> /usr/local/gcc/gcc-20180920/gcc/testsuite/g++.dg/cpp2a/constexpr-virtual2.C:33:26: error: non-constant condition for static assertion
> >> /usr/local/gcc/gcc-20180920/gcc/testsuite/g++.dg/cpp2a/constexpr-virtual2.C:33:23: error: expression '((& X2::_ZTV2X2) + 16)' does not designate a 'constexpr' function
> >> /usr/local/gcc/gcc-20180920/gcc/testsuite/g++.dg/cpp2a/constexpr-virtual2.C:37:27: error: non-constant condition for static assertion
> >> /usr/local/gcc/gcc-20180920/gcc/testsuite/g++.dg/cpp2a/constexpr-virtual2.C:37:24: error: expression '((& X2::_ZTV2X2) + 16)' does not designate a 'constexpr' function
> >> /usr/local/gcc/gcc-20180920/gcc/testsuite/g++.dg/cpp2a/constexpr-virtual2.C:41:26: error: non-constant condition for static assertion
> >> /usr/local/gcc/gcc-20180920/gcc/testsuite/g++.dg/cpp2a/constexpr-virtual2.C:41:23: error: expression '((& X4::_ZTV2X4) + 16)' does not designate a 'constexpr' function
> >> /usr/local/gcc/gcc-20180920/gcc/testsuite/g++.dg/cpp2a/constexpr-virtual2.C:45:26: error: non-constant condition for static assertion
> >> /usr/local/gcc/gcc-20180920/gcc/testsuite/g++.dg/cpp2a/constexpr-virtual2.C:45:23: error: expression '((& X4::_ZTV2X4) + 16)' does not designate a 'constexpr' function
> >> /usr/local/gcc/gcc-20180920/gcc/testsuite/g++.dg/cpp2a/constexpr-virtual2.C:49:27: error: non-constant condition for static assertion
> >> /usr/local/gcc/gcc-20180920/gcc/testsuite/g++.dg/cpp2a/constexpr-virtual2.C:49:24: error: expression '((& X4::_ZTV2X4) + 16)' does not designate a 'constexpr' function
> >> compiler exited with status 1
> >> FAIL: g++.dg/cpp2a/constexpr-virtual2.C (test for excess errors)
> >
> > I think the primary problem here is:
> > /* When using function descriptors, the address of the
> > vtable entry is treated as a function pointer. */
> > if (TARGET_VTABLE_USES_DESCRIPTORS)
> > e2 = build1 (NOP_EXPR, TREE_TYPE (e2),
> > cp_build_addr_expr (e2, complain));
> > in typeck.c, on non-descriptor targets we have an INDIRECT_REF where we
> > read the vtable function pointer. On ia64, the above optimizes the
> > INDIRECT_REF away, so what the cxx_eval_call_expression actually gets
> > after constexpr evaluating the CALL_FN is not ADDR_EXPR of a function,
> > but the address of the function descriptor (e.g. &_ZTV2X2 + 16 ).
> >
> > So, perhaps in cxx_eval_call_expression we need:
> > if (TREE_CODE (fun) == ADDR_EXPR)
> > fun = TREE_OPERAND (fun, 0);
> > + else if (TARGET_VTABLE_USES_DESCRIPTORS
> > + && TREE_CODE (fun) == POINTER_PLUS_EXPR
> > + && ...)
> > where we verify that p+ first argument is ADDR_EXPR of a virtual table,
> > second arg is INTEGER_CST and just walk the DECL_INITIAL of that, finding
> > the FDESC_EXPR at the right offset (therefore, I believe you need following
> > rather than the patch you've posted, so that you can actually find it) and
> > finally pick the function from the FDESC_EXPR entry.
> > Makes me wonder what happens with indirect calls in constexpr evaluation,
> > e.g. if I do:
> > constexpr int bar () { return 42; }
> > constexpr int foo () { int (*fn) () = bar; return fn (); }
> > static_assert (foo () == 42);
> > but apparently this works.
> >
> > --- gcc/cp/class.c.jj 2018-09-20 09:56:59.229751895 +0200
> > +++ gcc/cp/class.c 2018-09-20 10:12:17.447370890 +0200
> > @@ -9266,7 +9266,6 @@ build_vtbl_initializer (tree binfo,
> > tree vcall_index;
> > tree fn, fn_original;
> > tree init = NULL_TREE;
> > - tree idx = size_int (jx++);
> >
> > fn = BV_FN (v);
> > fn_original = fn;
> > @@ -9370,7 +9369,7 @@ build_vtbl_initializer (tree binfo,
> > int i;
> > if (init == size_zero_node)
> > for (i = 0; i < TARGET_VTABLE_USES_DESCRIPTORS; ++i)
> > - CONSTRUCTOR_APPEND_ELT (*inits, idx, init);
> > + CONSTRUCTOR_APPEND_ELT (*inits, size_int (jx++), init);
> > else
> > for (i = 0; i < TARGET_VTABLE_USES_DESCRIPTORS; ++i)
> > {
> > @@ -9378,11 +9377,11 @@ build_vtbl_initializer (tree binfo,
> > fn, build_int_cst (NULL_TREE, i));
> > TREE_CONSTANT (fdesc) = 1;
> >
> > - CONSTRUCTOR_APPEND_ELT (*inits, idx, fdesc);
> > + CONSTRUCTOR_APPEND_ELT (*inits, size_int (jx++), fdesc);
> > }
> > }
> > else
> > - CONSTRUCTOR_APPEND_ELT (*inits, idx, init);
> > + CONSTRUCTOR_APPEND_ELT (*inits, size_int (jx++), init);
> > }
> > }
>
> This patch is OK. And your suggestion for cxx_eval_call_expression
> sounds right, too. Marek, will you follow up on that?
Here is the full patch. Besides the above already posted hunks and
proposed cxx_eval_call_expression changes I had to also divide token
in the OBJ_TYPE_REF handling by TARGET_VTABLE_USES_DESCRIPTORS, because
DECL_VINDEX of the second virtual table function is there 2 and of the third
4 etc.
Tested with a cross to ia64-linux on all the constexpr-virtual*.C testcases,
Jeff tested it on ia64-linux native and I've bootstrapped/regtested on
x86_64-linux and i686-linux. Ok for trunk?
2018-12-08 Jakub Jelinek <jakub@redhat.com>
PR c++/87861
* class.c (build_vtbl_initializer): For TARGET_VTABLE_USES_DESCRIPTORS
bump index for each added word.
* constexpr.c (find_array_ctor_elt): Add forward declaration.
(cxx_eval_call_expression): Handle TARGET_VTABLE_USES_DESCRIPTORS
vtable calls.
(cxx_eval_constant_expression) <case OBJ_TYPE_REF>: Divide token
by TARGET_VTABLE_USES_DESCRIPTORS if non-zero.
--- gcc/cp/class.c.jj 2018-12-07 00:23:15.006998887 +0100
+++ gcc/cp/class.c 2018-12-07 09:39:52.736059638 +0100
@@ -9351,7 +9351,6 @@ build_vtbl_initializer (tree binfo,
tree vcall_index;
tree fn, fn_original;
tree init = NULL_TREE;
- tree idx = size_int (jx++);
fn = BV_FN (v);
fn_original = fn;
@@ -9455,7 +9454,7 @@ build_vtbl_initializer (tree binfo,
int i;
if (init == size_zero_node)
for (i = 0; i < TARGET_VTABLE_USES_DESCRIPTORS; ++i)
- CONSTRUCTOR_APPEND_ELT (*inits, idx, init);
+ CONSTRUCTOR_APPEND_ELT (*inits, size_int (jx++), init);
else
for (i = 0; i < TARGET_VTABLE_USES_DESCRIPTORS; ++i)
{
@@ -9463,11 +9462,11 @@ build_vtbl_initializer (tree binfo,
fn, build_int_cst (NULL_TREE, i));
TREE_CONSTANT (fdesc) = 1;
- CONSTRUCTOR_APPEND_ELT (*inits, idx, fdesc);
+ CONSTRUCTOR_APPEND_ELT (*inits, size_int (jx++), fdesc);
}
}
else
- CONSTRUCTOR_APPEND_ELT (*inits, idx, init);
+ CONSTRUCTOR_APPEND_ELT (*inits, size_int (jx++), init);
}
}
--- gcc/cp/constexpr.c.jj 2018-12-07 00:23:41.000000000 +0100
+++ gcc/cp/constexpr.c 2018-12-07 10:59:46.840562829 +0100
@@ -41,6 +41,9 @@ do { \
return t; \
} while (0)
+static HOST_WIDE_INT find_array_ctor_elt (tree ary, tree dindex,
+ bool insert = false);
+
/* Returns true iff FUN is an instantiation of a constexpr function
template or a defaulted constexpr function. */
@@ -1516,6 +1519,36 @@ cxx_eval_call_expression (const constexp
STRIP_NOPS (fun);
if (TREE_CODE (fun) == ADDR_EXPR)
fun = TREE_OPERAND (fun, 0);
+ /* For TARGET_VTABLE_USES_DESCRIPTORS targets, there is no
+ indirection, the called expression is a pointer into the
+ virtual table which should contain FDESC_EXPR. Extract the
+ FUNCTION_DECL from there. */
+ else if (TARGET_VTABLE_USES_DESCRIPTORS
+ && TREE_CODE (fun) == POINTER_PLUS_EXPR
+ && TREE_CODE (TREE_OPERAND (fun, 0)) == ADDR_EXPR
+ && TREE_CODE (TREE_OPERAND (fun, 1)) == INTEGER_CST)
+ {
+ tree d = TREE_OPERAND (TREE_OPERAND (fun, 0), 0);
+ if (VAR_P (d)
+ && DECL_VTABLE_OR_VTT_P (d)
+ && TREE_CODE (TREE_TYPE (d)) == ARRAY_TYPE
+ && TREE_TYPE (TREE_TYPE (d)) == vtable_entry_type
+ && DECL_INITIAL (d)
+ && TREE_CODE (DECL_INITIAL (d)) == CONSTRUCTOR)
+ {
+ tree i = int_const_binop (TRUNC_DIV_EXPR, TREE_OPERAND (fun, 1),
+ TYPE_SIZE_UNIT (vtable_entry_type));
+ HOST_WIDE_INT idx = find_array_ctor_elt (DECL_INITIAL (d), i);
+ if (idx >= 0)
+ {
+ tree fdesc
+ = (*CONSTRUCTOR_ELTS (DECL_INITIAL (d)))[idx].value;
+ if (TREE_CODE (fdesc) == FDESC_EXPR
+ && integer_zerop (TREE_OPERAND (fdesc, 1)))
+ fun = TREE_OPERAND (fdesc, 0);
+ }
+ }
+ }
}
if (TREE_CODE (fun) != FUNCTION_DECL)
{
@@ -2240,7 +2273,7 @@ array_index_cmp (tree key, tree index)
if none. If INSERT is true, insert a matching element rather than fail. */
static HOST_WIDE_INT
-find_array_ctor_elt (tree ary, tree dindex, bool insert = false)
+find_array_ctor_elt (tree ary, tree dindex, bool insert)
{
if (tree_int_cst_sgn (dindex) < 0)
return -1;
@@ -4834,6 +4867,8 @@ cxx_eval_constant_expression (const cons
/* 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));
+ if (TARGET_VTABLE_USES_DESCRIPTORS)
+ token /= MAX (TARGET_VTABLE_USES_DESCRIPTORS, 1);
r = TREE_VALUE (chain_index (token, virtuals));
break;
}
Jakub
next prev parent reply other threads:[~2018-12-08 9:07 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-09-14 17:21 C++ PATCH to implement P1064R0, Virtual Function Calls in Constant Expressions Marek Polacek
2018-09-14 17:41 ` Jakub Jelinek
2018-09-14 19:43 ` C++ PATCH to implement P1064R0, Virtual Function Calls in Constant Expressions (v2) Marek Polacek
2018-09-14 20:32 ` C++ PATCH to implement P1064R0, Virtual Function Calls in Constant Expressions Jason Merrill
2018-09-14 20:46 ` Marek Polacek
2018-09-17 21:51 ` Marek Polacek
2018-09-18 3:48 ` Jason Merrill
2018-09-18 15:37 ` C++ PATCH to implement P1064R0, Virtual Function Calls in Constant Expressions (v4) Marek Polacek
2018-09-18 18:36 ` Jason Merrill
2018-09-18 18:58 ` Marek Polacek
2018-09-19 13:27 ` Andreas Schwab
2018-09-19 14:19 ` Marek Polacek
2018-09-19 15:10 ` Andreas Schwab
2018-09-19 15:11 ` Marek Polacek
2018-09-19 17:35 ` Jason Merrill
2018-09-20 8:26 ` Andreas Schwab
2018-09-20 9:23 ` Jakub Jelinek
2018-09-27 7:16 ` Jason Merrill
2018-09-27 23:18 ` Marek Polacek
2018-09-28 5:44 ` Jason Merrill
2018-09-28 6:48 ` Jakub Jelinek
2018-12-08 9:07 ` Jakub Jelinek [this message]
2018-12-11 18:53 ` [C++ PATCH] FIx constexpr virtual function call handling on ia64 (PR c++/87861) Jason Merrill
2018-10-08 14:18 ` C++ PATCH to implement P1064R0, Virtual Function Calls in Constant Expressions (v4) Andreas Schwab
2018-10-10 11:53 ` Jakub Jelinek
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20181208090715.GS12380@tucnak \
--to=jakub@redhat.com \
--cc=gcc-patches@gcc.gnu.org \
--cc=jason@redhat.com \
--cc=polacek@redhat.com \
--cc=schwab@suse.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).