Skip to content

Commit

Permalink
Auto merge of rust-lang#128784 - tdittr:check-abi-on-fn-ptr, r=<try>
Browse files Browse the repository at this point in the history
Check ABI target compatibility for function pointers

Related tracking issue: rust-lang#87678

Compatibility of an ABI for a target was previously only performed on function definitions and `extern` blocks. This PR adds it also to function pointers to be consistent.

This might have broken some of the `tests/ui/` depending on the platform, so a try run seems like a good idea.

Also this might break existing code, because we now emit extra errors. Does this require a crater run?

# Example
```rust
// build with: --target=x86_64-unknown-linux-gnu

// These raise E0570
extern "thiscall" fn foo() {}
extern "thiscall" { fn bar() }

// This did not raise any error
fn baz(f: extern "thiscall" fn()) { f() }
```

# Places to check in the tests:
* [x] Check if we can use another ABI here
```
tests/debuginfo/type-names.rs
20:// gdb-check:type = type_names::GenericStruct<type_names::Struct1, extern "fastcall" fn(isize) -> usize>
375:    let generic_struct2: GenericStruct<Struct1, extern "fastcall" fn(isize) -> usize> =
```

try-job: aarch64-gnu
try-job: aarch64-apple
try-job: x86_64-msvc
try-job: x86_64-mingw
try-job: i686-msvc
try-job: i686-mingw
try-job: test-various
try-job: armhf-gnu
  • Loading branch information
bors committed Aug 16, 2024
2 parents d626fbd + b2be5a8 commit d7da183
Show file tree
Hide file tree
Showing 18 changed files with 773 additions and 84 deletions.
11 changes: 0 additions & 11 deletions compiler/rustc_hir_analysis/src/check/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,17 +51,6 @@ pub fn check_abi(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: Abi) {
});
}
}

// This ABI is only allowed on function pointers
if abi == Abi::CCmseNonSecureCall {
struct_span_code_err!(
tcx.dcx(),
span,
E0781,
"the `\"C-cmse-nonsecure-call\"` ABI is only allowed on function pointers"
)
.emit();
}
}

fn check_struct(tcx: TyCtxt<'_>, def_id: LocalDefId) {
Expand Down
19 changes: 15 additions & 4 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use rustc_errors::DiagCtxtHandle;
use rustc_hir as hir;
use rustc_hir::HirId;
use rustc_errors::{struct_span_code_err, DiagCtxtHandle, E0781};
use rustc_hir::{self as hir, HirId};
use rustc_middle::ty::layout::LayoutError;
use rustc_middle::ty::{self, ParamEnv, TyCtxt};
use rustc_span::Span;
Expand All @@ -26,7 +25,19 @@ pub fn validate_cmse_abi<'tcx>(
..
}) = hir_node
else {
// might happen when this ABI is used incorrectly. That will be handled elsewhere
let span = match tcx.parent_hir_node(hir_id) {
hir::Node::Item(hir::Item {
kind: hir::ItemKind::ForeignMod { .. }, span, ..
}) => *span,
_ => tcx.hir().span(hir_id),
};
struct_span_code_err!(
tcx.dcx(),
span,
E0781,
"the `\"C-cmse-nonsecure-call\"` ABI is only allowed on function pointers"
)
.emit();
return;
};

Expand Down
6 changes: 6 additions & 0 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2309,6 +2309,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
let fn_ty = tcx.mk_fn_sig(input_tys, output_ty, decl.c_variadic, safety, abi);
let bare_fn_ty = ty::Binder::bind_with_vars(fn_ty, bound_vars);

if let hir::Node::Ty(hir::Ty { kind: hir::TyKind::BareFn(bare_fn_ty), span, .. }) =
tcx.hir_node(hir_id)
{
crate::check::check_abi(tcx, hir_id, *span, bare_fn_ty.abi);
}

// reject function types that violate cmse ABI requirements
cmse::validate_cmse_abi(self.tcx(), self.dcx(), hir_id, abi, bare_fn_ty);

Expand Down
4 changes: 2 additions & 2 deletions tests/debuginfo/type-names.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
// gdb-check:type = type_names::GenericStruct<type_names::mod1::Struct2, type_names::mod1::mod2::Struct3>

// gdb-command:whatis generic_struct2
// gdb-check:type = type_names::GenericStruct<type_names::Struct1, extern "fastcall" fn(isize) -> usize>
// gdb-check:type = type_names::GenericStruct<type_names::Struct1, extern "system" fn(isize) -> usize>

// gdb-command:whatis mod_struct
// gdb-check:type = type_names::mod1::Struct2
Expand Down Expand Up @@ -372,7 +372,7 @@ fn main() {
let simple_struct = Struct1;
let generic_struct1: GenericStruct<mod1::Struct2, mod1::mod2::Struct3> =
GenericStruct(PhantomData);
let generic_struct2: GenericStruct<Struct1, extern "fastcall" fn(isize) -> usize> =
let generic_struct2: GenericStruct<Struct1, extern "system" fn(isize) -> usize> =
GenericStruct(PhantomData);
let mod_struct = mod1::Struct2;

Expand Down
122 changes: 112 additions & 10 deletions tests/ui/abi/unsupported.aarch64.stderr
Original file line number Diff line number Diff line change
@@ -1,55 +1,157 @@
error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target
--> $DIR/unsupported.rs:28:1
--> $DIR/unsupported.rs:34:15
|
LL | fn ptx_ptr(f: extern "ptx-kernel" fn()) {
| ^^^^^^^^^^^^^^^^^^^^^^^^

error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target
--> $DIR/unsupported.rs:38:1
|
LL | extern "ptx-kernel" {}
| ^^^^^^^^^^^^^^^^^^^^^^

error[E0570]: `"aapcs"` is not a supported ABI for the current target
--> $DIR/unsupported.rs:47:17
|
LL | fn aapcs_ptr(f: extern "aapcs" fn()) {
| ^^^^^^^^^^^^^^^^^^^

error[E0570]: `"aapcs"` is not a supported ABI for the current target
--> $DIR/unsupported.rs:55:1
|
LL | extern "aapcs" {}
| ^^^^^^^^^^^^^^^^^

error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target
--> $DIR/unsupported.rs:64:18
|
LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target
--> $DIR/unsupported.rs:68:1
|
LL | extern "msp430-interrupt" {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target
--> $DIR/unsupported.rs:73:15
|
LL | fn avr_ptr(f: extern "avr-interrupt" fn()) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target
--> $DIR/unsupported.rs:77:1
|
LL | extern "avr-interrupt" {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0570]: `"riscv-interrupt-m"` is not a supported ABI for the current target
--> $DIR/unsupported.rs:85:17
|
LL | fn riscv_ptr(f: extern "riscv-interrupt-m" fn()) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0570]: `"riscv-interrupt-m"` is not a supported ABI for the current target
--> $DIR/unsupported.rs:92:1
|
LL | extern "riscv-interrupt-m" {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0570]: `"x86-interrupt"` is not a supported ABI for the current target
--> $DIR/unsupported.rs:103:15
|
LL | fn x86_ptr(f: extern "x86-interrupt" fn()) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0570]: `"x86-interrupt"` is not a supported ABI for the current target
--> $DIR/unsupported.rs:110:1
|
LL | extern "x86-interrupt" {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0570]: `"thiscall"` is not a supported ABI for the current target
--> $DIR/unsupported.rs:122:20
|
LL | fn thiscall_ptr(f: extern "thiscall" fn()) {
| ^^^^^^^^^^^^^^^^^^^^^^

error[E0570]: `"thiscall"` is not a supported ABI for the current target
--> $DIR/unsupported.rs:130:1
|
LL | extern "thiscall" {}
| ^^^^^^^^^^^^^^^^^^^^

warning: use of calling convention not supported on this target
--> $DIR/unsupported.rs:148:19
|
LL | fn stdcall_ptr(f: extern "stdcall" fn()) {
| ^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #87678 <https://github.com/rust-lang/rust/issues/87678>
= note: `#[warn(unsupported_calling_conventions)]` on by default

warning: use of calling convention not supported on this target
--> $DIR/unsupported.rs:161:1
|
LL | extern "stdcall" {}
| ^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #87678 <https://github.com/rust-lang/rust/issues/87678>

error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target
--> $DIR/unsupported.rs:32:1
|
LL | extern "ptx-kernel" fn ptx() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0570]: `"aapcs"` is not a supported ABI for the current target
--> $DIR/unsupported.rs:30:1
--> $DIR/unsupported.rs:41:1
|
LL | extern "aapcs" fn aapcs() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target
--> $DIR/unsupported.rs:36:1
--> $DIR/unsupported.rs:62:1
|
LL | extern "msp430-interrupt" fn msp430() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target
--> $DIR/unsupported.rs:38:1
--> $DIR/unsupported.rs:71:1
|
LL | extern "avr-interrupt" fn avr() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0570]: `"riscv-interrupt-m"` is not a supported ABI for the current target
--> $DIR/unsupported.rs:40:1
--> $DIR/unsupported.rs:80:1
|
LL | extern "riscv-interrupt-m" fn riscv() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0570]: `"x86-interrupt"` is not a supported ABI for the current target
--> $DIR/unsupported.rs:45:1
--> $DIR/unsupported.rs:98:1
|
LL | extern "x86-interrupt" fn x86() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0570]: `"thiscall"` is not a supported ABI for the current target
--> $DIR/unsupported.rs:50:1
--> $DIR/unsupported.rs:116:1
|
LL | extern "thiscall" fn thiscall() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

warning: use of calling convention not supported on this target
--> $DIR/unsupported.rs:56:1
--> $DIR/unsupported.rs:137:1
|
LL | extern "stdcall" fn stdcall() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #87678 <https://github.com/rust-lang/rust/issues/87678>
= note: `#[warn(unsupported_calling_conventions)]` on by default

error: aborting due to 7 previous errors; 1 warning emitted
error: aborting due to 21 previous errors; 3 warnings emitted

For more information about this error, try `rustc --explain E0570`.
108 changes: 99 additions & 9 deletions tests/ui/abi/unsupported.arm.stderr
Original file line number Diff line number Diff line change
@@ -1,49 +1,139 @@
error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target
--> $DIR/unsupported.rs:28:1
--> $DIR/unsupported.rs:34:15
|
LL | fn ptx_ptr(f: extern "ptx-kernel" fn()) {
| ^^^^^^^^^^^^^^^^^^^^^^^^

error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target
--> $DIR/unsupported.rs:38:1
|
LL | extern "ptx-kernel" {}
| ^^^^^^^^^^^^^^^^^^^^^^

error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target
--> $DIR/unsupported.rs:64:18
|
LL | fn msp430_ptr(f: extern "msp430-interrupt" fn()) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target
--> $DIR/unsupported.rs:68:1
|
LL | extern "msp430-interrupt" {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target
--> $DIR/unsupported.rs:73:15
|
LL | fn avr_ptr(f: extern "avr-interrupt" fn()) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target
--> $DIR/unsupported.rs:77:1
|
LL | extern "avr-interrupt" {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0570]: `"riscv-interrupt-m"` is not a supported ABI for the current target
--> $DIR/unsupported.rs:85:17
|
LL | fn riscv_ptr(f: extern "riscv-interrupt-m" fn()) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0570]: `"riscv-interrupt-m"` is not a supported ABI for the current target
--> $DIR/unsupported.rs:92:1
|
LL | extern "riscv-interrupt-m" {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0570]: `"x86-interrupt"` is not a supported ABI for the current target
--> $DIR/unsupported.rs:103:15
|
LL | fn x86_ptr(f: extern "x86-interrupt" fn()) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0570]: `"x86-interrupt"` is not a supported ABI for the current target
--> $DIR/unsupported.rs:110:1
|
LL | extern "x86-interrupt" {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0570]: `"thiscall"` is not a supported ABI for the current target
--> $DIR/unsupported.rs:122:20
|
LL | fn thiscall_ptr(f: extern "thiscall" fn()) {
| ^^^^^^^^^^^^^^^^^^^^^^

error[E0570]: `"thiscall"` is not a supported ABI for the current target
--> $DIR/unsupported.rs:130:1
|
LL | extern "thiscall" {}
| ^^^^^^^^^^^^^^^^^^^^

warning: use of calling convention not supported on this target
--> $DIR/unsupported.rs:148:19
|
LL | fn stdcall_ptr(f: extern "stdcall" fn()) {
| ^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #87678 <https://github.com/rust-lang/rust/issues/87678>
= note: `#[warn(unsupported_calling_conventions)]` on by default

warning: use of calling convention not supported on this target
--> $DIR/unsupported.rs:161:1
|
LL | extern "stdcall" {}
| ^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #87678 <https://github.com/rust-lang/rust/issues/87678>

error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target
--> $DIR/unsupported.rs:32:1
|
LL | extern "ptx-kernel" fn ptx() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target
--> $DIR/unsupported.rs:36:1
--> $DIR/unsupported.rs:62:1
|
LL | extern "msp430-interrupt" fn msp430() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target
--> $DIR/unsupported.rs:38:1
--> $DIR/unsupported.rs:71:1
|
LL | extern "avr-interrupt" fn avr() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0570]: `"riscv-interrupt-m"` is not a supported ABI for the current target
--> $DIR/unsupported.rs:40:1
--> $DIR/unsupported.rs:80:1
|
LL | extern "riscv-interrupt-m" fn riscv() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0570]: `"x86-interrupt"` is not a supported ABI for the current target
--> $DIR/unsupported.rs:45:1
--> $DIR/unsupported.rs:98:1
|
LL | extern "x86-interrupt" fn x86() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0570]: `"thiscall"` is not a supported ABI for the current target
--> $DIR/unsupported.rs:50:1
--> $DIR/unsupported.rs:116:1
|
LL | extern "thiscall" fn thiscall() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

warning: use of calling convention not supported on this target
--> $DIR/unsupported.rs:56:1
--> $DIR/unsupported.rs:137:1
|
LL | extern "stdcall" fn stdcall() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #87678 <https://github.com/rust-lang/rust/issues/87678>
= note: `#[warn(unsupported_calling_conventions)]` on by default

error: aborting due to 6 previous errors; 1 warning emitted
error: aborting due to 18 previous errors; 3 warnings emitted

For more information about this error, try `rustc --explain E0570`.
Loading

0 comments on commit d7da183

Please sign in to comment.