Skip to content

Commit c33bab5

Browse files
committed
Add error for invalid item of instruction_set
1 parent 46e8d20 commit c33bab5

File tree

5 files changed

+106
-10
lines changed

5 files changed

+106
-10
lines changed

compiler/rustc_passes/messages.ftl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,10 @@ passes_coroutine_on_non_closure =
112112
attribute should be applied to closures
113113
.label = not a closure
114114
115+
passes_invalid_instruction_set =
116+
`[instruction_set]` attribute argument should be valid
117+
.label = `[instruction_set]` containes invalid argument
118+
115119
passes_coverage_not_fn_or_closure =
116120
attribute should be applied to a function definition or closure
117121
.label = not a function or closure

compiler/rustc_passes/src/check_attr.rs

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,10 @@
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::{
118
AttrKind, AttrStyle, Attribute, LitKind, MetaItemInner, MetaItemKind, MetaItemLit, ast,
9+
token::TokenKind, tokenstream::TokenTree, AttrKind, AttrStyle, Attribute, LitKind,
10+
MetaItemKind, MetaItemLit, NestedMetaItem,
1211
};
1312
use rustc_data_structures::fx::FxHashMap;
1413
use rustc_errors::{Applicability, DiagCtxtHandle, IntoDiagArg, MultiSpan, StashKey};
@@ -39,6 +38,8 @@ use rustc_target::spec::abi::Abi;
3938
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
4039
use rustc_trait_selection::infer::{TyCtxtInferExt, ValuePairs};
4140
use rustc_trait_selection::traits::ObligationCtxt;
41+
use std::cell::Cell;
42+
use std::collections::hash_map::Entry;
4243
use tracing::debug;
4344

4445
use crate::{errors, fluent_generated as fluent};
@@ -249,6 +250,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
249250
}
250251
[sym::linkage, ..] => self.check_linkage(attr, span, target),
251252
[sym::rustc_pub_transparent, ..] => self.check_rustc_pub_transparent( attr.span, span, attrs),
253+
[sym::instruction_set, ..] => {
254+
self.check_instruction_set(attr, item);
255+
}
252256
[
253257
// ok
254258
sym::allow
@@ -264,7 +268,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
264268
| sym::omit_gdb_pretty_printer_section // FIXME(omit_gdb_pretty_printer_section)
265269
| sym::used // handled elsewhere to restrict to static items
266270
| sym::repr // handled elsewhere to restrict to type decls items
267-
| sym::instruction_set // broken on stable!!!
268271
| sym::windows_subsystem // broken on stable!!!
269272
| sym::patchable_function_entry // FIXME(patchable_function_entry)
270273
| sym::deprecated_safe // FIXME(deprecated_safe)
@@ -2398,6 +2401,37 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
23982401
_ => {
23992402
self.dcx().emit_err(errors::AutoDiffAttr { attr_span: span });
24002403
self.abort.set(true);
2404+
}
2405+
}
2406+
2407+
fn check_instruction_set(&self, attr: &Attribute, _item: Option<ItemLike<'_>>) {
2408+
if let AttrKind::Normal(ref p) = attr.kind {
2409+
let inner_tokens = p.item.args.inner_tokens();
2410+
let mut tokens = inner_tokens.trees();
2411+
2412+
// Valid item for `instruction_set()` is:
2413+
// - arm::a32
2414+
// - arm::t32
2415+
let valid_attribute = match (tokens.next(), tokens.next(), tokens.next()) {
2416+
(
2417+
Some(TokenTree::Token(first_token, _)),
2418+
Some(TokenTree::Token(second_token, _)),
2419+
Some(TokenTree::Token(third_token, _)),
2420+
) => match (first_token.ident(), second_token.kind.clone(), third_token.ident()) {
2421+
(Some(first_ident), TokenKind::PathSep, Some(third_ident))
2422+
if first_ident.0.name == sym::arm =>
2423+
{
2424+
third_ident.0.name == sym::a32 || third_ident.0.name == sym::t32
2425+
}
2426+
_ => false,
2427+
},
2428+
_ => false,
2429+
};
2430+
2431+
if !valid_attribute {
2432+
self.dcx().emit_err(errors::InvalidInstructionSet { span: attr.span });
2433+
} else {
2434+
return;
24012435
}
24022436
}
24032437
}

compiler/rustc_passes/src/errors.rs

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use rustc_errors::{
1010
use rustc_hir::{self as hir, ExprKind, Target};
1111
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
1212
use rustc_middle::ty::{MainDefinition, Ty};
13-
use rustc_span::{DUMMY_SP, Span, Symbol};
13+
use rustc_span::{Span, Symbol, DUMMY_SP};
1414

1515
use crate::check_attr::ProcMacroKind;
1616
use crate::fluent_generated as fluent;
@@ -693,6 +693,13 @@ pub(crate) struct Linkage {
693693
#[primary_span]
694694
pub attr_span: Span,
695695
#[label]
696+
#[label]
697+
pub span: Span,
698+
}
699+
700+
#[diag(passes_invalid_instruction_set)]
701+
pub struct InvalidInstructionSet {
702+
#[primary_span]
696703
pub span: Span,
697704
}
698705

@@ -1363,11 +1370,15 @@ pub(crate) struct DuplicateLangItem {
13631370
impl<G: EmissionGuarantee> Diagnostic<'_, G> for DuplicateLangItem {
13641371
#[track_caller]
13651372
fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> {
1366-
let mut diag = Diag::new(dcx, level, match self.duplicate {
1367-
Duplicate::Plain => fluent::passes_duplicate_lang_item,
1368-
Duplicate::Crate => fluent::passes_duplicate_lang_item_crate,
1369-
Duplicate::CrateDepends => fluent::passes_duplicate_lang_item_crate_depends,
1370-
});
1373+
let mut diag = Diag::new(
1374+
dcx,
1375+
level,
1376+
match self.duplicate {
1377+
Duplicate::Plain => fluent::passes_duplicate_lang_item,
1378+
Duplicate::Crate => fluent::passes_duplicate_lang_item_crate,
1379+
Duplicate::CrateDepends => fluent::passes_duplicate_lang_item_crate_depends,
1380+
},
1381+
);
13711382
diag.code(E0152);
13721383
diag.arg("lang_item_name", self.lang_item_name);
13731384
diag.arg("crate_name", self.crate_name);
Lines changed: 21 additions & 0 deletions
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() {}
Lines changed: 26 additions & 0 deletions
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)