Skip to content

Commit e9cae2b

Browse files
committed
Add error for invalid item of instruction_set
1 parent 730d5d4 commit e9cae2b

File tree

5 files changed

+97
-5
lines changed

5 files changed

+97
-5
lines changed

compiler/rustc_passes/messages.ftl

+4
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,10 @@ passes_coroutine_on_non_closure =
104104
attribute should be applied to closures
105105
.label = not a closure
106106
107+
passes_invalid_instruction_set =
108+
`[instruction_set]` attribute argument should be valid
109+
.label = `[instruction_set]` containes invalid argument
110+
107111
passes_coverage_not_fn_or_closure =
108112
attribute should be applied to a function definition or closure
109113
.label = not a function or closure

compiler/rustc_passes/src/check_attr.rs

+39-5
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,9 @@
44
//! conflicts between multiple such attributes attached to the same
55
//! item.
66
7-
use std::cell::Cell;
8-
use std::collections::hash_map::Entry;
9-
107
use rustc_ast::{
11-
ast, AttrKind, AttrStyle, Attribute, LitKind, MetaItemKind, MetaItemLit, NestedMetaItem,
8+
ast, token::TokenKind, tokenstream::TokenTree, AttrKind, AttrStyle, Attribute, LitKind,
9+
MetaItemKind, MetaItemLit, NestedMetaItem,
1210
};
1311
use rustc_data_structures::fx::FxHashMap;
1412
use rustc_errors::{Applicability, DiagCtxtHandle, IntoDiagArg, MultiSpan, StashKey};
@@ -38,6 +36,8 @@ use rustc_target::spec::abi::Abi;
3836
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
3937
use rustc_trait_selection::infer::{TyCtxtInferExt, ValuePairs};
4038
use rustc_trait_selection::traits::ObligationCtxt;
39+
use std::cell::Cell;
40+
use std::collections::hash_map::Entry;
4141
use tracing::debug;
4242

4343
use crate::{errors, fluent_generated as fluent};
@@ -243,6 +243,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
243243
[sym::coroutine, ..] => {
244244
self.check_coroutine(attr, target);
245245
}
246+
[sym::instruction_set, ..] => {
247+
self.check_instruction_set(attr, item);
248+
}
246249
[
247250
// ok
248251
sym::allow
@@ -260,7 +263,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
260263
| sym::omit_gdb_pretty_printer_section // FIXME(omit_gdb_pretty_printer_section)
261264
| sym::used // handled elsewhere to restrict to static items
262265
| sym::repr // handled elsewhere to restrict to type decls items
263-
| sym::instruction_set // broken on stable!!!
264266
| sym::windows_subsystem // broken on stable!!!
265267
| sym::patchable_function_entry // FIXME(patchable_function_entry)
266268
| sym::deprecated_safe // FIXME(deprecated_safe)
@@ -2349,6 +2351,38 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
23492351
}
23502352
}
23512353
}
2354+
2355+
fn check_instruction_set(&self, attr: &Attribute, _item: Option<ItemLike<'_>>) {
2356+
if let AttrKind::Normal(ref p) = attr.kind {
2357+
let inner_tokens = p.item.args.inner_tokens();
2358+
let mut tokens = inner_tokens.trees();
2359+
2360+
// Valid item for `instruction_set()` is:
2361+
// - arm::a32
2362+
// - arm::t32
2363+
let valid_attribute = match (tokens.next(), tokens.next(), tokens.next()) {
2364+
(
2365+
Some(TokenTree::Token(first_token, _)),
2366+
Some(TokenTree::Token(second_token, _)),
2367+
Some(TokenTree::Token(third_token, _)),
2368+
) => match (first_token.ident(), second_token.kind.clone(), third_token.ident()) {
2369+
(Some(first_ident), TokenKind::PathSep, Some(third_ident))
2370+
if first_ident.0.name == sym::arm =>
2371+
{
2372+
third_ident.0.name == sym::a32 || third_ident.0.name == sym::t32
2373+
}
2374+
_ => false,
2375+
},
2376+
_ => false,
2377+
};
2378+
2379+
if !valid_attribute {
2380+
self.dcx().emit_err(errors::InvalidInstructionSet { span: attr.span });
2381+
} else {
2382+
return;
2383+
}
2384+
}
2385+
}
23522386
}
23532387

23542388
impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> {

compiler/rustc_passes/src/errors.rs

+7
Original file line numberDiff line numberDiff line change
@@ -643,6 +643,13 @@ pub struct CoroutineOnNonClosure {
643643
pub span: Span,
644644
}
645645

646+
#[derive(Diagnostic)]
647+
#[diag(passes_invalid_instruction_set)]
648+
pub struct InvalidInstructionSet {
649+
#[primary_span]
650+
pub span: Span,
651+
}
652+
646653
#[derive(Diagnostic)]
647654
#[diag(passes_empty_confusables)]
648655
pub(crate) struct EmptyConfusables {
+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#![feature(stmt_expr_attributes)]
2+
3+
#[instruction_set(arm::a32)]
4+
type ValidA = ();
5+
6+
#[instruction_set(arm::t32)]
7+
type ValidB = ();
8+
9+
#[instruction_set(asdfasdf)] //~ ERROR `[instruction_set]` attribute argument should be valid
10+
type InvalidA = ();
11+
12+
#[instruction_set(asdfasdf)] //~ ERROR `[instruction_set]` attribute argument should be valid
13+
mod InvalidB {}
14+
15+
#[instruction_set(asdfasdf)] //~ ERROR `[instruction_set]` attribute argument should be valid
16+
struct InvalidC;
17+
18+
#[instruction_set(asdfasdf)] //~ ERROR `[instruction_set]` attribute argument should be valid
19+
impl InvalidC {}
20+
21+
fn main() {}
+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
error: `[instruction_set]` attribute argument should be valid
2+
--> $DIR/instruction-set.rs:9:1
3+
|
4+
LL | #[instruction_set(asdfasdf)]
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
7+
error: `[instruction_set]` attribute argument should be valid
8+
--> $DIR/instruction-set.rs:12:1
9+
|
10+
LL | #[instruction_set(asdfasdf)]
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
12+
13+
error: `[instruction_set]` attribute argument should be valid
14+
--> $DIR/instruction-set.rs:15:1
15+
|
16+
LL | #[instruction_set(asdfasdf)]
17+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
18+
19+
error: `[instruction_set]` attribute argument should be valid
20+
--> $DIR/instruction-set.rs:18:1
21+
|
22+
LL | #[instruction_set(asdfasdf)]
23+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
24+
25+
error: aborting due to 4 previous errors
26+

0 commit comments

Comments
 (0)