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) {}

Reply via email to