about summary refs log tree commit diff
diff options
context:
space:
mode:
authorUrgau <urgau@numericable.fr>2025-05-03 15:19:08 +0200
committerUrgau <urgau@numericable.fr>2025-05-03 16:10:25 +0200
commitf4e1ec111c016f1dbbedb2628a30e9ce20d8e5f1 (patch)
tree0243040b5f256cff19c666c10160985396e31b7a
parent74a17fd049885f8b2c9d1e570a3afea364415d84 (diff)
downloadrust-f4e1ec111c016f1dbbedb2628a30e9ce20d8e5f1.tar.gz
rust-f4e1ec111c016f1dbbedb2628a30e9ce20d8e5f1.zip
Report the `unsafe_attr_outside_unsafe` lint at the closest node
-rw-r--r--compiler/rustc_ast_passes/src/ast_validation.rs2
-rw-r--r--compiler/rustc_expand/src/config.rs7
-rw-r--r--compiler/rustc_expand/src/expand.rs6
-rw-r--r--compiler/rustc_parse/src/validate_attr.rs16
-rw-r--r--tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-allow.rs16
5 files changed, 39 insertions, 8 deletions
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index f57f06f37a7..9b64bcc6df4 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -828,7 +828,7 @@ fn validate_generic_param_order(dcx: DiagCtxtHandle<'_>, generics: &[GenericPara
 
 impl<'a> Visitor<'a> for AstValidator<'a> {
     fn visit_attribute(&mut self, attr: &Attribute) {
-        validate_attr::check_attr(&self.sess.psess, attr);
+        validate_attr::check_attr(&self.sess.psess, attr, self.lint_node_id);
     }
 
     fn visit_ty(&mut self, ty: &'a Ty) {
diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs
index 2df3281568b..02af26b0156 100644
--- a/compiler/rustc_expand/src/config.rs
+++ b/compiler/rustc_expand/src/config.rs
@@ -274,7 +274,12 @@ impl<'a> StripUnconfigured<'a> {
     /// is in the original source file. Gives a compiler error if the syntax of
     /// the attribute is incorrect.
     pub(crate) fn expand_cfg_attr(&self, cfg_attr: &Attribute, recursive: bool) -> Vec<Attribute> {
-        validate_attr::check_attribute_safety(&self.sess.psess, AttributeSafety::Normal, &cfg_attr);
+        validate_attr::check_attribute_safety(
+            &self.sess.psess,
+            AttributeSafety::Normal,
+            &cfg_attr,
+            ast::CRATE_NODE_ID,
+        );
 
         // A trace attribute left in AST in place of the original `cfg_attr` attribute.
         // It can later be used by lints or other diagnostics.
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index 1f430b0018f..d4853d1357f 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -1983,7 +1983,11 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
         let mut span: Option<Span> = None;
         while let Some(attr) = attrs.next() {
             rustc_ast_passes::feature_gate::check_attribute(attr, self.cx.sess, features);
-            validate_attr::check_attr(&self.cx.sess.psess, attr);
+            validate_attr::check_attr(
+                &self.cx.sess.psess,
+                attr,
+                self.cx.current_expansion.lint_node_id,
+            );
 
             let current_span = if let Some(sp) = span { sp.to(attr.span) } else { attr.span };
             span = Some(current_span);
diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs
index 6a1c2af48ed..aa29b24fe91 100644
--- a/compiler/rustc_parse/src/validate_attr.rs
+++ b/compiler/rustc_parse/src/validate_attr.rs
@@ -3,7 +3,8 @@
 use rustc_ast::token::Delimiter;
 use rustc_ast::tokenstream::DelimSpan;
 use rustc_ast::{
-    self as ast, AttrArgs, Attribute, DelimArgs, MetaItem, MetaItemInner, MetaItemKind, Safety,
+    self as ast, AttrArgs, Attribute, DelimArgs, MetaItem, MetaItemInner, MetaItemKind, NodeId,
+    Safety,
 };
 use rustc_errors::{Applicability, FatalError, PResult};
 use rustc_feature::{AttributeSafety, AttributeTemplate, BUILTIN_ATTRIBUTE_MAP, BuiltinAttribute};
@@ -15,7 +16,7 @@ use rustc_span::{Span, Symbol, sym};
 
 use crate::{errors, parse_in};
 
-pub fn check_attr(psess: &ParseSess, attr: &Attribute) {
+pub fn check_attr(psess: &ParseSess, attr: &Attribute, id: NodeId) {
     if attr.is_doc_comment() || attr.has_name(sym::cfg_trace) || attr.has_name(sym::cfg_attr_trace)
     {
         return;
@@ -26,7 +27,7 @@ pub fn check_attr(psess: &ParseSess, attr: &Attribute) {
 
     // All non-builtin attributes are considered safe
     let safety = attr_info.map(|x| x.safety).unwrap_or(AttributeSafety::Normal);
-    check_attribute_safety(psess, safety, attr);
+    check_attribute_safety(psess, safety, attr, id);
 
     // Check input tokens for built-in and key-value attributes.
     match attr_info {
@@ -154,7 +155,12 @@ fn is_attr_template_compatible(template: &AttributeTemplate, meta: &ast::MetaIte
     }
 }
 
-pub fn check_attribute_safety(psess: &ParseSess, safety: AttributeSafety, attr: &Attribute) {
+pub fn check_attribute_safety(
+    psess: &ParseSess,
+    safety: AttributeSafety,
+    attr: &Attribute,
+    id: NodeId,
+) {
     let attr_item = attr.get_normal_item();
 
     if let AttributeSafety::Unsafe { unsafe_since } = safety {
@@ -185,7 +191,7 @@ pub fn check_attribute_safety(psess: &ParseSess, safety: AttributeSafety, attr:
                 psess.buffer_lint(
                     UNSAFE_ATTR_OUTSIDE_UNSAFE,
                     path_span,
-                    ast::CRATE_NODE_ID,
+                    id,
                     BuiltinLintDiag::UnsafeAttrOutsideUnsafe {
                         attribute_name_span: path_span,
                         sugg_spans: (diag_span.shrink_to_lo(), diag_span.shrink_to_hi()),
diff --git a/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-allow.rs b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-allow.rs
new file mode 100644
index 00000000000..76fdce7e5cf
--- /dev/null
+++ b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-allow.rs
@@ -0,0 +1,16 @@
+//@ check-pass
+//@ edition: 2021
+//
+// Anti-regression test for https://github.com/rust-lang/rust/issues/140602
+// where the generated warning couldn't be allowed due too being attached to
+// the wrong AST node.
+
+#![deny(unsafe_attr_outside_unsafe)]
+
+#[allow(unsafe_attr_outside_unsafe)]
+mod generated {
+    #[no_mangle]
+    fn _generated_foo() {}
+}
+
+fn main() {}