Auto merge of #76570 - cratelyn:implement-rfc-2945-c-unwind-abi, r=Amanieu
Implement RFC 2945: "C-unwind" ABI ## Implement RFC 2945: "C-unwind" ABI This branch implements [RFC 2945]. The tracking issue for this RFC is #74990. The feature gate for the issue is `#![feature(c_unwind)]`. This RFC was created as part of the ffi-unwind project group tracked at rust-lang/lang-team#19. ### Changes Further details will be provided in commit messages, but a high-level overview of the changes follows: * A boolean `unwind` payload is added to the `C`, `System`, `Stdcall`, and `Thiscall` variants, marking whether unwinding across FFI boundaries is acceptable. The cases where each of these variants' `unwind` member is true correspond with the `C-unwind`, `system-unwind`, `stdcall-unwind`, and `thiscall-unwind` ABI strings introduced in RFC 2945 [3]. * This commit adds a `c_unwind` feature gate for the new ABI strings. Tests for this feature gate are included in `src/test/ui/c-unwind/`, which ensure that this feature gate works correctly for each of the new ABIs. A new language features entry in the unstable book is added as well. * We adjust the `rustc_middle::ty::layout::fn_can_unwind` function, used to compute whether or not a `FnAbi` object represents a function that should be able to unwind when `panic=unwind` is in use. * Changes are also made to `rustc_mir_build::build::should_abort_on_panic` so that the function ABI is used to determind whether it should abort, assuming that the `panic=unwind` strategy is being used, and no explicit unwind attribute was provided. [RFC 2945]: https://github.com/rust-lang/rfcs/blob/master/text/2945-c-unwind-abi.md
This commit is contained in:
commit
17a07d71bf
43 changed files with 661 additions and 70 deletions
15
src/doc/unstable-book/src/language-features/c-unwind.md
Normal file
15
src/doc/unstable-book/src/language-features/c-unwind.md
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
# `c_unwind`
|
||||
|
||||
The tracking issue for this feature is: [#74990]
|
||||
|
||||
[#74990]: https://github.com/rust-lang/rust/issues/74990
|
||||
|
||||
------------------------
|
||||
|
||||
Introduces four new ABI strings: "C-unwind", "stdcall-unwind",
|
||||
"thiscall-unwind", and "system-unwind". These enable unwinding from other
|
||||
languages (such as C++) into Rust frames and from Rust into other languages.
|
||||
|
||||
See [RFC 2945] for more information.
|
||||
|
||||
[RFC 2945]: https://github.com/rust-lang/rfcs/blob/master/text/2945-c-unwind-abi.md
|
||||
18
src/test/codegen/unwind-abis/c-unwind-abi-panic-abort.rs
Normal file
18
src/test/codegen/unwind-abis/c-unwind-abi-panic-abort.rs
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
// compile-flags: -C panic=abort -C opt-level=0
|
||||
|
||||
// Test that `nounwind` atributes are applied to `C-unwind` extern functions when the
|
||||
// code is compiled with `panic=abort`. We disable optimizations above to prevent LLVM from
|
||||
// inferring the attribute.
|
||||
|
||||
#![crate_type = "lib"]
|
||||
#![feature(c_unwind)]
|
||||
|
||||
// CHECK: @rust_item_that_can_unwind() unnamed_addr #0 {
|
||||
#[no_mangle]
|
||||
pub extern "C-unwind" fn rust_item_that_can_unwind() {
|
||||
}
|
||||
|
||||
// Now, make sure that the LLVM attributes for this functions are correct. First, make
|
||||
// sure that the first item is correctly marked with the `nounwind` attribute:
|
||||
//
|
||||
// CHECK: attributes #0 = { {{.*}}nounwind{{.*}} }
|
||||
29
src/test/codegen/unwind-abis/c-unwind-abi.rs
Normal file
29
src/test/codegen/unwind-abis/c-unwind-abi.rs
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
// compile-flags: -C opt-level=0
|
||||
|
||||
// Test that `nounwind` atributes are correctly applied to exported `C` and `C-unwind` extern
|
||||
// functions. `C-unwind` functions MUST NOT have this attribute. We disable optimizations above
|
||||
// to prevent LLVM from inferring the attribute.
|
||||
|
||||
#![crate_type = "lib"]
|
||||
#![feature(c_unwind)]
|
||||
|
||||
// CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0 {
|
||||
#[no_mangle]
|
||||
pub extern "C" fn rust_item_that_cannot_unwind() {
|
||||
}
|
||||
|
||||
// CHECK: @rust_item_that_can_unwind() unnamed_addr #1 {
|
||||
#[no_mangle]
|
||||
pub extern "C-unwind" fn rust_item_that_can_unwind() {
|
||||
}
|
||||
|
||||
// Now, make some assertions that the LLVM attributes for these functions are correct. First, make
|
||||
// sure that the first item is correctly marked with the `nounwind` attribute:
|
||||
//
|
||||
// CHECK: attributes #0 = { {{.*}}nounwind{{.*}} }
|
||||
//
|
||||
// Next, let's assert that the second item, which CAN unwind, does not have this attribute.
|
||||
//
|
||||
// CHECK: attributes #1 = {
|
||||
// CHECK-NOT: nounwind
|
||||
// CHECK: }
|
||||
32
src/test/codegen/unwind-abis/stdcall-unwind-abi.rs
Normal file
32
src/test/codegen/unwind-abis/stdcall-unwind-abi.rs
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
// compile-flags: -C opt-level=0
|
||||
// ignore-arm stdcall isn't supported
|
||||
// ignore-aarch64 stdcall isn't supported
|
||||
// ignore-riscv64 stdcall isn't supported
|
||||
|
||||
// Test that `nounwind` atributes are correctly applied to exported `stdcall` and `stdcall-unwind`
|
||||
// extern functions. `stdcall-unwind` functions MUST NOT have this attribute. We disable
|
||||
// optimizations above to prevent LLVM from inferring the attribute.
|
||||
|
||||
#![crate_type = "lib"]
|
||||
#![feature(c_unwind)]
|
||||
|
||||
// CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0 {
|
||||
#[no_mangle]
|
||||
pub extern "stdcall" fn rust_item_that_cannot_unwind() {
|
||||
}
|
||||
|
||||
// CHECK: @rust_item_that_can_unwind() unnamed_addr #1 {
|
||||
#[no_mangle]
|
||||
pub extern "stdcall-unwind" fn rust_item_that_can_unwind() {
|
||||
}
|
||||
|
||||
// Now, make some assertions that the LLVM attributes for these functions are correct. First, make
|
||||
// sure that the first item is correctly marked with the `nounwind` attribute:
|
||||
//
|
||||
// CHECK: attributes #0 = { {{.*}}nounwind{{.*}} }
|
||||
//
|
||||
// Next, let's assert that the second item, which CAN unwind, does not have this attribute.
|
||||
//
|
||||
// CHECK: attributes #1 = {
|
||||
// CHECK-NOT: nounwind
|
||||
// CHECK: }
|
||||
29
src/test/codegen/unwind-abis/system-unwind-abi.rs
Normal file
29
src/test/codegen/unwind-abis/system-unwind-abi.rs
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
// compile-flags: -C opt-level=0
|
||||
|
||||
// Test that `nounwind` atributes are correctly applied to exported `system` and `system-unwind`
|
||||
// extern functions. `system-unwind` functions MUST NOT have this attribute. We disable
|
||||
// optimizations above to prevent LLVM from inferring the attribute.
|
||||
|
||||
#![crate_type = "lib"]
|
||||
#![feature(c_unwind)]
|
||||
|
||||
// CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0 {
|
||||
#[no_mangle]
|
||||
pub extern "system" fn rust_item_that_cannot_unwind() {
|
||||
}
|
||||
|
||||
// CHECK: @rust_item_that_can_unwind() unnamed_addr #1 {
|
||||
#[no_mangle]
|
||||
pub extern "system-unwind" fn rust_item_that_can_unwind() {
|
||||
}
|
||||
|
||||
// Now, make some assertions that the LLVM attributes for these functions are correct. First, make
|
||||
// sure that the first item is correctly marked with the `nounwind` attribute:
|
||||
//
|
||||
// CHECK: attributes #0 = { {{.*}}nounwind{{.*}} }
|
||||
//
|
||||
// Next, let's assert that the second item, which CAN unwind, does not have this attribute.
|
||||
//
|
||||
// CHECK: attributes #1 = {
|
||||
// CHECK-NOT: nounwind
|
||||
// CHECK: }
|
||||
33
src/test/codegen/unwind-abis/thiscall-unwind-abi.rs
Normal file
33
src/test/codegen/unwind-abis/thiscall-unwind-abi.rs
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
// compile-flags: -C opt-level=0
|
||||
// ignore-arm thiscall isn't supported
|
||||
// ignore-aarch64 thiscall isn't supported
|
||||
// ignore-riscv64 thiscall isn't supported
|
||||
|
||||
// Test that `nounwind` atributes are correctly applied to exported `thiscall` and
|
||||
// `thiscall-unwind` extern functions. `thiscall-unwind` functions MUST NOT have this attribute. We
|
||||
// disable optimizations above to prevent LLVM from inferring the attribute.
|
||||
|
||||
#![crate_type = "lib"]
|
||||
#![feature(abi_thiscall)]
|
||||
#![feature(c_unwind)]
|
||||
|
||||
// CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0 {
|
||||
#[no_mangle]
|
||||
pub extern "thiscall" fn rust_item_that_cannot_unwind() {
|
||||
}
|
||||
|
||||
// CHECK: @rust_item_that_can_unwind() unnamed_addr #1 {
|
||||
#[no_mangle]
|
||||
pub extern "thiscall-unwind" fn rust_item_that_can_unwind() {
|
||||
}
|
||||
|
||||
// Now, make some assertions that the LLVM attributes for these functions are correct. First, make
|
||||
// sure that the first item is correctly marked with the `nounwind` attribute:
|
||||
//
|
||||
// CHECK: attributes #0 = { {{.*}}nounwind{{.*}} }
|
||||
//
|
||||
// Next, let's assert that the second item, which CAN unwind, does not have this attribute.
|
||||
//
|
||||
// CHECK: attributes #1 = {
|
||||
// CHECK-NOT: nounwind
|
||||
// CHECK: }
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
-include ../tools.mk
|
||||
|
||||
all: archive
|
||||
# Compile `main.rs`, which will link into our library, and run it.
|
||||
$(RUSTC) main.rs
|
||||
$(call RUN,main)
|
||||
|
||||
ifdef IS_MSVC
|
||||
archive: add.o panic.o
|
||||
# Now, create an archive using these two objects.
|
||||
$(AR) crus $(TMPDIR)/add.lib $(TMPDIR)/add.o $(TMPDIR)/panic.o
|
||||
else
|
||||
archive: add.o panic.o
|
||||
# Now, create an archive using these two objects.
|
||||
$(AR) crus $(TMPDIR)/libadd.a $(TMPDIR)/add.o $(TMPDIR)/panic.o
|
||||
endif
|
||||
|
||||
# Compile `panic.rs` into an object file.
|
||||
#
|
||||
# Note that we invoke `rustc` directly, so we may emit an object rather
|
||||
# than an archive. We'll do that later.
|
||||
panic.o:
|
||||
$(BARE_RUSTC) $(RUSTFLAGS) \
|
||||
--out-dir $(TMPDIR) \
|
||||
--emit=obj panic.rs
|
||||
|
||||
# Compile `add.c` into an object file.
|
||||
add.o:
|
||||
$(call COMPILE_OBJ,$(TMPDIR)/add.o,add.c)
|
||||
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
|
||||
// An external function, defined in Rust.
|
||||
extern void panic_if_greater_than_10(unsigned x);
|
||||
|
||||
unsigned add_small_numbers(unsigned a, unsigned b) {
|
||||
unsigned c = a + b;
|
||||
panic_if_greater_than_10(c);
|
||||
return c;
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
//! A test for calling `C-unwind` functions across foreign function boundaries.
|
||||
//!
|
||||
//! This test triggers a panic in a Rust library that our foreign function invokes. This shows
|
||||
//! that we can unwind through the C code in that library, and catch the underlying panic.
|
||||
#![feature(c_unwind)]
|
||||
|
||||
use std::panic::{catch_unwind, AssertUnwindSafe};
|
||||
|
||||
fn main() {
|
||||
// Call `add_small_numbers`, passing arguments that will NOT trigger a panic.
|
||||
let (a, b) = (9, 1);
|
||||
let c = unsafe { add_small_numbers(a, b) };
|
||||
assert_eq!(c, 10);
|
||||
|
||||
// Call `add_small_numbers`, passing arguments that will trigger a panic, and catch it.
|
||||
let caught_unwind = catch_unwind(AssertUnwindSafe(|| {
|
||||
let (a, b) = (10, 1);
|
||||
let _c = unsafe { add_small_numbers(a, b) };
|
||||
unreachable!("should have unwound instead of returned");
|
||||
}));
|
||||
|
||||
// Assert that we did indeed panic, then unwrap and downcast the panic into the sum.
|
||||
assert!(caught_unwind.is_err());
|
||||
let panic_obj = caught_unwind.unwrap_err();
|
||||
let msg = panic_obj.downcast_ref::<String>().unwrap();
|
||||
assert_eq!(msg, "11");
|
||||
}
|
||||
|
||||
#[link(name = "add", kind = "static")]
|
||||
extern "C-unwind" {
|
||||
/// An external function, defined in C.
|
||||
///
|
||||
/// Returns the sum of two numbers, or panics if the sum is greater than 10.
|
||||
fn add_small_numbers(a: u32, b: u32) -> u32;
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
#![crate_type = "staticlib"]
|
||||
#![feature(c_unwind)]
|
||||
|
||||
/// This function will panic if `x` is greater than 10.
|
||||
///
|
||||
/// This function is called by `add_small_numbers`.
|
||||
#[no_mangle]
|
||||
pub extern "C-unwind" fn panic_if_greater_than_10(x: u32) {
|
||||
if x > 10 {
|
||||
panic!("{}", x); // That is too big!
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
-include ../tools.mk
|
||||
|
||||
all: $(call NATIVE_STATICLIB,add)
|
||||
$(RUSTC) main.rs
|
||||
$(call RUN,main) || exit 1
|
||||
12
src/test/run-make-fulldeps/c-unwind-abi-catch-panic/add.c
Normal file
12
src/test/run-make-fulldeps/c-unwind-abi-catch-panic/add.c
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
|
||||
// An external function, defined in Rust.
|
||||
extern void panic_if_greater_than_10(unsigned x);
|
||||
|
||||
unsigned add_small_numbers(unsigned a, unsigned b) {
|
||||
unsigned c = a + b;
|
||||
panic_if_greater_than_10(c);
|
||||
return c;
|
||||
}
|
||||
44
src/test/run-make-fulldeps/c-unwind-abi-catch-panic/main.rs
Normal file
44
src/test/run-make-fulldeps/c-unwind-abi-catch-panic/main.rs
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
//! A test for calling `C-unwind` functions across foreign function boundaries.
|
||||
//!
|
||||
//! This test triggers a panic when calling a foreign function that calls *back* into Rust.
|
||||
#![feature(c_unwind)]
|
||||
|
||||
use std::panic::{catch_unwind, AssertUnwindSafe};
|
||||
|
||||
fn main() {
|
||||
// Call `add_small_numbers`, passing arguments that will NOT trigger a panic.
|
||||
let (a, b) = (9, 1);
|
||||
let c = unsafe { add_small_numbers(a, b) };
|
||||
assert_eq!(c, 10);
|
||||
|
||||
// Call `add_small_numbers`, passing arguments that will trigger a panic, and catch it.
|
||||
let caught_unwind = catch_unwind(AssertUnwindSafe(|| {
|
||||
let (a, b) = (10, 1);
|
||||
let _c = unsafe { add_small_numbers(a, b) };
|
||||
unreachable!("should have unwound instead of returned");
|
||||
}));
|
||||
|
||||
// Assert that we did indeed panic, then unwrap and downcast the panic into the sum.
|
||||
assert!(caught_unwind.is_err());
|
||||
let panic_obj = caught_unwind.unwrap_err();
|
||||
let msg = panic_obj.downcast_ref::<String>().unwrap();
|
||||
assert_eq!(msg, "11");
|
||||
}
|
||||
|
||||
#[link(name = "add", kind = "static")]
|
||||
extern "C-unwind" {
|
||||
/// An external function, defined in C.
|
||||
///
|
||||
/// Returns the sum of two numbers, or panics if the sum is greater than 10.
|
||||
fn add_small_numbers(a: u32, b: u32) -> u32;
|
||||
}
|
||||
|
||||
/// This function will panic if `x` is greater than 10.
|
||||
///
|
||||
/// This function is called by `add_small_numbers`.
|
||||
#[no_mangle]
|
||||
pub extern "C-unwind" fn panic_if_greater_than_10(x: u32) {
|
||||
if x > 10 {
|
||||
panic!("{}", x); // That is too big!
|
||||
}
|
||||
}
|
||||
|
|
@ -7,7 +7,7 @@
|
|||
// compile-flags:-C panic=abort
|
||||
// aux-build:helper.rs
|
||||
|
||||
#![feature(start, rustc_private, new_uninit, panic_info_message)]
|
||||
#![feature(start, rustc_private, new_uninit, panic_info_message, lang_items)]
|
||||
#![feature(alloc_error_handler)]
|
||||
#![no_std]
|
||||
|
||||
|
|
@ -84,6 +84,13 @@ fn panic(panic_info: &core::panic::PanicInfo) -> ! {
|
|||
}
|
||||
}
|
||||
|
||||
// Because we are compiling this code with `-C panic=abort`, this wouldn't normally be needed.
|
||||
// However, `core` and `alloc` are both compiled with `-C panic=unwind`, which means that functions
|
||||
// in these libaries will refer to `rust_eh_personality` if LLVM can not *prove* the contents won't
|
||||
// unwind. So, for this test case we will define the symbol.
|
||||
#[lang = "eh_personality"]
|
||||
extern fn rust_eh_personality() {}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Page([[u64; 32]; 16]);
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
// aux-build:helper.rs
|
||||
// gate-test-default_alloc_error_handler
|
||||
|
||||
#![feature(start, rustc_private, new_uninit, panic_info_message)]
|
||||
#![feature(start, rustc_private, new_uninit, panic_info_message, lang_items)]
|
||||
#![feature(default_alloc_error_handler)]
|
||||
#![no_std]
|
||||
|
||||
|
|
@ -71,6 +71,13 @@ fn panic(panic_info: &core::panic::PanicInfo) -> ! {
|
|||
}
|
||||
}
|
||||
|
||||
// Because we are compiling this code with `-C panic=abort`, this wouldn't normally be needed.
|
||||
// However, `core` and `alloc` are both compiled with `-C panic=unwind`, which means that functions
|
||||
// in these libaries will refer to `rust_eh_personality` if LLVM can not *prove* the contents won't
|
||||
// unwind. So, for this test case we will define the symbol.
|
||||
#[lang = "eh_personality"]
|
||||
extern fn rust_eh_personality() {}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Page([[u64; 32]; 16]);
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ error[E0703]: invalid ABI: found `路濫狼á́́`
|
|||
LL | extern "路濫狼á́́" fn foo() {}
|
||||
| ^^^^^^^^^ invalid ABI
|
||||
|
|
||||
= help: valid ABIs: Rust, C, cdecl, stdcall, fastcall, vectorcall, thiscall, aapcs, win64, sysv64, ptx-kernel, msp430-interrupt, x86-interrupt, amdgpu-kernel, efiapi, avr-interrupt, avr-non-blocking-interrupt, C-cmse-nonsecure-call, system, rust-intrinsic, rust-call, platform-intrinsic, unadjusted
|
||||
= help: valid ABIs: Rust, C, C-unwind, cdecl, stdcall, stdcall-unwind, fastcall, vectorcall, thiscall, thiscall-unwind, aapcs, win64, sysv64, ptx-kernel, msp430-interrupt, x86-interrupt, amdgpu-kernel, efiapi, avr-interrupt, avr-non-blocking-interrupt, C-cmse-nonsecure-call, system, system-unwind, rust-intrinsic, rust-call, platform-intrinsic, unadjusted
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ error[E0703]: invalid ABI: found `invalid-ab_isize`
|
|||
LL | "invalid-ab_isize"
|
||||
| ^^^^^^^^^^^^^^^^^^ invalid ABI
|
||||
|
|
||||
= help: valid ABIs: Rust, C, cdecl, stdcall, fastcall, vectorcall, thiscall, aapcs, win64, sysv64, ptx-kernel, msp430-interrupt, x86-interrupt, amdgpu-kernel, efiapi, avr-interrupt, avr-non-blocking-interrupt, C-cmse-nonsecure-call, system, rust-intrinsic, rust-call, platform-intrinsic, unadjusted
|
||||
= help: valid ABIs: Rust, C, C-unwind, cdecl, stdcall, stdcall-unwind, fastcall, vectorcall, thiscall, thiscall-unwind, aapcs, win64, sysv64, ptx-kernel, msp430-interrupt, x86-interrupt, amdgpu-kernel, efiapi, avr-interrupt, avr-non-blocking-interrupt, C-cmse-nonsecure-call, system, system-unwind, rust-intrinsic, rust-call, platform-intrinsic, unadjusted
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
|||
12
src/test/ui/unwind-abis/feature-gate-c-unwind-enabled.rs
Normal file
12
src/test/ui/unwind-abis/feature-gate-c-unwind-enabled.rs
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
// Test that the "C-unwind" ABI is feature-gated, and *can* be used when the
|
||||
// `c_unwind` feature gate is enabled.
|
||||
|
||||
// check-pass
|
||||
|
||||
#![feature(c_unwind)]
|
||||
|
||||
extern "C-unwind" fn f() {}
|
||||
|
||||
fn main() {
|
||||
f();
|
||||
}
|
||||
9
src/test/ui/unwind-abis/feature-gate-c-unwind.rs
Normal file
9
src/test/ui/unwind-abis/feature-gate-c-unwind.rs
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
// Test that the "C-unwind" ABI is feature-gated, and cannot be used when the
|
||||
// `c_unwind` feature gate is not used.
|
||||
|
||||
extern "C-unwind" fn f() {}
|
||||
//~^ ERROR C-unwind ABI is experimental and subject to change [E0658]
|
||||
|
||||
fn main() {
|
||||
f();
|
||||
}
|
||||
12
src/test/ui/unwind-abis/feature-gate-c-unwind.stderr
Normal file
12
src/test/ui/unwind-abis/feature-gate-c-unwind.stderr
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
error[E0658]: C-unwind ABI is experimental and subject to change
|
||||
--> $DIR/feature-gate-c-unwind.rs:4:8
|
||||
|
|
||||
LL | extern "C-unwind" fn f() {}
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #74990 <https://github.com/rust-lang/rust/issues/74990> for more information
|
||||
= help: add `#![feature(c_unwind)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
13
src/test/ui/unwind-abis/feature-gate-stdcall-unwind.rs
Normal file
13
src/test/ui/unwind-abis/feature-gate-stdcall-unwind.rs
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
// ignore-arm stdcall isn't supported
|
||||
// ignore-aarch64 stdcall isn't supported
|
||||
// ignore-riscv64 stdcall isn't supported
|
||||
|
||||
// Test that the "stdcall-unwind" ABI is feature-gated, and cannot be used when
|
||||
// the `c_unwind` feature gate is not used.
|
||||
|
||||
extern "stdcall-unwind" fn f() {}
|
||||
//~^ ERROR stdcall-unwind ABI is experimental and subject to change [E0658]
|
||||
|
||||
fn main() {
|
||||
f();
|
||||
}
|
||||
12
src/test/ui/unwind-abis/feature-gate-stdcall-unwind.stderr
Normal file
12
src/test/ui/unwind-abis/feature-gate-stdcall-unwind.stderr
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
error[E0658]: stdcall-unwind ABI is experimental and subject to change
|
||||
--> $DIR/feature-gate-stdcall-unwind.rs:8:8
|
||||
|
|
||||
LL | extern "stdcall-unwind" fn f() {}
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #74990 <https://github.com/rust-lang/rust/issues/74990> for more information
|
||||
= help: add `#![feature(c_unwind)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
9
src/test/ui/unwind-abis/feature-gate-system-unwind.rs
Normal file
9
src/test/ui/unwind-abis/feature-gate-system-unwind.rs
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
// Test that the "system-unwind" ABI is feature-gated, and cannot be used when
|
||||
// the `c_unwind` feature gate is not used.
|
||||
|
||||
extern "system-unwind" fn f() {}
|
||||
//~^ ERROR system-unwind ABI is experimental and subject to change [E0658]
|
||||
|
||||
fn main() {
|
||||
f();
|
||||
}
|
||||
12
src/test/ui/unwind-abis/feature-gate-system-unwind.stderr
Normal file
12
src/test/ui/unwind-abis/feature-gate-system-unwind.stderr
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
error[E0658]: system-unwind ABI is experimental and subject to change
|
||||
--> $DIR/feature-gate-system-unwind.rs:4:8
|
||||
|
|
||||
LL | extern "system-unwind" fn f() {}
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #74990 <https://github.com/rust-lang/rust/issues/74990> for more information
|
||||
= help: add `#![feature(c_unwind)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
13
src/test/ui/unwind-abis/feature-gate-thiscall-unwind.rs
Normal file
13
src/test/ui/unwind-abis/feature-gate-thiscall-unwind.rs
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
// ignore-arm thiscall isn't supported
|
||||
// ignore-aarch64 thiscall isn't supported
|
||||
// ignore-riscv64 thiscall isn't supported
|
||||
|
||||
// Test that the "thiscall-unwind" ABI is feature-gated, and cannot be used when
|
||||
// the `c_unwind` feature gate is not used.
|
||||
|
||||
extern "thiscall-unwind" fn f() {}
|
||||
//~^ ERROR thiscall-unwind ABI is experimental and subject to change [E0658]
|
||||
|
||||
fn main() {
|
||||
f();
|
||||
}
|
||||
12
src/test/ui/unwind-abis/feature-gate-thiscall-unwind.stderr
Normal file
12
src/test/ui/unwind-abis/feature-gate-thiscall-unwind.stderr
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
error[E0658]: thiscall-unwind ABI is experimental and subject to change
|
||||
--> $DIR/feature-gate-thiscall-unwind.rs:8:8
|
||||
|
|
||||
LL | extern "thiscall-unwind" fn f() {}
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #74990 <https://github.com/rust-lang/rust/issues/74990> for more information
|
||||
= help: add `#![feature(c_unwind)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
Loading…
Add table
Add a link
Reference in a new issue