Skip to content

Commit

Permalink
Rollup merge of rust-lang#58762 - petrochenkov:unwind, r=Mark-Simulacrum
Browse files Browse the repository at this point in the history
Mention `unwind(aborts)` in diagnostics for `#[unwind]`

Simplify input validation for `#[unwind]`, add tests

cc rust-lang#58760
r? @Mark-Simulacrum
  • Loading branch information
Centril authored Mar 9, 2019
2 parents 2485fb3 + dc00a8a commit df1b061
Show file tree
Hide file tree
Showing 7 changed files with 74 additions and 34 deletions.
7 changes: 5 additions & 2 deletions src/librustc_mir/build/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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; }

Expand All @@ -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,
Expand Down
48 changes: 17 additions & 31 deletions src/libsyntax/attr/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down Expand Up @@ -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
})
}

Expand Down
2 changes: 1 addition & 1 deletion src/libsyntax/feature_gate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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))),
Expand Down
11 changes: 11 additions & 0 deletions src/test/ui/malformed/malformed-unwind-1.rs
Original file line number Diff line number Diff line change
@@ -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 changes: 14 additions & 0 deletions src/test/ui/malformed/malformed-unwind-1.stderr
Original file line number Diff line number Diff line change
@@ -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 changes: 11 additions & 0 deletions src/test/ui/malformed/malformed-unwind-2.rs
Original file line number Diff line number Diff line change
@@ -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 changes: 15 additions & 0 deletions src/test/ui/malformed/malformed-unwind-2.stderr
Original file line number Diff line number Diff line change
@@ -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`.

0 comments on commit df1b061

Please sign in to comment.