diff options
author | Jakub Jelinek <jakub@gcc.gnu.org> | 2018-12-11 21:37:53 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2018-12-11 21:37:53 +0100 |
commit | 582d2481f7380441c345bf1dfe698f90f34dd6cf (patch) | |
tree | d4a98b7a3f984eb5a9776ad9a0437508358bea3e /gcc/cp/constexpr.c | |
parent | 3c0517a6531112d2dec16d18cdabb1513d387b7a (diff) | |
download | gcc-582d2481f7380441c345bf1dfe698f90f34dd6cf.zip gcc-582d2481f7380441c345bf1dfe698f90f34dd6cf.tar.gz gcc-582d2481f7380441c345bf1dfe698f90f34dd6cf.tar.bz2 |
re PR c++/87861 (ICE in output_constructor_regular_field, at varasm.c:5165)
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.
From-SVN: r267032
Diffstat (limited to 'gcc/cp/constexpr.c')
-rw-r--r-- | gcc/cp/constexpr.c | 37 |
1 files changed, 36 insertions, 1 deletions
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index 44db380..96326c3 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -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 constexpr_ctx *ctx, tree t, 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 constexpr_ctx *ctx, tree 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)); + if (TARGET_VTABLE_USES_DESCRIPTORS) + token /= MAX (TARGET_VTABLE_USES_DESCRIPTORS, 1); r = TREE_VALUE (chain_index (token, virtuals)); break; } |