From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 14090 invoked by alias); 8 Dec 2018 09:07:28 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 14081 invoked by uid 89); 8 Dec 2018 09:07:27 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-16.9 required=5.0 tests=BAYES_00,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,SPF_HELO_PASS autolearn=ham version=3.3.2 spammy=marek, Marek, bump, designate X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Sat, 08 Dec 2018 09:07:24 +0000 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 13F073082DDD; Sat, 8 Dec 2018 09:07:23 +0000 (UTC) Received: from tucnak.zalov.cz (ovpn-117-214.ams2.redhat.com [10.36.117.214]) by smtp.corp.redhat.com (Postfix) with ESMTPS id CB07917010; Sat, 8 Dec 2018 09:07:18 +0000 (UTC) Received: from tucnak.zalov.cz (localhost [127.0.0.1]) by tucnak.zalov.cz (8.15.2/8.15.2) with ESMTP id wB897G0J028835; Sat, 8 Dec 2018 10:07:17 +0100 Received: (from jakub@localhost) by tucnak.zalov.cz (8.15.2/8.15.2/Submit) id wB897FOf028834; Sat, 8 Dec 2018 10:07:15 +0100 Date: Sat, 08 Dec 2018 09:07:00 -0000 From: Jakub Jelinek To: Jason Merrill Cc: Andreas Schwab , Marek Polacek , GCC Patches Subject: [C++ PATCH] FIx constexpr virtual function call handling on ia64 (PR c++/87861) Message-ID: <20181208090715.GS12380@tucnak> Reply-To: Jakub Jelinek References: <20180918185534.GR16755@redhat.com> <20180919140518.GN5587@redhat.com> <20180919151023.GO5587@redhat.com> <20180920092059.GE8250@tucnak> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.9.2 (2017-12-15) X-IsSubscribed: yes X-SW-Source: 2018-12/txt/msg00508.txt.bz2 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 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) : 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