aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust/backend/rust-constexpr.cc
diff options
context:
space:
mode:
authorFaisal Abbas <90.abbasfaisal@gmail.com>2022-08-08 12:09:44 +0100
committerPhilip Herron <philip.herron@embecosm.com>2022-08-25 12:40:27 +0100
commitbd31c63fe15c4e39d3036ff7adcd22eadd6b53ea (patch)
tree94b8456931257c82bc75a91c5292f856e12b0e1e /gcc/rust/backend/rust-constexpr.cc
parenta38ad0b614ff5d601e5425824ad760235710eee5 (diff)
downloadgcc-bd31c63fe15c4e39d3036ff7adcd22eadd6b53ea.zip
gcc-bd31c63fe15c4e39d3036ff7adcd22eadd6b53ea.tar.gz
gcc-bd31c63fe15c4e39d3036ff7adcd22eadd6b53ea.tar.bz2
rust-constexpr.cc: port over more cases to eval_constant_expression
Diffstat (limited to 'gcc/rust/backend/rust-constexpr.cc')
-rw-r--r--gcc/rust/backend/rust-constexpr.cc132
1 files changed, 117 insertions, 15 deletions
diff --git a/gcc/rust/backend/rust-constexpr.cc b/gcc/rust/backend/rust-constexpr.cc
index 340960e..df4ceba 100644
--- a/gcc/rust/backend/rust-constexpr.cc
+++ b/gcc/rust/backend/rust-constexpr.cc
@@ -1514,6 +1514,21 @@ reduced_constant_expression_p (tree t)
}
}
+/* TEMP is the constant value of a temporary object of type TYPE. Adjust
+ the type of the value to match. */
+
+static tree
+adjust_temp_type (tree type, tree temp)
+{
+ if (same_type_p (TREE_TYPE (temp), type))
+ return temp;
+
+ gcc_assert (scalarish_type_p (type));
+ /* Now we know we're dealing with a scalar, and a prvalue of non-class
+ type is cv-unqualified. */
+ return fold_convert (cv_unqualified (type), temp);
+}
+
static tree
eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval,
bool *non_constant_p, bool *overflow_p,
@@ -1544,6 +1559,7 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval,
return t;
}
+ constexpr_ctx new_ctx;
tree r = t;
tree_code tcode = TREE_CODE (t);
switch (tcode)
@@ -1561,6 +1577,14 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval,
}
break;
+ case VAR_DECL:
+ if (DECL_HAS_VALUE_EXPR_P (t))
+ {
+ r = DECL_VALUE_EXPR (t);
+ return eval_constant_expression (ctx, r, lval, non_constant_p,
+ overflow_p);
+ }
+
case PARM_DECL:
if (lval && !TYPE_REF_P (TREE_TYPE (t)))
/* glvalue use. */;
@@ -1643,6 +1667,67 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval,
overflow_p);
break;
+ case TARGET_EXPR: {
+ tree type = TREE_TYPE (t);
+
+ if (!literal_type_p (type))
+ {
+ if (!ctx->quiet)
+ {
+ auto_diagnostic_group d;
+ error ("temporary of non-literal type %qT in a "
+ "constant expression",
+ type);
+ // explain_non_literal_class (type);
+ }
+ *non_constant_p = true;
+ break;
+ }
+ gcc_checking_assert (!TARGET_EXPR_DIRECT_INIT_P (t));
+ /* Avoid evaluating a TARGET_EXPR more than once. */
+ tree slot = TARGET_EXPR_SLOT (t);
+ if (tree *p = ctx->global->values.get (slot))
+ {
+ if (lval)
+ return slot;
+ r = *p;
+ break;
+ }
+ if ((AGGREGATE_TYPE_P (type) || VECTOR_TYPE_P (type)))
+ {
+ /* We're being expanded without an explicit target, so start
+ initializing a new object; expansion with an explicit target
+ strips the TARGET_EXPR before we get here. */
+ new_ctx = *ctx;
+ /* Link CTX to NEW_CTX so that lookup_placeholder can resolve
+ any PLACEHOLDER_EXPR within the initializer that refers to the
+ former object under construction. */
+ new_ctx.parent = ctx;
+ new_ctx.ctor = build_constructor (type, NULL);
+ CONSTRUCTOR_NO_CLEARING (new_ctx.ctor) = true;
+ new_ctx.object = slot;
+ ctx->global->values.put (new_ctx.object, new_ctx.ctor);
+ ctx = &new_ctx;
+ }
+ /* Pass false for 'lval' because this indicates
+ initialization of a temporary. */
+ r = eval_constant_expression (ctx, TREE_OPERAND (t, 1), false,
+ non_constant_p, overflow_p);
+ if (*non_constant_p)
+ break;
+ /* Adjust the type of the result to the type of the temporary. */
+ r = adjust_temp_type (type, r);
+ if (TARGET_EXPR_CLEANUP (t) && !CLEANUP_EH_ONLY (t))
+ ctx->global->cleanups->safe_push (TARGET_EXPR_CLEANUP (t));
+ r = unshare_constructor (r);
+ ctx->global->values.put (slot, r);
+ if (ctx->save_exprs)
+ ctx->save_exprs->safe_push (slot);
+ if (lval)
+ return slot;
+ }
+ break;
+
case CALL_EXPR:
r = eval_call_expression (ctx, t, false, non_constant_p, overflow_p);
break;
@@ -1667,6 +1752,38 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval,
}
break;
+ case DECL_EXPR: {
+ r = DECL_EXPR_DECL (t);
+
+ if (AGGREGATE_TYPE_P (TREE_TYPE (r)) || VECTOR_TYPE_P (TREE_TYPE (r)))
+ {
+ new_ctx = *ctx;
+ new_ctx.object = r;
+ new_ctx.ctor = build_constructor (TREE_TYPE (r), NULL);
+ CONSTRUCTOR_NO_CLEARING (new_ctx.ctor) = true;
+ ctx->global->values.put (r, new_ctx.ctor);
+ ctx = &new_ctx;
+ }
+
+ if (tree init = DECL_INITIAL (r))
+ {
+ init = eval_constant_expression (ctx, init, false, non_constant_p,
+ overflow_p);
+ /* Don't share a CONSTRUCTOR that might be changed. */
+ init = unshare_constructor (init);
+ /* Remember that a constant object's constructor has already
+ run. */
+ if (CLASS_TYPE_P (TREE_TYPE (r)) && RS_TYPE_CONST_P (TREE_TYPE (r)))
+ TREE_READONLY (init) = true;
+ ctx->global->values.put (r, init);
+ }
+ else if (ctx == &new_ctx)
+ /* We gave it a CONSTRUCTOR above. */;
+ else
+ ctx->global->values.put (r, NULL_TREE);
+ }
+ break;
+
/* These differ from cxx_eval_unary_expression in that this doesn't
check for a constant operand or result; an address can be
constant without its operand being, and vice versa. */
@@ -2526,21 +2643,6 @@ eval_binary_expression (const constexpr_ctx *ctx, tree t, bool lval,
return fold_binary_loc (loc, code, type, lhs, rhs);
}
-/* TEMP is the constant value of a temporary object of type TYPE. Adjust
- the type of the value to match. */
-
-static tree
-adjust_temp_type (tree type, tree temp)
-{
- if (same_type_p (TREE_TYPE (temp), type))
- return temp;
-
- gcc_assert (scalarish_type_p (type));
- /* Now we know we're dealing with a scalar, and a prvalue of non-class
- type is cv-unqualified. */
- return fold_convert (cv_unqualified (type), temp);
-}
-
/* Helper function of cxx_bind_parameters_in_call. Return non-NULL
if *TP is address of a static variable (or part of it) currently being
constructed or of a heap artificial variable. */