}
Ok(())
}
+
+ fn in_std(&self) -> bool {
+ let this = self.eval_context_ref();
+ this.tcx.def_path(this.frame().instance.def_id()).krate
+ == this.tcx.def_path(this.tcx.lang_items().start_fn().unwrap()).krate
+ }
}
/// Check that the number of args is what we expect.
// Incomplete shims that we "stub out" just to get pre-main initialization code to work.
// These shims are enabled only when the caller is in the standard library.
"pthread_attr_getguardsize"
- if this.frame().instance.to_string().starts_with("std::sys::unix::") => {
+ if this.in_std() => {
this.check_abi(abi, Abi::C { unwind: false })?;
let &[ref _attr, ref guard_size] = check_arg_count(args)?;
let guard_size = this.deref_operand(guard_size)?;
| "pthread_attr_init"
| "pthread_attr_destroy"
- if this.frame().instance.to_string().starts_with("std::sys::unix::") => {
+ if this.in_std() => {
this.check_abi(abi, Abi::C { unwind: false })?;
let &[_] = check_arg_count(args)?;
this.write_null(dest)?;
}
| "pthread_attr_setstacksize"
- if this.frame().instance.to_string().starts_with("std::sys::unix::") => {
+ if this.in_std() => {
this.check_abi(abi, Abi::C { unwind: false })?;
let &[_, _] = check_arg_count(args)?;
this.write_null(dest)?;
| "signal"
| "sigaltstack"
- if this.frame().instance.to_string().starts_with("std::sys::unix::") => {
+ if this.in_std() => {
this.check_abi(abi, Abi::C { unwind: false })?;
let &[_, _] = check_arg_count(args)?;
this.write_null(dest)?;
}
| "sigaction"
| "mprotect"
- if this.frame().instance.to_string().starts_with("std::sys::unix::") => {
+ if this.in_std() => {
this.check_abi(abi, Abi::C { unwind: false })?;
let &[_, _, _] = check_arg_count(args)?;
this.write_null(dest)?;
// Incomplete shims that we "stub out" just to get pre-main initialization code to work.
// These shims are enabled only when the caller is in the standard library.
- "pthread_getattr_np"
- if this.frame().instance.to_string().starts_with("std::sys::unix::") =>
- {
+ "pthread_getattr_np" if this.in_std() => {
this.check_abi(abi, Abi::C { unwind: false })?;
let &[ref _thread, ref _attr] = check_arg_count(args)?;
this.write_null(dest)?;
// Incomplete shims that we "stub out" just to get pre-main initialization code to work.
// These shims are enabled only when the caller is in the standard library.
- "mmap" if this.frame().instance.to_string().starts_with("std::sys::unix::") => {
+ "mmap" if this.in_std() => {
this.check_abi(abi, Abi::C { unwind: false })?;
// This is a horrible hack, but since the guard page mechanism calls mmap and expects a particular return value, we just give it that value.
let &[ref addr, _, _, _, _, _] = check_arg_count(args)?;
// Incomplete shims that we "stub out" just to get pre-main initialization code to work.
// These shims are enabled only when the caller is in the standard library.
- "GetProcessHeap"
- if this.frame().instance.to_string().starts_with("std::sys::windows::") =>
- {
+ "GetProcessHeap" if this.in_std() => {
this.check_abi(abi, Abi::System { unwind: false })?;
let &[] = check_arg_count(args)?;
// Just fake a HANDLE
this.write_scalar(Scalar::from_machine_isize(1, this), dest)?;
}
- "SetConsoleTextAttribute"
- if this.frame().instance.to_string().starts_with("std::sys::windows::") =>
- {
+ "SetConsoleTextAttribute" if this.in_std() => {
this.check_abi(abi, Abi::System { unwind: false })?;
#[allow(non_snake_case)]
let &[ref _hConsoleOutput, ref _wAttribute] = check_arg_count(args)?;
// Pretend these does not exist / nothing happened, by returning zero.
this.write_null(dest)?;
}
- "AddVectoredExceptionHandler"
- if this.frame().instance.to_string().starts_with("std::sys::windows::") =>
- {
+ "AddVectoredExceptionHandler" if this.in_std() => {
this.check_abi(abi, Abi::System { unwind: false })?;
#[allow(non_snake_case)]
let &[ref _First, ref _Handler] = check_arg_count(args)?;
// Any non zero value works for the stdlib. This is just used for stack overflows anyway.
this.write_scalar(Scalar::from_machine_usize(1, this), dest)?;
}
- "SetThreadStackGuarantee"
- if this.frame().instance.to_string().starts_with("std::sys::windows::") =>
- {
+ "SetThreadStackGuarantee" if this.in_std() => {
this.check_abi(abi, Abi::System { unwind: false })?;
#[allow(non_snake_case)]
let &[_StackSizeInBytes] = check_arg_count(args)?;
| "EnterCriticalSection"
| "LeaveCriticalSection"
| "DeleteCriticalSection"
- if this.frame().instance.to_string().starts_with("std::sys::windows::") =>
+ if this.in_std() =>
{
this.check_abi(abi, Abi::System { unwind: false })?;
#[allow(non_snake_case)]
// (Windows locks are reentrant, and we have only 1 thread,
// so not doing any futher checks here is at least not incorrect.)
}
- "TryEnterCriticalSection"
- if this.frame().instance.to_string().starts_with("std::sys::windows::") =>
- {
+ "TryEnterCriticalSection" if this.in_std() => {
this.check_abi(abi, Abi::System { unwind: false })?;
#[allow(non_snake_case)]
let &[ref _lpCriticalSection] = check_arg_count(args)?;
--- /dev/null
+//! `GetProcessHeap()` is special on Windows that it's only supported within libstd.
+//! (On Linux and macOS, it's just always unsupported.)
+
+fn main() {
+ extern "system" {
+ fn GetProcessHeap() -> *mut std::ffi::c_void;
+ }
+ unsafe {
+ GetProcessHeap();
+ //~^ ERROR unsupported operation: can't call foreign function: GetProcessHeap
+ }
+}
--- /dev/null
+//! `signal()` is special on Linux and macOS that it's only supported within libstd.
+// ignore-windows: No libc on Windows
+#![feature(rustc_private)]
+
+extern crate libc;
+
+fn main() {
+ unsafe {
+ libc::signal(libc::SIGPIPE, libc::SIG_IGN);
+ //~^ ERROR unsupported operation: can't call foreign function: signal
+ }
+}
--- /dev/null
+#![no_std]
+
+fn main() {
+ extern crate std;
+}
--- /dev/null
+#![no_std]
+
+extern crate std as foo;
+
+fn main() {}
--- /dev/null
+//! Make sure we can call foreign functions that are only allowed within libstd if we are "libstd"
+//! (defining the `start` lang item).
+#![feature(lang_items, rustc_private, core_intrinsics)]
+#![no_std]
+
+use core::{intrinsics, panic::PanicInfo};
+
+#[lang = "eh_personality"]
+fn rust_eh_personality() {}
+
+#[panic_handler]
+fn panic_handler(_: &PanicInfo<'_>) -> ! {
+ intrinsics::abort()
+}
+
+#[lang = "start"]
+fn start(main: fn(), _argc: isize, _argv: *const *const u8) -> isize {
+ main();
+ 0
+}
+
+fn main() {
+ #[cfg(unix)]
+ unsafe {
+ extern crate libc;
+ assert_eq!(libc::signal(libc::SIGPIPE, libc::SIG_IGN), 0);
+ }
+ #[cfg(windows)]
+ unsafe {
+ extern "system" {
+ fn GetProcessHeap() -> *mut core::ffi::c_void;
+ fn ExitProcess(code: u32) -> !;
+ }
+ assert_eq!(GetProcessHeap() as usize, 1);
+ // Early exit to avoid the requirement of
+ // `std::sys::windows::thread_local_key::p_thread_callback`.
+ ExitProcess(0);
+ }
+}