aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust/backend/rust-constexpr.cc
diff options
context:
space:
mode:
authorFaisal Abbas <90.abbasfaisal@gmail.com>2022-07-30 18:24:42 +0100
committerPhilip Herron <philip.herron@embecosm.com>2022-08-25 12:40:26 +0100
commit266891d17c751d104d8c75e0258cf1b462756ad9 (patch)
tree15b7600afa59e77cca4105cf859d066f961e3e30 /gcc/rust/backend/rust-constexpr.cc
parentfdbe92d898f11a4d395b5ee9a547707675edf442 (diff)
downloadgcc-266891d17c751d104d8c75e0258cf1b462756ad9.zip
gcc-266891d17c751d104d8c75e0258cf1b462756ad9.tar.gz
gcc-266891d17c751d104d8c75e0258cf1b462756ad9.tar.bz2
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.
Diffstat (limited to 'gcc/rust/backend/rust-constexpr.cc')
-rw-r--r--gcc/rust/backend/rust-constexpr.cc141
1 files changed, 141 insertions, 0 deletions
diff --git a/gcc/rust/backend/rust-constexpr.cc b/gcc/rust/backend/rust-constexpr.cc
index 1244047..ebd6dde 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<void*>(sizeof 0)
+ */
+ if (!ctx->quiet)
+ error_at (loc,
+ "%<reinterpret_cast<%T>(%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;
}