summary refs log tree commit diff
path: root/compiler/rustc_attr_parsing
diff options
context:
space:
mode:
authorFolkert de Vries <folkert@folkertdev.nl>2025-06-09 20:08:52 +0200
committerFolkert de Vries <folkert@folkertdev.nl>2025-06-18 12:37:08 +0200
commit1fdf2b562070ec98c5b32ee67b8c6d8145127a6e (patch)
treeb03e6e19001df8984537f2843f246c8453c1bcf6 /compiler/rustc_attr_parsing
parent1bb335244c311a07cee165c28c553c869e6f64a9 (diff)
downloadrust-1fdf2b562070ec98c5b32ee67b8c6d8145127a6e.tar.gz
rust-1fdf2b562070ec98c5b32ee67b8c6d8145127a6e.zip
add `#[align]` attribute
Right now it's used for functions with `fn_align`, in the future it will
get more uses (statics, struct fields, etc.)
Diffstat (limited to 'compiler/rustc_attr_parsing')
-rw-r--r--compiler/rustc_attr_parsing/messages.ftl3
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/repr.rs58
-rw-r--r--compiler/rustc_attr_parsing/src/context.rs3
-rw-r--r--compiler/rustc_attr_parsing/src/session_diagnostics.rs8
4 files changed, 69 insertions, 3 deletions
diff --git a/compiler/rustc_attr_parsing/messages.ftl b/compiler/rustc_attr_parsing/messages.ftl
index b9b386635f6..0891afc003e 100644
--- a/compiler/rustc_attr_parsing/messages.ftl
+++ b/compiler/rustc_attr_parsing/messages.ftl
@@ -44,6 +44,9 @@ attr_parsing_incorrect_repr_format_packed_expect_integer =
 attr_parsing_incorrect_repr_format_packed_one_or_zero_arg =
     incorrect `repr(packed)` attribute format: `packed` takes exactly one parenthesized argument, or no parentheses at all
 
+attr_parsing_invalid_alignment_value =
+    invalid alignment value: {$error_part}
+
 attr_parsing_invalid_issue_string =
     `issue` must be a non-zero numeric string or "none"
     .must_not_be_zero = `issue` must not be "0", use "none" instead
diff --git a/compiler/rustc_attr_parsing/src/attributes/repr.rs b/compiler/rustc_attr_parsing/src/attributes/repr.rs
index ae9e7871874..c9f9f34bdb7 100644
--- a/compiler/rustc_attr_parsing/src/attributes/repr.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/repr.rs
@@ -4,7 +4,7 @@ use rustc_attr_data_structures::{AttributeKind, IntType, ReprAttr};
 use rustc_feature::{AttributeTemplate, template};
 use rustc_span::{DUMMY_SP, Span, Symbol, sym};
 
-use super::{CombineAttributeParser, ConvertFn};
+use super::{AcceptMapping, AttributeParser, CombineAttributeParser, ConvertFn, FinalizeContext};
 use crate::context::{AcceptContext, Stage};
 use crate::parser::{ArgParser, MetaItemListParser, MetaItemParser};
 use crate::session_diagnostics;
@@ -203,7 +203,7 @@ fn parse_repr_align<S: Stage>(
                 });
             }
             Align => {
-                cx.dcx().emit_err(session_diagnostics::IncorrectReprFormatAlignOneArg {
+                cx.emit_err(session_diagnostics::IncorrectReprFormatAlignOneArg {
                     span: param_span,
                 });
             }
@@ -266,3 +266,57 @@ fn parse_alignment(node: &LitKind) -> Result<Align, &'static str> {
         Err("not an unsuffixed integer")
     }
 }
+
+/// Parse #[align(N)].
+#[derive(Default)]
+pub(crate) struct AlignParser(Option<(Align, Span)>);
+
+impl AlignParser {
+    const PATH: &'static [Symbol] = &[sym::align];
+    const TEMPLATE: AttributeTemplate = template!(Word, List: "<alignment in bytes>");
+
+    fn parse<'c, S: Stage>(
+        &mut self,
+        cx: &'c mut AcceptContext<'_, '_, S>,
+        args: &'c ArgParser<'_>,
+    ) {
+        match args {
+            ArgParser::NoArgs | ArgParser::NameValue(_) => {
+                cx.expected_list(cx.attr_span);
+            }
+            ArgParser::List(list) => {
+                let Some(align) = list.single() else {
+                    cx.expected_single_argument(list.span);
+                    return;
+                };
+
+                let Some(lit) = align.lit() else {
+                    cx.emit_err(session_diagnostics::IncorrectReprFormatExpectInteger {
+                        span: align.span(),
+                    });
+
+                    return;
+                };
+
+                match parse_alignment(&lit.kind) {
+                    Ok(literal) => self.0 = Ord::max(self.0, Some((literal, cx.attr_span))),
+                    Err(message) => {
+                        cx.emit_err(session_diagnostics::InvalidAlignmentValue {
+                            span: lit.span,
+                            error_part: message,
+                        });
+                    }
+                }
+            }
+        }
+    }
+}
+
+impl<S: Stage> AttributeParser<S> for AlignParser {
+    const ATTRIBUTES: AcceptMapping<Self, S> = &[(Self::PATH, Self::TEMPLATE, Self::parse)];
+
+    fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
+        let (align, span) = self.0?;
+        Some(AttributeKind::Align { align, span })
+    }
+}
diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs
index 51c1760da30..d7570634c1f 100644
--- a/compiler/rustc_attr_parsing/src/context.rs
+++ b/compiler/rustc_attr_parsing/src/context.rs
@@ -19,7 +19,7 @@ use crate::attributes::confusables::ConfusablesParser;
 use crate::attributes::deprecation::DeprecationParser;
 use crate::attributes::inline::{InlineParser, RustcForceInlineParser};
 use crate::attributes::lint_helpers::AsPtrParser;
-use crate::attributes::repr::ReprParser;
+use crate::attributes::repr::{AlignParser, ReprParser};
 use crate::attributes::stability::{
     BodyStabilityParser, ConstStabilityIndirectParser, ConstStabilityParser, StabilityParser,
 };
@@ -90,6 +90,7 @@ macro_rules! attribute_parsers {
 attribute_parsers!(
     pub(crate) static ATTRIBUTE_PARSERS = [
         // tidy-alphabetical-start
+        AlignParser,
         BodyStabilityParser,
         ConfusablesParser,
         ConstStabilityParser,
diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs
index 57ac92a0ca1..337921a318c 100644
--- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs
+++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs
@@ -451,6 +451,14 @@ pub(crate) struct EmptyConfusables {
 }
 
 #[derive(Diagnostic)]
+#[diag(attr_parsing_invalid_alignment_value, code = E0589)]
+pub(crate) struct InvalidAlignmentValue {
+    #[primary_span]
+    pub span: Span,
+    pub error_part: &'static str,
+}
+
+#[derive(Diagnostic)]
 #[diag(attr_parsing_repr_ident, code = E0565)]
 pub(crate) struct ReprIdent {
     #[primary_span]