https://gcc.gnu.org/g:4a04226a360057f555cc8bc3577f93501a728896

commit r17-2229-g4a04226a360057f555cc8bc3577f93501a728896
Author: Philip Herron <[email protected]>
Date:   Wed Jun 24 15:02:45 2026 +0100

    gccrs: Fix ICE when handling offset on types with unknown size
    
    This patch also threads through the expr locus for where intrinsics are
    called from so we can improve the diagnostics.
    
    Fixes Rust-GCC#4592
    
    gcc/rust/ChangeLog:
    
            * backend/rust-compile-extern.h: add expr locus
            * backend/rust-compile-intrinsic.cc (Intrinsics::compile): likewise
            * backend/rust-compile-intrinsic.h: likewise
            * backend/rust-compile-resolve-path.cc: likewise
            * backend/rust-intrinsic-handlers.cc (op_with_overflow): likewise
            (rotate_left): likewise
            (rotate_right): likewise
            (wrapping_op): likewise
            (atomic_store): likewise
            (atomic_load): likewise
            (unchecked_op): likewise
            (copy): likewise
            (expect): likewise
            (try_handler): likewise
            (sorry): likewise
            (assume): likewise
            (discriminant_value): likewise
            (variant_count): likewise
            (move_val_init): likewise
            (uninit): likewise
            (prefetch_read_data): likewise
            (prefetch_write_data): likewise
            (transmute): likewise
            (sizeof_handler): likewise
            (min_align_of_handler): likewise
            (offset): likewise
            (bswap_handler): likewise
            (ctlz_handler): likewise
            (ctlz_nonzero_handler): likewise
            (cttz_handler): likewise
            (cttz_nonzero_handler): likewise
            * backend/rust-intrinsic-handlers.h (std::function<tree): likewise
            (rotate_left): likewise
            (rotate_right): likewise
            (offset): likewise
            (sizeof_handler): likewise
            (min_align_of_handler): likewise
            (transmute): likewise
            (uninit): likewise
            (move_val_init): likewise
            (assume): likewise
            (discriminant_value): likewise
            (variant_count): likewise
            (bswap_handler): likewise
            (ctlz_handler): likewise
            (ctlz_nonzero_handler): likewise
            (cttz_handler): likewise
            (cttz_nonzero_handler): likewise
            (wrapping_op): likewise
            (prefetch_read_data): likewise
            (prefetch_write_data): likewise
            (sorry): likewise
            * backend/rust-tree.cc (pointer_offset_expression): check for size
    
    gcc/testsuite/ChangeLog:
    
            * rust/compile/issue-4592.rs: New test.
    
    Signed-off-by: Philip Herron <[email protected]>

Diff:
---
 gcc/rust/backend/rust-compile-extern.h        |  2 +-
 gcc/rust/backend/rust-compile-intrinsic.cc    |  4 +-
 gcc/rust/backend/rust-compile-intrinsic.h     |  3 +-
 gcc/rust/backend/rust-compile-resolve-path.cc |  2 +-
 gcc/rust/backend/rust-intrinsic-handlers.cc   | 57 +++++++++++++--------------
 gcc/rust/backend/rust-intrinsic-handlers.h    | 50 ++++++++++++-----------
 gcc/rust/backend/rust-tree.cc                 |  9 ++++-
 gcc/testsuite/rust/compile/issue-4592.rs      | 22 +++++++++++
 8 files changed, 89 insertions(+), 60 deletions(-)

diff --git a/gcc/rust/backend/rust-compile-extern.h 
b/gcc/rust/backend/rust-compile-extern.h
index c0dfab096a62..4eabf0ddb853 100644
--- a/gcc/rust/backend/rust-compile-extern.h
+++ b/gcc/rust/backend/rust-compile-extern.h
@@ -118,7 +118,7 @@ public:
     if (fntype->get_abi () == ABI::INTRINSIC)
       {
        Intrinsics compile (ctx);
-       tree fndecl = compile.compile (fntype);
+       tree fndecl = compile.compile (fntype, ref_locus);
        ctx->insert_function_decl (fntype, fndecl);
        return;
       }
diff --git a/gcc/rust/backend/rust-compile-intrinsic.cc 
b/gcc/rust/backend/rust-compile-intrinsic.cc
index ab6423092735..a00b2a50ef07 100644
--- a/gcc/rust/backend/rust-compile-intrinsic.cc
+++ b/gcc/rust/backend/rust-compile-intrinsic.cc
@@ -86,7 +86,7 @@ Intrinsics::Intrinsics (Context *ctx) : ctx (ctx) {}
  * compiler
  */
 tree
-Intrinsics::compile (TyTy::FnType *fntype)
+Intrinsics::compile (TyTy::FnType *fntype, location_t expr_locus)
 {
   rust_assert (fntype->get_abi () == ABI::INTRINSIC);
 
@@ -99,7 +99,7 @@ Intrinsics::compile (TyTy::FnType *fntype)
   // is it an generic builtin?
   auto it = generic_intrinsics.find (fntype->get_identifier ());
   if (it != generic_intrinsics.end ())
-    return it->second (ctx, fntype);
+    return it->second (ctx, fntype, expr_locus);
 
   location_t locus = ctx->get_mappings ().lookup_location (fntype->get_ref ());
   rust_error_at (locus, ErrorCode::E0093,
diff --git a/gcc/rust/backend/rust-compile-intrinsic.h 
b/gcc/rust/backend/rust-compile-intrinsic.h
index dceb0864fd49..33011734e2a1 100644
--- a/gcc/rust/backend/rust-compile-intrinsic.h
+++ b/gcc/rust/backend/rust-compile-intrinsic.h
@@ -18,7 +18,6 @@
 #define RUST_COMPILE_INTRINSIC
 
 #include "rust-compile-context.h"
-#include "langhooks.h"
 
 namespace Rust {
 namespace Compile {
@@ -28,7 +27,7 @@ class Intrinsics
 public:
   Intrinsics (Context *ctx);
 
-  tree compile (TyTy::FnType *fntype);
+  tree compile (TyTy::FnType *fntype, location_t expr_locus);
 
 private:
   Context *ctx;
diff --git a/gcc/rust/backend/rust-compile-resolve-path.cc 
b/gcc/rust/backend/rust-compile-resolve-path.cc
index 2cfdca5de7ca..d665df70f07e 100644
--- a/gcc/rust/backend/rust-compile-resolve-path.cc
+++ b/gcc/rust/backend/rust-compile-resolve-path.cc
@@ -182,7 +182,7 @@ ResolvePathRef::resolve_with_node_id (
       else if (fntype->get_abi () == ABI::INTRINSIC)
        {
          Intrinsics compile (ctx);
-         fn = compile.compile (fntype);
+         fn = compile.compile (fntype, expr_locus);
          TREE_USED (fn) = 1;
          return address_expression (fn, expr_locus);
        }
diff --git a/gcc/rust/backend/rust-intrinsic-handlers.cc 
b/gcc/rust/backend/rust-intrinsic-handlers.cc
index 39432ea7c580..8ea93d7f781c 100644
--- a/gcc/rust/backend/rust-intrinsic-handlers.cc
+++ b/gcc/rust/backend/rust-intrinsic-handlers.cc
@@ -1029,19 +1029,19 @@ cttz_handler (Context *ctx, TyTy::FnType *fntype, bool 
nonzero)
 const HandlerBuilder
 op_with_overflow (tree_code op)
 {
-  return [op] (Context *ctx, TyTy::FnType *fntype) {
+  return [op] (Context *ctx, TyTy::FnType *fntype, location_t) {
     return inner::op_with_overflow (ctx, fntype, op);
   };
 }
 
 tree
-rotate_left (Context *ctx, TyTy::FnType *fntype)
+rotate_left (Context *ctx, TyTy::FnType *fntype, location_t)
 {
   return handlers::rotate (ctx, fntype, LROTATE_EXPR);
 }
 
 tree
-rotate_right (Context *ctx, TyTy::FnType *fntype)
+rotate_right (Context *ctx, TyTy::FnType *fntype, location_t)
 {
   return handlers::rotate (ctx, fntype, RROTATE_EXPR);
 }
@@ -1049,7 +1049,7 @@ rotate_right (Context *ctx, TyTy::FnType *fntype)
 const HandlerBuilder
 wrapping_op (tree_code op)
 {
-  return [op] (Context *ctx, TyTy::FnType *fntype) {
+  return [op] (Context *ctx, TyTy::FnType *fntype, location_t) {
     return inner::wrapping_op (ctx, fntype, op);
   };
 }
@@ -1057,7 +1057,7 @@ wrapping_op (tree_code op)
 HandlerBuilder
 atomic_store (int ordering)
 {
-  return [ordering] (Context *ctx, TyTy::FnType *fntype) {
+  return [ordering] (Context *ctx, TyTy::FnType *fntype, location_t) {
     return inner::atomic_store (ctx, fntype, ordering);
   };
 }
@@ -1065,7 +1065,7 @@ atomic_store (int ordering)
 HandlerBuilder
 atomic_load (int ordering)
 {
-  return [ordering] (Context *ctx, TyTy::FnType *fntype) {
+  return [ordering] (Context *ctx, TyTy::FnType *fntype, location_t) {
     return inner::atomic_load (ctx, fntype, ordering);
   };
 }
@@ -1073,7 +1073,7 @@ atomic_load (int ordering)
 const HandlerBuilder
 unchecked_op (tree_code op)
 {
-  return [op] (Context *ctx, TyTy::FnType *fntype) {
+  return [op] (Context *ctx, TyTy::FnType *fntype, location_t) {
     return inner::unchecked_op (ctx, fntype, op);
   };
 }
@@ -1081,7 +1081,7 @@ unchecked_op (tree_code op)
 const HandlerBuilder
 copy (bool overlaps)
 {
-  return [overlaps] (Context *ctx, TyTy::FnType *fntype) {
+  return [overlaps] (Context *ctx, TyTy::FnType *fntype, location_t) {
     return inner::copy (ctx, fntype, overlaps);
   };
 }
@@ -1089,7 +1089,7 @@ copy (bool overlaps)
 const HandlerBuilder
 expect (bool likely)
 {
-  return [likely] (Context *ctx, TyTy::FnType *fntype) {
+  return [likely] (Context *ctx, TyTy::FnType *fntype, location_t) {
     return inner::expect (ctx, fntype, likely);
   };
 }
@@ -1097,13 +1097,13 @@ expect (bool likely)
 const HandlerBuilder
 try_handler (bool is_new_api)
 {
-  return [is_new_api] (Context *ctx, TyTy::FnType *fntype) {
+  return [is_new_api] (Context *ctx, TyTy::FnType *fntype, location_t) {
     return inner::try_handler (ctx, fntype, is_new_api);
   };
 }
 
 tree
-sorry (Context *ctx, TyTy::FnType *fntype)
+sorry (Context *ctx, TyTy::FnType *fntype, location_t)
 {
   rust_sorry_at (fntype->get_locus (), "intrinsic %qs is not yet implemented",
                 fntype->get_identifier ().c_str ());
@@ -1112,7 +1112,7 @@ sorry (Context *ctx, TyTy::FnType *fntype)
 }
 
 tree
-assume (Context *ctx, TyTy::FnType *fntype)
+assume (Context *ctx, TyTy::FnType *fntype, location_t)
 {
   // TODO: make sure this is actually helping the compiler optimize
 
@@ -1157,7 +1157,7 @@ assume (Context *ctx, TyTy::FnType *fntype)
 }
 
 tree
-discriminant_value (Context *ctx, TyTy::FnType *fntype)
+discriminant_value (Context *ctx, TyTy::FnType *fntype, location_t)
 {
   rust_assert (fntype->get_params ().size () == 1);
   rust_assert (fntype->has_substitutions ());
@@ -1218,7 +1218,7 @@ discriminant_value (Context *ctx, TyTy::FnType *fntype)
 }
 
 tree
-variant_count (Context *ctx, TyTy::FnType *fntype)
+variant_count (Context *ctx, TyTy::FnType *fntype, location_t)
 {
   rust_assert (fntype->get_num_type_params () == 1);
   auto &mapping = fntype->get_substs ().at (0);
@@ -1269,7 +1269,7 @@ variant_count (Context *ctx, TyTy::FnType *fntype)
 }
 
 tree
-move_val_init (Context *ctx, TyTy::FnType *fntype)
+move_val_init (Context *ctx, TyTy::FnType *fntype, location_t)
 {
   rust_assert (fntype->get_params ().size () == 2);
 
@@ -1323,7 +1323,7 @@ move_val_init (Context *ctx, TyTy::FnType *fntype)
 }
 
 tree
-uninit (Context *ctx, TyTy::FnType *fntype)
+uninit (Context *ctx, TyTy::FnType *fntype, location_t)
 {
   // uninit has _zero_ parameters its parameter is the generic one
   rust_assert (fntype->get_params ().size () == 0);
@@ -1389,12 +1389,12 @@ uninit (Context *ctx, TyTy::FnType *fntype)
 }
 
 tree
-prefetch_read_data (Context *ctx, TyTy::FnType *fntype)
+prefetch_read_data (Context *ctx, TyTy::FnType *fntype, location_t)
 {
   return prefetch_data (ctx, fntype, Prefetch::Read);
 }
 tree
-prefetch_write_data (Context *ctx, TyTy::FnType *fntype)
+prefetch_write_data (Context *ctx, TyTy::FnType *fntype, location_t)
 {
   return prefetch_data (ctx, fntype, Prefetch::Write);
 }
@@ -1502,7 +1502,7 @@ rotate (Context *ctx, TyTy::FnType *fntype, tree_code op)
 }
 
 tree
-transmute (Context *ctx, TyTy::FnType *fntype)
+transmute (Context *ctx, TyTy::FnType *fntype, location_t)
 {
   // transmute intrinsic has one parameter
   rust_assert (fntype->get_params ().size () == 1);
@@ -1576,7 +1576,7 @@ transmute (Context *ctx, TyTy::FnType *fntype)
 }
 
 tree
-sizeof_handler (Context *ctx, TyTy::FnType *fntype)
+sizeof_handler (Context *ctx, TyTy::FnType *fntype, location_t)
 {
   // size_of has _zero_ parameters its parameter is the generic one
   rust_assert (fntype->get_params ().size () == 0);
@@ -1613,7 +1613,7 @@ sizeof_handler (Context *ctx, TyTy::FnType *fntype)
  * pub fn min_align_of<T>() -> usize;
  */
 tree
-min_align_of_handler (Context *ctx, TyTy::FnType *fntype)
+min_align_of_handler (Context *ctx, TyTy::FnType *fntype, location_t)
 {
   // min_align_of has _zero_ parameters its parameter is the generic one
   rust_assert (fntype->get_params ().size () == 0);
@@ -1649,7 +1649,7 @@ min_align_of_handler (Context *ctx, TyTy::FnType *fntype)
 }
 
 tree
-offset (Context *ctx, TyTy::FnType *fntype)
+offset (Context *ctx, TyTy::FnType *fntype, location_t expr_locus)
 {
   // offset intrinsic has two params dst pointer and offset isize
   rust_assert (fntype->get_params ().size () == 2);
@@ -1670,8 +1670,7 @@ offset (Context *ctx, TyTy::FnType *fntype)
   // BUILTIN offset FN BODY BEGIN
   tree dst = Backend::var_expression (dst_param, UNDEF_LOCATION);
   tree size = Backend::var_expression (size_param, UNDEF_LOCATION);
-  tree pointer_offset_expr
-    = pointer_offset_expression (dst, size, BUILTINS_LOCATION);
+  tree pointer_offset_expr = pointer_offset_expression (dst, size, expr_locus);
   auto return_statement
     = Backend::return_statement (fndecl, pointer_offset_expr, UNDEF_LOCATION);
   ctx->add_statement (return_statement);
@@ -1686,7 +1685,7 @@ offset (Context *ctx, TyTy::FnType *fntype)
  * pub const fn bswap<T: Copy>(x: T) -> T;
  */
 tree
-bswap_handler (Context *ctx, TyTy::FnType *fntype)
+bswap_handler (Context *ctx, TyTy::FnType *fntype, location_t)
 {
   rust_assert (fntype->get_params ().size () == 1);
 
@@ -1843,25 +1842,25 @@ bswap_handler (Context *ctx, TyTy::FnType *fntype)
 }
 
 tree
-ctlz_handler (Context *ctx, TyTy::FnType *fntype)
+ctlz_handler (Context *ctx, TyTy::FnType *fntype, location_t)
 {
   return inner::ctlz_handler (ctx, fntype, false);
 }
 
 tree
-ctlz_nonzero_handler (Context *ctx, TyTy::FnType *fntype)
+ctlz_nonzero_handler (Context *ctx, TyTy::FnType *fntype, location_t)
 {
   return inner::ctlz_handler (ctx, fntype, true);
 }
 
 tree
-cttz_handler (Context *ctx, TyTy::FnType *fntype)
+cttz_handler (Context *ctx, TyTy::FnType *fntype, location_t)
 {
   return inner::cttz_handler (ctx, fntype, false);
 }
 
 tree
-cttz_nonzero_handler (Context *ctx, TyTy::FnType *fntype)
+cttz_nonzero_handler (Context *ctx, TyTy::FnType *fntype, location_t)
 {
   return inner::cttz_handler (ctx, fntype, true);
 }
diff --git a/gcc/rust/backend/rust-intrinsic-handlers.h 
b/gcc/rust/backend/rust-intrinsic-handlers.h
index 8a5605366b33..34e9f49d73b4 100644
--- a/gcc/rust/backend/rust-intrinsic-handlers.h
+++ b/gcc/rust/backend/rust-intrinsic-handlers.h
@@ -47,35 +47,37 @@ inline tree unchecked_op (Context *ctx, TyTy::FnType 
*fntype, tree_code op);
 
 } // namespace inner
 
-using HandlerBuilder = std::function<tree (Context *, TyTy::FnType *)>;
+using HandlerBuilder
+  = std::function<tree (Context *, TyTy::FnType *, location_t)>;
 
 const HandlerBuilder op_with_overflow (tree_code op);
 
-tree rotate_left (Context *ctx, TyTy::FnType *fntype);
-tree rotate_right (Context *ctx, TyTy::FnType *fntype);
+tree rotate_left (Context *ctx, TyTy::FnType *fntype, location_t expr_locus);
+tree rotate_right (Context *ctx, TyTy::FnType *fntype, location_t expr_locus);
 
 const HandlerBuilder wrapping_op (tree_code op);
-tree offset (Context *ctx, TyTy::FnType *fntype);
-tree sizeof_handler (Context *ctx, TyTy::FnType *fntype);
-tree min_align_of_handler (Context *ctx, TyTy::FnType *fntype);
-tree transmute (Context *ctx, TyTy::FnType *fntype);
+tree offset (Context *ctx, TyTy::FnType *fntype, location_t expr_locus);
+tree sizeof_handler (Context *ctx, TyTy::FnType *fntype, location_t 
expr_locus);
+tree min_align_of_handler (Context *ctx, TyTy::FnType *fntype,
+                          location_t expr_locus);
+tree transmute (Context *ctx, TyTy::FnType *fntype, location_t expr_locus);
 tree rotate (Context *ctx, TyTy::FnType *fntype, tree_code op);
-tree uninit (Context *ctx, TyTy::FnType *fntype);
-tree move_val_init (Context *ctx, TyTy::FnType *fntype);
-tree assume (Context *ctx, TyTy::FnType *fntype);
-tree discriminant_value (Context *ctx, TyTy::FnType *fntype);
-tree variant_count (Context *ctx, TyTy::FnType *fntype);
-tree bswap_handler (Context *ctx, TyTy::FnType *fntype);
-tree ctlz_handler (Context *ctx, TyTy::FnType *fntype);
-tree ctlz_nonzero_handler (Context *ctx, TyTy::FnType *fntype);
-tree cttz_handler (Context *ctx, TyTy::FnType *fntype);
-tree cttz_nonzero_handler (Context *ctx, TyTy::FnType *fntype);
+tree uninit (Context *ctx, TyTy::FnType *fntype, location_t expr_locus);
+tree move_val_init (Context *ctx, TyTy::FnType *fntype, location_t expr_locus);
+tree assume (Context *ctx, TyTy::FnType *fntype, location_t expr_locus);
+tree discriminant_value (Context *ctx, TyTy::FnType *fntype,
+                        location_t expr_locus);
+tree variant_count (Context *ctx, TyTy::FnType *fntype, location_t expr_locus);
+tree bswap_handler (Context *ctx, TyTy::FnType *fntype, location_t expr_locus);
+tree ctlz_handler (Context *ctx, TyTy::FnType *fntype, location_t expr_locus);
+tree ctlz_nonzero_handler (Context *ctx, TyTy::FnType *fntype,
+                          location_t expr_locus);
+tree cttz_handler (Context *ctx, TyTy::FnType *fntype, location_t expr_locus);
+tree cttz_nonzero_handler (Context *ctx, TyTy::FnType *fntype,
+                          location_t expr_locus);
 
 tree prefetch_data (Context *ctx, TyTy::FnType *fntype, Prefetch kind);
 
-const std::function<tree (Context *, TyTy::FnType *)>
-wrapping_op (tree_code op);
-
 HandlerBuilder atomic_store (int ordering);
 
 HandlerBuilder atomic_load (int ordering);
@@ -88,9 +90,11 @@ const HandlerBuilder expect (bool likely);
 
 const HandlerBuilder try_handler (bool is_new_api);
 
-tree prefetch_read_data (Context *ctx, TyTy::FnType *fntype);
-tree prefetch_write_data (Context *ctx, TyTy::FnType *fntype);
-tree sorry (Context *ctx, TyTy::FnType *fntype);
+tree prefetch_read_data (Context *ctx, TyTy::FnType *fntype,
+                        location_t expr_locus);
+tree prefetch_write_data (Context *ctx, TyTy::FnType *fntype,
+                         location_t expr_locus);
+tree sorry (Context *ctx, TyTy::FnType *fntype, location_t expr_locus);
 
 } // namespace handlers
 
diff --git a/gcc/rust/backend/rust-tree.cc b/gcc/rust/backend/rust-tree.cc
index b7a50376ecd8..6588ff249593 100644
--- a/gcc/rust/backend/rust-tree.cc
+++ b/gcc/rust/backend/rust-tree.cc
@@ -688,10 +688,15 @@ get_fndecl_from_callee (tree fn)
 tree
 pointer_offset_expression (tree base_tree, tree index_tree, location_t 
location)
 {
-  tree element_type_tree = TREE_TYPE (TREE_TYPE (base_tree));
+  tree base_type_tree = TREE_TYPE (base_tree);
+  tree element_type_tree
+    = TREE_TYPE (base_type_tree) ? TREE_TYPE (base_type_tree) : 
error_mark_node;
   if (base_tree == error_mark_node || TREE_TYPE (base_tree) == error_mark_node
       || index_tree == error_mark_node || element_type_tree == error_mark_node)
-    return error_mark_node;
+    {
+      error_at (location, "unknown element size type for %qT", base_type_tree);
+      return error_mark_node;
+    }
 
   tree element_size = TYPE_SIZE_UNIT (element_type_tree);
   index_tree = fold_convert_loc (location, sizetype, index_tree);
diff --git a/gcc/testsuite/rust/compile/issue-4592.rs 
b/gcc/testsuite/rust/compile/issue-4592.rs
new file mode 100644
index 000000000000..11f966792f0a
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-4592.rs
@@ -0,0 +1,22 @@
+#![feature(no_core, intrinsics, staged_api, lang_items)]
+#![no_core]
+
+#[lang = "sized"]
+pub trait Sized {}
+
+extern "rust-intrinsic" {
+    #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
+    fn offset<T>(dst: *const T, offset: isize) -> *const T;
+}
+
+#[lang = "const_ptr"]
+impl<T> *const T {
+    pub const unsafe fn offset(self, count: isize) -> *const T {
+        unsafe { offset(self, count) } // { dg-error {unknown element size 
type for .const struct \*const \[i32\].} }
+    }
+}
+
+fn main() {
+    let my_slice: &[i32] = &[1, 2, 3];
+    let ptr = unsafe { (my_slice as *const [i32]).offset(0) };
+}

Reply via email to