diff --git a/compiler/rustc_codegen_cranelift/example/mini_core.rs b/compiler/rustc_codegen_cranelift/example/mini_core.rs index 5293b458d8c4f..da40a8444c4ef 100644 --- a/compiler/rustc_codegen_cranelift/example/mini_core.rs +++ b/compiler/rustc_codegen_cranelift/example/mini_core.rs @@ -493,18 +493,48 @@ macro_rules! panic_const { } panic_const! { - panic_const_add_overflow = "attempt to add with overflow", - panic_const_sub_overflow = "attempt to subtract with overflow", - panic_const_mul_overflow = "attempt to multiply with overflow", - panic_const_div_overflow = "attempt to divide with overflow", - panic_const_rem_overflow = "attempt to calculate the remainder with overflow", panic_const_neg_overflow = "attempt to negate with overflow", - panic_const_shr_overflow = "attempt to shift right with overflow", - panic_const_shl_overflow = "attempt to shift left with overflow", panic_const_div_by_zero = "attempt to divide by zero", panic_const_rem_by_zero = "attempt to calculate the remainder with a divisor of zero", } +macro_rules! panic_overflow { + ($($lang_unsigned:ident, $lang_signed:ident = $message:tt,)+) => { + $( + #[cfg_attr(not(panic = "immediate-abort"), inline(never), cold)] + #[cfg_attr(panic = "immediate-abort", inline)] + #[track_caller] + #[lang = stringify!($lang_unsigned)] + pub fn $lang_unsigned(_lhs: u128, _rhs: u128) -> ! { + unsafe { + libc::printf($message as *const str as *const i8); + intrinsics::abort() + } + } + #[cfg_attr(not(panic = "immediate-abort"), inline(never), cold)] + #[cfg_attr(panic = "immediate-abort", inline)] + #[track_caller] + #[lang = stringify!($lang_signed)] + pub fn $lang_signed(_lhs: i128, _rhs: i128) -> ! { + unsafe { + libc::printf($message as *const str as *const i8); + intrinsics::abort() + } + } + )+ + }; +} + +panic_overflow! { + panic_add_overflow_unsigned, panic_add_overflow_signed = "attempt to add with overflow", + panic_sub_overflow_unsigned, panic_sub_overflow_signed = "attempt to subtract with overflow", + panic_mul_overflow_unsigned, panic_mul_overflow_signed = "attempt to multiply with overflow", + panic_div_overflow_unsigned, panic_div_overflow_signed = "attempt to divide with overflow", + panic_rem_overflow_unsigned, panic_rem_overflow_signed = "attempt to calculate the remainder with overflow", + panic_shl_overflow_unsigned, panic_shl_overflow_signed = "attempt to shift left with overflow", + panic_shr_overflow_unsigned, panic_shr_overflow_signed = "attempt to shift left right with overflow", +} + #[lang = "panic_bounds_check"] #[track_caller] fn panic_bounds_check(index: usize, len: usize) -> ! { diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index 4f483cdc5d6c7..02b2bcef907c9 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -434,6 +434,50 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { source_info.span, ) } + AssertKind::Overflow(binop, lhs, rhs) => { + let tcx = fx.tcx; + let is_signed = lhs.ty(fx.mir, tcx).is_signed(); + + use rustc_hir::LangItem::*; + let lang = match (binop, is_signed) { + (mir::BinOp::Add, true) => PanicAddOverflowSigned, + (mir::BinOp::Add, false) => PanicAddOverflowUnsigned, + (mir::BinOp::Sub, true) => PanicSubOverflowSigned, + (mir::BinOp::Sub, false) => PanicSubOverflowUnsigned, + (mir::BinOp::Mul, true) => PanicMulOverflowSigned, + (mir::BinOp::Mul, false) => PanicMulOverflowUnsigned, + (mir::BinOp::Div, true) => PanicDivOverflowSigned, + (mir::BinOp::Div, false) => PanicDivOverflowUnsigned, + (mir::BinOp::Rem, true) => PanicRemOverflowSigned, + (mir::BinOp::Rem, false) => PanicRemOverflowUnsigned, + (mir::BinOp::Shl, true) => PanicShlOverflowSigned, + (mir::BinOp::Shl, false) => PanicShlOverflowUnsigned, + (mir::BinOp::Shr, true) => PanicShrOverflowSigned, + (mir::BinOp::Shr, false) => PanicShrOverflowUnsigned, + _ => bug!("binop {:?} should not have overflow assert", binop), + }; + + let lhs = codegen_operand(fx, lhs).load_scalar(fx); + let rhs = codegen_operand(fx, rhs).load_scalar(fx); + + let i128_ty = tcx.types.i128; + let clif_128_ty = fx.clif_type(i128_ty).unwrap(); + + let lhs = + clif_int_or_float_cast(fx, lhs, is_signed, clif_128_ty, is_signed); + let rhs = + clif_int_or_float_cast(fx, rhs, is_signed, clif_128_ty, is_signed); + + let location = fx.get_caller_location(source_info).load_scalar(fx); + + codegen_panic_inner( + fx, + lang, + &[lhs, rhs, location], + *unwind, + source_info.span, + ) + } _ => { let location = fx.get_caller_location(source_info).load_scalar(fx); diff --git a/compiler/rustc_codegen_gcc/example/mini_core.rs b/compiler/rustc_codegen_gcc/example/mini_core.rs index 2e165cc3c129d..2ad8aabeb4d3b 100644 --- a/compiler/rustc_codegen_gcc/example/mini_core.rs +++ b/compiler/rustc_codegen_gcc/example/mini_core.rs @@ -505,18 +505,48 @@ macro_rules! panic_const { } panic_const! { - panic_const_add_overflow = "attempt to add with overflow", - panic_const_sub_overflow = "attempt to subtract with overflow", - panic_const_mul_overflow = "attempt to multiply with overflow", - panic_const_div_overflow = "attempt to divide with overflow", - panic_const_rem_overflow = "attempt to calculate the remainder with overflow", panic_const_neg_overflow = "attempt to negate with overflow", - panic_const_shr_overflow = "attempt to shift right with overflow", - panic_const_shl_overflow = "attempt to shift left with overflow", panic_const_div_by_zero = "attempt to divide by zero", panic_const_rem_by_zero = "attempt to calculate the remainder with a divisor of zero", } +macro_rules! panic_overflow { + ($($lang_unsigned:ident, $lang_signed:ident = $message:tt,)+) => { + $( + #[cfg_attr(not(panic = "immediate-abort"), inline(never), cold)] + #[cfg_attr(panic = "immediate-abort", inline)] + #[track_caller] + #[lang = stringify!($lang_unsigned)] + pub fn $lang_unsigned(_lhs: u128, _rhs: u128) -> ! { + unsafe { + libc::printf($message as *const str as *const i8); + intrinsics::abort() + } + } + #[cfg_attr(not(panic = "immediate-abort"), inline(never), cold)] + #[cfg_attr(panic = "immediate-abort", inline)] + #[track_caller] + #[lang = stringify!($lang_signed)] + pub fn $lang_signed(_lhs: i128, _rhs: i128) -> ! { + unsafe { + libc::printf($message as *const str as *const i8); + intrinsics::abort() + } + } + )+ + }; +} + +panic_overflow! { + panic_add_overflow_unsigned, panic_add_overflow_signed = "attempt to add with overflow", + panic_sub_overflow_unsigned, panic_sub_overflow_signed = "attempt to subtract with overflow", + panic_mul_overflow_unsigned, panic_mul_overflow_signed = "attempt to multiply with overflow", + panic_div_overflow_unsigned, panic_div_overflow_signed = "attempt to divide with overflow", + panic_rem_overflow_unsigned, panic_rem_overflow_signed = "attempt to calculate the remainder with overflow", + panic_shl_overflow_unsigned, panic_shl_overflow_signed = "attempt to shift left with overflow", + panic_shr_overflow_unsigned, panic_shr_overflow_signed = "attempt to shift left right with overflow", +} + #[lang = "panic_cannot_unwind"] fn panic_cannot_unwind() -> ! { unsafe { diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index cf643931717be..bbdebdb3462aa 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -740,40 +740,90 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let location = self.get_caller_location(bx, terminator.source_info).immediate(); // Put together the arguments to the panic entry point. - let (lang_item, args) = match msg { + let ((fn_abi, llfn, instance), args) = match msg { AssertKind::BoundsCheck { len, index } => { let len = self.codegen_operand(bx, len).immediate(); let index = self.codegen_operand(bx, index).immediate(); // It's `fn panic_bounds_check(index: usize, len: usize)`, // and `#[track_caller]` adds an implicit third argument. - (LangItem::PanicBoundsCheck, vec![index, len, location]) + ( + common::build_langcall(bx, span, LangItem::PanicBoundsCheck), + vec![index, len, location], + ) } AssertKind::MisalignedPointerDereference { required, found } => { let required = self.codegen_operand(bx, required).immediate(); let found = self.codegen_operand(bx, found).immediate(); // It's `fn panic_misaligned_pointer_dereference(required: usize, found: usize)`, // and `#[track_caller]` adds an implicit third argument. - (LangItem::PanicMisalignedPointerDereference, vec![required, found, location]) - } - AssertKind::NullPointerDereference => { - // It's `fn panic_null_pointer_dereference()`, - // `#[track_caller]` adds an implicit argument. - (LangItem::PanicNullPointerDereference, vec![location]) + ( + common::build_langcall(bx, span, LangItem::PanicMisalignedPointerDereference), + vec![required, found, location], + ) } AssertKind::InvalidEnumConstruction(source) => { let source = self.codegen_operand(bx, source).immediate(); // It's `fn panic_invalid_enum_construction(source: u128)`, // `#[track_caller]` adds an implicit argument. - (LangItem::PanicInvalidEnumConstruction, vec![source, location]) + ( + common::build_langcall(bx, span, LangItem::PanicInvalidEnumConstruction), + vec![source, location], + ) + } + AssertKind::Overflow(binop, lhs, rhs) => { + let tcx = bx.tcx(); + + let is_signed = lhs.ty(self.mir, tcx).is_signed(); + + let lang = match (binop, is_signed) { + (mir::BinOp::Add, true) => LangItem::PanicAddOverflowSigned, + (mir::BinOp::Add, false) => LangItem::PanicAddOverflowUnsigned, + (mir::BinOp::Sub, true) => LangItem::PanicSubOverflowSigned, + (mir::BinOp::Sub, false) => LangItem::PanicSubOverflowUnsigned, + (mir::BinOp::Mul, true) => LangItem::PanicMulOverflowSigned, + (mir::BinOp::Mul, false) => LangItem::PanicMulOverflowUnsigned, + (mir::BinOp::Div, true) => LangItem::PanicDivOverflowSigned, + (mir::BinOp::Div, false) => LangItem::PanicDivOverflowUnsigned, + (mir::BinOp::Rem, true) => LangItem::PanicRemOverflowSigned, + (mir::BinOp::Rem, false) => LangItem::PanicRemOverflowUnsigned, + (mir::BinOp::Shl, true) => LangItem::PanicShlOverflowSigned, + (mir::BinOp::Shl, false) => LangItem::PanicShlOverflowUnsigned, + (mir::BinOp::Shr, true) => LangItem::PanicShrOverflowSigned, + (mir::BinOp::Shr, false) => LangItem::PanicShrOverflowUnsigned, + _ => bug!("binop {:?} should not have overflow assert", binop), + }; + + let (lhs, rhs) = if is_signed { + let i128_ty = tcx.types.i128; + let i128_llty = bx.immediate_backend_type(bx.layout_of(i128_ty)); + + let lhs = self.codegen_operand(bx, lhs).immediate(); + let lhs = bx.sext(lhs, i128_llty); + let rhs = self.codegen_operand(bx, rhs).immediate(); + let rhs = bx.sext(rhs, i128_llty); + + (lhs, rhs) + } else { + let u128_ty = tcx.types.u128; + let u128_llty = bx.immediate_backend_type(bx.layout_of(u128_ty)); + + let lhs = self.codegen_operand(bx, lhs).immediate(); + let lhs = bx.zext(lhs, u128_llty); + let rhs = self.codegen_operand(bx, rhs).immediate(); + let rhs = bx.zext(rhs, u128_llty); + + (lhs, rhs) + }; + + // signature fn(lhs, rhs), plus #[track_caller] location + (common::build_langcall(bx, span, lang), vec![lhs, rhs, location]) } _ => { // It's `pub fn panic_...()` and `#[track_caller]` adds an implicit argument. - (msg.panic_function(), vec![location]) + (common::build_langcall(bx, span, msg.panic_function()), vec![location]) } }; - let (fn_abi, llfn, instance) = common::build_langcall(bx, span, lang_item); - // Codegen the actual panic invoke/call. let merging_succ = helper.do_call( self, diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index 80f0af9d663cb..58448e5334693 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -289,16 +289,23 @@ language_item_table! { PanicCannotUnwind, sym::panic_cannot_unwind, panic_cannot_unwind, Target::Fn, GenericRequirement::Exact(0); PanicInCleanup, sym::panic_in_cleanup, panic_in_cleanup, Target::Fn, GenericRequirement::Exact(0); /// Constant panic messages, used for codegen of MIR asserts. - PanicAddOverflow, sym::panic_const_add_overflow, panic_const_add_overflow, Target::Fn, GenericRequirement::None; - PanicSubOverflow, sym::panic_const_sub_overflow, panic_const_sub_overflow, Target::Fn, GenericRequirement::None; - PanicMulOverflow, sym::panic_const_mul_overflow, panic_const_mul_overflow, Target::Fn, GenericRequirement::None; - PanicDivOverflow, sym::panic_const_div_overflow, panic_const_div_overflow, Target::Fn, GenericRequirement::None; - PanicRemOverflow, sym::panic_const_rem_overflow, panic_const_rem_overflow, Target::Fn, GenericRequirement::None; - PanicNegOverflow, sym::panic_const_neg_overflow, panic_const_neg_overflow, Target::Fn, GenericRequirement::None; - PanicShrOverflow, sym::panic_const_shr_overflow, panic_const_shr_overflow, Target::Fn, GenericRequirement::None; - PanicShlOverflow, sym::panic_const_shl_overflow, panic_const_shl_overflow, Target::Fn, GenericRequirement::None; - PanicDivZero, sym::panic_const_div_by_zero, panic_const_div_by_zero, Target::Fn, GenericRequirement::None; - PanicRemZero, sym::panic_const_rem_by_zero, panic_const_rem_by_zero, Target::Fn, GenericRequirement::None; + PanicAddOverflowSigned, sym::panic_add_overflow_signed, panic_add_overflow_signed, Target::Fn, GenericRequirement::None; + PanicAddOverflowUnsigned, sym::panic_add_overflow_unsigned, panic_add_overflow_unsigned, Target::Fn, GenericRequirement::None; + PanicSubOverflowSigned, sym::panic_sub_overflow_signed, panic_sub_overflow_signed, Target::Fn, GenericRequirement::None; + PanicSubOverflowUnsigned, sym::panic_sub_overflow_unsigned, panic_sub_overflow_unsigned, Target::Fn, GenericRequirement::None; + PanicMulOverflowSigned, sym::panic_mul_overflow_signed, panic_mul_overflow_signed, Target::Fn, GenericRequirement::None; + PanicMulOverflowUnsigned, sym::panic_mul_overflow_unsigned, panic_mul_overflow_unsigned, Target::Fn, GenericRequirement::None; + PanicDivOverflowSigned, sym::panic_div_overflow_signed, panic_div_overflow_signed, Target::Fn, GenericRequirement::None; + PanicDivOverflowUnsigned, sym::panic_div_overflow_unsigned, panic_div_overflow_unsigned, Target::Fn, GenericRequirement::None; + PanicRemOverflowSigned, sym::panic_rem_overflow_signed, panic_rem_overflow_signed, Target::Fn, GenericRequirement::None; + PanicRemOverflowUnsigned, sym::panic_rem_overflow_unsigned, panic_rem_overflow_unsigned, Target::Fn, GenericRequirement::None; + PanicShlOverflowSigned, sym::panic_shl_overflow_signed, panic_shl_overflow_signed, Target::Fn, GenericRequirement::None; + PanicShlOverflowUnsigned, sym::panic_shl_overflow_unsigned, panic_shl_overflow_unsigned, Target::Fn, GenericRequirement::None; + PanicShrOverflowSigned, sym::panic_shr_overflow_signed, panic_shr_overflow_signed, Target::Fn, GenericRequirement::None; + PanicShrOverflowUnsigned, sym::panic_shr_overflow_unsigned, panic_shr_overflow_unsigned, Target::Fn, GenericRequirement::None; + PanicNegOverflow, sym::panic_const_neg_overflow, panic_const_neg_overflow, Target::Fn, GenericRequirement::None; + PanicDivZero, sym::panic_const_div_by_zero, panic_const_div_by_zero, Target::Fn, GenericRequirement::None; + PanicRemZero, sym::panic_const_rem_by_zero, panic_const_rem_by_zero, Target::Fn, GenericRequirement::None; PanicCoroutineResumed, sym::panic_const_coroutine_resumed, panic_const_coroutine_resumed, Target::Fn, GenericRequirement::None; PanicAsyncFnResumed, sym::panic_const_async_fn_resumed, panic_const_async_fn_resumed, Target::Fn, GenericRequirement::None; PanicAsyncGenFnResumed, sym::panic_const_async_gen_fn_resumed, panic_const_async_gen_fn_resumed, Target::Fn, GenericRequirement::None; diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs index 650c44aa41fbe..dca72d4e09bba 100644 --- a/compiler/rustc_middle/src/mir/terminator.rs +++ b/compiler/rustc_middle/src/mir/terminator.rs @@ -176,15 +176,19 @@ impl AssertKind { pub fn panic_function(&self) -> LangItem { use AssertKind::*; match self { - Overflow(BinOp::Add, _, _) => LangItem::PanicAddOverflow, - Overflow(BinOp::Sub, _, _) => LangItem::PanicSubOverflow, - Overflow(BinOp::Mul, _, _) => LangItem::PanicMulOverflow, - Overflow(BinOp::Div, _, _) => LangItem::PanicDivOverflow, - Overflow(BinOp::Rem, _, _) => LangItem::PanicRemOverflow, - OverflowNeg(_) => LangItem::PanicNegOverflow, - Overflow(BinOp::Shr, _, _) => LangItem::PanicShrOverflow, - Overflow(BinOp::Shl, _, _) => LangItem::PanicShlOverflow, + Overflow( + BinOp::Add + | BinOp::Sub + | BinOp::Mul + | BinOp::Div + | BinOp::Rem + | BinOp::Shr + | BinOp::Shl, + _, + _, + ) => bug!("Binops handled elsewhere"), Overflow(op, _, _) => bug!("{:?} cannot overflow", op), + OverflowNeg(_) => LangItem::PanicNegOverflow, DivisionByZero(_) => LangItem::PanicDivZero, RemainderByZero(_) => LangItem::PanicRemZero, ResumedAfterReturn(CoroutineKind::Coroutine(_)) => LangItem::PanicCoroutineResumed, diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 3aa55cc8eb9fb..6fa517a56b6c4 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -908,6 +908,28 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> { mir::AssertKind::InvalidEnumConstruction(_) => { push_mono_lang_item(self, LangItem::PanicInvalidEnumConstruction); } + mir::AssertKind::Overflow(binop, lhs, _rhs) => { + let is_signed = lhs.ty(self.body, tcx).is_signed(); + let lang = match (binop, is_signed) { + (mir::BinOp::Add, true) => LangItem::PanicAddOverflowSigned, + (mir::BinOp::Add, false) => LangItem::PanicAddOverflowUnsigned, + (mir::BinOp::Sub, true) => LangItem::PanicSubOverflowSigned, + (mir::BinOp::Sub, false) => LangItem::PanicSubOverflowUnsigned, + (mir::BinOp::Mul, true) => LangItem::PanicMulOverflowSigned, + (mir::BinOp::Mul, false) => LangItem::PanicMulOverflowUnsigned, + (mir::BinOp::Div, true) => LangItem::PanicDivOverflowSigned, + (mir::BinOp::Div, false) => LangItem::PanicDivOverflowUnsigned, + (mir::BinOp::Rem, true) => LangItem::PanicRemOverflowSigned, + (mir::BinOp::Rem, false) => LangItem::PanicRemOverflowUnsigned, + (mir::BinOp::Shl, true) => LangItem::PanicShlOverflowSigned, + (mir::BinOp::Shl, false) => LangItem::PanicShlOverflowUnsigned, + (mir::BinOp::Shr, true) => LangItem::PanicShrOverflowSigned, + (mir::BinOp::Shr, false) => LangItem::PanicShrOverflowUnsigned, + _ => bug!("binop {:?} should not have overflow assert", binop), + }; + + push_mono_lang_item(self, lang); + } _ => { push_mono_lang_item(self, msg.panic_function()); } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 257ac3f51c2c1..969719161da38 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1434,9 +1434,10 @@ symbols! { panic_2015, panic_2021, panic_abort, + panic_add_overflow_signed, + panic_add_overflow_unsigned, panic_bounds_check, panic_cannot_unwind, - panic_const_add_overflow, panic_const_async_fn_resumed, panic_const_async_fn_resumed_drop, panic_const_async_fn_resumed_panic, @@ -1447,18 +1448,14 @@ symbols! { panic_const_coroutine_resumed_drop, panic_const_coroutine_resumed_panic, panic_const_div_by_zero, - panic_const_div_overflow, panic_const_gen_fn_none, panic_const_gen_fn_none_drop, panic_const_gen_fn_none_panic, - panic_const_mul_overflow, panic_const_neg_overflow, panic_const_rem_by_zero, - panic_const_rem_overflow, - panic_const_shl_overflow, - panic_const_shr_overflow, - panic_const_sub_overflow, panic_display, + panic_div_overflow_signed, + panic_div_overflow_unsigned, panic_fmt, panic_handler, panic_impl, @@ -1468,10 +1465,20 @@ symbols! { panic_invalid_enum_construction, panic_location, panic_misaligned_pointer_dereference, + panic_mul_overflow_signed, + panic_mul_overflow_unsigned, panic_nounwind, panic_null_pointer_dereference, + panic_rem_overflow_signed, + panic_rem_overflow_unsigned, panic_runtime, + panic_shl_overflow_signed, + panic_shl_overflow_unsigned, + panic_shr_overflow_signed, + panic_shr_overflow_unsigned, panic_str_2015, + panic_sub_overflow_signed, + panic_sub_overflow_unsigned, panic_unwind, panicking, param_attrs, diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs index 3609dd1fe2e02..ecd31f4f6b7b0 100644 --- a/library/core/src/panicking.rs +++ b/library/core/src/panicking.rs @@ -185,14 +185,7 @@ macro_rules! panic_const { pub mod panic_const { use super::*; panic_const! { - panic_const_add_overflow = "attempt to add with overflow", - panic_const_sub_overflow = "attempt to subtract with overflow", - panic_const_mul_overflow = "attempt to multiply with overflow", - panic_const_div_overflow = "attempt to divide with overflow", - panic_const_rem_overflow = "attempt to calculate the remainder with overflow", panic_const_neg_overflow = "attempt to negate with overflow", - panic_const_shr_overflow = "attempt to shift right with overflow", - panic_const_shl_overflow = "attempt to shift left with overflow", panic_const_div_by_zero = "attempt to divide by zero", panic_const_rem_by_zero = "attempt to calculate the remainder with a divisor of zero", panic_const_coroutine_resumed = "coroutine resumed after completion", @@ -214,6 +207,45 @@ pub mod panic_const { } } +macro_rules! panic_overflow { + ($($lang_unsigned:ident, $lang_signed:ident = $message:tt,)+) => { + $( + #[cfg_attr(not(panic = "immediate-abort"), inline(never), cold)] + #[cfg_attr(panic = "immediate-abort", inline)] + #[track_caller] + #[lang = stringify!($lang_unsigned)] + pub fn $lang_unsigned(lhs: u128, rhs: u128) -> ! { + if cfg!(panic = "immediate-abort") { + super::intrinsics::abort() + } + + panic_fmt(format_args!($message, lhs, rhs)) + } + #[cfg_attr(not(panic = "immediate-abort"), inline(never), cold)] + #[cfg_attr(panic = "immediate-abort", inline)] + #[track_caller] + #[lang = stringify!($lang_signed)] + pub fn $lang_signed(lhs: i128, rhs: i128) -> ! { + if cfg!(panic = "immediate-abort") { + super::intrinsics::abort() + } + + panic_fmt(format_args!($message, lhs, rhs)) + } + )+ + }; +} + +panic_overflow! { + panic_add_overflow_unsigned, panic_add_overflow_signed = "attempt to compute `{} + {}`, which would overflow", + panic_sub_overflow_unsigned, panic_sub_overflow_signed = "attempt to compute `{} - {}`, which would overflow", + panic_mul_overflow_unsigned, panic_mul_overflow_signed = "attempt to compute `{} * {}`, which would overflow", + panic_div_overflow_unsigned, panic_div_overflow_signed = "attempt to compute `{} / {}`, which would overflow", + panic_rem_overflow_unsigned, panic_rem_overflow_signed = "attempt to compute `{} % {}`, which would overflow", + panic_shl_overflow_unsigned, panic_shl_overflow_signed = "attempt to compute `{} << {}`, which would overflow", + panic_shr_overflow_unsigned, panic_shr_overflow_signed = "attempt to compute `{} >> {}, which would overflow", +} + /// Like `panic`, but without unwinding and track_caller to reduce the impact on codesize on the caller. /// If you want `#[track_caller]` for nicer errors, call `panic_nounwind_fmt` directly. #[cfg_attr(not(panic = "immediate-abort"), inline(never), cold)] diff --git a/tests/codegen-llvm/fromrangeiter-overflow-checks.rs b/tests/codegen-llvm/fromrangeiter-overflow-checks.rs index 4d27f118ddd37..847aac30b2f6c 100644 --- a/tests/codegen-llvm/fromrangeiter-overflow-checks.rs +++ b/tests/codegen-llvm/fromrangeiter-overflow-checks.rs @@ -19,7 +19,7 @@ pub unsafe fn iterrangefrom_remainder(x: RangeFromIter) -> RangeFrom { // DEBUG: i32 noundef %x // NOCHECKS: i32 noundef returned %x // DEBUG: br i1 - // DEBUG: call core::panicking::panic_const::panic_const_add_overflow + // DEBUG: call core::panicking::panic_add_overflow_signed // DEBUG: unreachable // NOCHECKS-NOT: unreachable // NOCHECKS: ret i32 %x diff --git a/tests/codegen-llvm/inherit_overflow.rs b/tests/codegen-llvm/inherit_overflow.rs index e4a5ef39fc548..5bad39d953d83 100644 --- a/tests/codegen-llvm/inherit_overflow.rs +++ b/tests/codegen-llvm/inherit_overflow.rs @@ -4,7 +4,7 @@ //@[NOASSERT] compile-flags: -Coverflow-checks=off // CHECK-LABEL: define{{.*}} @assertion -// ASSERT: call void @{{.*4core9panicking11panic_const24panic_const_add_overflow}} +// ASSERT: call void @{{.*4core9panicking27panic_add_overflow_unsigned}} // NOASSERT: ret i8 0 #[no_mangle] pub fn assertion() -> u8 { diff --git a/tests/codegen-units/item-collection/implicit-panic-call.rs b/tests/codegen-units/item-collection/implicit-panic-call.rs index 3b442942cc5c4..f126d43f5be0e 100644 --- a/tests/codegen-units/item-collection/implicit-panic-call.rs +++ b/tests/codegen-units/item-collection/implicit-panic-call.rs @@ -22,10 +22,10 @@ fn panic_div_zero() -> ! { loop {} } -#[lang = "panic_const_div_overflow"] +#[lang = "panic_div_overflow_signed"] #[inline] #[track_caller] -fn panic_div_overflow() -> ! { +fn panic_div_overflow(_lhs: i128, _rhs: i128) -> ! { loop {} } diff --git a/tests/ui/numbers-arithmetic/overflowing-add.rs b/tests/ui/numbers-arithmetic/overflowing-add.rs index a63fc3bccf1dc..e7d6e2cd6da34 100644 --- a/tests/ui/numbers-arithmetic/overflowing-add.rs +++ b/tests/ui/numbers-arithmetic/overflowing-add.rs @@ -1,6 +1,6 @@ //@ run-fail //@ regex-error-pattern: thread 'main'.*panicked -//@ error-pattern: attempt to add with overflow +//@ regex-error-pattern: attempt to compute.*\+.* which would overflow //@ compile-flags: -C debug-assertions //@ needs-subprocess diff --git a/tests/ui/numbers-arithmetic/overflowing-mul.rs b/tests/ui/numbers-arithmetic/overflowing-mul.rs index 2645a32d5ad0d..21ca42d7f6dfe 100644 --- a/tests/ui/numbers-arithmetic/overflowing-mul.rs +++ b/tests/ui/numbers-arithmetic/overflowing-mul.rs @@ -1,6 +1,6 @@ //@ run-fail //@ regex-error-pattern: thread 'main'.*panicked -//@ error-pattern: attempt to multiply with overflow +//@ regex-error-pattern: attempt to compute.*\*.* which would overflow //@ needs-subprocess //@ compile-flags: -C debug-assertions diff --git a/tests/ui/numbers-arithmetic/overflowing-pow-signed.rs b/tests/ui/numbers-arithmetic/overflowing-pow-signed.rs index 6db6682e16fd6..a7c8ba372fe72 100644 --- a/tests/ui/numbers-arithmetic/overflowing-pow-signed.rs +++ b/tests/ui/numbers-arithmetic/overflowing-pow-signed.rs @@ -1,6 +1,6 @@ //@ run-fail //@ regex-error-pattern: thread 'main'.*panicked -//@ error-pattern: attempt to multiply with overflow +//@ regex-error-pattern: attempt to compute.*\*.* which would overflow //@ needs-subprocess //@ compile-flags: -C debug-assertions diff --git a/tests/ui/numbers-arithmetic/overflowing-pow-unsigned.rs b/tests/ui/numbers-arithmetic/overflowing-pow-unsigned.rs index bde0de6f6f575..97cc1c5a51067 100644 --- a/tests/ui/numbers-arithmetic/overflowing-pow-unsigned.rs +++ b/tests/ui/numbers-arithmetic/overflowing-pow-unsigned.rs @@ -1,6 +1,6 @@ //@ run-fail //@ regex-error-pattern: thread 'main'.*panicked -//@ error-pattern: attempt to multiply with overflow +//@ regex-error-pattern: attempt to compute.*\*.* which would overflow //@ needs-subprocess //@ compile-flags: -C debug-assertions diff --git a/tests/ui/numbers-arithmetic/overflowing-sub.rs b/tests/ui/numbers-arithmetic/overflowing-sub.rs index 1718fccad7ae5..0d8b8ef52e056 100644 --- a/tests/ui/numbers-arithmetic/overflowing-sub.rs +++ b/tests/ui/numbers-arithmetic/overflowing-sub.rs @@ -1,6 +1,6 @@ //@ run-fail //@ regex-error-pattern: thread 'main'.*panicked -//@ error-pattern: attempt to subtract with overflow +//@ regex-error-pattern: attempt to compute.*-.* which would overflow //@ needs-subprocess //@ compile-flags: -C debug-assertions diff --git a/tests/ui/numbers-arithmetic/overflowing_add_large_signed.rs b/tests/ui/numbers-arithmetic/overflowing_add_large_signed.rs new file mode 100644 index 0000000000000..9cb1a80e9e9b9 --- /dev/null +++ b/tests/ui/numbers-arithmetic/overflowing_add_large_signed.rs @@ -0,0 +1,11 @@ +//@ run-fail +//@ regex-error-pattern: thread 'main'.*panicked +//@ regex-error-pattern: attempt to compute.*\+.* which would overflow +//@ compile-flags: -C debug-assertions +//@ needs-subprocess + +#![allow(arithmetic_overflow)] + +fn main() { + let _x = i128::MIN + -100_i128; +} diff --git a/tests/ui/numbers-arithmetic/overflowing_add_large_unsigned.rs b/tests/ui/numbers-arithmetic/overflowing_add_large_unsigned.rs new file mode 100644 index 0000000000000..93ef90f1a373e --- /dev/null +++ b/tests/ui/numbers-arithmetic/overflowing_add_large_unsigned.rs @@ -0,0 +1,11 @@ +//@ run-fail +//@ regex-error-pattern: thread 'main'.*panicked +//@ regex-error-pattern: attempt to compute.*\+.* which would overflow +//@ compile-flags: -C debug-assertions +//@ needs-subprocess + +#![allow(arithmetic_overflow)] + +fn main() { + let _x = u128::MAX + 100; +}