diff --git a/clippy_lints/src/undocumented_unsafe_blocks.rs b/clippy_lints/src/undocumented_unsafe_blocks.rs index 59c3d42b3538..ac13a309e7b8 100644 --- a/clippy_lints/src/undocumented_unsafe_blocks.rs +++ b/clippy_lints/src/undocumented_unsafe_blocks.rs @@ -48,6 +48,7 @@ impl LateLintPass<'_> for UndocumentedUnsafeBlocks { if block.rules == BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided) && !in_external_macro(cx.tcx.sess, block.span) && !is_lint_allowed(cx, UNDOCUMENTED_UNSAFE_BLOCKS, block.hir_id) + && !is_unsafe_from_proc_macro(cx, block) && !block_has_safety_comment(cx, block) { let source_map = cx.tcx.sess.source_map(); @@ -69,6 +70,17 @@ impl LateLintPass<'_> for UndocumentedUnsafeBlocks { } } +fn is_unsafe_from_proc_macro(cx: &LateContext<'_>, block: &Block<'_>) -> bool { + let source_map = cx.sess().source_map(); + let file_pos = source_map.lookup_byte_offset(block.span.lo()); + file_pos + .sf + .src + .as_deref() + .and_then(|src| src.get(file_pos.pos.to_usize()..)) + .map_or(true, |src| !src.starts_with("unsafe")) +} + /// Checks if the lines immediately preceding the block contain a safety comment. fn block_has_safety_comment(cx: &LateContext<'_>, block: &Block<'_>) -> bool { // This intentionally ignores text before the start of a function so something like: diff --git a/tests/ui/auxiliary/proc_macro_unsafe.rs b/tests/ui/auxiliary/proc_macro_unsafe.rs new file mode 100644 index 000000000000..3c40f77469b8 --- /dev/null +++ b/tests/ui/auxiliary/proc_macro_unsafe.rs @@ -0,0 +1,18 @@ +// compile-flags: --emit=link +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::{Delimiter, Group, Ident, TokenStream, TokenTree}; + +#[proc_macro] +pub fn unsafe_block(input: TokenStream) -> TokenStream { + let span = input.into_iter().next().unwrap().span(); + TokenStream::from_iter([TokenTree::Ident(Ident::new("unsafe", span)), { + let mut group = Group::new(Delimiter::Brace, TokenStream::new()); + group.set_span(span); + TokenTree::Group(group) + }]) +} diff --git a/tests/ui/undocumented_unsafe_blocks.rs b/tests/ui/undocumented_unsafe_blocks.rs index fcfb49dcdd44..80fb198ab538 100644 --- a/tests/ui/undocumented_unsafe_blocks.rs +++ b/tests/ui/undocumented_unsafe_blocks.rs @@ -1,5 +1,9 @@ +// aux-build:proc_macro_unsafe.rs + #![warn(clippy::undocumented_unsafe_blocks)] +extern crate proc_macro_unsafe; + // Valid comments fn nested_local() { @@ -241,6 +245,10 @@ fn in_multiline_macro_call(x: *const u32) { ); } +fn from_proc_macro() { + proc_macro_unsafe::unsafe_block!(token); +} + // Invalid comments fn no_comment() { diff --git a/tests/ui/undocumented_unsafe_blocks.stderr b/tests/ui/undocumented_unsafe_blocks.stderr index 4f5c1111c7e3..746bbe2f1414 100644 --- a/tests/ui/undocumented_unsafe_blocks.stderr +++ b/tests/ui/undocumented_unsafe_blocks.stderr @@ -1,5 +1,5 @@ error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:247:5 + --> $DIR/undocumented_unsafe_blocks.rs:255:5 | LL | unsafe {} | ^^^^^^^^^ @@ -8,7 +8,7 @@ LL | unsafe {} = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:251:14 + --> $DIR/undocumented_unsafe_blocks.rs:259:14 | LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; | ^^^^^^^^^^^^^ @@ -16,7 +16,7 @@ LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:251:29 + --> $DIR/undocumented_unsafe_blocks.rs:259:29 | LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; | ^^^^^^^^^^^^^ @@ -24,7 +24,7 @@ LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:251:48 + --> $DIR/undocumented_unsafe_blocks.rs:259:48 | LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; | ^^^^^^^^^^^^^ @@ -32,7 +32,7 @@ LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:255:18 + --> $DIR/undocumented_unsafe_blocks.rs:263:18 | LL | let _ = (42, unsafe {}, "test", unsafe {}); | ^^^^^^^^^ @@ -40,7 +40,7 @@ LL | let _ = (42, unsafe {}, "test", unsafe {}); = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:255:37 + --> $DIR/undocumented_unsafe_blocks.rs:263:37 | LL | let _ = (42, unsafe {}, "test", unsafe {}); | ^^^^^^^^^ @@ -48,7 +48,7 @@ LL | let _ = (42, unsafe {}, "test", unsafe {}); = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:259:14 + --> $DIR/undocumented_unsafe_blocks.rs:267:14 | LL | let _ = *unsafe { &42 }; | ^^^^^^^^^^^^^^ @@ -56,7 +56,7 @@ LL | let _ = *unsafe { &42 }; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:264:19 + --> $DIR/undocumented_unsafe_blocks.rs:272:19 | LL | let _ = match unsafe {} { | ^^^^^^^^^ @@ -64,7 +64,7 @@ LL | let _ = match unsafe {} { = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:270:14 + --> $DIR/undocumented_unsafe_blocks.rs:278:14 | LL | let _ = &unsafe {}; | ^^^^^^^^^ @@ -72,7 +72,7 @@ LL | let _ = &unsafe {}; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:274:14 + --> $DIR/undocumented_unsafe_blocks.rs:282:14 | LL | let _ = [unsafe {}; 5]; | ^^^^^^^^^ @@ -80,7 +80,7 @@ LL | let _ = [unsafe {}; 5]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:278:13 + --> $DIR/undocumented_unsafe_blocks.rs:286:13 | LL | let _ = unsafe {}; | ^^^^^^^^^ @@ -88,7 +88,7 @@ LL | let _ = unsafe {}; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:288:8 + --> $DIR/undocumented_unsafe_blocks.rs:296:8 | LL | t!(unsafe {}); | ^^^^^^^^^ @@ -96,7 +96,7 @@ LL | t!(unsafe {}); = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:294:13 + --> $DIR/undocumented_unsafe_blocks.rs:302:13 | LL | unsafe {} | ^^^^^^^^^ @@ -108,7 +108,7 @@ LL | t!(); = note: this error originates in the macro `t` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:302:5 + --> $DIR/undocumented_unsafe_blocks.rs:310:5 | LL | unsafe {} // SAFETY: | ^^^^^^^^^ @@ -116,7 +116,7 @@ LL | unsafe {} // SAFETY: = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:306:5 + --> $DIR/undocumented_unsafe_blocks.rs:314:5 | LL | unsafe { | ^^^^^^^^ @@ -124,7 +124,7 @@ LL | unsafe { = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:316:5 + --> $DIR/undocumented_unsafe_blocks.rs:324:5 | LL | unsafe {}; | ^^^^^^^^^ @@ -132,7 +132,7 @@ LL | unsafe {}; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> $DIR/undocumented_unsafe_blocks.rs:320:20 + --> $DIR/undocumented_unsafe_blocks.rs:328:20 | LL | println!("{}", unsafe { String::from_utf8_unchecked(vec![]) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^