diff options
Diffstat (limited to 'compiler/rustc_passes/src')
| -rw-r--r-- | compiler/rustc_passes/src/check_attr.rs | 44 | ||||
| -rw-r--r-- | compiler/rustc_passes/src/errors.rs | 17 |
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)] |
