diff --git a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs index 6289b1c726684..59aaf31631dd2 100644 --- a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs @@ -17,8 +17,8 @@ use crate::diagnostics::{ AsNeededCompatibility, BothFfiConstAndPure, BundleNeedsStatic, EmptyLinkName, ExportSymbolsNeedsStatic, ImportNameTypeRaw, ImportNameTypeX86, IncompatibleWasmLink, InvalidLinkModifier, InvalidMachoSection, InvalidMachoSectionReason, LinkFrameworkApple, - LinkOrdinalOutOfRange, LinkRequiresName, MultipleModifiers, NullOnLinkName, NullOnLinkSection, - RawDylibOnlyWindows, WholeArchiveNeedsStatic, + LinkOrdinalOutOfRange, LinkRequiresName, LinkSectionForeignBpfOnly, MultipleModifiers, + NullOnLinkName, NullOnLinkSection, RawDylibOnlyWindows, WholeArchiveNeedsStatic, }; pub(crate) struct LinkNameParser; @@ -505,6 +505,8 @@ impl SingleAttributeParser for LinkSectionParser { Allow(Target::Method(MethodKind::Inherent)), Allow(Target::Method(MethodKind::Trait { body: true })), Allow(Target::Method(MethodKind::TraitImpl)), + Allow(Target::ForeignStatic), + Allow(Target::ForeignFn), ]); const TEMPLATE: AttributeTemplate = template!( NameValueStr: "name", @@ -512,6 +514,13 @@ impl SingleAttributeParser for LinkSectionParser { ); fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option { + if matches!(cx.target, Target::ForeignStatic | Target::ForeignFn) + && cx.sess.target.arch != Arch::Bpf + { + cx.emit_err(LinkSectionForeignBpfOnly { span: cx.attr_span }); + return None; + } + let nv = cx.expect_name_value(args, cx.attr_span, None)?; let name = cx.expect_string_literal(nv)?; if name.as_str().contains('\0') { diff --git a/compiler/rustc_attr_parsing/src/diagnostics.rs b/compiler/rustc_attr_parsing/src/diagnostics.rs index 9d72bdcb75ce3..7ec21a2decbba 100644 --- a/compiler/rustc_attr_parsing/src/diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/diagnostics.rs @@ -1235,6 +1235,13 @@ pub(crate) struct NullOnLinkSection { pub span: Span, } +#[derive(Diagnostic)] +#[diag("`link_section` on foreign items is only supported on BPF targets")] +pub(crate) struct LinkSectionForeignBpfOnly { + #[primary_span] + pub span: Span, +} + #[derive(Diagnostic)] #[diag("link name may not contain null characters", code = E0648)] pub(crate) struct NullOnLinkName { diff --git a/compiler/rustc_codegen_llvm/src/callee.rs b/compiler/rustc_codegen_llvm/src/callee.rs index 9215273eed17d..76e93f9e8fce3 100644 --- a/compiler/rustc_codegen_llvm/src/callee.rs +++ b/compiler/rustc_codegen_llvm/src/callee.rs @@ -10,6 +10,7 @@ use rustc_middle::ty::{self, Instance, TypeVisitableExt}; use rustc_target::spec::{Arch, Env}; use tracing::debug; +use crate::base; use crate::context::CodegenCx; use crate::llvm::{self, Value}; @@ -152,6 +153,13 @@ pub(crate) fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'t cx.assume_dso_local(llfn, true); + if tcx.is_foreign_item(instance_def_id) { + base::set_link_section(llfn, tcx.codegen_fn_attrs(instance_def_id)); + if tcx.sess.target.arch == Arch::Bpf { + cx.dbg_scope_foreign_fn(instance, fn_abi, Some(llfn)); + } + } + llfn }; diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index 5ecd5c19b6f8e..76fae918de115 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -465,6 +465,13 @@ impl<'ll> CodegenCx<'ll, '_> { llvm::set_dllimport_storage_class(g); } + if self.tcx.is_foreign_item(def_id) { + base::set_link_section(g, fn_attrs); + if self.tcx.sess.target.arch == Arch::Bpf { + debuginfo::build_extern_static_di_node(self, def_id, g); + } + } + self.instances.borrow_mut().insert(instance, g); g } diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/di_builder.rs b/compiler/rustc_codegen_llvm/src/debuginfo/di_builder.rs index 0b5ef6c687404..73f3ff44b54c1 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/di_builder.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/di_builder.rs @@ -43,6 +43,7 @@ pub(crate) trait DIBuilderExt<'ll> { unsafe { llvm::LLVMDIBuilderCreateExpression(this, addr_ops.as_ptr(), addr_ops.len()) } } + /// Creates a DIGlobalVariable debug info node. fn create_static_variable( &self, scope: Option<&'ll llvm::Metadata>, @@ -52,6 +53,7 @@ pub(crate) trait DIBuilderExt<'ll> { line_number: c_uint, ty: &'ll llvm::Metadata, is_local_to_unit: bool, + is_definition: bool, val: &'ll llvm::Value, decl: Option<&'ll llvm::Metadata>, align: Option, @@ -59,14 +61,14 @@ pub(crate) trait DIBuilderExt<'ll> { let this = self.as_di_builder(); let align_in_bits = align.map_or(0, |align| align.bits() as u32); - // `LLVMDIBuilderCreateGlobalVariableExpression` would assert if we + // `LLVMRustDIBuilderCreateGlobalVariableExpression` would assert if we // gave it a null `Expr` pointer, so give it an empty expression // instead, which is what the C++ `createGlobalVariableExpression` // method would do if given a null `DIExpression` pointer. let expr = self.create_expression(&[]); let global_var_expr = unsafe { - llvm::LLVMDIBuilderCreateGlobalVariableExpression( + llvm::LLVMRustDIBuilderCreateGlobalVariableExpression( this, scope, name.as_ptr(), @@ -77,6 +79,7 @@ pub(crate) trait DIBuilderExt<'ll> { line_number, ty, is_local_to_unit.to_llvm_bool(), + is_definition.to_llvm_bool(), expr, decl, align_in_bits, diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 33f6eca6be9cc..67507adf1e9e0 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -1462,43 +1462,57 @@ fn build_generic_type_param_di_nodes<'ll, 'tcx>( } } -/// Creates debug information for the given global variable. +/// Creates debug information for the given global variable (definition). /// /// Adds the created debuginfo nodes directly to the crate's IR. pub(crate) fn build_global_var_di_node<'ll>( cx: &CodegenCx<'ll, '_>, def_id: DefId, global: &'ll Value, +) { + let DefKind::Static { nested, .. } = cx.tcx.def_kind(def_id) else { bug!() }; + if nested { + return; + } + + let is_local_to_unit = is_node_local_to_unit(cx, def_id); + build_static_var_di_node_inner(cx, def_id, global, is_local_to_unit, true); +} + +/// Creates debug information for a foreign static (declaration, not definition). +pub(crate) fn build_extern_static_di_node<'ll>( + cx: &CodegenCx<'ll, '_>, + def_id: DefId, + global: &'ll Value, +) { + build_static_var_di_node_inner(cx, def_id, global, false, false); +} + +fn build_static_var_di_node_inner<'ll>( + cx: &CodegenCx<'ll, '_>, + def_id: DefId, + global: &'ll Value, + is_local_to_unit: bool, + is_definition: bool, ) { if cx.dbg_cx.is_none() { return; } - // Only create type information if full debuginfo is enabled if cx.sess().opts.debuginfo != DebugInfo::Full { return; } let tcx = cx.tcx; - // We may want to remove the namespace scope if we're in an extern block (see - // https://github.com/rust-lang/rust/pull/46457#issuecomment-351750952). let var_scope = get_namespace_for_item(cx, def_id); let (file_metadata, line_number) = file_metadata_from_def_id(cx, Some(def_id)); - let is_local_to_unit = is_node_local_to_unit(cx, def_id); - - let DefKind::Static { nested, .. } = cx.tcx.def_kind(def_id) else { bug!() }; - if nested { - return; - } let variable_type = Instance::mono(cx.tcx, def_id).ty(cx.tcx, cx.typing_env()); let type_di_node = type_di_node(cx, variable_type); let var_name = tcx.item_name(def_id); let var_name = var_name.as_str(); let linkage_name = mangled_name_of_instance(cx, Instance::mono(tcx, def_id)).name; - // When empty, linkage_name field is omitted, - // which is what we want for no_mangle statics let linkage_name = if var_name == linkage_name { "" } else { linkage_name }; let global_align = cx.align_of(variable_type); @@ -1511,8 +1525,9 @@ pub(crate) fn build_global_var_di_node<'ll>( line_number, type_di_node, is_local_to_unit, - global, // (value) - None, // (decl) + is_definition, + global, + None, Some(global_align), ); } @@ -1789,6 +1804,7 @@ pub(crate) fn create_vtable_di_node<'ll, 'tcx>( UNKNOWN_LINE_NUMBER, vtable_type_di_node, true, // (is_local_to_unit) + true, // (is_definition) vtable, // (value) None, // (decl) None::, diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs index d6d9946450899..dc1254cd3afee 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs @@ -27,10 +27,10 @@ use smallvec::SmallVec; use tracing::debug; pub(crate) use self::di_builder::DIBuilderExt; -pub(crate) use self::metadata::build_global_var_di_node; use self::metadata::{ UNKNOWN_COLUMN_NUMBER, UNKNOWN_LINE_NUMBER, file_metadata, spanned_type_di_node, type_di_node, }; +pub(crate) use self::metadata::{build_extern_static_di_node, build_global_var_di_node}; use self::namespace::mangled_name_of_instance; use self::utils::{DIB, create_DIArray, is_node_local_to_unit}; use crate::builder::Builder; @@ -755,3 +755,90 @@ impl<'ll, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> { metadata::create_vtable_di_node(self, ty, trait_ref, vtable) } } + +impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { + /// Creates a `DISubprogram` for a foreign function declaration (without `SPFlagDefinition`). + /// + /// This is gated to BPF targets and emits the debug info that LLVM's BPF backend + /// needs to generate BTF FUNC entries for kfunc resolution. + pub(crate) fn dbg_scope_foreign_fn( + &self, + instance: Instance<'tcx>, + fn_abi: &FnAbi<'tcx, Ty<'tcx>>, + llfn: Option<&'ll Value>, + ) { + if self.dbg_cx.is_none() { + return; + } + + if self.sess().opts.debuginfo != DebugInfo::Full { + return; + } + + let tcx = self.tcx; + let def_id = instance.def_id(); + + let scope = namespace::item_namespace( + self, + DefId { + krate: def_id.krate, + index: tcx.def_key(def_id).parent.expect("dbg_scope_foreign_fn: missing parent?"), + }, + ); + + let span = tcx.def_span(def_id); + let loc = self.lookup_debug_loc(span.lo()); + let file_metadata = file_metadata(self, &loc.file); + + let signature: Vec<_> = iter::once(if fn_abi.ret.is_ignore() { + None + } else { + Some(type_di_node(self, fn_abi.ret.layout.ty)) + }) + .chain(fn_abi.args.iter().map(|arg| Some(type_di_node(self, arg.layout.ty)))) + .collect(); + + let function_type_metadata = create_subroutine_type(self, &signature); + + let mut name = String::with_capacity(64); + type_names::push_item_name(tcx, def_id, false, &mut name); + + let linkage_name = &mangled_name_of_instance(self, instance).name; + let linkage_name = if &name == linkage_name { "" } else { linkage_name }; + + let scope_line = loc.line; + + let mut flags = DIFlags::FlagPrototyped; + if fn_abi.ret.layout.is_uninhabited() { + flags |= DIFlags::FlagNoReturn; + } + + // No SPFlagDefinition -- this is a declaration only. + let mut spflags = DISPFlags::SPFlagZero; + if self.sess().opts.optimize != config::OptLevel::No { + spflags |= DISPFlags::SPFlagOptimized; + } + + let template_parameters = create_DIArray(DIB(self), &[]); + + unsafe { + llvm::LLVMRustDIBuilderCreateFunction( + DIB(self), + scope, + name.as_c_char_ptr(), + name.len(), + linkage_name.as_c_char_ptr(), + linkage_name.len(), + file_metadata, + loc.line, + function_type_metadata, + scope_line, + flags, + spflags, + llfn, + template_parameters, + None, + ); + } + } +} diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 1a60b59a93525..514326311f4c1 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -1901,7 +1901,7 @@ unsafe extern "C" { Length: size_t, ) -> &'ll Metadata; - pub(crate) fn LLVMDIBuilderCreateGlobalVariableExpression<'ll>( + pub(crate) fn LLVMRustDIBuilderCreateGlobalVariableExpression<'ll>( Builder: &DIBuilder<'ll>, Scope: Option<&'ll Metadata>, Name: *const c_uchar, // See "PTR_LEN_STR". @@ -1912,6 +1912,7 @@ unsafe extern "C" { LineNo: c_uint, Ty: &'ll Metadata, LocalToUnit: llvm::Bool, + IsDefined: llvm::Bool, Expr: &'ll Metadata, Decl: Option<&'ll Metadata>, AlignInBits: u32, diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index 983a506bd4ac6..5c0edde77e63f 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -1071,6 +1071,22 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateMethod( return wrap(Sub); } +// Wraps DIBuilder::createGlobalVariableExpression. Unlike the LLVM-C API +// (LLVMDIBuilderCreateGlobalVariableExpression), this exposes the IsDefined +// parameter instead of hard-coding it to true. +extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateGlobalVariableExpression( + LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, + size_t NameLen, const char *Linkage, size_t LinkLen, LLVMMetadataRef File, + unsigned LineNo, LLVMMetadataRef Ty, LLVMBool LocalToUnit, + LLVMBool IsDefined, LLVMMetadataRef Expr, LLVMMetadataRef Decl, + uint32_t AlignInBits) { + return wrap(unwrap(Builder)->createGlobalVariableExpression( + unwrapDI(Scope), {Name, NameLen}, {Linkage, LinkLen}, + unwrapDI(File), LineNo, unwrapDI(Ty), LocalToUnit, + IsDefined, unwrap(Expr), unwrapDI(Decl), nullptr, + AlignInBits)); +} + extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariantPart( LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, size_t NameLen, LLVMMetadataRef File, unsigned LineNumber, diff --git a/tests/codegen-llvm/bpf-extern-debuginfo.rs b/tests/codegen-llvm/bpf-extern-debuginfo.rs new file mode 100644 index 0000000000000..a038e06ea05c9 --- /dev/null +++ b/tests/codegen-llvm/bpf-extern-debuginfo.rs @@ -0,0 +1,35 @@ +// Checks that BPF extern declarations are emitted as debug info declarations. +// +//@ only-bpf +//@ needs-llvm-components: bpf +//@ compile-flags: --target bpfel-unknown-none -C debuginfo=2 + +#![no_std] +#![no_main] +#![crate_type = "lib"] + +extern "C" { + // CHECK: !DIGlobalVariable(name: "KERNEL_VERSION" + // CHECK-SAME: isLocal: false + // CHECK-SAME: isDefinition: false + #[link_section = ".ksyms"] + pub static KERNEL_VERSION: u64; +} + +extern "C" { + // CHECK: !DISubprogram(name: "bpf_kfunc" + // CHECK-SAME: flags: DIFlagPrototyped + // CHECK-NOT: DISPFlagDefinition + #[link_section = ".ksyms"] + pub fn bpf_kfunc(x: u64) -> u64; +} + +#[no_mangle] +pub fn test_extern_items() -> u64 { + unsafe { KERNEL_VERSION + bpf_kfunc(42) } +} + +#[panic_handler] +fn panic(_info: &core::panic::PanicInfo) -> ! { + loop {} +} diff --git a/tests/codegen-llvm/extern-no-debuginfo-non-bpf.rs b/tests/codegen-llvm/extern-no-debuginfo-non-bpf.rs new file mode 100644 index 0000000000000..82c12797c39bd --- /dev/null +++ b/tests/codegen-llvm/extern-no-debuginfo-non-bpf.rs @@ -0,0 +1,24 @@ +// Checks that extern declarations do not get debug info outside BPF targets. +// +//@ compile-flags: -C debuginfo=2 + +#![crate_type = "lib"] + +extern "C" { + // CHECK: @EXTERN_STATIC = external {{.*}}global i32 + // CHECK-NOT: !DIGlobalVariable(name: "EXTERN_STATIC" + pub static EXTERN_STATIC: i32; +} + +extern "C" { + // CHECK: declare {{.*}}void @extern_fn() + // CHECK-NOT: !DISubprogram(name: "extern_fn" + pub fn extern_fn(); +} + +pub fn use_extern_items() -> i32 { + unsafe { + extern_fn(); + EXTERN_STATIC + } +} diff --git a/tests/codegen-llvm/link-section-foreign.rs b/tests/codegen-llvm/link-section-foreign.rs new file mode 100644 index 0000000000000..415cd95c271ba --- /dev/null +++ b/tests/codegen-llvm/link-section-foreign.rs @@ -0,0 +1,35 @@ +// Verifies that #[link_section] works on foreign (extern) items. +// This is only supported on BPF targets. +// +//@ only-bpf +//@ needs-llvm-components: bpf +//@ compile-flags: --target bpfel-unknown-none -C no-prepopulate-passes + +#![no_std] +#![no_main] +#![crate_type = "lib"] + +extern "C" { + // CHECK: @EXTERN_STATIC = external global i32, section ".ksyms" + #[link_section = ".ksyms"] + pub static EXTERN_STATIC: i32; +} + +extern "C" { + // CHECK: declare {{.*}}void @extern_fn(){{.*}} section ".ksyms" + #[link_section = ".ksyms"] + pub fn extern_fn(); +} + +#[no_mangle] +pub fn use_extern_items() -> i32 { + unsafe { + extern_fn(); + EXTERN_STATIC + } +} + +#[panic_handler] +fn panic(_info: &core::panic::PanicInfo) -> ! { + loop {} +} diff --git a/tests/ui/attributes/attr-on-mac-call.stderr b/tests/ui/attributes/attr-on-mac-call.stderr index 3454998af2922..8d28d790188a5 100644 --- a/tests/ui/attributes/attr-on-mac-call.stderr +++ b/tests/ui/attributes/attr-on-mac-call.stderr @@ -129,7 +129,7 @@ warning: the `link_section` attribute cannot be used on macro calls LL | #[link_section = "__TEXT,__text"] | ^^^^^^^^^^^^ | - = help: the `link_section` attribute can be applied to functions and statics + = help: the `link_section` attribute can be applied to foreign statics, functions, and statics = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: placing this attribute on a macro invocation does nothing even if the macro expands to what would be a valid target for the attribute diff --git a/tests/ui/attributes/codegen_attr_on_required_trait_method.stderr b/tests/ui/attributes/codegen_attr_on_required_trait_method.stderr index b5452ba2882c0..f3fc7041e03c5 100644 --- a/tests/ui/attributes/codegen_attr_on_required_trait_method.stderr +++ b/tests/ui/attributes/codegen_attr_on_required_trait_method.stderr @@ -26,7 +26,7 @@ error: the `link_section` attribute cannot be used on required trait methods LL | #[link_section = "__TEXT,__text"] | ^^^^^^^^^^^^ | - = help: the `link_section` attribute can be applied to functions with a body and statics + = help: the `link_section` attribute can be applied to foreign functions, foreign statics, functions with a body, and statics = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! error: aborting due to 3 previous errors diff --git a/tests/ui/conditional-compilation/cfg_attr-attr-syntax-validation.stderr b/tests/ui/conditional-compilation/cfg_attr-attr-syntax-validation.stderr index f21c791cdf7f4..f3fed3d18820a 100644 --- a/tests/ui/conditional-compilation/cfg_attr-attr-syntax-validation.stderr +++ b/tests/ui/conditional-compilation/cfg_attr-attr-syntax-validation.stderr @@ -180,7 +180,7 @@ warning: the `link_section` attribute cannot be used on structs LL | #[cfg_attr(true, link_section)] | ^^^^^^^^^^^^ | - = help: the `link_section` attribute can be applied to functions and statics + = help: the `link_section` attribute can be applied to foreign statics, functions, and statics = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: requested on the command line with `-W unused-attributes` diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr index a677339551153..07bf48bb5e942 100644 --- a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr +++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr @@ -284,7 +284,7 @@ warning: the `link_section` attribute cannot be used on crates LL | #![link_section = ",1800"] | ^^^^^^^^^^^^ | - = help: the `link_section` attribute can be applied to functions and statics + = help: the `link_section` attribute can be applied to foreign statics, functions, and statics = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `must_use` attribute cannot be used on crates @@ -876,7 +876,7 @@ warning: the `link_section` attribute cannot be used on modules LL | #[link_section = ",1800"] | ^^^^^^^^^^^^ | - = help: the `link_section` attribute can be applied to functions and statics + = help: the `link_section` attribute can be applied to foreign statics, functions, and statics = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `link_section` attribute cannot be used on modules @@ -885,7 +885,7 @@ warning: the `link_section` attribute cannot be used on modules LL | mod inner { #![link_section=",1800"] } | ^^^^^^^^^^^^ | - = help: the `link_section` attribute can be applied to functions and statics + = help: the `link_section` attribute can be applied to foreign statics, functions, and statics = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `link_section` attribute cannot be used on structs @@ -894,7 +894,7 @@ warning: the `link_section` attribute cannot be used on structs LL | #[link_section = ",1800"] struct S; | ^^^^^^^^^^^^ | - = help: the `link_section` attribute can be applied to functions and statics + = help: the `link_section` attribute can be applied to foreign statics, functions, and statics = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `link_section` attribute cannot be used on type aliases @@ -903,7 +903,7 @@ warning: the `link_section` attribute cannot be used on type aliases LL | #[link_section = ",1800"] type T = S; | ^^^^^^^^^^^^ | - = help: the `link_section` attribute can be applied to functions and statics + = help: the `link_section` attribute can be applied to foreign statics, functions, and statics = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `link_section` attribute cannot be used on inherent impl blocks @@ -912,7 +912,7 @@ warning: the `link_section` attribute cannot be used on inherent impl blocks LL | #[link_section = ",1800"] impl S { } | ^^^^^^^^^^^^ | - = help: the `link_section` attribute can be applied to functions and statics + = help: the `link_section` attribute can be applied to foreign statics, functions, and statics = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `link_section` attribute cannot be used on traits @@ -921,7 +921,7 @@ warning: the `link_section` attribute cannot be used on traits LL | #[link_section = ",1800"] | ^^^^^^^^^^^^ | - = help: the `link_section` attribute can be applied to functions and statics + = help: the `link_section` attribute can be applied to foreign statics, functions, and statics = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `link` attribute cannot be used on modules @@ -1598,7 +1598,7 @@ warning: the `link_section` attribute cannot be used on required trait methods LL | #[link_section = ",1800"] | ^^^^^^^^^^^^ | - = help: the `link_section` attribute can be applied to functions with a body and statics + = help: the `link_section` attribute can be applied to foreign functions, foreign statics, functions with a body, and statics = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: 171 warnings emitted diff --git a/tests/ui/linkage-attr/link-section-foreign-bpf-only.rs b/tests/ui/linkage-attr/link-section-foreign-bpf-only.rs new file mode 100644 index 0000000000000..bd2d769d6e405 --- /dev/null +++ b/tests/ui/linkage-attr/link-section-foreign-bpf-only.rs @@ -0,0 +1,25 @@ +//@ add-minicore +//@ compile-flags: --target x86_64-unknown-linux-gnu +//@ needs-llvm-components: x86 +#![feature(no_core, rustc_attrs, lang_items)] +#![no_core] +#![crate_type = "lib"] + +extern crate minicore; +use minicore::*; + +extern "C" { + #[unsafe(link_section = ".ksyms")] + //~^ ERROR `link_section` on foreign items is only supported on BPF targets + static foo: u32; + + #[unsafe(link_section = ".ksyms")] + //~^ ERROR `link_section` on foreign items is only supported on BPF targets + fn bar(); +} + +#[unsafe(link_section = ".text")] +fn regular_fn() {} + +#[unsafe(link_section = ".data")] +static BAZ: u32 = 42; diff --git a/tests/ui/linkage-attr/link-section-foreign-bpf-only.stderr b/tests/ui/linkage-attr/link-section-foreign-bpf-only.stderr new file mode 100644 index 0000000000000..8bf61ec9eed52 --- /dev/null +++ b/tests/ui/linkage-attr/link-section-foreign-bpf-only.stderr @@ -0,0 +1,14 @@ +error: `link_section` on foreign items is only supported on BPF targets + --> $DIR/link-section-foreign-bpf-only.rs:12:5 + | +LL | #[unsafe(link_section = ".ksyms")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `link_section` on foreign items is only supported on BPF targets + --> $DIR/link-section-foreign-bpf-only.rs:16:5 + | +LL | #[unsafe(link_section = ".ksyms")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors +