https://gcc.gnu.org/g:1422fa61b44963f0b3ed19e110bd7ccbddd311ce

commit r16-4846-g1422fa61b44963f0b3ed19e110bd7ccbddd311ce
Author: Philip Herron <[email protected]>
Date:   Sun Aug 31 22:57:05 2025 +0100

    gccrs: Fix segv when handling invalid array capacities
    
    We need to catch the error node for the array capacity and return early.
    Otherwise we try to const evaluate something thats just silly. Also
    when compiling array expressions we can simply reuse the array capacity
    expression we already have cons folded.
    
    Fixes Rust-GCC#3965
    
    gcc/rust/ChangeLog:
    
            * backend/rust-compile-context.h: add assertions for context peeks
            * backend/rust-compile-expr.cc (CompileExpr::visit): check for 
valid loop context
            (CompileExpr::array_copied_expr): just reuse array tyty capacity 
value
            * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): 
catch error
    
    gcc/testsuite/ChangeLog:
    
            * rust/compile/issue-3965-1.rs: New test.
            * rust/compile/issue-3965-2.rs: New test.
    
    Signed-off-by: Philip Herron <[email protected]>

Diff:
---
 gcc/rust/backend/rust-compile-context.h        | 14 ++++++++++++--
 gcc/rust/backend/rust-compile-expr.cc          | 12 +++++++-----
 gcc/rust/typecheck/rust-hir-type-check-expr.cc |  2 ++
 gcc/testsuite/rust/compile/issue-3965-1.rs     |  4 ++++
 gcc/testsuite/rust/compile/issue-3965-2.rs     |  7 +++++++
 5 files changed, 32 insertions(+), 7 deletions(-)

diff --git a/gcc/rust/backend/rust-compile-context.h 
b/gcc/rust/backend/rust-compile-context.h
index 69bba515882f..e98bbc2d49f3 100644
--- a/gcc/rust/backend/rust-compile-context.h
+++ b/gcc/rust/backend/rust-compile-context.h
@@ -322,7 +322,13 @@ public:
 
   void push_loop_context (Bvariable *var) { loop_value_stack.push_back (var); }
 
-  Bvariable *peek_loop_context () { return loop_value_stack.back (); }
+  bool have_loop_context () const { return !loop_value_stack.empty (); }
+
+  Bvariable *peek_loop_context ()
+  {
+    rust_assert (!loop_value_stack.empty ());
+    return loop_value_stack.back ();
+  }
 
   Bvariable *pop_loop_context ()
   {
@@ -336,7 +342,11 @@ public:
     loop_begin_labels.push_back (label);
   }
 
-  tree peek_loop_begin_label () { return loop_begin_labels.back (); }
+  tree peek_loop_begin_label ()
+  {
+    rust_assert (!loop_begin_labels.empty ());
+    return loop_begin_labels.back ();
+  }
 
   tree pop_loop_begin_label ()
   {
diff --git a/gcc/rust/backend/rust-compile-expr.cc 
b/gcc/rust/backend/rust-compile-expr.cc
index 2bec52bfc4a8..946bbb1234f7 100644
--- a/gcc/rust/backend/rust-compile-expr.cc
+++ b/gcc/rust/backend/rust-compile-expr.cc
@@ -891,6 +891,10 @@ CompileExpr::visit (HIR::BreakExpr &expr)
 void
 CompileExpr::visit (HIR::ContinueExpr &expr)
 {
+  translated = error_mark_node;
+  if (!ctx->have_loop_context ())
+    return;
+
   tree label = ctx->peek_loop_begin_label ();
   if (expr.has_label ())
     {
@@ -2000,13 +2004,11 @@ CompileExpr::array_copied_expr (location_t expr_locus,
       return error_mark_node;
     }
 
-  ctx->push_const_context ();
-  tree capacity_expr = CompileExpr::Compile (elems.get_num_copies_expr (), 
ctx);
-  ctx->pop_const_context ();
-
+  auto capacity_tyty = array_tyty.get_capacity ();
+  tree capacity_expr = capacity_tyty->get_value ();
   if (!TREE_CONSTANT (capacity_expr))
     {
-      rust_error_at (expr_locus, "non const num copies %qT", array_type);
+      rust_error_at (expr_locus, "non const num copies %qT", capacity_expr);
       return error_mark_node;
     }
 
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.cc 
b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
index 9a772cba4c60..dc063587e0d8 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
@@ -1090,6 +1090,8 @@ TypeCheckExpr::visit (HIR::ArrayExpr &expr)
 
        auto capacity_expr_ty
          = TypeCheckExpr::Resolve (elems.get_num_copies_expr ());
+       if (capacity_expr_ty->is<TyTy::ErrorType> ())
+         return;
 
        context->insert_type (elems.get_num_copies_expr ().get_mappings (),
                              expected_ty);
diff --git a/gcc/testsuite/rust/compile/issue-3965-1.rs 
b/gcc/testsuite/rust/compile/issue-3965-1.rs
new file mode 100644
index 000000000000..291a2208c503
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-3965-1.rs
@@ -0,0 +1,4 @@
+fn main() {
+    [(); { continue }];
+    // { dg-error ".continue. outside of a loop .E0268." "" { target *-*-* } 
.-1 }
+}
diff --git a/gcc/testsuite/rust/compile/issue-3965-2.rs 
b/gcc/testsuite/rust/compile/issue-3965-2.rs
new file mode 100644
index 000000000000..d48503fa6c09
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-3965-2.rs
@@ -0,0 +1,7 @@
+fn main() {
+    loop { continue }
+
+    [(); {while true {break}; 0}];
+
+    [(); {while true {break}; 0}];
+}

Reply via email to