Rollup merge of #58762 - petrochenkov:unwind, r=Mark-Simulacrum
Mention `unwind(aborts)` in diagnostics for `#[unwind]` Simplify input validation for `#[unwind]`, add tests cc https://github.com/rust-lang/rust/issues/58760 r? @Mark-Simulacrum
This commit is contained in:
commit
79873f79b1
7 changed files with 74 additions and 34 deletions
|
@ -579,6 +579,10 @@ fn should_abort_on_panic<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
|||
// Not callable from C, so we can safely unwind through these
|
||||
if abi == Abi::Rust || abi == Abi::RustCall { return false; }
|
||||
|
||||
// Validate `#[unwind]` syntax regardless of platform-specific panic strategy
|
||||
let attrs = &tcx.get_attrs(fn_def_id);
|
||||
let unwind_attr = attr::find_unwind_attr(Some(tcx.sess.diagnostic()), attrs);
|
||||
|
||||
// We never unwind, so it's not relevant to stop an unwind
|
||||
if tcx.sess.panic_strategy() != PanicStrategy::Unwind { return false; }
|
||||
|
||||
|
@ -587,8 +591,7 @@ fn should_abort_on_panic<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
|||
|
||||
// This is a special case: some functions have a C abi but are meant to
|
||||
// unwind anyway. Don't stop them.
|
||||
let attrs = &tcx.get_attrs(fn_def_id);
|
||||
match attr::find_unwind_attr(Some(tcx.sess.diagnostic()), attrs) {
|
||||
match unwind_attr {
|
||||
None => true,
|
||||
Some(UnwindAttr::Allowed) => false,
|
||||
Some(UnwindAttr::Aborts) => true,
|
||||
|
|
|
@ -7,7 +7,7 @@ use crate::parse::ParseSess;
|
|||
use errors::{Applicability, Handler};
|
||||
use syntax_pos::{symbol::Symbol, Span};
|
||||
|
||||
use super::{list_contains_name, mark_used, MetaItemKind};
|
||||
use super::{mark_used, MetaItemKind};
|
||||
|
||||
enum AttrError {
|
||||
MultipleItem(Name),
|
||||
|
@ -79,40 +79,26 @@ pub enum UnwindAttr {
|
|||
|
||||
/// Determine what `#[unwind]` attribute is present in `attrs`, if any.
|
||||
pub fn find_unwind_attr(diagnostic: Option<&Handler>, attrs: &[Attribute]) -> Option<UnwindAttr> {
|
||||
let syntax_error = |attr: &Attribute| {
|
||||
mark_used(attr);
|
||||
diagnostic.map(|d| {
|
||||
span_err!(d, attr.span, E0633, "malformed `#[unwind]` attribute");
|
||||
});
|
||||
None
|
||||
};
|
||||
|
||||
attrs.iter().fold(None, |ia, attr| {
|
||||
if attr.path != "unwind" {
|
||||
return ia;
|
||||
}
|
||||
let meta = match attr.meta() {
|
||||
Some(meta) => meta.node,
|
||||
None => return ia,
|
||||
};
|
||||
match meta {
|
||||
MetaItemKind::Word => {
|
||||
syntax_error(attr)
|
||||
}
|
||||
MetaItemKind::List(ref items) => {
|
||||
mark_used(attr);
|
||||
if items.len() != 1 {
|
||||
syntax_error(attr)
|
||||
} else if list_contains_name(&items[..], "allowed") {
|
||||
Some(UnwindAttr::Allowed)
|
||||
} else if list_contains_name(&items[..], "aborts") {
|
||||
Some(UnwindAttr::Aborts)
|
||||
} else {
|
||||
syntax_error(attr)
|
||||
if attr.check_name("unwind") {
|
||||
if let Some(meta) = attr.meta() {
|
||||
if let MetaItemKind::List(items) = meta.node {
|
||||
if items.len() == 1 {
|
||||
if items[0].check_name("allowed") {
|
||||
return Some(UnwindAttr::Allowed);
|
||||
} else if items[0].check_name("aborts") {
|
||||
return Some(UnwindAttr::Aborts);
|
||||
}
|
||||
}
|
||||
|
||||
diagnostic.map(|d| {
|
||||
span_err!(d, attr.span, E0633, "malformed `#[unwind]` attribute");
|
||||
});
|
||||
}
|
||||
}
|
||||
_ => ia,
|
||||
}
|
||||
|
||||
ia
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -1176,7 +1176,7 @@ pub const BUILTIN_ATTRIBUTES: &[(&str, AttributeType, AttributeTemplate, Attribu
|
|||
"dropck_eyepatch",
|
||||
"may_dangle has unstable semantics and may be removed in the future",
|
||||
cfg_fn!(dropck_eyepatch))),
|
||||
("unwind", Whitelisted, template!(List: "allowed"), Gated(Stability::Unstable,
|
||||
("unwind", Whitelisted, template!(List: "allowed|aborts"), Gated(Stability::Unstable,
|
||||
"unwind_attributes",
|
||||
"#[unwind] is experimental",
|
||||
cfg_fn!(unwind_attributes))),
|
||||
|
|
11
src/test/ui/malformed/malformed-unwind-1.rs
Normal file
11
src/test/ui/malformed/malformed-unwind-1.rs
Normal file
|
@ -0,0 +1,11 @@
|
|||
#![feature(unwind_attributes)]
|
||||
|
||||
#[unwind]
|
||||
//~^ ERROR attribute must be of the form
|
||||
extern "C" fn f1() {}
|
||||
|
||||
#[unwind = ""]
|
||||
//~^ ERROR attribute must be of the form
|
||||
extern "C" fn f2() {}
|
||||
|
||||
fn main() {}
|
14
src/test/ui/malformed/malformed-unwind-1.stderr
Normal file
14
src/test/ui/malformed/malformed-unwind-1.stderr
Normal file
|
@ -0,0 +1,14 @@
|
|||
error: attribute must be of the form `#[unwind(allowed|aborts)]`
|
||||
--> $DIR/malformed-unwind-1.rs:3:1
|
||||
|
|
||||
LL | #[unwind]
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: attribute must be of the form `#[unwind(allowed|aborts)]`
|
||||
--> $DIR/malformed-unwind-1.rs:7:1
|
||||
|
|
||||
LL | #[unwind = ""]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
11
src/test/ui/malformed/malformed-unwind-2.rs
Normal file
11
src/test/ui/malformed/malformed-unwind-2.rs
Normal file
|
@ -0,0 +1,11 @@
|
|||
#![feature(unwind_attributes)]
|
||||
|
||||
#[unwind(allowed, aborts)]
|
||||
//~^ ERROR malformed `#[unwind]` attribute
|
||||
extern "C" fn f1() {}
|
||||
|
||||
#[unwind(unsupported)]
|
||||
//~^ ERROR malformed `#[unwind]` attribute
|
||||
extern "C" fn f2() {}
|
||||
|
||||
fn main() {}
|
15
src/test/ui/malformed/malformed-unwind-2.stderr
Normal file
15
src/test/ui/malformed/malformed-unwind-2.stderr
Normal file
|
@ -0,0 +1,15 @@
|
|||
error[E0633]: malformed `#[unwind]` attribute
|
||||
--> $DIR/malformed-unwind-2.rs:3:1
|
||||
|
|
||||
LL | #[unwind(allowed, aborts)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0633]: malformed `#[unwind]` attribute
|
||||
--> $DIR/malformed-unwind-2.rs:7:1
|
||||
|
|
||||
LL | #[unwind(unsupported)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0633`.
|
Loading…
Add table
Add a link
Reference in a new issue