https://gcc.gnu.org/g:d9de08d4cf6e8cb940015656da5a30ccbdb895b5
commit r17-4348-gd9de08d4cf6e8cb940015656da5a30ccbdb895b5 Author: Philip Herron <[email protected]> Date: Thu Sep 10 17:54:44 2026 +0100 gccrs: constructors that get borrowed need to be addressable When we have const expr dealing with slices we end up taking a pointer of an array as the data pointer. This is a cosntructor expr ususally but const eval expects these to be addressable objects like tmps holding onto the data but we get away with this in regular compilation because gcc optimizes it. Fixes Rust-GCC/gccrs#4867 Fixes Rust-GCC/gccrs#4868 gcc/rust/ChangeLog: * backend/rust-compile-expr.cc (CompileExpr::visit): make addressable * backend/rust-constexpr.cc (eval_store_expression): port over missing cp/constexpr.cc gcc/testsuite/ChangeLog: * rust/compile/issue-4867.rs: New test. Signed-off-by: Philip Herron <[email protected]> Diff: --- gcc/rust/backend/rust-compile-expr.cc | 15 +++++++++++++++ gcc/rust/backend/rust-constexpr.cc | 9 ++++++++- gcc/testsuite/rust/compile/issue-4867.rs | 28 ++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 1 deletion(-) diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc index 3229dea3646d..6480e946b155 100644 --- a/gcc/rust/backend/rust-compile-expr.cc +++ b/gcc/rust/backend/rust-compile-expr.cc @@ -1204,6 +1204,21 @@ CompileExpr::visit (HIR::BorrowExpr &expr) return; } + // const expr needs these to be addressable temps otherwise it cant cope. We + // get away with this during regular compilation because gcc middle end + // optimizes it + if (TREE_CODE (main_expr) == CONSTRUCTOR && !TREE_CONSTANT (main_expr)) + { + tree init_stmt = NULL_TREE; + Bvariable *tmp + = Backend::temporary_variable (ctx->peek_fn ().fndecl, + ctx->peek_enclosing_scope (), + TREE_TYPE (main_expr), main_expr, true, + expr.get_locus (), &init_stmt); + ctx->add_statement (init_stmt); + main_expr = Backend::var_expression (tmp, expr.get_locus ()); + } + TyTy::BaseType *tyty = nullptr; if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (), &tyty)) diff --git a/gcc/rust/backend/rust-constexpr.cc b/gcc/rust/backend/rust-constexpr.cc index 22d0ed3bd292..44fd235b925b 100644 --- a/gcc/rust/backend/rust-constexpr.cc +++ b/gcc/rust/backend/rust-constexpr.cc @@ -2763,7 +2763,14 @@ eval_store_expression (const constexpr_ctx *ctx, tree t, bool lval, /* Evaluate the value to be stored without knowing what object it will be stored in, so that any side-effects happen first. */ if (!SCALAR_TYPE_P (type)) - new_ctx.ctor = new_ctx.object = NULL_TREE; + { + new_ctx.ctor = new_ctx.object = NULL_TREE; + if (TREE_CODE (init) == CONSTRUCTOR) + { + new_ctx.ctor = build_constructor (TREE_TYPE (init), NULL); + CONSTRUCTOR_NO_CLEARING (new_ctx.ctor) = true; + } + } init = eval_constant_expression (&new_ctx, init, false, non_constant_p, overflow_p, jump_target); if (*non_constant_p) diff --git a/gcc/testsuite/rust/compile/issue-4867.rs b/gcc/testsuite/rust/compile/issue-4867.rs new file mode 100644 index 000000000000..7e6852347c74 --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-4867.rs @@ -0,0 +1,28 @@ +// { dg-options "-w" } +#![feature(intrinsics, staged_api)] +#![feature(no_core, lang_items)] +#![no_core] +#[lang = "sized"] +pub trait Sized {} +const X: () = trigger(); +extern "rust-intrinsic" { + #[rustc_const_stable(feature = "const_transmute", since = "1.0.0")] + fn transmute<T, U>(x: T) -> U; +} +struct Arg { + formatter: fn(&i8), + value: &'static i8, +} +const fn new<T>(x: &'static T, f: fn(&T)) -> Arg { + unsafe { + Arg { + formatter: transmute(f), + value: transmute(x), + } + } +} +const fn consume(x: &[Arg]) {} +const fn trigger() { + consume({ &[new(&1i8, display)] }); +} +fn display(x: &i8) {}
