Skip to content

Commit 51a0bf0

Browse files
error or warn when using no_mangle on language items
add suggestion on how to add a panic breakpoint Co-authored-by: Pat Pannuto <[email protected]> delete no_mangle from ui/panic-handler/panic-handler-wrong-location test issue an error for the usage of #[no_mangle] on internal language items delete the comments add newline rephrase note Co-authored-by: bjorn3 <[email protected]> update error not to leak implementation details delete no_mangle_span Co-authored-by: bjorn3 <[email protected]> delete commented code
1 parent 49e5e4e commit 51a0bf0

6 files changed

+86
-1
lines changed

compiler/rustc_codegen_ssa/src/codegen_attrs.rs

+30
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
8787
let mut link_ordinal_span = None;
8888
let mut no_sanitize_span = None;
8989
let mut mixed_export_name_no_mangle_lint_state = MixedExportNameAndNoMangleState::default();
90+
let mut no_mangle_span = None;
9091

9192
for attr in attrs.iter() {
9293
// In some cases, attribute are only valid on functions, but it's the `check_attr`
@@ -139,6 +140,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
139140
}
140141
sym::naked => codegen_fn_attrs.flags |= CodegenFnAttrFlags::NAKED,
141142
sym::no_mangle => {
143+
no_mangle_span = Some(attr.span());
142144
if tcx.opt_item_name(did.to_def_id()).is_some() {
143145
codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_MANGLE;
144146
mixed_export_name_no_mangle_lint_state.track_no_mangle(
@@ -621,6 +623,34 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
621623
}
622624
check_link_name_xor_ordinal(tcx, &codegen_fn_attrs, link_ordinal_span);
623625

626+
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL)
627+
&& codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NO_MANGLE)
628+
{
629+
let lang_item =
630+
lang_items::extract(attrs).map_or(None, |(name, _span)| LangItem::from_name(name));
631+
let mut err = tcx
632+
.dcx()
633+
.struct_span_err(
634+
no_mangle_span.unwrap_or_default(),
635+
"`#[no_mangle]` cannot be used on internal language items",
636+
)
637+
.with_note("Rustc requires this item to have a specific mangled name.")
638+
.with_span_label(tcx.def_span(did), "should be the internal language item");
639+
if let Some(lang_item) = lang_item {
640+
if let Some(link_name) = lang_item.link_name() {
641+
err = err
642+
.with_note("If you are trying to prevent mangling to ease debugging, many")
643+
.with_note(format!(
644+
"debuggers support a command such as `rbreak {link_name}` to"
645+
))
646+
.with_note(format!(
647+
"match `.*{link_name}.*` instead of `break {link_name}` on a specific name"
648+
))
649+
}
650+
}
651+
err.emit();
652+
}
653+
624654
// Any linkage to LLVM intrinsics for now forcibly marks them all as never
625655
// unwinds since LLVM sometimes can't handle codegen which `invoke`s
626656
// intrinsic functions.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Issue a error when the user uses #[no_mangle] on internal language items
2+
//@ edition:2024
3+
4+
#![feature(rustc_attrs)]
5+
6+
#[rustc_std_internal_symbol]
7+
#[unsafe(no_mangle)] //~ERROR `#[no_mangle]` cannot be used on internal language items
8+
fn internal_lang_function () {
9+
10+
}
11+
12+
fn main() {
13+
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
error: `#[no_mangle]` cannot be used on internal language items
2+
--> $DIR/no-mangle-on-internal-lang-items.rs:7:1
3+
|
4+
LL | #[unsafe(no_mangle)]
5+
| ^^^^^^^^^^^^^^^^^^^^
6+
LL | fn internal_lang_function () {
7+
| ---------------------------- should be the internal language item
8+
|
9+
= note: Rustc requires this item to have a specific mangled name.
10+
11+
error: aborting due to 1 previous error
12+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Issue an error when the user uses #[no_mangle] on the panic handler
2+
//@ edition:2024
3+
4+
#![crate_type="lib"]
5+
#![no_std]
6+
#![no_main]
7+
8+
use core::panic::PanicInfo;
9+
10+
#[unsafe(no_mangle)] //~ ERROR `#[no_mangle]` cannot be used on internal language items
11+
#[panic_handler]
12+
pub unsafe fn panic_fmt(pi: &PanicInfo) -> ! {
13+
loop {}
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
error: `#[no_mangle]` cannot be used on internal language items
2+
--> $DIR/no-mangle-on-panic-handler.rs:10:1
3+
|
4+
LL | #[unsafe(no_mangle)]
5+
| ^^^^^^^^^^^^^^^^^^^^
6+
LL | #[panic_handler]
7+
LL | pub unsafe fn panic_fmt(pi: &PanicInfo) -> ! {
8+
| -------------------------------------------- should be the internal language item
9+
|
10+
= note: Rustc requires this item to have a specific mangled name.
11+
= note: If you are trying to prevent mangling to ease debugging, many
12+
= note: debuggers support a command such as `rbreak rust_begin_unwind` to
13+
= note: match `.*rust_begin_unwind.*` instead of `break rust_begin_unwind` on a specific name
14+
15+
error: aborting due to 1 previous error
16+

tests/ui/panic-handler/panic-handler-wrong-location.rs

-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
#![no_main]
55

66
#[panic_handler] //~ ERROR `panic_impl` lang item must be applied to a function
7-
#[no_mangle]
87
static X: u32 = 42;
98

109
//~? ERROR `#[panic_handler]` function required, but not found

0 commit comments

Comments
 (0)