Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mention unwind(aborts) in diagnostics for #[unwind] #58762

Merged
merged 2 commits into from Mar 9, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 5 additions & 2 deletions src/librustc_mir/build/mod.rs
Expand Up @@ -581,6 +581,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 @@ -589,8 +593,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
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
Expand Up @@ -1173,7 +1173,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
@@ -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
@@ -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
@@ -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
@@ -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`.