From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1643) id 18D21385AC2C; Mon, 29 Aug 2022 15:34:05 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 18D21385AC2C DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1661787245; bh=2cOJEFe1+QKha7ztaCCvbwj5XxdRVN4M+ifIrBY3tDc=; h=From:To:Subject:Date:From; b=XKyUKC8JSqLH6ALuRuSElFmThfjvTBzePG1KlKZsrNwWtFk6fJoAuEd/QO3M1vPqc oU6VeCIuodlR4SPfDBxpk4RYqzl1+xw4a02I0Z3XGyO+GHEDSlULspCDOGZf/b9eSU 2BNVWJGjM4U0VBbrZFt2y+kVZv/Y1JheFKhQPNfM= Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Thomas Schwinge To: gcc-cvs@gcc.gnu.org Subject: [gcc/devel/rust/master] rust-constexpr.cc: port VIEW_CONVERT_EXPR and CONVERT_EXPR cases to eval_constant_expression(). Thro X-Act-Checkin: gcc X-Git-Author: Faisal Abbas <90.abbasfaisal@gmail.com> X-Git-Refname: refs/heads/devel/rust/master X-Git-Oldrev: fdbe92d898f11a4d395b5ee9a547707675edf442 X-Git-Newrev: 266891d17c751d104d8c75e0258cf1b462756ad9 Message-Id: <20220829153405.18D21385AC2C@sourceware.org> Date: Mon, 29 Aug 2022 15:34:05 +0000 (GMT) List-Id: https://gcc.gnu.org/g:266891d17c751d104d8c75e0258cf1b462756ad9 commit 266891d17c751d104d8c75e0258cf1b462756ad9 Author: Faisal Abbas <90.abbasfaisal@gmail.com> Date: Sat Jul 30 18:24:42 2022 +0100 rust-constexpr.cc: port VIEW_CONVERT_EXPR and CONVERT_EXPR cases to eval_constant_expression(). Throws away code under UNARY_PLUS_EXPR and PTRMEM_CST as those tree codes come from cp-tree.def. Diff: --- gcc/rust/backend/rust-constexpr.cc | 141 +++++++++++++++++++++++++++++++++++++ gcc/rust/backend/rust-tree.cc | 46 ++++++++++++ gcc/rust/backend/rust-tree.h | 17 +++++ 3 files changed, 204 insertions(+) diff --git a/gcc/rust/backend/rust-constexpr.cc b/gcc/rust/backend/rust-constexpr.cc index 1244047ef4f..ebd6ddec89d 100644 --- a/gcc/rust/backend/rust-constexpr.cc +++ b/gcc/rust/backend/rust-constexpr.cc @@ -574,6 +574,18 @@ fold_expr (tree expr) return folded; } +static bool +same_type_ignoring_tlq_and_bounds_p (tree type1, tree type2) +{ + while (TREE_CODE (type1) == ARRAY_TYPE && TREE_CODE (type2) == ARRAY_TYPE + && (!TYPE_DOMAIN (type1) || !TYPE_DOMAIN (type2))) + { + type1 = TREE_TYPE (type1); + type2 = TREE_TYPE (type2); + } + return same_type_ignoring_top_level_qualifiers_p (type1, type2); +} + static tree eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, bool *non_constant_p, bool *overflow_p, @@ -848,6 +860,135 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, jump_target); break; + /* FALLTHROUGH. */ + case CONVERT_EXPR: + case VIEW_CONVERT_EXPR: { + tree oldop = TREE_OPERAND (t, 0); + + tree op = eval_constant_expression (ctx, oldop, lval, non_constant_p, + overflow_p); + if (*non_constant_p) + return t; + tree type = TREE_TYPE (t); + + if (VOID_TYPE_P (type)) + return void_node; + + if (TREE_CODE (t) == CONVERT_EXPR && ARITHMETIC_TYPE_P (type) + && INDIRECT_TYPE_P (TREE_TYPE (op)) && ctx->manifestly_const_eval) + { + if (!ctx->quiet) + error_at (loc, + "conversion from pointer type %qT to arithmetic type " + "%qT in a constant expression", + TREE_TYPE (op), type); + *non_constant_p = true; + return t; + } + + if (TYPE_PTROB_P (type) && TYPE_PTR_P (TREE_TYPE (op)) + && VOID_TYPE_P (TREE_TYPE (TREE_TYPE (op)))) + { + /* Likewise, don't error when casting from void* when OP is + &heap uninit and similar. */ + tree sop = tree_strip_nop_conversions (op); + if (TREE_CODE (sop) == ADDR_EXPR && VAR_P (TREE_OPERAND (sop, 0)) + && DECL_ARTIFICIAL (TREE_OPERAND (sop, 0))) + /* OK */; + else + { + if (!ctx->quiet) + error_at (loc, "cast from %qT is not allowed", + TREE_TYPE (op)); + *non_constant_p = true; + return t; + } + } + + if (INDIRECT_TYPE_P (type) && TREE_CODE (op) == INTEGER_CST) + { + if (integer_zerop (op)) + { + if (TYPE_REF_P (type)) + { + if (!ctx->quiet) + error_at (loc, "dereferencing a null pointer"); + *non_constant_p = true; + return t; + } + } + else + { + /* This detects for example: + reinterpret_cast(sizeof 0) + */ + if (!ctx->quiet) + error_at (loc, + "%(%E)%> is not " + "a constant expression", + type, op); + *non_constant_p = true; + return t; + } + } + + if (INDIRECT_TYPE_P (type) && TREE_CODE (op) == NOP_EXPR + && TREE_TYPE (op) == ptr_type_node + && TREE_CODE (TREE_OPERAND (op, 0)) == ADDR_EXPR + && VAR_P (TREE_OPERAND (TREE_OPERAND (op, 0), 0)) + && (DECL_NAME (TREE_OPERAND (TREE_OPERAND (op, 0), 0)) + == heap_uninit_identifier + || DECL_NAME (TREE_OPERAND (TREE_OPERAND (op, 0), 0)) + == heap_vec_uninit_identifier)) + { + tree var = TREE_OPERAND (TREE_OPERAND (op, 0), 0); + tree var_size = TYPE_SIZE_UNIT (TREE_TYPE (var)); + tree elt_type = TREE_TYPE (type); + tree cookie_size = NULL_TREE; + if (TREE_CODE (elt_type) == RECORD_TYPE + && TYPE_NAME (elt_type) == heap_identifier) + { + tree fld1 = TYPE_FIELDS (elt_type); + tree fld2 = DECL_CHAIN (fld1); + elt_type = TREE_TYPE (TREE_TYPE (fld2)); + cookie_size = TYPE_SIZE_UNIT (TREE_TYPE (fld1)); + } + DECL_NAME (var) = (DECL_NAME (var) == heap_uninit_identifier + ? heap_identifier + : heap_vec_identifier); + TREE_TYPE (var) + = build_new_constexpr_heap_type (elt_type, cookie_size, var_size); + TREE_TYPE (TREE_OPERAND (op, 0)) + = build_pointer_type (TREE_TYPE (var)); + } + + if (op == oldop) + /* We didn't fold at the top so we could check for ptr-int + conversion. */ + return fold (t); + + tree sop; + + /* Handle an array's bounds having been deduced after we built + the wrapping expression. */ + if (same_type_ignoring_tlq_and_bounds_p (type, TREE_TYPE (op))) + r = op; + else if (sop = tree_strip_nop_conversions (op), + sop != op + && (same_type_ignoring_tlq_and_bounds_p (type, + TREE_TYPE (sop)))) + r = sop; + else + r = fold_build1 (tcode, type, op); + + /* Conversion of an out-of-range value has implementation-defined + behavior; the language considers it different from arithmetic + overflow, which is undefined. */ + if (TREE_OVERFLOW_P (r) && !TREE_OVERFLOW_P (op)) + TREE_OVERFLOW (r) = false; + } + break; + default: break; } diff --git a/gcc/rust/backend/rust-tree.cc b/gcc/rust/backend/rust-tree.cc index 98c112a7d83..82b58459d6f 100644 --- a/gcc/rust/backend/rust-tree.cc +++ b/gcc/rust/backend/rust-tree.cc @@ -4033,4 +4033,50 @@ location_of (tree t) return EXPR_LOCATION (t); } +/* For element type ELT_TYPE, return the appropriate type of the heap object + containing such element(s). COOKIE_SIZE is NULL or the size of cookie + in bytes. FULL_SIZE is NULL if it is unknown how big the heap allocation + will be, otherwise size of the heap object. If COOKIE_SIZE is NULL, + return array type ELT_TYPE[FULL_SIZE / sizeof(ELT_TYPE)], otherwise return + struct { size_t[COOKIE_SIZE/sizeof(size_t)]; ELT_TYPE[N]; } + where N is nothing (flexible array member) if FULL_SIZE is NULL, otherwise + it is computed such that the size of the struct fits into FULL_SIZE. */ + +tree +build_new_constexpr_heap_type (tree elt_type, tree cookie_size, tree full_size) +{ + gcc_assert (cookie_size == NULL_TREE || tree_fits_uhwi_p (cookie_size)); + gcc_assert (full_size == NULL_TREE || tree_fits_uhwi_p (full_size)); + unsigned HOST_WIDE_INT csz = cookie_size ? tree_to_uhwi (cookie_size) : 0; + tree itype2 = NULL_TREE; + if (full_size) + { + unsigned HOST_WIDE_INT fsz = tree_to_uhwi (full_size); + gcc_assert (fsz >= csz); + fsz -= csz; + fsz /= int_size_in_bytes (elt_type); + itype2 = build_index_type (size_int (fsz - 1)); + if (!cookie_size) + return build_cplus_array_type (elt_type, itype2); + } + else + gcc_assert (cookie_size); + csz /= int_size_in_bytes (sizetype); + tree itype1 = build_index_type (size_int (csz - 1)); + tree atype1 = build_cplus_array_type (sizetype, itype1); + tree atype2 = build_cplus_array_type (elt_type, itype2); + tree rtype = cxx_make_type (RECORD_TYPE); + TYPE_NAME (rtype) = heap_identifier; + tree fld1 = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE, atype1); + tree fld2 = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE, atype2); + DECL_FIELD_CONTEXT (fld1) = rtype; + DECL_FIELD_CONTEXT (fld2) = rtype; + DECL_ARTIFICIAL (fld1) = true; + DECL_ARTIFICIAL (fld2) = true; + TYPE_FIELDS (rtype) = fld1; + DECL_CHAIN (fld1) = fld2; + layout_type (rtype); + return rtype; +} + } // namespace Rust diff --git a/gcc/rust/backend/rust-tree.h b/gcc/rust/backend/rust-tree.h index b7c4676f0ab..d4b7d8671fe 100644 --- a/gcc/rust/backend/rust-tree.h +++ b/gcc/rust/backend/rust-tree.h @@ -1248,6 +1248,21 @@ extern GTY (()) tree cp_global_trees[CPTI_MAX]; are not constexprs. Other NOP_EXPRs are. */ #define REINTERPRET_CAST_P(NODE) TREE_LANG_FLAG_0 (NOP_EXPR_CHECK (NODE)) +/* Returns true if NODE is an object type: + + [basic.types] + + An object type is a (possibly cv-qualified) type that is not a + function type, not a reference type, and not a void type. + + Keep these checks in ascending order, for speed. */ +#define TYPE_OBJ_P(NODE) \ + (!TYPE_REF_P (NODE) && !VOID_TYPE_P (NODE) && !FUNC_OR_METHOD_TYPE_P (NODE)) + +/* Returns true if NODE is a pointer to an object. Keep these checks + in ascending tree code order. */ +#define TYPE_PTROB_P(NODE) (TYPE_PTR_P (NODE) && TYPE_OBJ_P (TREE_TYPE (NODE))) + #if defined ENABLE_TREE_CHECKING #define LANG_DECL_MIN_CHECK(NODE) \ @@ -2582,6 +2597,8 @@ extern bool require_deduced_type (tree, tsubst_flags_t = tf_warning_or_error); extern bool decl_constant_var_p (tree); +extern tree build_new_constexpr_heap_type (tree, tree, tree); + // forked from gcc/cp/cp-tree.h enum