about summary refs log tree commit diff
path: root/compiler/rustc_passes/src
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_passes/src')
-rw-r--r--compiler/rustc_passes/src/check_attr.rs44
-rw-r--r--compiler/rustc_passes/src/errors.rs17
2 files changed, 60 insertions, 1 deletions
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 0e28c51e981..e51f3657eaa 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -261,6 +261,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                         [sym::no_sanitize, ..] => {
                             self.check_no_sanitize(attr, span, target)
                         }
+                        [sym::sanitize, ..] => {
+                            self.check_sanitize(attr, span, target)
+                        }
                         [sym::thread_local, ..] => self.check_thread_local(attr, span, target),
                         [sym::doc, ..] => self.check_doc_attrs(
                             attr,
@@ -518,6 +521,46 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
         }
     }
 
+    /// Checks that the `#[sanitize(..)]` attribute is applied to a
+    /// function/closure/method, or to an impl block or module.
+    fn check_sanitize(&self, attr: &Attribute, target_span: Span, target: Target) {
+        let mut not_fn_impl_mod = None;
+        let mut no_body = None;
+
+        if let Some(list) = attr.meta_item_list() {
+            for item in list.iter() {
+                let MetaItemInner::MetaItem(set) = item else {
+                    return;
+                };
+                let segments = set.path.segments.iter().map(|x| x.ident.name).collect::<Vec<_>>();
+                match target {
+                    Target::Fn
+                    | Target::Closure
+                    | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent)
+                    | Target::Impl { .. }
+                    | Target::Mod => return,
+                    Target::Static if matches!(segments.as_slice(), [sym::address]) => return,
+
+                    // These are "functions", but they aren't allowed because they don't
+                    // have a body, so the usual explanation would be confusing.
+                    Target::Method(MethodKind::Trait { body: false }) | Target::ForeignFn => {
+                        no_body = Some(target_span);
+                    }
+
+                    _ => {
+                        not_fn_impl_mod = Some(target_span);
+                    }
+                }
+            }
+            self.dcx().emit_err(errors::SanitizeAttributeNotAllowed {
+                attr_span: attr.span(),
+                not_fn_impl_mod,
+                no_body,
+                help: (),
+            });
+        }
+    }
+
     /// Checks if `#[naked]` is applied to a function definition.
     fn check_naked(&self, hir_id: HirId, target: Target) {
         match target {
@@ -561,7 +604,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
             }
         }
     }
-
     /// Checks if `#[collapse_debuginfo]` is applied to a macro.
     fn check_collapse_debuginfo(&self, attr: &Attribute, span: Span, target: Target) {
         match target {
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index c5d5155d0e5..bd608dc2fee 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -1499,6 +1499,23 @@ pub(crate) struct NoSanitize<'a> {
     pub attr_str: &'a str,
 }
 
+/// "sanitize attribute not allowed here"
+#[derive(Diagnostic)]
+#[diag(passes_sanitize_attribute_not_allowed)]
+pub(crate) struct SanitizeAttributeNotAllowed {
+    #[primary_span]
+    pub attr_span: Span,
+    /// "not a function, impl block, or module"
+    #[label(passes_not_fn_impl_mod)]
+    pub not_fn_impl_mod: Option<Span>,
+    /// "function has no body"
+    #[label(passes_no_body)]
+    pub no_body: Option<Span>,
+    /// "sanitize attribute can be applied to a function (with body), impl block, or module"
+    #[help]
+    pub help: (),
+}
+
 // FIXME(jdonszelmann): move back to rustc_attr
 #[derive(Diagnostic)]
 #[diag(passes_rustc_const_stable_indirect_pairing)]