aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust/backend/rust-constexpr.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/rust/backend/rust-constexpr.cc')
-rw-r--r--gcc/rust/backend/rust-constexpr.cc110
1 files changed, 110 insertions, 0 deletions
diff --git a/gcc/rust/backend/rust-constexpr.cc b/gcc/rust/backend/rust-constexpr.cc
index 357caef..3d7b8b0 100644
--- a/gcc/rust/backend/rust-constexpr.cc
+++ b/gcc/rust/backend/rust-constexpr.cc
@@ -825,6 +825,8 @@ rs_fold_indirect_ref (const constexpr_ctx *ctx, location_t loc, tree type,
return NULL_TREE;
}
+// forked from gcc/cp/constexpr.cc cxx_eval_indirect_ref
+
static tree
rs_eval_indirect_ref (const constexpr_ctx *ctx, tree t, bool lval,
bool *non_constant_p, bool *overflow_p)
@@ -935,6 +937,59 @@ eval_logical_expression (const constexpr_ctx *ctx, tree t, tree bailout_value,
return r;
}
+// forked from gcc/cp/constexp.rcc lookup_placeholder
+
+/* Find the object of TYPE under initialization in CTX. */
+
+static tree
+lookup_placeholder (const constexpr_ctx *ctx, bool lval, tree type)
+{
+ if (!ctx)
+ return NULL_TREE;
+
+ /* Prefer the outermost matching object, but don't cross
+ CONSTRUCTOR_PLACEHOLDER_BOUNDARY constructors. */
+ if (ctx->ctor && !CONSTRUCTOR_PLACEHOLDER_BOUNDARY (ctx->ctor))
+ if (tree outer_ob = lookup_placeholder (ctx->parent, lval, type))
+ return outer_ob;
+
+ /* We could use ctx->object unconditionally, but using ctx->ctor when we
+ can is a minor optimization. */
+ if (!lval && ctx->ctor && same_type_p (TREE_TYPE (ctx->ctor), type))
+ return ctx->ctor;
+
+ if (!ctx->object)
+ return NULL_TREE;
+
+ /* Since an object cannot have a field of its own type, we can search outward
+ from ctx->object to find the unique containing object of TYPE. */
+ tree ob = ctx->object;
+ while (ob)
+ {
+ if (same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (ob), type))
+ break;
+ if (handled_component_p (ob))
+ ob = TREE_OPERAND (ob, 0);
+ else
+ ob = NULL_TREE;
+ }
+
+ return ob;
+}
+
+// forked from gcc/cp/constexp.rcc inline_asm_in_constexpr_error
+
+/* Complain about an attempt to evaluate inline assembly. */
+
+static void
+inline_asm_in_constexpr_error (location_t loc)
+{
+ auto_diagnostic_group d;
+ error_at (loc, "inline assembly is not a constant expression");
+ inform (loc, "only unevaluated inline assembly is allowed in a "
+ "%<constexpr%> function in C++20");
+}
+
static tree
eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval,
bool *non_constant_p, bool *overflow_p,
@@ -1096,6 +1151,14 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval,
r = rs_eval_indirect_ref (ctx, t, lval, non_constant_p, overflow_p);
break;
+ case PAREN_EXPR:
+ gcc_assert (!REF_PARENTHESIZED_P (t));
+ /* A PAREN_EXPR resulting from __builtin_assoc_barrier has no effect in
+ constant expressions since it's unaffected by -fassociative-math. */
+ r = eval_constant_expression (ctx, TREE_OPERAND (t, 0), lval,
+ non_constant_p, overflow_p);
+ break;
+
case NOP_EXPR:
if (REINTERPRET_CAST_P (t))
{
@@ -1151,6 +1214,25 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval,
}
break;
+ case ADDR_EXPR: {
+ tree oldop = TREE_OPERAND (t, 0);
+ tree op = eval_constant_expression (ctx, oldop,
+ /*lval*/ true, non_constant_p,
+ overflow_p);
+ /* Don't VERIFY_CONSTANT here. */
+ if (*non_constant_p)
+ return t;
+ gcc_checking_assert (TREE_CODE (op) != CONSTRUCTOR);
+ /* This function does more aggressive folding than fold itself. */
+ r = build_fold_addr_expr_with_type (op, TREE_TYPE (t));
+ if (TREE_CODE (r) == ADDR_EXPR && TREE_OPERAND (r, 0) == oldop)
+ {
+ ggc_free (r);
+ return t;
+ }
+ break;
+ }
+
case REALPART_EXPR:
case IMAGPART_EXPR:
if (lval)
@@ -1362,6 +1444,34 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval,
}
break;
+ case PLACEHOLDER_EXPR:
+ /* Use of the value or address of the current object. */
+ if (tree ctor = lookup_placeholder (ctx, lval, TREE_TYPE (t)))
+ {
+ if (TREE_CODE (ctor) == CONSTRUCTOR)
+ return ctor;
+ else
+ return eval_constant_expression (ctx, ctor, lval, non_constant_p,
+ overflow_p);
+ }
+ /* A placeholder without a referent. We can get here when
+ checking whether NSDMIs are noexcept, or in massage_init_elt;
+ just say it's non-constant for now. */
+ gcc_assert (ctx->quiet);
+ *non_constant_p = true;
+ break;
+
+ case ANNOTATE_EXPR:
+ r = eval_constant_expression (ctx, TREE_OPERAND (t, 0), lval,
+ non_constant_p, overflow_p, jump_target);
+ break;
+
+ case ASM_EXPR:
+ if (!ctx->quiet)
+ inline_asm_in_constexpr_error (loc);
+ *non_constant_p = true;
+ return t;
+
default:
break;
}