Add panic=immediate-abort
This commit is contained in:
@@ -63,8 +63,8 @@ pub fn inject(
|
||||
|
||||
if sess.is_test_crate() {
|
||||
let panic_strategy = match (panic_strategy, sess.opts.unstable_opts.panic_abort_tests) {
|
||||
(PanicStrategy::Abort, true) => PanicStrategy::Abort,
|
||||
(PanicStrategy::Abort, false) => {
|
||||
(PanicStrategy::Abort | PanicStrategy::ImmediateAbort, true) => panic_strategy,
|
||||
(PanicStrategy::Abort | PanicStrategy::ImmediateAbort, false) => {
|
||||
if panic_strategy == platform_panic_strategy {
|
||||
// Silently allow compiling with panic=abort on these platforms,
|
||||
// but with old behavior (abort if a test fails).
|
||||
@@ -287,10 +287,8 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> Box<ast::Item> {
|
||||
let ecx = &cx.ext_cx;
|
||||
let test_ident = Ident::new(sym::test, sp);
|
||||
|
||||
let runner_name = match cx.panic_strategy {
|
||||
PanicStrategy::Unwind => "test_main_static",
|
||||
PanicStrategy::Abort => "test_main_static_abort",
|
||||
};
|
||||
let runner_name =
|
||||
if cx.panic_strategy.unwinds() { "test_main_static" } else { "test_main_static_abort" };
|
||||
|
||||
// test::test_main_static(...)
|
||||
let mut test_runner = cx.test_runner.clone().unwrap_or_else(|| {
|
||||
|
||||
@@ -15,9 +15,9 @@ use rustc_middle::mir::mono::Visibility;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_session::config::DebugInfo;
|
||||
use rustc_span::Symbol;
|
||||
use rustc_target::spec::RelocModel;
|
||||
#[cfg(feature = "master")]
|
||||
use rustc_target::spec::SymbolVisibility;
|
||||
use rustc_target::spec::{PanicStrategy, RelocModel};
|
||||
|
||||
use crate::builder::Builder;
|
||||
use crate::context::CodegenCx;
|
||||
@@ -101,7 +101,7 @@ pub fn compile_codegen_unit(
|
||||
// Instantiate monomorphizations without filling out definitions yet...
|
||||
let context = new_context(tcx);
|
||||
|
||||
if tcx.sess.panic_strategy() == PanicStrategy::Unwind {
|
||||
if tcx.sess.panic_strategy().unwinds() {
|
||||
context.add_command_line_option("-fexceptions");
|
||||
context.add_driver_option("-fexceptions");
|
||||
}
|
||||
|
||||
@@ -29,7 +29,6 @@ use rustc_middle::ty::layout::LayoutOf;
|
||||
use rustc_middle::ty::{self, Instance, Ty};
|
||||
use rustc_span::{Span, Symbol, sym};
|
||||
use rustc_target::callconv::{ArgAbi, PassMode};
|
||||
use rustc_target::spec::PanicStrategy;
|
||||
|
||||
#[cfg(feature = "master")]
|
||||
use crate::abi::FnAbiGccExt;
|
||||
@@ -1334,7 +1333,7 @@ fn try_intrinsic<'a, 'b, 'gcc, 'tcx>(
|
||||
_catch_func: RValue<'gcc>,
|
||||
dest: PlaceRef<'tcx, RValue<'gcc>>,
|
||||
) {
|
||||
if bx.sess().panic_strategy() == PanicStrategy::Abort {
|
||||
if !bx.sess().panic_strategy().unwinds() {
|
||||
bx.call(bx.type_void(), None, None, try_func, &[data], None, None);
|
||||
// Return 0 unconditionally from the intrinsic call;
|
||||
// we can never unwind.
|
||||
|
||||
@@ -18,7 +18,6 @@ use rustc_middle::{bug, span_bug};
|
||||
use rustc_span::{Span, Symbol, sym};
|
||||
use rustc_symbol_mangling::{mangle_internal_symbol, symbol_name_for_instance_in_crate};
|
||||
use rustc_target::callconv::PassMode;
|
||||
use rustc_target::spec::PanicStrategy;
|
||||
use tracing::debug;
|
||||
|
||||
use crate::abi::FnAbiLlvmExt;
|
||||
@@ -674,7 +673,7 @@ fn catch_unwind_intrinsic<'ll, 'tcx>(
|
||||
catch_func: &'ll Value,
|
||||
dest: PlaceRef<'tcx, &'ll Value>,
|
||||
) {
|
||||
if bx.sess().panic_strategy() == PanicStrategy::Abort {
|
||||
if !bx.sess().panic_strategy().unwinds() {
|
||||
let try_func_ty = bx.type_func(&[bx.type_ptr()], bx.type_void());
|
||||
bx.call(try_func_ty, None, None, try_func, &[data], None, None);
|
||||
// Return 0 unconditionally from the intrinsic call;
|
||||
|
||||
@@ -106,7 +106,7 @@ unsafe fn configure_llvm(sess: &Session) {
|
||||
|
||||
if sess.target.os == "emscripten"
|
||||
&& !sess.opts.unstable_opts.emscripten_wasm_eh
|
||||
&& sess.panic_strategy() == PanicStrategy::Unwind
|
||||
&& sess.panic_strategy().unwinds()
|
||||
{
|
||||
add("-enable-emscripten-cxx-exceptions", false);
|
||||
}
|
||||
|
||||
@@ -47,8 +47,8 @@ use rustc_span::Symbol;
|
||||
use rustc_target::spec::crt_objects::CrtObjects;
|
||||
use rustc_target::spec::{
|
||||
BinaryFormat, Cc, LinkOutputKind, LinkSelfContainedComponents, LinkSelfContainedDefault,
|
||||
LinkerFeatures, LinkerFlavor, LinkerFlavorCli, Lld, PanicStrategy, RelocModel, RelroLevel,
|
||||
SanitizerSet, SplitDebuginfo,
|
||||
LinkerFeatures, LinkerFlavor, LinkerFlavorCli, Lld, RelocModel, RelroLevel, SanitizerSet,
|
||||
SplitDebuginfo,
|
||||
};
|
||||
use tracing::{debug, info, warn};
|
||||
|
||||
@@ -2512,10 +2512,10 @@ fn add_order_independent_options(
|
||||
if sess.target.os == "emscripten" {
|
||||
cmd.cc_arg(if sess.opts.unstable_opts.emscripten_wasm_eh {
|
||||
"-fwasm-exceptions"
|
||||
} else if sess.panic_strategy() == PanicStrategy::Abort {
|
||||
"-sDISABLE_EXCEPTION_CATCHING=1"
|
||||
} else {
|
||||
} else if sess.panic_strategy().unwinds() {
|
||||
"-sDISABLE_EXCEPTION_CATCHING=0"
|
||||
} else {
|
||||
"-sDISABLE_EXCEPTION_CATCHING=1"
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ interface_out_dir_error =
|
||||
failed to find or create the directory specified by `--out-dir`
|
||||
|
||||
interface_proc_macro_crate_panic_abort =
|
||||
building proc macro crate with `panic=abort` may crash the compiler should the proc-macro panic
|
||||
building proc macro crate with `panic=abort` or `panic=immediate-abort` may crash the compiler should the proc-macro panic
|
||||
|
||||
interface_temps_dir_error =
|
||||
failed to find or create the directory specified by `--temps-dir`
|
||||
|
||||
@@ -42,7 +42,6 @@ use rustc_span::{
|
||||
DUMMY_SP, ErrorGuaranteed, ExpnKind, FileName, SourceFileHash, SourceFileHashAlgorithm, Span,
|
||||
Symbol, sym,
|
||||
};
|
||||
use rustc_target::spec::PanicStrategy;
|
||||
use rustc_trait_selection::{solve, traits};
|
||||
use tracing::{info, instrument};
|
||||
|
||||
@@ -282,7 +281,7 @@ fn configure_and_expand(
|
||||
feature_err(sess, sym::export_stable, DUMMY_SP, "`sdylib` crate type is unstable").emit();
|
||||
}
|
||||
|
||||
if is_proc_macro_crate && sess.panic_strategy() == PanicStrategy::Abort {
|
||||
if is_proc_macro_crate && !sess.panic_strategy().unwinds() {
|
||||
sess.dcx().emit_warn(errors::ProcMacroCratePanicAbort);
|
||||
}
|
||||
|
||||
|
||||
@@ -98,6 +98,13 @@ metadata_full_metadata_not_found =
|
||||
metadata_global_alloc_required =
|
||||
no global memory allocator found but one is required; link to std or add `#[global_allocator]` to a static item that implements the GlobalAlloc trait
|
||||
|
||||
metadata_incompatible_with_immediate_abort =
|
||||
the crate `{$crate_name}` was compiled with a panic strategy which is incompatible with `immediate-abort`
|
||||
|
||||
metadata_incompatible_with_immediate_abort_core =
|
||||
the crate `core` was compiled with a panic strategy which is incompatible with `immediate-abort`
|
||||
.help = consider building the standard library from source with `cargo build -Zbuild-std`
|
||||
|
||||
metadata_incompatible_panic_in_drop_strategy =
|
||||
the crate `{$crate_name}` is compiled with the panic-in-drop strategy `{$found_strategy}` which is incompatible with this crate's strategy of `{$desired_strategy}`
|
||||
|
||||
|
||||
@@ -1027,6 +1027,10 @@ impl CStore {
|
||||
let name = match desired_strategy {
|
||||
PanicStrategy::Unwind => sym::panic_unwind,
|
||||
PanicStrategy::Abort => sym::panic_abort,
|
||||
PanicStrategy::ImmediateAbort => {
|
||||
// Immediate-aborting panics don't use a runtime.
|
||||
return;
|
||||
}
|
||||
};
|
||||
info!("panic runtime not found -- loading {}", name);
|
||||
|
||||
|
||||
@@ -61,11 +61,13 @@ use rustc_session::config::CrateType;
|
||||
use rustc_session::cstore::CrateDepKind;
|
||||
use rustc_session::cstore::LinkagePreference::{self, RequireDynamic, RequireStatic};
|
||||
use rustc_span::sym;
|
||||
use rustc_target::spec::PanicStrategy;
|
||||
use tracing::info;
|
||||
|
||||
use crate::creader::CStore;
|
||||
use crate::errors::{
|
||||
BadPanicStrategy, CrateDepMultiple, IncompatiblePanicInDropStrategy, LibRequired,
|
||||
BadPanicStrategy, CrateDepMultiple, IncompatiblePanicInDropStrategy,
|
||||
IncompatibleWithImmediateAbort, IncompatibleWithImmediateAbortCore, LibRequired,
|
||||
NonStaticCrateDep, RequiredPanicStrategy, RlibRequired, RustcDriverHelp, RustcLibRequired,
|
||||
TwoPanicRuntimes,
|
||||
};
|
||||
@@ -402,15 +404,43 @@ fn activate_injected_dep(
|
||||
/// there's only going to be one panic runtime in the output.
|
||||
fn verify_ok(tcx: TyCtxt<'_>, list: &DependencyList) {
|
||||
let sess = &tcx.sess;
|
||||
let list: Vec<_> = list
|
||||
.iter_enumerated()
|
||||
.filter_map(
|
||||
|(cnum, linkage)| if *linkage == Linkage::NotLinked { None } else { Some(cnum) },
|
||||
)
|
||||
.collect();
|
||||
if list.is_empty() {
|
||||
return;
|
||||
}
|
||||
let mut panic_runtime = None;
|
||||
for (cnum, linkage) in list.iter_enumerated() {
|
||||
if let Linkage::NotLinked = *linkage {
|
||||
continue;
|
||||
}
|
||||
let desired_strategy = sess.panic_strategy();
|
||||
|
||||
// If we are panic=immediate-abort, make sure everything in the dependency tree has also been
|
||||
// compiled with immediate-abort.
|
||||
if list
|
||||
.iter()
|
||||
.any(|cnum| tcx.required_panic_strategy(*cnum) == Some(PanicStrategy::ImmediateAbort))
|
||||
{
|
||||
let mut invalid_crates = Vec::new();
|
||||
for cnum in list.iter().copied() {
|
||||
if tcx.required_panic_strategy(cnum) != Some(PanicStrategy::ImmediateAbort) {
|
||||
invalid_crates.push(cnum);
|
||||
// If core is incompatible, it's very likely that we'd emit an error for every
|
||||
// sysroot crate, so instead of doing that emit a single fatal error that suggests
|
||||
// using build-std.
|
||||
if tcx.crate_name(cnum) == sym::core {
|
||||
sess.dcx().emit_fatal(IncompatibleWithImmediateAbortCore);
|
||||
}
|
||||
}
|
||||
}
|
||||
for cnum in invalid_crates {
|
||||
sess.dcx()
|
||||
.emit_err(IncompatibleWithImmediateAbort { crate_name: tcx.crate_name(cnum) });
|
||||
}
|
||||
}
|
||||
|
||||
let mut panic_runtime = None;
|
||||
for cnum in list.iter().copied() {
|
||||
if tcx.is_panic_runtime(cnum) {
|
||||
if let Some((prev, _)) = panic_runtime {
|
||||
let prev_name = tcx.crate_name(prev);
|
||||
@@ -430,8 +460,6 @@ fn verify_ok(tcx: TyCtxt<'_>, list: &DependencyList) {
|
||||
// only one, but we perform validation here that all the panic strategy
|
||||
// compilation modes for the whole DAG are valid.
|
||||
if let Some((runtime_cnum, found_strategy)) = panic_runtime {
|
||||
let desired_strategy = sess.panic_strategy();
|
||||
|
||||
// First up, validate that our selected panic runtime is indeed exactly
|
||||
// our same strategy.
|
||||
if found_strategy != desired_strategy {
|
||||
@@ -445,10 +473,7 @@ fn verify_ok(tcx: TyCtxt<'_>, list: &DependencyList) {
|
||||
// strategy. If the dep isn't linked, we ignore it, and if our strategy
|
||||
// is abort then it's compatible with everything. Otherwise all crates'
|
||||
// panic strategy must match our own.
|
||||
for (cnum, linkage) in list.iter_enumerated() {
|
||||
if let Linkage::NotLinked = *linkage {
|
||||
continue;
|
||||
}
|
||||
for cnum in list.iter().copied() {
|
||||
if cnum == runtime_cnum || tcx.is_compiler_builtins(cnum) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -75,6 +75,16 @@ pub struct RequiredPanicStrategy {
|
||||
pub desired_strategy: PanicStrategy,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(metadata_incompatible_with_immediate_abort)]
|
||||
pub struct IncompatibleWithImmediateAbort {
|
||||
pub crate_name: Symbol,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(metadata_incompatible_with_immediate_abort_core)]
|
||||
pub struct IncompatibleWithImmediateAbortCore;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(metadata_incompatible_panic_in_drop_strategy)]
|
||||
pub struct IncompatiblePanicInDropStrategy {
|
||||
|
||||
@@ -98,5 +98,6 @@ pub fn required(tcx: TyCtxt<'_>, lang_item: LangItem) -> bool {
|
||||
lang_item != LangItem::EhPersonality && lang_item != LangItem::EhCatchTypeinfo
|
||||
}
|
||||
PanicStrategy::Unwind => true,
|
||||
PanicStrategy::ImmediateAbort => false,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ use rustc_macros::{HashStable, TyDecodable, TyEncodable, extension};
|
||||
use rustc_session::config::OptLevel;
|
||||
use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, Symbol, sym};
|
||||
use rustc_target::callconv::FnAbi;
|
||||
use rustc_target::spec::{HasTargetSpec, HasX86AbiOpt, PanicStrategy, Target, X86Abi};
|
||||
use rustc_target::spec::{HasTargetSpec, HasX86AbiOpt, Target, X86Abi};
|
||||
use tracing::debug;
|
||||
use {rustc_abi as abi, rustc_hir as hir};
|
||||
|
||||
@@ -1198,7 +1198,7 @@ pub fn fn_can_unwind(tcx: TyCtxt<'_>, fn_def_id: Option<DefId>, abi: ExternAbi)
|
||||
//
|
||||
// Note that this is true regardless ABI specified on the function -- a `extern "C-unwind"`
|
||||
// function defined in Rust is also required to abort.
|
||||
if tcx.sess.panic_strategy() == PanicStrategy::Abort && !tcx.is_foreign_item(did) {
|
||||
if !tcx.sess.panic_strategy().unwinds() && !tcx.is_foreign_item(did) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1206,7 +1206,7 @@ pub fn fn_can_unwind(tcx: TyCtxt<'_>, fn_def_id: Option<DefId>, abi: ExternAbi)
|
||||
//
|
||||
// This is not part of `codegen_fn_attrs` as it can differ between crates
|
||||
// and therefore cannot be computed in core.
|
||||
if tcx.sess.opts.unstable_opts.panic_in_drop == PanicStrategy::Abort
|
||||
if !tcx.sess.opts.unstable_opts.panic_in_drop.unwinds()
|
||||
&& tcx.is_lang_item(did, LangItem::DropInPlace)
|
||||
{
|
||||
return false;
|
||||
@@ -1245,7 +1245,7 @@ pub fn fn_can_unwind(tcx: TyCtxt<'_>, fn_def_id: Option<DefId>, abi: ExternAbi)
|
||||
| RiscvInterruptS
|
||||
| RustInvalid
|
||||
| Unadjusted => false,
|
||||
Rust | RustCall | RustCold => tcx.sess.panic_strategy() == PanicStrategy::Unwind,
|
||||
Rust | RustCall | RustCold => tcx.sess.panic_strategy().unwinds(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -86,7 +86,6 @@ use rustc_span::def_id::{DefId, LocalDefId};
|
||||
use rustc_span::source_map::dummy_spanned;
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::{DUMMY_SP, Span};
|
||||
use rustc_target::spec::PanicStrategy;
|
||||
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
|
||||
use rustc_trait_selection::infer::TyCtxtInferExt as _;
|
||||
use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode, ObligationCtxt};
|
||||
@@ -1149,7 +1148,7 @@ fn can_return<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, typing_env: ty::Typing
|
||||
|
||||
fn can_unwind<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> bool {
|
||||
// Nothing can unwind when landing pads are off.
|
||||
if tcx.sess.panic_strategy() == PanicStrategy::Abort {
|
||||
if !tcx.sess.panic_strategy().unwinds() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -101,12 +101,15 @@ fn has_ffi_unwind_calls(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> bool {
|
||||
}
|
||||
|
||||
fn required_panic_strategy(tcx: TyCtxt<'_>, _: LocalCrate) -> Option<PanicStrategy> {
|
||||
let local_strategy = tcx.sess.panic_strategy();
|
||||
|
||||
if tcx.is_panic_runtime(LOCAL_CRATE) {
|
||||
return Some(tcx.sess.panic_strategy());
|
||||
return Some(local_strategy);
|
||||
}
|
||||
|
||||
if tcx.sess.panic_strategy() == PanicStrategy::Abort {
|
||||
return Some(PanicStrategy::Abort);
|
||||
match local_strategy {
|
||||
PanicStrategy::Abort | PanicStrategy::ImmediateAbort => return Some(local_strategy),
|
||||
_ => {}
|
||||
}
|
||||
|
||||
for def_id in tcx.hir_body_owners() {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
use rustc_index::bit_set::DenseBitSet;
|
||||
use rustc_middle::mir::*;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_target::spec::PanicStrategy;
|
||||
use tracing::debug;
|
||||
|
||||
use crate::patch::MirPatch;
|
||||
@@ -13,7 +12,7 @@ pub(super) struct RemoveNoopLandingPads;
|
||||
|
||||
impl<'tcx> crate::MirPass<'tcx> for RemoveNoopLandingPads {
|
||||
fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
|
||||
sess.panic_strategy() != PanicStrategy::Abort
|
||||
sess.panic_strategy().unwinds()
|
||||
}
|
||||
|
||||
fn run_pass(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||
|
||||
@@ -29,7 +29,8 @@ use rustc_span::{
|
||||
SourceFileHashAlgorithm, Symbol, sym,
|
||||
};
|
||||
use rustc_target::spec::{
|
||||
FramePointer, LinkSelfContainedComponents, LinkerFeatures, SplitDebuginfo, Target, TargetTuple,
|
||||
FramePointer, LinkSelfContainedComponents, LinkerFeatures, PanicStrategy, SplitDebuginfo,
|
||||
Target, TargetTuple,
|
||||
};
|
||||
use tracing::debug;
|
||||
|
||||
@@ -2799,6 +2800,12 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
|
||||
}
|
||||
}
|
||||
|
||||
if !unstable_options_enabled && cg.panic == Some(PanicStrategy::ImmediateAbort) {
|
||||
early_dcx.early_fatal(
|
||||
"`-Cpanic=immediate-abort` requires `-Zunstable-options` and a nightly compiler",
|
||||
)
|
||||
}
|
||||
|
||||
let crate_name = matches.opt_str("crate-name");
|
||||
let unstable_features = UnstableFeatures::from_environment(crate_name.as_deref());
|
||||
// Parse any `-l` flags, which link to native libraries.
|
||||
|
||||
@@ -125,7 +125,9 @@ pub(crate) fn disallow_cfgs(sess: &Session, user_cfgs: &Cfg) {
|
||||
None | Some(_),
|
||||
) => disallow(cfg, "-Z sanitizer=cfi"),
|
||||
(sym::proc_macro, None) => disallow(cfg, "--crate-type proc-macro"),
|
||||
(sym::panic, Some(sym::abort | sym::unwind)) => disallow(cfg, "-C panic"),
|
||||
(sym::panic, Some(sym::abort | sym::unwind | sym::immediate_abort)) => {
|
||||
disallow(cfg, "-C panic")
|
||||
}
|
||||
(sym::target_feature, Some(_)) => disallow(cfg, "-C target-feature"),
|
||||
(sym::unix, None)
|
||||
| (sym::windows, None)
|
||||
@@ -204,6 +206,9 @@ pub(crate) fn default_configuration(sess: &Session) -> Cfg {
|
||||
}
|
||||
|
||||
ins_sym!(sym::panic, sess.panic_strategy().desc_symbol());
|
||||
if sess.panic_strategy() == PanicStrategy::ImmediateAbort {
|
||||
ins_sym!(sym::panic, PanicStrategy::Abort.desc_symbol());
|
||||
}
|
||||
|
||||
// JUSTIFICATION: before wrapper fn is available
|
||||
#[allow(rustc::bad_opt_access)]
|
||||
|
||||
@@ -802,7 +802,7 @@ mod desc {
|
||||
pub(crate) const parse_threads: &str = parse_number;
|
||||
pub(crate) const parse_time_passes_format: &str = "`text` (default) or `json`";
|
||||
pub(crate) const parse_passes: &str = "a space-separated list of passes, or `all`";
|
||||
pub(crate) const parse_panic_strategy: &str = "either `unwind` or `abort`";
|
||||
pub(crate) const parse_panic_strategy: &str = "either `unwind`, `abort`, or `immediate-abort`";
|
||||
pub(crate) const parse_on_broken_pipe: &str = "either `kill`, `error`, or `inherit`";
|
||||
pub(crate) const parse_patchable_function_entry: &str = "either two comma separated integers (total_nops,prefix_nops), with prefix_nops <= total_nops, or one integer (total_nops)";
|
||||
pub(crate) const parse_opt_panic_strategy: &str = parse_panic_strategy;
|
||||
@@ -1165,6 +1165,7 @@ pub mod parse {
|
||||
match v {
|
||||
Some("unwind") => *slot = Some(PanicStrategy::Unwind),
|
||||
Some("abort") => *slot = Some(PanicStrategy::Abort),
|
||||
Some("immediate-abort") => *slot = Some(PanicStrategy::ImmediateAbort),
|
||||
_ => return false,
|
||||
}
|
||||
true
|
||||
@@ -1174,6 +1175,7 @@ pub mod parse {
|
||||
match v {
|
||||
Some("unwind") => *slot = PanicStrategy::Unwind,
|
||||
Some("abort") => *slot = PanicStrategy::Abort,
|
||||
Some("immediate-abort") => *slot = PanicStrategy::ImmediateAbort,
|
||||
_ => return false,
|
||||
}
|
||||
true
|
||||
|
||||
@@ -777,9 +777,11 @@ impl Session {
|
||||
// Otherwise, we can defer to the `-C force-unwind-tables=<yes/no>`
|
||||
// value, if it is provided, or disable them, if not.
|
||||
self.target.requires_uwtable
|
||||
|| self.opts.cg.force_unwind_tables.unwrap_or(
|
||||
self.panic_strategy() == PanicStrategy::Unwind || self.target.default_uwtable,
|
||||
)
|
||||
|| self
|
||||
.opts
|
||||
.cg
|
||||
.force_unwind_tables
|
||||
.unwrap_or(self.panic_strategy().unwinds() || self.target.default_uwtable)
|
||||
}
|
||||
|
||||
/// Returns the number of query threads that should be used for this
|
||||
@@ -1229,7 +1231,7 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
|
||||
}
|
||||
|
||||
// KCFI requires panic=abort
|
||||
if sess.is_sanitizer_kcfi_enabled() && sess.panic_strategy() != PanicStrategy::Abort {
|
||||
if sess.is_sanitizer_kcfi_enabled() && sess.panic_strategy().unwinds() {
|
||||
sess.dcx().emit_err(errors::SanitizerKcfiRequiresPanicAbort);
|
||||
}
|
||||
|
||||
|
||||
@@ -1195,6 +1195,7 @@ symbols! {
|
||||
if_let_rescope,
|
||||
if_while_or_patterns,
|
||||
ignore,
|
||||
immediate_abort,
|
||||
impl_header_lifetime_elision,
|
||||
impl_lint_pass,
|
||||
impl_trait_in_assoc_type,
|
||||
|
||||
@@ -834,6 +834,7 @@ crate::target_spec_enum! {
|
||||
pub enum PanicStrategy {
|
||||
Unwind = "unwind",
|
||||
Abort = "abort",
|
||||
ImmediateAbort = "immediate-abort",
|
||||
}
|
||||
|
||||
parse_error_type = "panic strategy";
|
||||
@@ -852,8 +853,13 @@ impl PanicStrategy {
|
||||
match *self {
|
||||
PanicStrategy::Unwind => sym::unwind,
|
||||
PanicStrategy::Abort => sym::abort,
|
||||
PanicStrategy::ImmediateAbort => sym::immediate_abort,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unwinds(self) -> bool {
|
||||
matches!(self, PanicStrategy::Unwind)
|
||||
}
|
||||
}
|
||||
|
||||
crate::target_spec_enum! {
|
||||
|
||||
@@ -22,8 +22,6 @@ compiler_builtins = { path = "../compiler-builtins/compiler-builtins", features
|
||||
compiler-builtins-mem = ['compiler_builtins/mem']
|
||||
compiler-builtins-c = ["compiler_builtins/c"]
|
||||
compiler-builtins-no-f16-f128 = ["compiler_builtins/no-f16-f128"]
|
||||
# Make panics and failed asserts immediately abort without formatting any message
|
||||
panic_immediate_abort = ["core/panic_immediate_abort"]
|
||||
# Choose algorithms that are optimized for binary size instead of runtime performance
|
||||
optimize_for_size = ["core/optimize_for_size"]
|
||||
|
||||
|
||||
@@ -408,12 +408,12 @@ pub const fn handle_alloc_error(layout: Layout) -> ! {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "panic_immediate_abort"))]
|
||||
#[cfg(not(panic = "immediate_abort"))]
|
||||
{
|
||||
core::intrinsics::const_eval_select((layout,), ct_error, rt_error)
|
||||
}
|
||||
|
||||
#[cfg(feature = "panic_immediate_abort")]
|
||||
#[cfg(panic = "immediate_abort")]
|
||||
ct_error(layout)
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ mod tests;
|
||||
// ensure that the code generation related to these panics is minimal as there's
|
||||
// only one location which panics rather than a bunch throughout the module.
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
|
||||
#[cfg_attr(not(panic = "immediate_abort"), inline(never))]
|
||||
#[track_caller]
|
||||
fn capacity_overflow() -> ! {
|
||||
panic!("capacity overflow");
|
||||
|
||||
@@ -2020,7 +2020,7 @@ impl<T, A: Allocator> Vec<T, A> {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn swap_remove(&mut self, index: usize) -> T {
|
||||
#[cold]
|
||||
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
|
||||
#[cfg_attr(not(panic = "immediate_abort"), inline(never))]
|
||||
#[track_caller]
|
||||
#[optimize(size)]
|
||||
fn assert_failed(index: usize, len: usize) -> ! {
|
||||
@@ -2102,7 +2102,7 @@ impl<T, A: Allocator> Vec<T, A> {
|
||||
#[must_use = "if you don't need a reference to the value, use `Vec::insert` instead"]
|
||||
pub fn insert_mut(&mut self, index: usize, element: T) -> &mut T {
|
||||
#[cold]
|
||||
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
|
||||
#[cfg_attr(not(panic = "immediate_abort"), inline(never))]
|
||||
#[track_caller]
|
||||
#[optimize(size)]
|
||||
fn assert_failed(index: usize, len: usize) -> ! {
|
||||
@@ -2166,7 +2166,7 @@ impl<T, A: Allocator> Vec<T, A> {
|
||||
#[rustc_confusables("delete", "take")]
|
||||
pub fn remove(&mut self, index: usize) -> T {
|
||||
#[cold]
|
||||
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
|
||||
#[cfg_attr(not(panic = "immediate_abort"), inline(never))]
|
||||
#[track_caller]
|
||||
#[optimize(size)]
|
||||
fn assert_failed(index: usize, len: usize) -> ! {
|
||||
@@ -2955,7 +2955,7 @@ impl<T, A: Allocator> Vec<T, A> {
|
||||
A: Clone,
|
||||
{
|
||||
#[cold]
|
||||
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
|
||||
#[cfg_attr(not(panic = "immediate_abort"), inline(never))]
|
||||
#[track_caller]
|
||||
#[optimize(size)]
|
||||
fn assert_failed(at: usize, len: usize) -> ! {
|
||||
|
||||
@@ -16,7 +16,7 @@ test = false
|
||||
bench = false
|
||||
|
||||
[features]
|
||||
# Make panics and failed asserts immediately abort without formatting any message
|
||||
# Issue a compile error that says to use -Cpanic=immediate-abort
|
||||
panic_immediate_abort = []
|
||||
# Choose algorithms that are optimized for binary size instead of runtime performance
|
||||
optimize_for_size = []
|
||||
|
||||
@@ -778,7 +778,7 @@ impl Display for BorrowMutError {
|
||||
}
|
||||
|
||||
// This ensures the panicking code is outlined from `borrow_mut` for `RefCell`.
|
||||
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
|
||||
#[cfg_attr(not(panic = "immediate_abort"), inline(never))]
|
||||
#[track_caller]
|
||||
#[cold]
|
||||
const fn panic_already_borrowed(err: BorrowMutError) -> ! {
|
||||
@@ -790,7 +790,7 @@ const fn panic_already_borrowed(err: BorrowMutError) -> ! {
|
||||
}
|
||||
|
||||
// This ensures the panicking code is outlined from `borrow` for `RefCell`.
|
||||
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
|
||||
#[cfg_attr(not(panic = "immediate_abort"), inline(never))]
|
||||
#[track_caller]
|
||||
#[cold]
|
||||
const fn panic_already_mutably_borrowed(err: BorrowError) -> ! {
|
||||
|
||||
@@ -1387,8 +1387,8 @@ pub const fn can_not_overflow<T>(radix: u32, is_signed_ty: bool, digits: &[u8])
|
||||
radix <= 16 && digits.len() <= size_of::<T>() * 2 - is_signed_ty as usize
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
|
||||
#[cfg_attr(feature = "panic_immediate_abort", inline)]
|
||||
#[cfg_attr(not(panic = "immediate_abort"), inline(never))]
|
||||
#[cfg_attr(panic = "immediate_abort", inline)]
|
||||
#[cold]
|
||||
#[track_caller]
|
||||
const fn from_ascii_radix_panic(radix: u32) -> ! {
|
||||
|
||||
@@ -2161,8 +2161,8 @@ impl<T, E> Option<Result<T, E>> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
|
||||
#[cfg_attr(feature = "panic_immediate_abort", inline)]
|
||||
#[cfg_attr(not(panic = "immediate_abort"), inline(never))]
|
||||
#[cfg_attr(panic = "immediate_abort", inline)]
|
||||
#[cold]
|
||||
#[track_caller]
|
||||
const fn unwrap_failed() -> ! {
|
||||
@@ -2170,8 +2170,8 @@ const fn unwrap_failed() -> ! {
|
||||
}
|
||||
|
||||
// This is a separate function to reduce the code size of .expect() itself.
|
||||
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
|
||||
#[cfg_attr(feature = "panic_immediate_abort", inline)]
|
||||
#[cfg_attr(not(panic = "immediate_abort"), inline(never))]
|
||||
#[cfg_attr(panic = "immediate_abort", inline)]
|
||||
#[cold]
|
||||
#[track_caller]
|
||||
const fn expect_failed(msg: &str) -> ! {
|
||||
|
||||
@@ -33,7 +33,10 @@ use crate::intrinsics::const_eval_select;
|
||||
use crate::panic::{Location, PanicInfo};
|
||||
|
||||
#[cfg(feature = "panic_immediate_abort")]
|
||||
const _: () = assert!(cfg!(panic = "abort"), "panic_immediate_abort requires -C panic=abort");
|
||||
compile_error!(
|
||||
"panic_immediate_abort is now a real panic strategy! \
|
||||
Enable it with the compiler flags `-Zunstable-options -Cpanic=immediate-abort`"
|
||||
);
|
||||
|
||||
// First we define the two main entry points that all panics go through.
|
||||
// In the end both are just convenience wrappers around `panic_impl`.
|
||||
@@ -44,16 +47,16 @@ const _: () = assert!(cfg!(panic = "abort"), "panic_immediate_abort requires -C
|
||||
/// site as much as possible (so that `panic!()` has as low an impact
|
||||
/// on (e.g.) the inlining of other functions as possible), by moving
|
||||
/// the actual formatting into this shared place.
|
||||
// If panic_immediate_abort, inline the abort call,
|
||||
// If panic=immediate-abort, inline the abort call,
|
||||
// otherwise avoid inlining because of it is cold path.
|
||||
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
|
||||
#[cfg_attr(feature = "panic_immediate_abort", inline)]
|
||||
#[cfg_attr(not(panic = "immediate_abort"), inline(never), cold)]
|
||||
#[cfg_attr(panic = "immediate_abort", inline)]
|
||||
#[track_caller]
|
||||
#[lang = "panic_fmt"] // needed for const-evaluated panics
|
||||
#[rustc_do_not_const_check] // hooked by const-eval
|
||||
#[rustc_const_stable_indirect] // must follow stable const rules since it is exposed to stable
|
||||
pub const fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! {
|
||||
if cfg!(feature = "panic_immediate_abort") {
|
||||
if cfg!(panic = "immediate_abort") {
|
||||
super::intrinsics::abort()
|
||||
}
|
||||
|
||||
@@ -78,8 +81,8 @@ pub const fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! {
|
||||
/// Like `panic_fmt`, but for non-unwinding panics.
|
||||
///
|
||||
/// Has to be a separate function so that it can carry the `rustc_nounwind` attribute.
|
||||
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
|
||||
#[cfg_attr(feature = "panic_immediate_abort", inline)]
|
||||
#[cfg_attr(not(panic = "immediate_abort"), inline(never), cold)]
|
||||
#[cfg_attr(panic = "immediate_abort", inline)]
|
||||
#[track_caller]
|
||||
// This attribute has the key side-effect that if the panic handler ignores `can_unwind`
|
||||
// and unwinds anyway, we will hit the "unwinding out of nounwind function" guard,
|
||||
@@ -94,7 +97,7 @@ pub const fn panic_nounwind_fmt(fmt: fmt::Arguments<'_>, force_no_backtrace: boo
|
||||
// We don't unwind anyway at compile-time so we can call the regular `panic_fmt`.
|
||||
panic_fmt(fmt)
|
||||
} else #[track_caller] {
|
||||
if cfg!(feature = "panic_immediate_abort") {
|
||||
if cfg!(panic = "immediate_abort") {
|
||||
super::intrinsics::abort()
|
||||
}
|
||||
|
||||
@@ -123,10 +126,10 @@ pub const fn panic_nounwind_fmt(fmt: fmt::Arguments<'_>, force_no_backtrace: boo
|
||||
// above.
|
||||
|
||||
/// The underlying implementation of core's `panic!` macro when no formatting is used.
|
||||
// Never inline unless panic_immediate_abort to avoid code
|
||||
// Never inline unless panic=immediate-abort to avoid code
|
||||
// bloat at the call sites as much as possible.
|
||||
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
|
||||
#[cfg_attr(feature = "panic_immediate_abort", inline)]
|
||||
#[cfg_attr(not(panic = "immediate_abort"), inline(never), cold)]
|
||||
#[cfg_attr(panic = "immediate_abort", inline)]
|
||||
#[track_caller]
|
||||
#[rustc_const_stable_indirect] // must follow stable const rules since it is exposed to stable
|
||||
#[lang = "panic"] // used by lints and miri for panics
|
||||
@@ -158,10 +161,10 @@ macro_rules! panic_const {
|
||||
$(
|
||||
/// This is a panic called with a message that's a result of a MIR-produced Assert.
|
||||
//
|
||||
// never inline unless panic_immediate_abort to avoid code
|
||||
// never inline unless panic=immediate-abort to avoid code
|
||||
// bloat at the call sites as much as possible
|
||||
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
|
||||
#[cfg_attr(feature = "panic_immediate_abort", inline)]
|
||||
#[cfg_attr(not(panic = "immediate_abort"), inline(never), cold)]
|
||||
#[cfg_attr(panic = "immediate_abort", inline)]
|
||||
#[track_caller]
|
||||
#[rustc_const_stable_indirect] // must follow stable const rules since it is exposed to stable
|
||||
#[lang = stringify!($lang)]
|
||||
@@ -216,8 +219,8 @@ pub mod panic_const {
|
||||
|
||||
/// 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(feature = "panic_immediate_abort"), inline(never), cold)]
|
||||
#[cfg_attr(feature = "panic_immediate_abort", inline)]
|
||||
#[cfg_attr(not(panic = "immediate_abort"), inline(never), cold)]
|
||||
#[cfg_attr(panic = "immediate_abort", inline)]
|
||||
#[lang = "panic_nounwind"] // needed by codegen for non-unwinding panics
|
||||
#[rustc_nounwind]
|
||||
#[rustc_const_stable_indirect] // must follow stable const rules since it is exposed to stable
|
||||
@@ -226,8 +229,8 @@ pub const fn panic_nounwind(expr: &'static str) -> ! {
|
||||
}
|
||||
|
||||
/// Like `panic_nounwind`, but also inhibits showing a backtrace.
|
||||
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
|
||||
#[cfg_attr(feature = "panic_immediate_abort", inline)]
|
||||
#[cfg_attr(not(panic = "immediate_abort"), inline(never), cold)]
|
||||
#[cfg_attr(panic = "immediate_abort", inline)]
|
||||
#[rustc_nounwind]
|
||||
pub fn panic_nounwind_nobacktrace(expr: &'static str) -> ! {
|
||||
panic_nounwind_fmt(fmt::Arguments::new_const(&[expr]), /* force_no_backtrace */ true);
|
||||
@@ -259,25 +262,25 @@ pub const fn panic_display<T: fmt::Display>(x: &T) -> ! {
|
||||
panic_fmt(format_args!("{}", *x));
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold, optimize(size))]
|
||||
#[cfg_attr(feature = "panic_immediate_abort", inline)]
|
||||
#[cfg_attr(not(panic = "immediate_abort"), inline(never), cold, optimize(size))]
|
||||
#[cfg_attr(panic = "immediate_abort", inline)]
|
||||
#[track_caller]
|
||||
#[lang = "panic_bounds_check"] // needed by codegen for panic on OOB array/slice access
|
||||
fn panic_bounds_check(index: usize, len: usize) -> ! {
|
||||
if cfg!(feature = "panic_immediate_abort") {
|
||||
if cfg!(panic = "immediate_abort") {
|
||||
super::intrinsics::abort()
|
||||
}
|
||||
|
||||
panic!("index out of bounds: the len is {len} but the index is {index}")
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold, optimize(size))]
|
||||
#[cfg_attr(feature = "panic_immediate_abort", inline)]
|
||||
#[cfg_attr(not(panic = "immediate_abort"), inline(never), cold, optimize(size))]
|
||||
#[cfg_attr(panic = "immediate_abort", inline)]
|
||||
#[track_caller]
|
||||
#[lang = "panic_misaligned_pointer_dereference"] // needed by codegen for panic on misaligned pointer deref
|
||||
#[rustc_nounwind] // `CheckAlignment` MIR pass requires this function to never unwind
|
||||
fn panic_misaligned_pointer_dereference(required: usize, found: usize) -> ! {
|
||||
if cfg!(feature = "panic_immediate_abort") {
|
||||
if cfg!(panic = "immediate_abort") {
|
||||
super::intrinsics::abort()
|
||||
}
|
||||
|
||||
@@ -289,13 +292,13 @@ fn panic_misaligned_pointer_dereference(required: usize, found: usize) -> ! {
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold, optimize(size))]
|
||||
#[cfg_attr(feature = "panic_immediate_abort", inline)]
|
||||
#[cfg_attr(not(panic = "immediate_abort"), inline(never), cold, optimize(size))]
|
||||
#[cfg_attr(panic = "immediate_abort", inline)]
|
||||
#[track_caller]
|
||||
#[lang = "panic_null_pointer_dereference"] // needed by codegen for panic on null pointer deref
|
||||
#[rustc_nounwind] // `CheckNull` MIR pass requires this function to never unwind
|
||||
fn panic_null_pointer_dereference() -> ! {
|
||||
if cfg!(feature = "panic_immediate_abort") {
|
||||
if cfg!(panic = "immediate_abort") {
|
||||
super::intrinsics::abort()
|
||||
}
|
||||
|
||||
@@ -305,13 +308,13 @@ fn panic_null_pointer_dereference() -> ! {
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold, optimize(size))]
|
||||
#[cfg_attr(feature = "panic_immediate_abort", inline)]
|
||||
#[cfg_attr(not(panic = "immediate_abort"), inline(never), cold, optimize(size))]
|
||||
#[cfg_attr(panic = "immediate_abort", inline)]
|
||||
#[track_caller]
|
||||
#[lang = "panic_invalid_enum_construction"] // needed by codegen for panic on invalid enum construction.
|
||||
#[rustc_nounwind] // `CheckEnums` MIR pass requires this function to never unwind
|
||||
fn panic_invalid_enum_construction(source: u128) -> ! {
|
||||
if cfg!(feature = "panic_immediate_abort") {
|
||||
if cfg!(panic = "immediate_abort") {
|
||||
super::intrinsics::abort()
|
||||
}
|
||||
|
||||
@@ -328,8 +331,8 @@ fn panic_invalid_enum_construction(source: u128) -> ! {
|
||||
///
|
||||
/// This function is called directly by the codegen backend, and must not have
|
||||
/// any extra arguments (including those synthesized by track_caller).
|
||||
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold, optimize(size))]
|
||||
#[cfg_attr(feature = "panic_immediate_abort", inline)]
|
||||
#[cfg_attr(not(panic = "immediate_abort"), inline(never), cold, optimize(size))]
|
||||
#[cfg_attr(panic = "immediate_abort", inline)]
|
||||
#[lang = "panic_cannot_unwind"] // needed by codegen for panic in nounwind function
|
||||
#[rustc_nounwind]
|
||||
fn panic_cannot_unwind() -> ! {
|
||||
@@ -344,8 +347,8 @@ fn panic_cannot_unwind() -> ! {
|
||||
///
|
||||
/// This function is called directly by the codegen backend, and must not have
|
||||
/// any extra arguments (including those synthesized by track_caller).
|
||||
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold, optimize(size))]
|
||||
#[cfg_attr(feature = "panic_immediate_abort", inline)]
|
||||
#[cfg_attr(not(panic = "immediate_abort"), inline(never), cold, optimize(size))]
|
||||
#[cfg_attr(panic = "immediate_abort", inline)]
|
||||
#[lang = "panic_in_cleanup"] // needed by codegen for panic in nounwind function
|
||||
#[rustc_nounwind]
|
||||
fn panic_in_cleanup() -> ! {
|
||||
@@ -377,8 +380,8 @@ pub enum AssertKind {
|
||||
}
|
||||
|
||||
/// Internal function for `assert_eq!` and `assert_ne!` macros
|
||||
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold, optimize(size))]
|
||||
#[cfg_attr(feature = "panic_immediate_abort", inline)]
|
||||
#[cfg_attr(not(panic = "immediate_abort"), inline(never), cold, optimize(size))]
|
||||
#[cfg_attr(panic = "immediate_abort", inline)]
|
||||
#[track_caller]
|
||||
#[doc(hidden)]
|
||||
pub fn assert_failed<T, U>(
|
||||
@@ -395,8 +398,8 @@ where
|
||||
}
|
||||
|
||||
/// Internal function for `assert_match!`
|
||||
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold, optimize(size))]
|
||||
#[cfg_attr(feature = "panic_immediate_abort", inline)]
|
||||
#[cfg_attr(not(panic = "immediate_abort"), inline(never), cold, optimize(size))]
|
||||
#[cfg_attr(panic = "immediate_abort", inline)]
|
||||
#[track_caller]
|
||||
#[doc(hidden)]
|
||||
pub fn assert_matches_failed<T: fmt::Debug + ?Sized>(
|
||||
@@ -415,8 +418,8 @@ pub fn assert_matches_failed<T: fmt::Debug + ?Sized>(
|
||||
}
|
||||
|
||||
/// Non-generic version of the above functions, to avoid code bloat.
|
||||
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold, optimize(size))]
|
||||
#[cfg_attr(feature = "panic_immediate_abort", inline)]
|
||||
#[cfg_attr(not(panic = "immediate_abort"), inline(never), cold, optimize(size))]
|
||||
#[cfg_attr(panic = "immediate_abort", inline)]
|
||||
#[track_caller]
|
||||
fn assert_failed_inner(
|
||||
kind: AssertKind,
|
||||
|
||||
@@ -1847,7 +1847,7 @@ impl<T, E> Result<Result<T, E>, E> {
|
||||
}
|
||||
|
||||
// This is a separate function to reduce the code size of the methods
|
||||
#[cfg(not(feature = "panic_immediate_abort"))]
|
||||
#[cfg(not(panic = "immediate_abort"))]
|
||||
#[inline(never)]
|
||||
#[cold]
|
||||
#[track_caller]
|
||||
@@ -1859,7 +1859,7 @@ fn unwrap_failed(msg: &str, error: &dyn fmt::Debug) -> ! {
|
||||
// that gets immediately thrown away, since vtables don't get cleaned up
|
||||
// by dead code elimination if a trait object is constructed even if it goes
|
||||
// unused
|
||||
#[cfg(feature = "panic_immediate_abort")]
|
||||
#[cfg(panic = "immediate_abort")]
|
||||
#[inline]
|
||||
#[cold]
|
||||
#[track_caller]
|
||||
|
||||
@@ -31,8 +31,8 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
|
||||
#[cfg_attr(feature = "panic_immediate_abort", inline)]
|
||||
#[cfg_attr(not(panic = "immediate_abort"), inline(never), cold)]
|
||||
#[cfg_attr(panic = "immediate_abort", inline)]
|
||||
#[track_caller]
|
||||
const fn slice_index_fail(start: usize, end: usize, len: usize) -> ! {
|
||||
if start > len {
|
||||
|
||||
@@ -3858,8 +3858,8 @@ impl<T> [T] {
|
||||
{
|
||||
// The panic code path was put into a cold function to not bloat the
|
||||
// call site.
|
||||
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
|
||||
#[cfg_attr(feature = "panic_immediate_abort", inline)]
|
||||
#[cfg_attr(not(panic = "immediate_abort"), inline(never), cold)]
|
||||
#[cfg_attr(panic = "immediate_abort", inline)]
|
||||
#[track_caller]
|
||||
const fn len_mismatch_fail(dst_len: usize, src_len: usize) -> ! {
|
||||
const_panic!(
|
||||
|
||||
@@ -840,8 +840,8 @@ unsafe fn bidirectional_merge<T: FreezeMarker, F: FnMut(&T, &T) -> bool>(
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
|
||||
#[cfg_attr(feature = "panic_immediate_abort", inline)]
|
||||
#[cfg_attr(not(panic = "immediate_abort"), inline(never), cold)]
|
||||
#[cfg_attr(panic = "immediate_abort", inline)]
|
||||
fn panic_on_ord_violation() -> ! {
|
||||
// This is indicative of a logic bug in the user-provided comparison function or Ord
|
||||
// implementation. They are expected to implement a total order as explained in the Ord
|
||||
|
||||
@@ -64,12 +64,12 @@ pub use validations::{next_code_point, utf8_char_width};
|
||||
#[cold]
|
||||
#[track_caller]
|
||||
#[rustc_allow_const_fn_unstable(const_eval_select)]
|
||||
#[cfg(not(feature = "panic_immediate_abort"))]
|
||||
#[cfg(not(panic = "immediate_abort"))]
|
||||
const fn slice_error_fail(s: &str, begin: usize, end: usize) -> ! {
|
||||
crate::intrinsics::const_eval_select((s, begin, end), slice_error_fail_ct, slice_error_fail_rt)
|
||||
}
|
||||
|
||||
#[cfg(feature = "panic_immediate_abort")]
|
||||
#[cfg(panic = "immediate_abort")]
|
||||
const fn slice_error_fail(s: &str, begin: usize, end: usize) -> ! {
|
||||
slice_error_fail_ct(s, begin, end)
|
||||
}
|
||||
|
||||
@@ -106,11 +106,6 @@ compiler-builtins-no-f16-f128 = ["alloc/compiler-builtins-no-f16-f128"]
|
||||
llvm-libunwind = ["unwind/llvm-libunwind"]
|
||||
system-llvm-libunwind = ["unwind/system-llvm-libunwind"]
|
||||
|
||||
# Make panics and failed asserts immediately abort without formatting any message
|
||||
panic_immediate_abort = [
|
||||
"core/panic_immediate_abort",
|
||||
"alloc/panic_immediate_abort",
|
||||
]
|
||||
# Choose algorithms that are optimized for binary size instead of runtime performance
|
||||
optimize_for_size = ["core/optimize_for_size", "alloc/optimize_for_size"]
|
||||
|
||||
|
||||
@@ -331,7 +331,7 @@ fn default_hook(info: &PanicHookInfo<'_>) {
|
||||
|
||||
#[cfg(not(test))]
|
||||
#[doc(hidden)]
|
||||
#[cfg(feature = "panic_immediate_abort")]
|
||||
#[cfg(panic = "immediate_abort")]
|
||||
#[unstable(feature = "update_panic_count", issue = "none")]
|
||||
pub mod panic_count {
|
||||
/// A reason for forcing an immediate abort on panic.
|
||||
@@ -371,7 +371,7 @@ pub mod panic_count {
|
||||
|
||||
#[cfg(not(test))]
|
||||
#[doc(hidden)]
|
||||
#[cfg(not(feature = "panic_immediate_abort"))]
|
||||
#[cfg(not(panic = "immediate_abort"))]
|
||||
#[unstable(feature = "update_panic_count", issue = "none")]
|
||||
pub mod panic_count {
|
||||
use crate::cell::Cell;
|
||||
@@ -499,13 +499,13 @@ pub mod panic_count {
|
||||
pub use realstd::rt::panic_count;
|
||||
|
||||
/// Invoke a closure, capturing the cause of an unwinding panic if one occurs.
|
||||
#[cfg(feature = "panic_immediate_abort")]
|
||||
#[cfg(panic = "immediate_abort")]
|
||||
pub unsafe fn catch_unwind<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<dyn Any + Send>> {
|
||||
Ok(f())
|
||||
}
|
||||
|
||||
/// Invoke a closure, capturing the cause of an unwinding panic if one occurs.
|
||||
#[cfg(not(feature = "panic_immediate_abort"))]
|
||||
#[cfg(not(panic = "immediate_abort"))]
|
||||
pub unsafe fn catch_unwind<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<dyn Any + Send>> {
|
||||
union Data<F, R> {
|
||||
f: ManuallyDrop<F>,
|
||||
@@ -720,14 +720,14 @@ pub fn panic_handler(info: &core::panic::PanicInfo<'_>) -> ! {
|
||||
#[unstable(feature = "libstd_sys_internals", reason = "used by the panic! macro", issue = "none")]
|
||||
#[cfg_attr(not(any(test, doctest)), lang = "begin_panic")]
|
||||
// lang item for CTFE panic support
|
||||
// never inline unless panic_immediate_abort to avoid code
|
||||
// never inline unless panic=immediate-abort to avoid code
|
||||
// bloat at the call sites as much as possible
|
||||
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold, optimize(size))]
|
||||
#[cfg_attr(feature = "panic_immediate_abort", inline)]
|
||||
#[cfg_attr(not(panic = "immediate_abort"), inline(never), cold, optimize(size))]
|
||||
#[cfg_attr(panic = "immediate_abort", inline)]
|
||||
#[track_caller]
|
||||
#[rustc_do_not_const_check] // hooked by const-eval
|
||||
pub const fn begin_panic<M: Any + Send>(msg: M) -> ! {
|
||||
if cfg!(feature = "panic_immediate_abort") {
|
||||
if cfg!(panic = "immediate_abort") {
|
||||
intrinsics::abort()
|
||||
}
|
||||
|
||||
@@ -861,7 +861,7 @@ fn panic_with_hook(
|
||||
|
||||
/// This is the entry point for `resume_unwind`.
|
||||
/// It just forwards the payload to the panic runtime.
|
||||
#[cfg_attr(feature = "panic_immediate_abort", inline)]
|
||||
#[cfg_attr(panic = "immediate_abort", inline)]
|
||||
pub fn resume_unwind(payload: Box<dyn Any + Send>) -> ! {
|
||||
panic_count::increase(false);
|
||||
|
||||
@@ -890,16 +890,14 @@ pub fn resume_unwind(payload: Box<dyn Any + Send>) -> ! {
|
||||
/// on which to slap yer breakpoints.
|
||||
#[inline(never)]
|
||||
#[cfg_attr(not(test), rustc_std_internal_symbol)]
|
||||
#[cfg(not(feature = "panic_immediate_abort"))]
|
||||
#[cfg(not(panic = "immediate_abort"))]
|
||||
fn rust_panic(msg: &mut dyn PanicPayload) -> ! {
|
||||
let code = unsafe { __rust_start_panic(msg) };
|
||||
rtabort!("failed to initiate panic, error {code}")
|
||||
}
|
||||
|
||||
#[cfg_attr(not(test), rustc_std_internal_symbol)]
|
||||
#[cfg(feature = "panic_immediate_abort")]
|
||||
#[cfg(panic = "immediate_abort")]
|
||||
fn rust_panic(_: &mut dyn PanicPayload) -> ! {
|
||||
unsafe {
|
||||
crate::intrinsics::abort();
|
||||
}
|
||||
crate::intrinsics::abort();
|
||||
}
|
||||
|
||||
@@ -39,11 +39,11 @@ fn __rust_abort() {
|
||||
// - nothing (so this macro is a no-op)
|
||||
macro_rules! rtprintpanic {
|
||||
($($t:tt)*) => {
|
||||
#[cfg(not(feature = "panic_immediate_abort"))]
|
||||
#[cfg(not(panic = "immediate_abort"))]
|
||||
if let Some(mut out) = crate::sys::stdio::panic_output() {
|
||||
let _ = crate::io::Write::write_fmt(&mut out, format_args!($($t)*));
|
||||
}
|
||||
#[cfg(feature = "panic_immediate_abort")]
|
||||
#[cfg(panic = "immediate_abort")]
|
||||
{
|
||||
let _ = format_args!($($t)*);
|
||||
}
|
||||
|
||||
@@ -230,7 +230,7 @@ impl fmt::Display for AccessError {
|
||||
impl Error for AccessError {}
|
||||
|
||||
// This ensures the panicking code is outlined from `with` for `LocalKey`.
|
||||
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
|
||||
#[cfg_attr(not(panic = "immediate_abort"), inline(never))]
|
||||
#[track_caller]
|
||||
#[cold]
|
||||
fn panic_access_error(err: AccessError) -> ! {
|
||||
|
||||
@@ -31,7 +31,6 @@ llvm-libunwind = ["std/llvm-libunwind"]
|
||||
system-llvm-libunwind = ["std/system-llvm-libunwind"]
|
||||
optimize_for_size = ["std/optimize_for_size"]
|
||||
panic-unwind = ["std/panic-unwind"]
|
||||
panic_immediate_abort = ["std/panic_immediate_abort"]
|
||||
profiler = ["dep:profiler_builtins"]
|
||||
std_detect_file_io = ["std/std_detect_file_io"]
|
||||
std_detect_dlsym_getauxval = ["std/std_detect_dlsym_getauxval"]
|
||||
|
||||
@@ -471,11 +471,13 @@ If not specified, overflow checks are enabled if
|
||||
This option lets you control what happens when the code panics.
|
||||
|
||||
* `abort`: terminate the process upon panic
|
||||
* `immediate-abort`: terminate the process upon panic, and do not call any panic hooks
|
||||
* `unwind`: unwind the stack upon panic
|
||||
|
||||
If not specified, the default depends on the target.
|
||||
|
||||
If any crate in the crate graph uses `abort`, the final binary (`bin`, `dylib`, `cdylib`, `staticlib`) must also use `abort`.
|
||||
If any crate in the crate graph uses `immediate-abort`, every crate in the graph must use `immediate-abort`.
|
||||
If `std` is used as a `dylib` with `unwind`, the final binary must also use `unwind`.
|
||||
|
||||
## passes
|
||||
|
||||
@@ -201,6 +201,8 @@ pub struct TestProps {
|
||||
/// Build and use `minicore` as `core` stub for `no_core` tests in cross-compilation scenarios
|
||||
/// that don't otherwise want/need `-Z build-std`.
|
||||
pub add_core_stubs: bool,
|
||||
/// Add these flags to the build of `minicore`.
|
||||
pub core_stubs_compile_flags: Vec<String>,
|
||||
/// Whether line annotatins are required for the given error kind.
|
||||
pub dont_require_annotations: HashSet<ErrorKind>,
|
||||
/// Whether pretty printers should be disabled in gdb.
|
||||
@@ -253,6 +255,7 @@ mod directives {
|
||||
pub const FILECHECK_FLAGS: &'static str = "filecheck-flags";
|
||||
pub const NO_AUTO_CHECK_CFG: &'static str = "no-auto-check-cfg";
|
||||
pub const ADD_CORE_STUBS: &'static str = "add-core-stubs";
|
||||
pub const CORE_STUBS_COMPILE_FLAGS: &'static str = "core-stubs-compile-flags";
|
||||
// This isn't a real directive, just one that is probably mistyped often
|
||||
pub const INCORRECT_COMPILER_FLAGS: &'static str = "compiler-flags";
|
||||
pub const DISABLE_GDB_PRETTY_PRINTERS: &'static str = "disable-gdb-pretty-printers";
|
||||
@@ -311,6 +314,7 @@ impl TestProps {
|
||||
no_auto_check_cfg: false,
|
||||
has_enzyme: false,
|
||||
add_core_stubs: false,
|
||||
core_stubs_compile_flags: vec![],
|
||||
dont_require_annotations: Default::default(),
|
||||
disable_gdb_pretty_printers: false,
|
||||
compare_output_by_lines: false,
|
||||
@@ -653,6 +657,21 @@ impl TestProps {
|
||||
|
||||
self.update_add_core_stubs(ln, config);
|
||||
|
||||
if let Some(flags) = config.parse_name_value_directive(
|
||||
ln,
|
||||
directives::CORE_STUBS_COMPILE_FLAGS,
|
||||
testfile,
|
||||
line_number,
|
||||
) {
|
||||
let flags = split_flags(&flags);
|
||||
for flag in &flags {
|
||||
if flag == "--edition" || flag.starts_with("--edition=") {
|
||||
panic!("you must use `//@ edition` to configure the edition");
|
||||
}
|
||||
}
|
||||
self.core_stubs_compile_flags.extend(flags);
|
||||
}
|
||||
|
||||
if let Some(err_kind) = config.parse_name_value_directive(
|
||||
ln,
|
||||
DONT_REQUIRE_ANNOTATIONS,
|
||||
|
||||
@@ -19,6 +19,7 @@ pub(crate) const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
|
||||
"check-test-line-numbers-match",
|
||||
"compare-output-by-lines",
|
||||
"compile-flags",
|
||||
"core-stubs-compile-flags",
|
||||
"disable-gdb-pretty-printers",
|
||||
"doc-flags",
|
||||
"dont-check-compiler-stderr",
|
||||
|
||||
@@ -1322,6 +1322,7 @@ impl<'test> TestCx<'test> {
|
||||
|
||||
rustc.args(&["--crate-type", "rlib"]);
|
||||
rustc.arg("-Cpanic=abort");
|
||||
rustc.args(self.props.core_stubs_compile_flags.clone());
|
||||
|
||||
let res = self.compose_and_run(rustc, self.config.compile_lib_path.as_path(), None, None);
|
||||
if !res.status.success() {
|
||||
@@ -1432,6 +1433,12 @@ impl<'test> TestCx<'test> {
|
||||
|
||||
aux_rustc.arg("-L").arg(&aux_dir);
|
||||
|
||||
if aux_props.add_core_stubs {
|
||||
let minicore_path = self.build_minicore();
|
||||
aux_rustc.arg("--extern");
|
||||
aux_rustc.arg(&format!("minicore={}", minicore_path));
|
||||
}
|
||||
|
||||
let auxres = aux_cx.compose_and_run(
|
||||
aux_rustc,
|
||||
aux_cx.config.compile_lib_path.as_path(),
|
||||
@@ -1858,14 +1865,13 @@ impl<'test> TestCx<'test> {
|
||||
}
|
||||
}
|
||||
|
||||
rustc.args(&self.props.compile_flags);
|
||||
|
||||
// FIXME(jieyouxu): we should report a fatal error or warning if user wrote `-Cpanic=` with
|
||||
// something that's not `abort` and `-Cforce-unwind-tables` with a value that is not `yes`,
|
||||
// however, by moving this last we should override previous `-Cpanic`s and
|
||||
// `-Cforce-unwind-tables`s. Note that checking here is very fragile, because we'd have to
|
||||
// account for all possible compile flag splittings (they have some... intricacies and are
|
||||
// not yet normalized).
|
||||
// something that's not `abort` and `-Cforce-unwind-tables` with a value that is not `yes`.
|
||||
//
|
||||
// We could apply these last and override any provided flags. That would ensure that the
|
||||
// build works, but some tests want to exercise that mixing panic modes in specific ways is
|
||||
// rejected. So we enable aborting panics and unwind tables before adding flags, just to
|
||||
// change the default.
|
||||
//
|
||||
// `minicore` requires `#![no_std]` and `#![no_core]`, which means no unwinding panics.
|
||||
if self.props.add_core_stubs {
|
||||
@@ -1873,6 +1879,8 @@ impl<'test> TestCx<'test> {
|
||||
rustc.arg("-Cforce-unwind-tables=yes");
|
||||
}
|
||||
|
||||
rustc.args(&self.props.compile_flags);
|
||||
|
||||
rustc
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
cargo-features = ["profile-rustflags"]
|
||||
|
||||
[package]
|
||||
name = "panic_scenarios"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[lib]
|
||||
path = "lib.rs"
|
||||
|
||||
[profile.release]
|
||||
rustflags = ["-Zmerge-functions=disabled", "-Zcodegen-source-order", "--emit=llvm-ir"]
|
||||
65
tests/run-make-cargo/panic-immediate-abort-codegen/lib.rs
Normal file
65
tests/run-make-cargo/panic-immediate-abort-codegen/lib.rs
Normal file
@@ -0,0 +1,65 @@
|
||||
#![no_std]
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub fn panic_noarg() {
|
||||
// CHECK-LABEL: @panic_noarg(
|
||||
// CHECK-NEXT: start:
|
||||
// CHECK-NEXT: tail call void @llvm.trap()
|
||||
panic!();
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub fn panic_str() {
|
||||
// CHECK-LABEL: @panic_str(
|
||||
// CHECK-NEXT: start:
|
||||
// CHECK-NEXT: tail call void @llvm.trap()
|
||||
panic!("ouch");
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub fn bounds_check(x: &[u8], idx: usize) -> &u8 {
|
||||
// CHECK-LABEL: @bounds_check(
|
||||
// CHECK-NEXT: start:
|
||||
// CHECK-NEXT: icmp ult
|
||||
// CHECK-NEXT: br i1
|
||||
// CHECK: bb1:
|
||||
// CHECK-NEXT: getelementptr inbounds nuw i8
|
||||
// CHECK-NEXT: ret ptr
|
||||
// CHECK: panic:
|
||||
// CHECK-NEXT: tail call void @llvm.trap()
|
||||
&x[idx]
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub fn str_bounds_check(x: &str, idx: usize) -> &str {
|
||||
// CHECK-LABEL: @str_bounds_check(
|
||||
// CHECK-NOT: call
|
||||
// CHECK: tail call void @llvm.trap()
|
||||
// CHECK-NOT: call
|
||||
&x[idx..]
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub fn unsigned_integer_div(x: u16, y: u16) -> u16 {
|
||||
// CHECK-LABEL: @unsigned_integer_div(
|
||||
// CHECK-NEXT: start:
|
||||
// CHECK-NEXT: icmp eq i16
|
||||
// CHECK-NEXT: br i1
|
||||
// CHECK: bb1:
|
||||
// CHECK-NEXT: udiv i16
|
||||
// CHECK-NEXT: ret i16
|
||||
// CHECK: panic:
|
||||
// CHECK-NEXT: tail call void @llvm.trap()
|
||||
x / y
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub fn refcell_already_borrowed() {
|
||||
// CHECK-LABEL: @refcell_already_borrowed(
|
||||
// CHECK-NOT: call
|
||||
// CHECK: tail call void @llvm.trap()
|
||||
// CHECK-NOT: call
|
||||
let r = core::cell::RefCell::new(0u8);
|
||||
let _guard = r.borrow_mut();
|
||||
r.borrow_mut();
|
||||
}
|
||||
41
tests/run-make-cargo/panic-immediate-abort-codegen/rmake.rs
Normal file
41
tests/run-make-cargo/panic-immediate-abort-codegen/rmake.rs
Normal file
@@ -0,0 +1,41 @@
|
||||
#![deny(warnings)]
|
||||
|
||||
use run_make_support::{cargo, llvm_filecheck, path, rfs, target};
|
||||
|
||||
fn main() {
|
||||
let target_dir = path("target");
|
||||
|
||||
cargo()
|
||||
.args(&[
|
||||
"build",
|
||||
"--release",
|
||||
"--lib",
|
||||
"--manifest-path",
|
||||
"Cargo.toml",
|
||||
"-Zbuild-std=core",
|
||||
"--target",
|
||||
&target(),
|
||||
])
|
||||
.env("RUSTFLAGS", "-Zunstable-options -Cpanic=immediate-abort")
|
||||
.env("CARGO_TARGET_DIR", &target_dir)
|
||||
.env("RUSTC_BOOTSTRAP", "1")
|
||||
// Visual Studio 2022 requires that the LIB env var be set so it can
|
||||
// find the Windows SDK.
|
||||
.env("LIB", std::env::var("LIB").unwrap_or_default())
|
||||
.run();
|
||||
|
||||
let out_dir = target_dir.join(target()).join("release").join("deps");
|
||||
let ir_file = rfs::read_dir(out_dir)
|
||||
.find_map(|e| {
|
||||
let path = e.unwrap().path();
|
||||
let file_name = path.file_name().unwrap().to_str().unwrap();
|
||||
if file_name.starts_with("panic_scenarios") && file_name.ends_with(".ll") {
|
||||
Some(path)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
llvm_filecheck().patterns("lib.rs").input_file(ir_file).run();
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
[package]
|
||||
name = "hello"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
@@ -0,0 +1 @@
|
||||
fn main() {}
|
||||
28
tests/run-make-cargo/panic-immediate-abort-works/rmake.rs
Normal file
28
tests/run-make-cargo/panic-immediate-abort-works/rmake.rs
Normal file
@@ -0,0 +1,28 @@
|
||||
//@ needs-target-std
|
||||
|
||||
#![deny(warnings)]
|
||||
|
||||
use run_make_support::{cargo, path, target};
|
||||
|
||||
fn main() {
|
||||
let target_dir = path("target");
|
||||
|
||||
cargo()
|
||||
.current_dir("hello")
|
||||
.args(&[
|
||||
"build",
|
||||
"--release",
|
||||
"--manifest-path",
|
||||
"Cargo.toml",
|
||||
"-Zbuild-std",
|
||||
"--target",
|
||||
&target(),
|
||||
])
|
||||
.env("RUSTFLAGS", "-Zunstable-options -Cpanic=immediate-abort")
|
||||
.env("CARGO_TARGET_DIR", &target_dir)
|
||||
.env("RUSTC_BOOTSTRAP", "1")
|
||||
// Visual Studio 2022 requires that the LIB env var be set so it can
|
||||
// find the Windows SDK.
|
||||
.env("LIB", std::env::var("LIB").unwrap_or_default())
|
||||
.run();
|
||||
}
|
||||
@@ -18,7 +18,7 @@ warning: unexpected `cfg` condition value: `UNEXPECTED_VALUE`
|
||||
LL | cfg_macro::my_lib_macro_value!();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: expected values for `panic` are: `abort` and `unwind`
|
||||
= note: expected values for `panic` are: `abort`, `immediate_abort`, and `unwind`
|
||||
= note: using a cfg inside a macro will use the cfgs from the destination crate and not the ones from the defining crate
|
||||
= help: try referring to `cfg_macro::my_lib_macro_value` crate for guidance on how handle this unexpected cfg
|
||||
= help: the macro `cfg_macro::my_lib_macro_value` may come from an old version of the `cfg_macro` crate, try updating your dependency with `cargo update -p cfg_macro`
|
||||
|
||||
@@ -18,7 +18,7 @@ warning: unexpected `cfg` condition value: `UNEXPECTED_VALUE`
|
||||
LL | cfg_macro::my_lib_macro_value!();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: expected values for `panic` are: `abort` and `unwind`
|
||||
= note: expected values for `panic` are: `abort`, `immediate_abort`, and `unwind`
|
||||
= note: using a cfg inside a macro will use the cfgs from the destination crate and not the ones from the defining crate
|
||||
= help: try referring to `cfg_macro::my_lib_macro_value` crate for guidance on how handle this unexpected cfg
|
||||
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
|
||||
|
||||
@@ -80,7 +80,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
|
||||
LL | panic = "_UNEXPECTED_VALUE",
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: expected values for `panic` are: `abort` and `unwind`
|
||||
= note: expected values for `panic` are: `abort`, `immediate_abort`, and `unwind`
|
||||
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
|
||||
|
||||
warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
//@ compile-flags:-C panic=abort
|
||||
//@ no-prefer-dynamic
|
||||
|
||||
#![feature(no_core)]
|
||||
#![crate_type = "rlib"]
|
||||
#![no_std]
|
||||
#![no_core]
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
//@ compile-flags:-C panic=immediate-abort -Zunstable-options
|
||||
//@ no-prefer-dynamic
|
||||
|
||||
#![feature(no_core)]
|
||||
#![crate_type = "rlib"]
|
||||
#![no_std]
|
||||
#![no_core]
|
||||
@@ -0,0 +1,18 @@
|
||||
//@ compile-flags:-C panic=unwind
|
||||
//@ no-prefer-dynamic
|
||||
//@ add-core-stubs
|
||||
|
||||
#![crate_type = "rlib"]
|
||||
#![feature(no_core)]
|
||||
#![no_std]
|
||||
#![no_core]
|
||||
|
||||
extern crate minicore;
|
||||
|
||||
extern "C-unwind" fn foo() {}
|
||||
|
||||
#[inline]
|
||||
fn bar() {
|
||||
let ptr: extern "C-unwind" fn() = foo;
|
||||
ptr();
|
||||
}
|
||||
@@ -2,4 +2,4 @@
|
||||
|
||||
fn main() {}
|
||||
|
||||
//~? ERROR incorrect value `foo` for codegen option `panic` - either `unwind` or `abort` was expected
|
||||
//~? ERROR incorrect value `foo` for codegen option `panic` - either `unwind`, `abort`, or `immediate-abort` was expected
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
error: incorrect value `foo` for codegen option `panic` - either `unwind` or `abort` was expected
|
||||
error: incorrect value `foo` for codegen option `panic` - either `unwind`, `abort`, or `immediate-abort` was expected
|
||||
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
|
||||
fn main() {}
|
||||
|
||||
//~? ERROR codegen option `panic` requires either `unwind` or `abort`
|
||||
//~? ERROR codegen option `panic` requires either `unwind`, `abort`, or `immediate-abort`
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
error: codegen option `panic` requires either `unwind` or `abort` (C panic=<value>)
|
||||
error: codegen option `panic` requires either `unwind`, `abort`, or `immediate-abort` (C panic=<value>)
|
||||
|
||||
|
||||
15
tests/ui/panic-runtime/immediate-abort-default-sysroot.rs
Normal file
15
tests/ui/panic-runtime/immediate-abort-default-sysroot.rs
Normal file
@@ -0,0 +1,15 @@
|
||||
//@ build-fail
|
||||
//@ aux-build:needs-unwind.rs
|
||||
//@ compile-flags:-C panic=immediate-abort -Zunstable-options
|
||||
//@ no-prefer-dynamic
|
||||
|
||||
extern crate needs_unwind;
|
||||
|
||||
// immediate-abort does not require any panic runtime, so trying to build a binary crate with
|
||||
// panic=immediate-abort and the precompiled sysroot will fail to link, because no panic runtime
|
||||
// provides the panic entrypoints used by sysroot crates.
|
||||
// This test ensures that we get a clean compile error instead of a linker error.
|
||||
|
||||
fn main() {}
|
||||
|
||||
//~? ERROR the crate `core` was compiled with a panic strategy which is incompatible with `immediate-abort`
|
||||
@@ -0,0 +1,4 @@
|
||||
error: the crate `core` was compiled with a panic strategy which is incompatible with `immediate-abort`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
21
tests/ui/panic-runtime/need-abort-got-immediate-abort.rs
Normal file
21
tests/ui/panic-runtime/need-abort-got-immediate-abort.rs
Normal file
@@ -0,0 +1,21 @@
|
||||
//@ build-fail
|
||||
//@ aux-build:needs-abort.rs
|
||||
//@ compile-flags:-Cpanic=immediate-abort -Zunstable-options
|
||||
//@ no-prefer-dynamic
|
||||
//@ add-core-stubs
|
||||
//@ core-stubs-compile-flags: -Cpanic=immediate-abort -Zunstable-options
|
||||
|
||||
#![feature(no_core)]
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
#![no_core]
|
||||
|
||||
extern crate minicore;
|
||||
extern crate needs_abort;
|
||||
|
||||
#[no_mangle]
|
||||
extern "C" fn main(_argc: i32, _argv: *const *const u8) -> i32 {
|
||||
0
|
||||
}
|
||||
|
||||
//~? ERROR the crate `needs_abort` was compiled with a panic strategy which is incompatible with `immediate-abort`
|
||||
@@ -0,0 +1,4 @@
|
||||
error: the crate `needs_abort` was compiled with a panic strategy which is incompatible with `immediate-abort`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
20
tests/ui/panic-runtime/need-immediate-abort-got-abort.rs
Normal file
20
tests/ui/panic-runtime/need-immediate-abort-got-abort.rs
Normal file
@@ -0,0 +1,20 @@
|
||||
//@ build-fail
|
||||
//@ aux-build:needs-immediate-abort.rs
|
||||
//@ compile-flags:-C panic=abort
|
||||
//@ no-prefer-dynamic
|
||||
//@ add-core-stubs
|
||||
//@ core-stubs-compile-flags: -Zunstable-options -Cpanic=immediate-abort
|
||||
|
||||
#![feature(no_core)]
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
#![no_core]
|
||||
|
||||
extern crate minicore;
|
||||
extern crate needs_immediate_abort;
|
||||
|
||||
extern "C" fn main(argc: i32, argv: *const *const u8) -> i32 {
|
||||
0
|
||||
}
|
||||
|
||||
//~? ERROR the crate `need_immediate_abort_got_abort` was compiled with a panic strategy which is incompatible with `immediate-abort`
|
||||
@@ -0,0 +1,4 @@
|
||||
error: the crate `need_immediate_abort_got_abort` was compiled with a panic strategy which is incompatible with `immediate-abort`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
20
tests/ui/panic-runtime/need-immediate-abort-got-unwind.rs
Normal file
20
tests/ui/panic-runtime/need-immediate-abort-got-unwind.rs
Normal file
@@ -0,0 +1,20 @@
|
||||
//@ build-fail
|
||||
//@ needs-unwind
|
||||
//@ aux-build:needs-immediate-abort.rs
|
||||
//@ no-prefer-dynamic
|
||||
//@ add-core-stubs
|
||||
//@ core-stubs-compile-flags: -Zunstable-options -Cpanic=immediate-abort
|
||||
|
||||
#![feature(no_core)]
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
#![no_core]
|
||||
|
||||
extern crate minicore;
|
||||
extern crate needs_immediate_abort;
|
||||
|
||||
extern "C" fn main(argc: i32, argv: *const *const u8) -> i32 {
|
||||
0
|
||||
}
|
||||
|
||||
//~? ERROR the crate `need_immediate_abort_got_unwind` was compiled with a panic strategy which is incompatible with `immediate-abort`
|
||||
@@ -0,0 +1,4 @@
|
||||
error: the crate `need_immediate_abort_got_unwind` was compiled with a panic strategy which is incompatible with `immediate-abort`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
21
tests/ui/panic-runtime/need-unwind-got-immediate-abort.rs
Normal file
21
tests/ui/panic-runtime/need-unwind-got-immediate-abort.rs
Normal file
@@ -0,0 +1,21 @@
|
||||
//@ build-fail
|
||||
//@ aux-build:needs-unwind-immediate-abort.rs
|
||||
//@ compile-flags:-C panic=immediate-abort -Zunstable-options
|
||||
//@ no-prefer-dynamic
|
||||
//@ add-core-stubs
|
||||
//@ core-stubs-compile-flags: -Zunstable-options -Cpanic=immediate-abort
|
||||
|
||||
#![feature(no_core)]
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
#![no_core]
|
||||
|
||||
extern crate minicore;
|
||||
extern crate needs_unwind_immediate_abort;
|
||||
|
||||
#[no_mangle]
|
||||
extern "C" fn main(_argc: i32, _argv: *const *const u8) -> i32 {
|
||||
0
|
||||
}
|
||||
|
||||
//~? ERROR the crate `needs_unwind_immediate_abort` was compiled with a panic strategy which is incompatible with `immediate-abort`
|
||||
@@ -0,0 +1,4 @@
|
||||
error: the crate `needs_unwind_immediate_abort` was compiled with a panic strategy which is incompatible with `immediate-abort`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
//@ force-host
|
||||
//@ check-pass
|
||||
|
||||
//~? WARN building proc macro crate with `panic=abort` may crash the compiler should the proc-macro panic
|
||||
//~? WARN building proc macro crate with `panic=abort` or `panic=immediate-abort` may crash the compiler should the proc-macro panic
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
warning: building proc macro crate with `panic=abort` may crash the compiler should the proc-macro panic
|
||||
warning: building proc macro crate with `panic=abort` or `panic=immediate-abort` may crash the compiler should the proc-macro panic
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
||||
|
||||
Reference in New Issue
Block a user