Skip to content

Commit f68063d

Browse files
committed
Add error for invalid item of instruction_set
1 parent 012ae13 commit f68063d

File tree

5 files changed

+106
-10
lines changed

5 files changed

+106
-10
lines changed

compiler/rustc_passes/messages.ftl

+4
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

+38-4
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)
@@ -2375,6 +2378,37 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
23752378
_ => {
23762379
self.dcx().emit_err(errors::AutoDiffAttr { attr_span: span });
23772380
self.abort.set(true);
2381+
}
2382+
}
2383+
2384+
fn check_instruction_set(&self, attr: &Attribute, _item: Option<ItemLike<'_>>) {
2385+
if let AttrKind::Normal(ref p) = attr.kind {
2386+
let inner_tokens = p.item.args.inner_tokens();
2387+
let mut tokens = inner_tokens.trees();
2388+
2389+
// Valid item for `instruction_set()` is:
2390+
// - arm::a32
2391+
// - arm::t32
2392+
let valid_attribute = match (tokens.next(), tokens.next(), tokens.next()) {
2393+
(
2394+
Some(TokenTree::Token(first_token, _)),
2395+
Some(TokenTree::Token(second_token, _)),
2396+
Some(TokenTree::Token(third_token, _)),
2397+
) => match (first_token.ident(), second_token.kind.clone(), third_token.ident()) {
2398+
(Some(first_ident), TokenKind::PathSep, Some(third_ident))
2399+
if first_ident.0.name == sym::arm =>
2400+
{
2401+
third_ident.0.name == sym::a32 || third_ident.0.name == sym::t32
2402+
}
2403+
_ => false,
2404+
},
2405+
_ => false,
2406+
};
2407+
2408+
if !valid_attribute {
2409+
self.dcx().emit_err(errors::InvalidInstructionSet { span: attr.span });
2410+
} else {
2411+
return;
23782412
}
23792413
}
23802414
}

compiler/rustc_passes/src/errors.rs

+17-6
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;
@@ -686,6 +686,13 @@ pub(crate) struct Linkage {
686686
#[primary_span]
687687
pub attr_span: Span,
688688
#[label]
689+
#[label]
690+
pub span: Span,
691+
}
692+
693+
#[diag(passes_invalid_instruction_set)]
694+
pub struct InvalidInstructionSet {
695+
#[primary_span]
689696
pub span: Span,
690697
}
691698

@@ -1356,11 +1363,15 @@ pub(crate) struct DuplicateLangItem {
13561363
impl<G: EmissionGuarantee> Diagnostic<'_, G> for DuplicateLangItem {
13571364
#[track_caller]
13581365
fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> {
1359-
let mut diag = Diag::new(dcx, level, match self.duplicate {
1360-
Duplicate::Plain => fluent::passes_duplicate_lang_item,
1361-
Duplicate::Crate => fluent::passes_duplicate_lang_item_crate,
1362-
Duplicate::CrateDepends => fluent::passes_duplicate_lang_item_crate_depends,
1363-
});
1366+
let mut diag = Diag::new(
1367+
dcx,
1368+
level,
1369+
match self.duplicate {
1370+
Duplicate::Plain => fluent::passes_duplicate_lang_item,
1371+
Duplicate::Crate => fluent::passes_duplicate_lang_item_crate,
1372+
Duplicate::CrateDepends => fluent::passes_duplicate_lang_item_crate_depends,
1373+
},
1374+
);
13641375
diag.code(E0152);
13651376
diag.arg("lang_item_name", self.lang_item_name);
13661377
diag.arg("crate_name", self.crate_name);
+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)