This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [C++ PATCH] FIx constexpr virtual function call handling on ia64 (PR c++/87861)


On 12/8/18 4:07 AM, Jakub Jelinek wrote:
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?

OK.

Jason


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]