Skip to content

Commit a93c6ad

Browse files
committed
port attribute to the new parsing infrastructure
1 parent bec7474 commit a93c6ad

File tree

12 files changed

+268
-188
lines changed

12 files changed

+268
-188
lines changed

compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs

Lines changed: 104 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use rustc_feature::{AttributeTemplate, template};
2-
use rustc_hir::attrs::{AttributeKind, CoverageAttrKind, OptimizeAttr, UsedBy};
2+
use rustc_hir::attrs::{AttributeKind, CoverageAttrKind, OptimizeAttr, SanitizerSet, UsedBy};
33
use rustc_hir::{MethodKind, Target};
44
use rustc_session::parse::feature_err;
55
use rustc_span::{Span, Symbol, sym};
@@ -9,7 +9,7 @@ use super::{
99
NoArgsAttributeParser, OnDuplicate, SingleAttributeParser,
1010
};
1111
use crate::context::MaybeWarn::{Allow, Warn};
12-
use crate::context::{AcceptContext, AllowedTargets, FinalizeContext, Stage};
12+
use crate::context::{ALL_TARGETS, AcceptContext, AllowedTargets, FinalizeContext, Stage};
1313
use crate::parser::ArgParser;
1414
use crate::session_diagnostics::{NakedFunctionIncompatibleAttribute, NullOnExport};
1515

@@ -449,3 +449,105 @@ impl<S: Stage> CombineAttributeParser<S> for TargetFeatureParser {
449449
Warn(Target::MacroDef),
450450
]);
451451
}
452+
453+
pub(crate) struct SanitizeParser;
454+
455+
impl<S: Stage> SingleAttributeParser<S> for SanitizeParser {
456+
const PATH: &[Symbol] = &[sym::sanitize];
457+
458+
// FIXME: still checked in check_attrs.rs
459+
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
460+
461+
const TEMPLATE: AttributeTemplate = template!(List: &[
462+
r#"address = "on|off""#,
463+
r#"kernel_address = "on|off""#,
464+
r#"cfi = "on|off""#,
465+
r#"hwaddress = "on|off""#,
466+
r#"kcfi = "on|off""#,
467+
r#"memory = "on|off""#,
468+
r#"memtag = "on|off""#,
469+
r#"shadow_call_stack = "on|off""#,
470+
r#"thread = "on|off""#
471+
]);
472+
473+
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
474+
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
475+
476+
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
477+
let Some(list) = args.list() else {
478+
cx.expected_list(cx.attr_span);
479+
return None;
480+
};
481+
482+
let mut on_set = SanitizerSet::empty();
483+
let mut off_set = SanitizerSet::empty();
484+
485+
for item in list.mixed() {
486+
let Some(item) = item.meta_item() else {
487+
cx.expected_name_value(item.span(), None);
488+
continue;
489+
};
490+
491+
let path = item.path().word_sym();
492+
let Some(value) = item.args().name_value() else {
493+
cx.expected_name_value(item.span(), path);
494+
continue;
495+
};
496+
497+
let mut apply = |s: SanitizerSet| {
498+
let is_on = match value.value_as_str() {
499+
Some(sym::on) => true,
500+
Some(sym::off) => false,
501+
Some(_) => {
502+
cx.expected_specific_argument_strings(
503+
value.value_span,
504+
vec!["true", "false"],
505+
);
506+
return;
507+
}
508+
None => {
509+
cx.expected_string_literal(value.value_span, Some(value.value_as_lit()));
510+
return;
511+
}
512+
};
513+
514+
if is_on {
515+
on_set |= s;
516+
} else {
517+
off_set |= s;
518+
}
519+
};
520+
521+
match path {
522+
Some(sym::address) | Some(sym::kernel_address) => {
523+
apply(SanitizerSet::ADDRESS | SanitizerSet::KERNELADDRESS)
524+
}
525+
Some(sym::cfi) => apply(SanitizerSet::CFI),
526+
Some(sym::kcfi) => apply(SanitizerSet::KCFI),
527+
Some(sym::memory) => apply(SanitizerSet::MEMORY),
528+
Some(sym::memtag) => apply(SanitizerSet::MEMTAG),
529+
Some(sym::shadow_call_stack) => apply(SanitizerSet::SHADOWCALLSTACK),
530+
Some(sym::thread) => apply(SanitizerSet::THREAD),
531+
Some(sym::hwaddress) => apply(SanitizerSet::HWADDRESS),
532+
_ => {
533+
cx.expected_specific_argument_strings(
534+
item.path().span(),
535+
vec![
536+
"address",
537+
"cfi",
538+
"kcfi",
539+
"memory",
540+
"memtag",
541+
"shadow_call_stack",
542+
"thread",
543+
"hwaddress",
544+
],
545+
);
546+
continue;
547+
}
548+
}
549+
}
550+
551+
Some(AttributeKind::Sanitize { on_set, off_set, span: cx.attr_span })
552+
}
553+
}

compiler/rustc_attr_parsing/src/context.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use crate::attributes::allow_unstable::{
2222
use crate::attributes::body::CoroutineParser;
2323
use crate::attributes::codegen_attrs::{
2424
ColdParser, CoverageParser, ExportNameParser, NakedParser, NoMangleParser, OptimizeParser,
25-
TargetFeatureParser, TrackCallerParser, UsedParser,
25+
SanitizeParser, TargetFeatureParser, TrackCallerParser, UsedParser,
2626
};
2727
use crate::attributes::confusables::ConfusablesParser;
2828
use crate::attributes::deprecation::DeprecationParser;
@@ -187,6 +187,7 @@ attribute_parsers!(
187187
Single<RustcLayoutScalarValidRangeEnd>,
188188
Single<RustcLayoutScalarValidRangeStart>,
189189
Single<RustcObjectLifetimeDefaultParser>,
190+
Single<SanitizeParser>,
190191
Single<ShouldPanicParser>,
191192
Single<SkipDuringMethodDispatchParser>,
192193
Single<TransparencyParser>,

compiler/rustc_codegen_ssa/messages.ftl

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -171,9 +171,6 @@ codegen_ssa_invalid_monomorphization_unsupported_symbol = invalid monomorphizati
171171
172172
codegen_ssa_invalid_monomorphization_unsupported_symbol_of_size = invalid monomorphization of `{$name}` intrinsic: unsupported {$symbol} from `{$in_ty}` with element `{$in_elem}` of size `{$size}` to `{$ret_ty}`
173173
174-
codegen_ssa_invalid_sanitize = invalid argument for `sanitize`
175-
.note = expected one of: `address`, `kernel_address`, `cfi`, `hwaddress`, `kcfi`, `memory`, `memtag`, `shadow_call_stack`, or `thread`
176-
177174
codegen_ssa_invalid_windows_subsystem = invalid windows subsystem `{$subsystem}`, only `windows` and `console` are allowed
178175
179176
codegen_ssa_ld64_unimplemented_modifier = `as-needed` modifier not implemented yet for ld64

compiler/rustc_codegen_ssa/src/codegen_attrs.rs

Lines changed: 8 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,9 @@ fn process_builtin_attrs(
292292
codegen_fn_attrs.linkage = linkage;
293293
}
294294
}
295+
AttributeKind::Sanitize { span, .. } => {
296+
interesting_spans.sanitize = Some(*span);
297+
}
295298
_ => {}
296299
}
297300
}
@@ -309,7 +312,6 @@ fn process_builtin_attrs(
309312
codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR_ZEROED
310313
}
311314
sym::thread_local => codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL,
312-
sym::sanitize => interesting_spans.sanitize = Some(attr.span()),
313315
sym::instruction_set => {
314316
codegen_fn_attrs.instruction_set = parse_instruction_set_attr(tcx, attr)
315317
}
@@ -559,79 +561,9 @@ fn opt_trait_item(tcx: TyCtxt<'_>, def_id: DefId) -> Option<DefId> {
559561
}
560562
}
561563

562-
/// For an attr that has the `sanitize` attribute, read the list of
563-
/// disabled sanitizers. `current_attr` holds the information about
564-
/// previously parsed attributes.
565-
fn parse_sanitize_attr(
566-
tcx: TyCtxt<'_>,
567-
attr: &Attribute,
568-
current_attr: SanitizerSet,
569-
) -> SanitizerSet {
570-
let mut result = current_attr;
571-
if let Some(list) = attr.meta_item_list() {
572-
for item in list.iter() {
573-
let MetaItemInner::MetaItem(set) = item else {
574-
tcx.dcx().emit_err(errors::InvalidSanitize { span: attr.span() });
575-
break;
576-
};
577-
let segments = set.path.segments.iter().map(|x| x.ident.name).collect::<Vec<_>>();
578-
match segments.as_slice() {
579-
// Similar to clang, sanitize(address = ..) and
580-
// sanitize(kernel_address = ..) control both ASan and KASan
581-
// Source: https://reviews.llvm.org/D44981.
582-
[sym::address] | [sym::kernel_address] if set.value_str() == Some(sym::off) => {
583-
result |= SanitizerSet::ADDRESS | SanitizerSet::KERNELADDRESS
584-
}
585-
[sym::address] | [sym::kernel_address] if set.value_str() == Some(sym::on) => {
586-
result &= !SanitizerSet::ADDRESS;
587-
result &= !SanitizerSet::KERNELADDRESS;
588-
}
589-
[sym::cfi] if set.value_str() == Some(sym::off) => result |= SanitizerSet::CFI,
590-
[sym::cfi] if set.value_str() == Some(sym::on) => result &= !SanitizerSet::CFI,
591-
[sym::kcfi] if set.value_str() == Some(sym::off) => result |= SanitizerSet::KCFI,
592-
[sym::kcfi] if set.value_str() == Some(sym::on) => result &= !SanitizerSet::KCFI,
593-
[sym::memory] if set.value_str() == Some(sym::off) => {
594-
result |= SanitizerSet::MEMORY
595-
}
596-
[sym::memory] if set.value_str() == Some(sym::on) => {
597-
result &= !SanitizerSet::MEMORY
598-
}
599-
[sym::memtag] if set.value_str() == Some(sym::off) => {
600-
result |= SanitizerSet::MEMTAG
601-
}
602-
[sym::memtag] if set.value_str() == Some(sym::on) => {
603-
result &= !SanitizerSet::MEMTAG
604-
}
605-
[sym::shadow_call_stack] if set.value_str() == Some(sym::off) => {
606-
result |= SanitizerSet::SHADOWCALLSTACK
607-
}
608-
[sym::shadow_call_stack] if set.value_str() == Some(sym::on) => {
609-
result &= !SanitizerSet::SHADOWCALLSTACK
610-
}
611-
[sym::thread] if set.value_str() == Some(sym::off) => {
612-
result |= SanitizerSet::THREAD
613-
}
614-
[sym::thread] if set.value_str() == Some(sym::on) => {
615-
result &= !SanitizerSet::THREAD
616-
}
617-
[sym::hwaddress] if set.value_str() == Some(sym::off) => {
618-
result |= SanitizerSet::HWADDRESS
619-
}
620-
[sym::hwaddress] if set.value_str() == Some(sym::on) => {
621-
result &= !SanitizerSet::HWADDRESS
622-
}
623-
_ => {
624-
tcx.dcx().emit_err(errors::InvalidSanitize { span: attr.span() });
625-
}
626-
}
627-
}
628-
}
629-
result
630-
}
631-
632564
fn disabled_sanitizers_for(tcx: TyCtxt<'_>, did: LocalDefId) -> SanitizerSet {
633565
// Backtrack to the crate root.
634-
let disabled = match tcx.opt_local_parent(did) {
566+
let mut disabled = match tcx.opt_local_parent(did) {
635567
// Check the parent (recursively).
636568
Some(parent) => tcx.disabled_sanitizers_for(parent),
637569
// We reached the crate root without seeing an attribute, so
@@ -640,8 +572,10 @@ fn disabled_sanitizers_for(tcx: TyCtxt<'_>, did: LocalDefId) -> SanitizerSet {
640572
};
641573

642574
// Check for a sanitize annotation directly on this def.
643-
if let Some(attr) = tcx.get_attr(did, sym::sanitize) {
644-
return parse_sanitize_attr(tcx, attr, disabled);
575+
if let Some((on_set, off_set)) = find_attr!(tcx.get_all_attrs(did), AttributeKind::Sanitize {on_set, off_set, ..} => (on_set, off_set))
576+
{
577+
disabled &= !*on_set;
578+
disabled |= *off_set;
645579
}
646580
disabled
647581
}

compiler/rustc_codegen_ssa/src/errors.rs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1120,14 +1120,6 @@ impl IntoDiagArg for ExpectedPointerMutability {
11201120
}
11211121
}
11221122

1123-
#[derive(Diagnostic)]
1124-
#[diag(codegen_ssa_invalid_sanitize)]
1125-
#[note]
1126-
pub(crate) struct InvalidSanitize {
1127-
#[primary_span]
1128-
pub span: Span,
1129-
}
1130-
11311123
#[derive(Diagnostic)]
11321124
#[diag(codegen_ssa_target_feature_safe_trait)]
11331125
pub(crate) struct TargetFeatureSafeTrait {

compiler/rustc_hir/src/attrs/data_structures.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use rustc_macros::{Decodable, Encodable, HashStable_Generic, PrintAttribute};
66
use rustc_span::def_id::DefId;
77
use rustc_span::hygiene::Transparency;
88
use rustc_span::{Ident, Span, Symbol};
9+
pub use rustc_target::spec::SanitizerSet;
910
use thin_vec::ThinVec;
1011

1112
use crate::attrs::pretty_printing::PrintAttribute;
@@ -479,6 +480,9 @@ pub enum AttributeKind {
479480
/// Represents `#[rustc_object_lifetime_default]`.
480481
RustcObjectLifetimeDefault,
481482

483+
/// Represents `#[sanitize]`
484+
Sanitize { on_set: SanitizerSet, off_set: SanitizerSet, span: Span },
485+
482486
/// Represents `#[should_panic]`
483487
ShouldPanic { reason: Option<Symbol>, span: Span },
484488

compiler/rustc_hir/src/attrs/encode_cross_crate.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ impl AttributeKind {
7373
RustcLayoutScalarValidRangeEnd(..) => Yes,
7474
RustcLayoutScalarValidRangeStart(..) => Yes,
7575
RustcObjectLifetimeDefault => No,
76+
Sanitize { .. } => No,
7677
ShouldPanic { .. } => No,
7778
SkipDuringMethodDispatch { .. } => No,
7879
SpecializationTrait(..) => No,

compiler/rustc_hir/src/attrs/pretty_printing.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use rustc_ast::{AttrStyle, IntTy, UintTy};
66
use rustc_ast_pretty::pp::Printer;
77
use rustc_span::hygiene::Transparency;
88
use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol};
9+
use rustc_target::spec::SanitizerSet;
910
use thin_vec::ThinVec;
1011

1112
/// This trait is used to print attributes in `rustc_hir_pretty`.
@@ -146,4 +147,14 @@ macro_rules! print_tup {
146147
print_tup!(A B C D E F G H);
147148
print_skip!(Span, (), ErrorGuaranteed);
148149
print_disp!(u16, bool, NonZero<u32>);
149-
print_debug!(Symbol, Ident, UintTy, IntTy, Align, AttrStyle, CommentKind, Transparency);
150+
print_debug!(
151+
Symbol,
152+
Ident,
153+
UintTy,
154+
IntTy,
155+
Align,
156+
AttrStyle,
157+
CommentKind,
158+
Transparency,
159+
SanitizerSet,
160+
);

0 commit comments

Comments
 (0)