about summary refs log tree commit diff
path: root/compiler/rustc_attr_parsing/src
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_attr_parsing/src')
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs63
-rw-r--r--compiler/rustc_attr_parsing/src/context.rs3
-rw-r--r--compiler/rustc_attr_parsing/src/lints.rs12
3 files changed, 77 insertions, 1 deletions
diff --git a/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs
index 180130c7be4..849141c34f7 100644
--- a/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs
@@ -1,3 +1,4 @@
+use rustc_ast::AttrStyle;
 use rustc_errors::DiagArgValue;
 use rustc_hir::attrs::MacroUseArgs;
 
@@ -133,3 +134,65 @@ impl<S: Stage> NoArgsAttributeParser<S> for AllowInternalUnsafeParser {
     ]);
     const CREATE: fn(Span) -> AttributeKind = |span| AttributeKind::AllowInternalUnsafe(span);
 }
+
+pub(crate) struct MacroExportParser;
+
+impl<S: Stage> SingleAttributeParser<S> for MacroExportParser {
+    const PATH: &[Symbol] = &[sym::macro_export];
+    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
+    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
+    const TEMPLATE: AttributeTemplate = template!(Word, List: &["local_inner_macros"]);
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[
+        Allow(Target::MacroDef),
+        Error(Target::WherePredicate),
+        Error(Target::Crate),
+    ]);
+
+    fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
+        let suggestions = || {
+            <Self as SingleAttributeParser<S>>::TEMPLATE
+                .suggestions(AttrStyle::Inner, "macro_export")
+        };
+        let local_inner_macros = match args {
+            ArgParser::NoArgs => false,
+            ArgParser::List(list) => {
+                let Some(l) = list.single() else {
+                    let span = cx.attr_span;
+                    cx.emit_lint(
+                        AttributeLintKind::InvalidMacroExportArguments {
+                            suggestions: suggestions(),
+                        },
+                        span,
+                    );
+                    return None;
+                };
+                match l.meta_item().and_then(|i| i.path().word_sym()) {
+                    Some(sym::local_inner_macros) => true,
+                    _ => {
+                        let span = cx.attr_span;
+                        cx.emit_lint(
+                            AttributeLintKind::InvalidMacroExportArguments {
+                                suggestions: suggestions(),
+                            },
+                            span,
+                        );
+                        return None;
+                    }
+                }
+            }
+            ArgParser::NameValue(_) => {
+                let span = cx.attr_span;
+                let suggestions = suggestions();
+                cx.emit_err(IllFormedAttributeInputLint {
+                    num_suggestions: suggestions.len(),
+                    suggestions: DiagArgValue::StrListSepByAnd(
+                        suggestions.into_iter().map(|s| format!("`{s}`").into()).collect(),
+                    ),
+                    span,
+                });
+                return None;
+            }
+        };
+        Some(AttributeKind::MacroExport { span: cx.attr_span, local_inner_macros })
+    }
+}
diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs
index ee5b7322b02..4c32bb87a24 100644
--- a/compiler/rustc_attr_parsing/src/context.rs
+++ b/compiler/rustc_attr_parsing/src/context.rs
@@ -40,7 +40,7 @@ use crate::attributes::lint_helpers::{
 };
 use crate::attributes::loop_match::{ConstContinueParser, LoopMatchParser};
 use crate::attributes::macro_attrs::{
-    AllowInternalUnsafeParser, MacroEscapeParser, MacroUseParser,
+    AllowInternalUnsafeParser, MacroEscapeParser, MacroExportParser, MacroUseParser,
 };
 use crate::attributes::must_use::MustUseParser;
 use crate::attributes::no_implicit_prelude::NoImplicitPreludeParser;
@@ -183,6 +183,7 @@ attribute_parsers!(
         Single<LinkOrdinalParser>,
         Single<LinkSectionParser>,
         Single<LinkageParser>,
+        Single<MacroExportParser>,
         Single<MoveSizeLimitParser>,
         Single<MustUseParser>,
         Single<ObjcClassParser>,
diff --git a/compiler/rustc_attr_parsing/src/lints.rs b/compiler/rustc_attr_parsing/src/lints.rs
index b1a971eec32..ab8ba0daf1f 100644
--- a/compiler/rustc_attr_parsing/src/lints.rs
+++ b/compiler/rustc_attr_parsing/src/lints.rs
@@ -31,6 +31,18 @@ pub fn emit_attribute_lint<L: LintEmitter>(lint: &AttributeLint<L::Id>, lint_emi
                 },
             );
         }
+        AttributeLintKind::InvalidMacroExportArguments { suggestions } => lint_emitter
+            .emit_node_span_lint(
+                rustc_session::lint::builtin::INVALID_MACRO_EXPORT_ARGUMENTS,
+                *id,
+                *span,
+                session_diagnostics::IllFormedAttributeInput {
+                    num_suggestions: suggestions.len(),
+                    suggestions: DiagArgValue::StrListSepByAnd(
+                        suggestions.into_iter().map(|s| format!("`{s}`").into()).collect(),
+                    ),
+                },
+            ),
         AttributeLintKind::EmptyAttribute { first_span } => lint_emitter.emit_node_span_lint(
             rustc_session::lint::builtin::UNUSED_ATTRIBUTES,
             *id,