diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 6e2143858de8c..999d733e3a7c9 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -4,7 +4,7 @@ use rustc_abi::{Align, ExternAbi}; use rustc_ast::expand::autodiff_attrs::{AutoDiffAttrs, DiffActivity, DiffMode}; use rustc_ast::{LitKind, MetaItem, MetaItemInner, attr}; use rustc_attr_data_structures::{ - AttributeKind, InlineAttr, InstructionSetAttr, OptimizeAttr, ReprAttr, UsedBy, find_attr, + AttributeKind, InlineAttr, InstructionSetAttr, OptimizeAttr, UsedBy, find_attr, }; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId}; @@ -109,14 +109,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { if let hir::Attribute::Parsed(p) = attr { match p { - AttributeKind::Repr(reprs) => { - codegen_fn_attrs.alignment = reprs - .iter() - .filter_map( - |(r, _)| if let ReprAttr::ReprAlign(x) = r { Some(*x) } else { None }, - ) - .max(); - } AttributeKind::Cold(_) => codegen_fn_attrs.flags |= CodegenFnAttrFlags::COLD, AttributeKind::ExportName { name, .. } => { codegen_fn_attrs.export_name = Some(*name); diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index 9a60c1510349a..74a9611d426ce 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -13,6 +13,10 @@ passes_abi_ne = passes_abi_of = fn_abi_of({$fn_name}) = {$fn_abi} +passes_align_attr_application = + `#[align(...)]` should be applied to a function item + .label = not a function item + passes_align_should_be_repr_align = `#[align(...)]` is not supported on {$item} items .suggestion = use `#[repr(align(...))]` instead diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 4bc48cb6aca6f..b2c6f21cd8845 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -1887,7 +1887,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { /// Checks if the `#[align]` attributes on `item` are valid. fn check_align(&self, span: Span, target: Target, align: Align, repr_span: Span) { match target { - Target::Fn | Target::Method(_) => {} + Target::Fn | Target::Method(_) | Target::ForeignFn => {} Target::Struct | Target::Union | Target::Enum => { self.dcx().emit_err(errors::AlignShouldBeReprAlign { span: repr_span, @@ -1896,10 +1896,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { }); } _ => { - self.dcx().emit_err(errors::AttrApplication::StructEnumUnion { - hint_span: repr_span, - span, - }); + self.dcx().emit_err(errors::AlignAttrApplication { hint_span: repr_span, span }); } } diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index d498827707332..76608c2795dce 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -1838,3 +1838,12 @@ pub(crate) struct AlignShouldBeReprAlign { pub item: &'static str, pub align_bytes: u64, } + +#[derive(Diagnostic)] +#[diag(passes_align_attr_application)] +pub(crate) struct AlignAttrApplication { + #[primary_span] + pub hint_span: Span, + #[label] + pub span: Span, +} diff --git a/tests/codegen/align-fn.rs b/tests/codegen/align-fn.rs index 90073ff308143..c871d1259507f 100644 --- a/tests/codegen/align-fn.rs +++ b/tests/codegen/align-fn.rs @@ -1,4 +1,5 @@ //@ compile-flags: -C no-prepopulate-passes -Z mir-opt-level=0 -Clink-dead-code +//@ edition: 2024 #![crate_type = "lib"] #![feature(fn_align)] @@ -116,3 +117,24 @@ pub fn align_specified_twice_2() {} #[align(32)] #[align(256)] pub fn align_specified_twice_3() {} + +const _: () = { + // CHECK-LABEL: align_unmangled + // CHECK-SAME: align 256 + #[unsafe(no_mangle)] + #[align(32)] + #[align(256)] + extern "C" fn align_unmangled() {} +}; + +unsafe extern "C" { + #[align(256)] + fn align_unmangled(); +} + +// FIXME also check `gen` et al +// CHECK-LABEL: async_align +// CHECK-SAME: align 64 +#[unsafe(no_mangle)] +#[align(64)] +pub async fn async_align() {} diff --git a/tests/ui/attributes/fn-align-dyn.rs b/tests/ui/attributes/fn-align-dyn.rs new file mode 100644 index 0000000000000..d67de05e7a9fd --- /dev/null +++ b/tests/ui/attributes/fn-align-dyn.rs @@ -0,0 +1,15 @@ +//@ run-pass +#![feature(fn_align)] + +trait Test { + #[align(4096)] + fn foo(&self); + + #[align(4096)] + fn foo1(&self); +} + +fn main() { + assert_eq!((::foo as fn(_) as usize & !1) % 4096, 0); + assert_eq!((::foo1 as fn(_) as usize & !1) % 4096, 0); +} diff --git a/tests/ui/attributes/malformed-fn-align.rs b/tests/ui/attributes/malformed-fn-align.rs index f5ab9555e561f..e06e611684242 100644 --- a/tests/ui/attributes/malformed-fn-align.rs +++ b/tests/ui/attributes/malformed-fn-align.rs @@ -21,5 +21,29 @@ fn f3() {} #[repr(align(16))] //~ ERROR `#[repr(align(...))]` is not supported on function items fn f4() {} +#[align(-1)] //~ ERROR expected unsuffixed literal, found `-` +fn f5() {} + +#[align(3)] //~ ERROR invalid alignment value: not a power of two +fn f6() {} + +#[align(4usize)] //~ ERROR invalid alignment value: not an unsuffixed integer [E0589] +//~^ ERROR suffixed literals are not allowed in attributes +fn f7() {} + +#[align(16)] +#[align(3)] //~ ERROR invalid alignment value: not a power of two +#[align(16)] +fn f8() {} + #[align(16)] //~ ERROR `#[align(...)]` is not supported on struct items struct S1; + +#[align(32)] //~ ERROR `#[align(...)]` should be applied to a function item +const FOO: i32 = 42; + +#[align(32)] //~ ERROR `#[align(...)]` should be applied to a function item +mod test {} + +#[align(32)] //~ ERROR `#[align(...)]` should be applied to a function item +use ::std::iter; diff --git a/tests/ui/attributes/malformed-fn-align.stderr b/tests/ui/attributes/malformed-fn-align.stderr index b769d0b457ddd..af3625b1f3b9e 100644 --- a/tests/ui/attributes/malformed-fn-align.stderr +++ b/tests/ui/attributes/malformed-fn-align.stderr @@ -1,3 +1,17 @@ +error: expected unsuffixed literal, found `-` + --> $DIR/malformed-fn-align.rs:24:9 + | +LL | #[align(-1)] + | ^ + +error: suffixed literals are not allowed in attributes + --> $DIR/malformed-fn-align.rs:30:9 + | +LL | #[align(4usize)] + | ^^^^^^ + | + = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.) + error[E0539]: malformed `align` attribute input --> $DIR/malformed-fn-align.rs:5:5 | @@ -37,6 +51,24 @@ error[E0589]: invalid alignment value: not a power of two LL | #[align(0)] | ^ +error[E0589]: invalid alignment value: not a power of two + --> $DIR/malformed-fn-align.rs:27:9 + | +LL | #[align(3)] + | ^ + +error[E0589]: invalid alignment value: not an unsuffixed integer + --> $DIR/malformed-fn-align.rs:30:9 + | +LL | #[align(4usize)] + | ^^^^^^ + +error[E0589]: invalid alignment value: not a power of two + --> $DIR/malformed-fn-align.rs:35:9 + | +LL | #[align(3)] + | ^ + error: `#[repr(align(...))]` is not supported on function items --> $DIR/malformed-fn-align.rs:21:8 | @@ -50,7 +82,7 @@ LL | #[repr(align(16))] | ^^^^^^^^^ error: `#[align(...)]` is not supported on struct items - --> $DIR/malformed-fn-align.rs:24:1 + --> $DIR/malformed-fn-align.rs:39:1 | LL | #[align(16)] | ^^^^^^^^^^^^ @@ -61,7 +93,31 @@ LL - #[align(16)] LL + #[repr(align(16))] | -error: aborting due to 7 previous errors +error: `#[align(...)]` should be applied to a function item + --> $DIR/malformed-fn-align.rs:42:1 + | +LL | #[align(32)] + | ^^^^^^^^^^^^ +LL | const FOO: i32 = 42; + | -------------------- not a function item + +error: `#[align(...)]` should be applied to a function item + --> $DIR/malformed-fn-align.rs:45:1 + | +LL | #[align(32)] + | ^^^^^^^^^^^^ +LL | mod test {} + | ----------- not a function item + +error: `#[align(...)]` should be applied to a function item + --> $DIR/malformed-fn-align.rs:48:1 + | +LL | #[align(32)] + | ^^^^^^^^^^^^ +LL | use ::std::iter; + | ---------------- not a function item + +error: aborting due to 15 previous errors Some errors have detailed explanations: E0539, E0589, E0805. For more information about an error, try `rustc --explain E0539`.