about summary refs log tree commit diff
path: root/compiler/rustc_attr_parsing
diff options
context:
space:
mode:
authorGuillaume Gomez <guillaume1.gomez@gmail.com>2025-08-14 11:39:39 +0200
committerGitHub <noreply@github.com>2025-08-14 11:39:39 +0200
commit44d3217c20ab0bdbbc9bd2edfc6810e6e605369e (patch)
treecd1b6f5e01ab44d4842ae7a329cf49eb430df7e4 /compiler/rustc_attr_parsing
parentf493f804d73c651e09ceccdd700f25d55077e009 (diff)
parentd435197afcb019a692aa1faf8b7169e167ac1de8 (diff)
downloadrust-44d3217c20ab0bdbbc9bd2edfc6810e6e605369e.tar.gz
rust-44d3217c20ab0bdbbc9bd2edfc6810e6e605369e.zip
Rollup merge of #145323 - scrabsha:push-pqwvmznzzmpr, r=jdonszelmann
Port the `#[linkage]` attribute to the new attribute system

r? `@jdonszelmann`
Diffstat (limited to 'compiler/rustc_attr_parsing')
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/link_attrs.rs76
-rw-r--r--compiler/rustc_attr_parsing/src/context.rs3
2 files changed, 77 insertions, 2 deletions
diff --git a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs
index d406c30b83e..e4ced2e37c5 100644
--- a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs
@@ -1,6 +1,6 @@
 use rustc_feature::{AttributeTemplate, template};
-use rustc_hir::attrs::AttributeKind;
 use rustc_hir::attrs::AttributeKind::{LinkName, LinkOrdinal, LinkSection};
+use rustc_hir::attrs::{AttributeKind, Linkage};
 use rustc_span::{Span, Symbol, sym};
 
 use crate::attributes::{
@@ -129,3 +129,77 @@ impl<S: Stage> SingleAttributeParser<S> for LinkOrdinalParser {
         Some(LinkOrdinal { ordinal, span: cx.attr_span })
     }
 }
+
+pub(crate) struct LinkageParser;
+
+impl<S: Stage> SingleAttributeParser<S> for LinkageParser {
+    const PATH: &[Symbol] = &[sym::linkage];
+
+    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
+
+    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
+
+    const TEMPLATE: AttributeTemplate = template!(NameValueStr: [
+        "available_externally",
+        "common",
+        "extern_weak",
+        "external",
+        "internal",
+        "linkonce",
+        "linkonce_odr",
+        "weak",
+        "weak_odr",
+    ]);
+
+    fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
+        let Some(name_value) = args.name_value() else {
+            cx.expected_name_value(cx.attr_span, Some(sym::linkage));
+            return None;
+        };
+
+        let Some(value) = name_value.value_as_str() else {
+            cx.expected_string_literal(name_value.value_span, Some(name_value.value_as_lit()));
+            return None;
+        };
+
+        // Use the names from src/llvm/docs/LangRef.rst here. Most types are only
+        // applicable to variable declarations and may not really make sense for
+        // Rust code in the first place but allow them anyway and trust that the
+        // user knows what they're doing. Who knows, unanticipated use cases may pop
+        // up in the future.
+        //
+        // ghost, dllimport, dllexport and linkonce_odr_autohide are not supported
+        // and don't have to be, LLVM treats them as no-ops.
+        let linkage = match value {
+            sym::available_externally => Linkage::AvailableExternally,
+            sym::common => Linkage::Common,
+            sym::extern_weak => Linkage::ExternalWeak,
+            sym::external => Linkage::External,
+            sym::internal => Linkage::Internal,
+            sym::linkonce => Linkage::LinkOnceAny,
+            sym::linkonce_odr => Linkage::LinkOnceODR,
+            sym::weak => Linkage::WeakAny,
+            sym::weak_odr => Linkage::WeakODR,
+
+            _ => {
+                cx.expected_specific_argument(
+                    name_value.value_span,
+                    vec![
+                        "available_externally",
+                        "common",
+                        "extern_weak",
+                        "external",
+                        "internal",
+                        "linkonce",
+                        "linkonce_odr",
+                        "weak",
+                        "weak_odr",
+                    ],
+                );
+                return None;
+            }
+        };
+
+        Some(AttributeKind::Linkage(linkage, cx.attr_span))
+    }
+}
diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs
index 1420753a44e..6045a8b28a2 100644
--- a/compiler/rustc_attr_parsing/src/context.rs
+++ b/compiler/rustc_attr_parsing/src/context.rs
@@ -27,7 +27,7 @@ use crate::attributes::dummy::DummyParser;
 use crate::attributes::inline::{InlineParser, RustcForceInlineParser};
 use crate::attributes::link_attrs::{
     ExportStableParser, FfiConstParser, FfiPureParser, LinkNameParser, LinkOrdinalParser,
-    LinkSectionParser, StdInternalSymbolParser,
+    LinkSectionParser, LinkageParser, StdInternalSymbolParser,
 };
 use crate::attributes::lint_helpers::{
     AsPtrParser, AutomaticallyDerivedParser, PassByValueParser, PubTransparentParser,
@@ -167,6 +167,7 @@ attribute_parsers!(
         Single<LinkNameParser>,
         Single<LinkOrdinalParser>,
         Single<LinkSectionParser>,
+        Single<LinkageParser>,
         Single<MustUseParser>,
         Single<OptimizeParser>,
         Single<PathAttributeParser>,