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}]; +}
