From: Philip Herron <[email protected]>

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]>
---
This change was merged into the gccrs repository and is posted here for
upstream visibility and potential drive-by review, as requested by GCC
release managers.
Each commit email contains a link to its details on github from where you can
find the Pull-Request and associated discussions.


Commit on github: 
https://github.com/Rust-GCC/gccrs/commit/1f8c9523bba29177b7884aff330bc45f28f088ec

The commit has NOT been mentioned in any issue.

The commit has been mentioned in the following pull-request(s):
 - https://github.com/Rust-GCC/gccrs/pull/4603

 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(-)
 create mode 100644 gcc/testsuite/rust/compile/issue-4592.rs

diff --git a/gcc/rust/backend/rust-compile-extern.h 
b/gcc/rust/backend/rust-compile-extern.h
index c0dfab096..4eabf0ddb 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 ab6423092..a00b2a50e 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 dceb0864f..33011734e 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 2cfdca5de..d665df70f 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 39432ea7c..8ea93d7f7 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 8a5605366..34e9f49d7 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 b7a50376e..6588ff249 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 000000000..11f966792
--- /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) };
+}

base-commit: 00f321321159557c5c75317af58d0f0fbeb6a735
-- 
2.54.0

Reply via email to