mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 08:13:41 +00:00
Parse unsafe attributes
This commit is contained in:
parent
76e7a0849c
commit
67f5dd1ef1
@ -488,6 +488,7 @@ pub struct Crate {
|
||||
/// E.g., `#[test]`, `#[derive(..)]`, `#[rustfmt::skip]` or `#[feature = "foo"]`.
|
||||
#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
|
||||
pub struct MetaItem {
|
||||
pub unsafety: Unsafe,
|
||||
pub path: Path,
|
||||
pub kind: MetaItemKind,
|
||||
pub span: Span,
|
||||
@ -2823,7 +2824,12 @@ pub struct NormalAttr {
|
||||
impl NormalAttr {
|
||||
pub fn from_ident(ident: Ident) -> Self {
|
||||
Self {
|
||||
item: AttrItem { path: Path::from_ident(ident), args: AttrArgs::Empty, tokens: None },
|
||||
item: AttrItem {
|
||||
unsafety: Unsafe::No,
|
||||
path: Path::from_ident(ident),
|
||||
args: AttrArgs::Empty,
|
||||
tokens: None,
|
||||
},
|
||||
tokens: None,
|
||||
}
|
||||
}
|
||||
@ -2831,6 +2837,7 @@ impl NormalAttr {
|
||||
|
||||
#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
|
||||
pub struct AttrItem {
|
||||
pub unsafety: Unsafe,
|
||||
pub path: Path,
|
||||
pub args: AttrArgs,
|
||||
// Tokens for the meta item, e.g. just the `foo` within `#[foo]` or `#![foo]`.
|
||||
|
@ -1,6 +1,8 @@
|
||||
//! Functions dealing with attributes and meta items.
|
||||
|
||||
use crate::ast::{AttrArgs, AttrArgsEq, AttrId, AttrItem, AttrKind, AttrStyle, AttrVec, Attribute};
|
||||
use crate::ast::{
|
||||
AttrArgs, AttrArgsEq, AttrId, AttrItem, AttrKind, AttrStyle, AttrVec, Attribute, Unsafe,
|
||||
};
|
||||
use crate::ast::{DelimArgs, Expr, ExprKind, LitKind, MetaItemLit};
|
||||
use crate::ast::{MetaItem, MetaItemKind, NestedMetaItem, NormalAttr};
|
||||
use crate::ast::{Path, PathSegment, DUMMY_NODE_ID};
|
||||
@ -238,7 +240,12 @@ impl AttrItem {
|
||||
}
|
||||
|
||||
pub fn meta(&self, span: Span) -> Option<MetaItem> {
|
||||
Some(MetaItem { path: self.path.clone(), kind: self.meta_kind()?, span })
|
||||
Some(MetaItem {
|
||||
unsafety: Unsafe::No,
|
||||
path: self.path.clone(),
|
||||
kind: self.meta_kind()?,
|
||||
span,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn meta_kind(&self) -> Option<MetaItemKind> {
|
||||
@ -371,7 +378,8 @@ impl MetaItem {
|
||||
_ => path.span.hi(),
|
||||
};
|
||||
let span = path.span.with_hi(hi);
|
||||
Some(MetaItem { path, kind, span })
|
||||
// FIX THIS LATER
|
||||
Some(MetaItem { unsafety: Unsafe::No, path, kind, span })
|
||||
}
|
||||
}
|
||||
|
||||
@ -555,11 +563,12 @@ pub fn mk_doc_comment(
|
||||
pub fn mk_attr(
|
||||
g: &AttrIdGenerator,
|
||||
style: AttrStyle,
|
||||
unsafety: Unsafe,
|
||||
path: Path,
|
||||
args: AttrArgs,
|
||||
span: Span,
|
||||
) -> Attribute {
|
||||
mk_attr_from_item(g, AttrItem { path, args, tokens: None }, None, style, span)
|
||||
mk_attr_from_item(g, AttrItem { unsafety, path, args, tokens: None }, None, style, span)
|
||||
}
|
||||
|
||||
pub fn mk_attr_from_item(
|
||||
@ -577,15 +586,22 @@ pub fn mk_attr_from_item(
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mk_attr_word(g: &AttrIdGenerator, style: AttrStyle, name: Symbol, span: Span) -> Attribute {
|
||||
pub fn mk_attr_word(
|
||||
g: &AttrIdGenerator,
|
||||
style: AttrStyle,
|
||||
unsafety: Unsafe,
|
||||
name: Symbol,
|
||||
span: Span,
|
||||
) -> Attribute {
|
||||
let path = Path::from_ident(Ident::new(name, span));
|
||||
let args = AttrArgs::Empty;
|
||||
mk_attr(g, style, path, args, span)
|
||||
mk_attr(g, style, unsafety, path, args, span)
|
||||
}
|
||||
|
||||
pub fn mk_attr_nested_word(
|
||||
g: &AttrIdGenerator,
|
||||
style: AttrStyle,
|
||||
unsafety: Unsafe,
|
||||
outer: Symbol,
|
||||
inner: Symbol,
|
||||
span: Span,
|
||||
@ -601,12 +617,13 @@ pub fn mk_attr_nested_word(
|
||||
delim: Delimiter::Parenthesis,
|
||||
tokens: inner_tokens,
|
||||
});
|
||||
mk_attr(g, style, path, attr_args, span)
|
||||
mk_attr(g, style, unsafety, path, attr_args, span)
|
||||
}
|
||||
|
||||
pub fn mk_attr_name_value_str(
|
||||
g: &AttrIdGenerator,
|
||||
style: AttrStyle,
|
||||
unsafety: Unsafe,
|
||||
name: Symbol,
|
||||
val: Symbol,
|
||||
span: Span,
|
||||
@ -621,7 +638,7 @@ pub fn mk_attr_name_value_str(
|
||||
});
|
||||
let path = Path::from_ident(Ident::new(name, span));
|
||||
let args = AttrArgs::Eq(span, AttrArgsEq::Ast(expr));
|
||||
mk_attr(g, style, path, args, span)
|
||||
mk_attr(g, style, unsafety, path, args, span)
|
||||
}
|
||||
|
||||
pub fn filter_by_name(attrs: &[Attribute], name: Symbol) -> impl Iterator<Item = &Attribute> {
|
||||
|
@ -647,8 +647,10 @@ fn noop_visit_attribute<T: MutVisitor>(attr: &mut Attribute, vis: &mut T) {
|
||||
let Attribute { kind, id: _, style: _, span } = attr;
|
||||
match kind {
|
||||
AttrKind::Normal(normal) => {
|
||||
let NormalAttr { item: AttrItem { path, args, tokens }, tokens: attr_tokens } =
|
||||
&mut **normal;
|
||||
let NormalAttr {
|
||||
item: AttrItem { unsafety: _, path, args, tokens },
|
||||
tokens: attr_tokens,
|
||||
} = &mut **normal;
|
||||
vis.visit_path(path);
|
||||
visit_attr_args(args, vis);
|
||||
visit_lazy_tts(tokens, vis);
|
||||
@ -678,7 +680,7 @@ fn noop_visit_meta_list_item<T: MutVisitor>(li: &mut NestedMetaItem, vis: &mut T
|
||||
}
|
||||
|
||||
fn noop_visit_meta_item<T: MutVisitor>(mi: &mut MetaItem, vis: &mut T) {
|
||||
let MetaItem { path: _, kind, span } = mi;
|
||||
let MetaItem { unsafety: _, path: _, kind, span } = mi;
|
||||
match kind {
|
||||
MetaItemKind::Word => {}
|
||||
MetaItemKind::List(mis) => visit_thin_vec(mis, |mi| vis.visit_meta_list_item(mi)),
|
||||
@ -840,7 +842,7 @@ fn visit_nonterminal<T: MutVisitor>(nt: &mut token::Nonterminal, vis: &mut T) {
|
||||
token::NtTy(ty) => vis.visit_ty(ty),
|
||||
token::NtLiteral(expr) => vis.visit_expr(expr),
|
||||
token::NtMeta(item) => {
|
||||
let AttrItem { path, args, tokens } = item.deref_mut();
|
||||
let AttrItem { unsafety: _, path, args, tokens } = item.deref_mut();
|
||||
vis.visit_path(path);
|
||||
visit_attr_args(args, vis);
|
||||
visit_lazy_tts(tokens, vis);
|
||||
|
@ -1801,6 +1801,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
let attr = attr::mk_attr_nested_word(
|
||||
&self.tcx.sess.psess.attr_id_generator,
|
||||
AttrStyle::Outer,
|
||||
Unsafe::No,
|
||||
sym::allow,
|
||||
sym::unreachable_code,
|
||||
self.lower_span(span),
|
||||
|
@ -911,6 +911,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
let kind = match attr.kind {
|
||||
AttrKind::Normal(ref normal) => AttrKind::Normal(P(NormalAttr {
|
||||
item: AttrItem {
|
||||
unsafety: normal.item.unsafety,
|
||||
path: normal.item.path.clone(),
|
||||
args: self.lower_attr_args(&normal.item.args),
|
||||
tokens: None,
|
||||
|
@ -561,6 +561,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
|
||||
gate_all!(mut_ref, "mutable by-reference bindings are experimental");
|
||||
gate_all!(precise_capturing, "precise captures on `impl Trait` are experimental");
|
||||
gate_all!(global_registration, "global registration is experimental");
|
||||
gate_all!(unsafe_attributes, "`#[unsafe()]` markers for attributes are experimental");
|
||||
|
||||
if !visitor.features.never_patterns {
|
||||
if let Some(spans) = spans.get(&sym::never_patterns) {
|
||||
|
@ -16,7 +16,7 @@ use rustc_ast::token::{self, BinOpToken, CommentKind, Delimiter, Nonterminal, To
|
||||
use rustc_ast::tokenstream::{Spacing, TokenStream, TokenTree};
|
||||
use rustc_ast::util::classify;
|
||||
use rustc_ast::util::comments::{Comment, CommentStyle};
|
||||
use rustc_ast::{self as ast, AttrArgs, AttrArgsEq, BlockCheckMode, PatKind};
|
||||
use rustc_ast::{self as ast, AttrArgs, AttrArgsEq, BlockCheckMode, PatKind, Unsafe};
|
||||
use rustc_ast::{attr, BindingMode, ByRef, DelimArgs, RangeEnd, RangeSyntax, Term};
|
||||
use rustc_ast::{GenericArg, GenericBound, SelfKind};
|
||||
use rustc_ast::{InlineAsmOperand, InlineAsmRegOrRegClass};
|
||||
@ -249,6 +249,7 @@ pub fn print_crate<'a>(
|
||||
let fake_attr = attr::mk_attr_nested_word(
|
||||
g,
|
||||
ast::AttrStyle::Inner,
|
||||
Unsafe::No,
|
||||
sym::feature,
|
||||
sym::prelude_import,
|
||||
DUMMY_SP,
|
||||
@ -259,7 +260,8 @@ pub fn print_crate<'a>(
|
||||
// root, so this is not needed, and actually breaks things.
|
||||
if edition.is_rust_2015() {
|
||||
// `#![no_std]`
|
||||
let fake_attr = attr::mk_attr_word(g, ast::AttrStyle::Inner, sym::no_std, DUMMY_SP);
|
||||
let fake_attr =
|
||||
attr::mk_attr_word(g, ast::AttrStyle::Inner, Unsafe::No, sym::no_std, DUMMY_SP);
|
||||
s.print_attribute(&fake_attr);
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ pub fn inject(krate: &mut ast::Crate, psess: &ParseSess, attrs: &[String]) {
|
||||
));
|
||||
|
||||
let start_span = parser.token.span;
|
||||
let AttrItem { path, args, tokens: _ } = match parser.parse_attr_item(false) {
|
||||
let AttrItem { unsafety, path, args, tokens: _ } = match parser.parse_attr_item(false) {
|
||||
Ok(ai) => ai,
|
||||
Err(err) => {
|
||||
err.emit();
|
||||
@ -33,6 +33,7 @@ pub fn inject(krate: &mut ast::Crate, psess: &ParseSess, attrs: &[String]) {
|
||||
krate.attrs.push(mk_attr(
|
||||
&psess.attr_id_generator,
|
||||
AttrStyle::Inner,
|
||||
unsafety,
|
||||
path,
|
||||
args,
|
||||
start_span.to(end_span),
|
||||
|
@ -203,6 +203,7 @@ impl<'a> MutVisitor for EntryPointCleaner<'a> {
|
||||
let allow_dead_code = attr::mk_attr_nested_word(
|
||||
&self.sess.psess.attr_id_generator,
|
||||
ast::AttrStyle::Outer,
|
||||
ast::Unsafe::No,
|
||||
sym::allow,
|
||||
sym::dead_code,
|
||||
self.def_site,
|
||||
|
@ -666,7 +666,7 @@ impl<'a> ExtCtxt<'a> {
|
||||
// Builds `#[name]`.
|
||||
pub fn attr_word(&self, name: Symbol, span: Span) -> ast::Attribute {
|
||||
let g = &self.sess.psess.attr_id_generator;
|
||||
attr::mk_attr_word(g, ast::AttrStyle::Outer, name, span)
|
||||
attr::mk_attr_word(g, ast::AttrStyle::Outer, ast::Unsafe::No, name, span)
|
||||
}
|
||||
|
||||
// Builds `#[name = val]`.
|
||||
@ -674,12 +674,12 @@ impl<'a> ExtCtxt<'a> {
|
||||
// Note: `span` is used for both the identifier and the value.
|
||||
pub fn attr_name_value_str(&self, name: Symbol, val: Symbol, span: Span) -> ast::Attribute {
|
||||
let g = &self.sess.psess.attr_id_generator;
|
||||
attr::mk_attr_name_value_str(g, ast::AttrStyle::Outer, name, val, span)
|
||||
attr::mk_attr_name_value_str(g, ast::AttrStyle::Outer, ast::Unsafe::No, name, val, span)
|
||||
}
|
||||
|
||||
// Builds `#[outer(inner)]`.
|
||||
pub fn attr_nested_word(&self, outer: Symbol, inner: Symbol, span: Span) -> ast::Attribute {
|
||||
let g = &self.sess.psess.attr_id_generator;
|
||||
attr::mk_attr_nested_word(g, ast::AttrStyle::Outer, outer, inner, span)
|
||||
attr::mk_attr_nested_word(g, ast::AttrStyle::Outer, ast::Unsafe::No, outer, inner, span)
|
||||
}
|
||||
}
|
||||
|
@ -778,7 +778,13 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||
if let SyntaxExtensionKind::Derive(..) = ext {
|
||||
self.gate_proc_macro_input(&item);
|
||||
}
|
||||
let meta = ast::MetaItem { kind: MetaItemKind::Word, span, path };
|
||||
// FIX THIS LATER
|
||||
let meta = ast::MetaItem {
|
||||
unsafety: ast::Unsafe::No,
|
||||
kind: MetaItemKind::Word,
|
||||
span,
|
||||
path,
|
||||
};
|
||||
let items = match expander.expand(self.cx, span, &meta, item, is_const) {
|
||||
ExpandResult::Ready(items) => items,
|
||||
ExpandResult::Retry(item) => {
|
||||
|
@ -59,6 +59,17 @@ pub enum AttributeType {
|
||||
CrateLevel,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Debug)]
|
||||
#[allow(dead_code)]
|
||||
pub enum AttributeSafety {
|
||||
/// Normal attribute that does not need `#[unsafe(...)]`
|
||||
Normal,
|
||||
|
||||
/// Unsafe attribute that requires safety obligations
|
||||
/// to be discharged
|
||||
Unsafe,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum AttributeGate {
|
||||
/// Is gated by a given feature gate, reason
|
||||
@ -177,6 +188,18 @@ macro_rules! ungated {
|
||||
name: sym::$attr,
|
||||
encode_cross_crate: $encode_cross_crate,
|
||||
type_: $typ,
|
||||
safety: AttributeSafety::Normal,
|
||||
template: $tpl,
|
||||
gate: Ungated,
|
||||
duplicates: $duplicates,
|
||||
}
|
||||
};
|
||||
(unsafe $attr:ident, $typ:expr, $tpl:expr, $duplicates:expr, $encode_cross_crate:expr $(,)?) => {
|
||||
BuiltinAttribute {
|
||||
name: sym::$attr,
|
||||
encode_cross_crate: $encode_cross_crate,
|
||||
type_: $typ,
|
||||
safety: AttributeSafety::Unsafe,
|
||||
template: $tpl,
|
||||
gate: Ungated,
|
||||
duplicates: $duplicates,
|
||||
@ -190,6 +213,7 @@ macro_rules! gated {
|
||||
name: sym::$attr,
|
||||
encode_cross_crate: $encode_cross_crate,
|
||||
type_: $typ,
|
||||
safety: AttributeSafety::Normal,
|
||||
template: $tpl,
|
||||
duplicates: $duplicates,
|
||||
gate: Gated(Stability::Unstable, sym::$gate, $msg, cfg_fn!($gate)),
|
||||
@ -200,6 +224,29 @@ macro_rules! gated {
|
||||
name: sym::$attr,
|
||||
encode_cross_crate: $encode_cross_crate,
|
||||
type_: $typ,
|
||||
safety: AttributeSafety::Normal,
|
||||
template: $tpl,
|
||||
duplicates: $duplicates,
|
||||
gate: Gated(Stability::Unstable, sym::$attr, $msg, cfg_fn!($attr)),
|
||||
}
|
||||
};
|
||||
(unsafe $attr:ident, $typ:expr, $tpl:expr, $duplicates:expr, $encode_cross_crate:expr, $gate:ident, $msg:expr $(,)?) => {
|
||||
BuiltinAttribute {
|
||||
name: sym::$attr,
|
||||
encode_cross_crate: $encode_cross_crate,
|
||||
type_: $typ,
|
||||
safety: AttributeSafety::Unsafe,
|
||||
template: $tpl,
|
||||
duplicates: $duplicates,
|
||||
gate: Gated(Stability::Unstable, sym::$gate, $msg, cfg_fn!($gate)),
|
||||
}
|
||||
};
|
||||
(unsafe $attr:ident, $typ:expr, $tpl:expr, $duplicates:expr, $encode_cross_crate:expr, $msg:expr $(,)?) => {
|
||||
BuiltinAttribute {
|
||||
name: sym::$attr,
|
||||
encode_cross_crate: $encode_cross_crate,
|
||||
type_: $typ,
|
||||
safety: AttributeSafety::Unsafe,
|
||||
template: $tpl,
|
||||
duplicates: $duplicates,
|
||||
gate: Gated(Stability::Unstable, sym::$attr, $msg, cfg_fn!($attr)),
|
||||
@ -228,6 +275,7 @@ macro_rules! rustc_attr {
|
||||
name: sym::$attr,
|
||||
encode_cross_crate: $encode_cross_crate,
|
||||
type_: $typ,
|
||||
safety: AttributeSafety::Normal,
|
||||
template: $tpl,
|
||||
duplicates: $duplicates,
|
||||
gate: Gated(Stability::Unstable, sym::rustc_attrs, $msg, cfg_fn!(rustc_attrs)),
|
||||
@ -258,6 +306,7 @@ pub struct BuiltinAttribute {
|
||||
/// Otherwise, it can only be used in the local crate.
|
||||
pub encode_cross_crate: EncodeCrossCrate,
|
||||
pub type_: AttributeType,
|
||||
pub safety: AttributeSafety,
|
||||
pub template: AttributeTemplate,
|
||||
pub duplicates: AttributeDuplicates,
|
||||
pub gate: AttributeGate,
|
||||
@ -375,9 +424,9 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
||||
),
|
||||
ungated!(no_link, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No),
|
||||
ungated!(repr, Normal, template!(List: "C"), DuplicatesOk, EncodeCrossCrate::No),
|
||||
ungated!(export_name, Normal, template!(NameValueStr: "name"), FutureWarnPreceding, EncodeCrossCrate::No),
|
||||
ungated!(link_section, Normal, template!(NameValueStr: "name"), FutureWarnPreceding, EncodeCrossCrate::No),
|
||||
ungated!(no_mangle, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No),
|
||||
ungated!(unsafe export_name, Normal, template!(NameValueStr: "name"), FutureWarnPreceding, EncodeCrossCrate::No),
|
||||
ungated!(unsafe link_section, Normal, template!(NameValueStr: "name"), FutureWarnPreceding, EncodeCrossCrate::No),
|
||||
ungated!(unsafe no_mangle, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No),
|
||||
ungated!(used, Normal, template!(Word, List: "compiler|linker"), WarnFollowing, EncodeCrossCrate::No),
|
||||
ungated!(link_ordinal, Normal, template!(List: "ordinal"), ErrorPreceding, EncodeCrossCrate::Yes),
|
||||
|
||||
@ -850,6 +899,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
||||
// FIXME: This can be `true` once we always use `tcx.is_diagnostic_item`.
|
||||
encode_cross_crate: EncodeCrossCrate::Yes,
|
||||
type_: Normal,
|
||||
safety: AttributeSafety::Normal,
|
||||
template: template!(NameValueStr: "name"),
|
||||
duplicates: ErrorFollowing,
|
||||
gate: Gated(
|
||||
|
@ -623,6 +623,7 @@ declare_features! (
|
||||
/// Allows unsafe on extern declarations and safety qualifiers over internal items.
|
||||
(unstable, unsafe_extern_blocks, "CURRENT_RUSTC_VERSION", Some(123743)),
|
||||
/// Allows unsized fn parameters.
|
||||
(unstable, unsafe_attributes, "CURRENT_RUSTC_VERSION", Some(123757)),
|
||||
(unstable, unsized_fn_params, "1.49.0", Some(48055)),
|
||||
/// Allows unsized rvalues at arguments and parameters.
|
||||
(incomplete, unsized_locals, "1.30.0", Some(48055)),
|
||||
|
@ -7,7 +7,7 @@ use rustc_ast as ast;
|
||||
use rustc_ast::attr;
|
||||
use rustc_ast::token::{self, Delimiter};
|
||||
use rustc_errors::{codes::*, Diag, PResult};
|
||||
use rustc_span::{sym, BytePos, Span};
|
||||
use rustc_span::{sym, symbol::kw, BytePos, Span};
|
||||
use thin_vec::ThinVec;
|
||||
use tracing::debug;
|
||||
|
||||
@ -252,9 +252,23 @@ impl<'a> Parser<'a> {
|
||||
maybe_whole!(self, NtMeta, |attr| attr.into_inner());
|
||||
|
||||
let do_parse = |this: &mut Self| {
|
||||
let is_unsafe = this.eat_keyword(kw::Unsafe);
|
||||
let unsafety = if is_unsafe {
|
||||
let unsafe_span = this.prev_token.span;
|
||||
this.psess.gated_spans.gate(sym::unsafe_attributes, unsafe_span);
|
||||
this.expect(&token::OpenDelim(Delimiter::Parenthesis))?;
|
||||
|
||||
ast::Unsafe::Yes(unsafe_span)
|
||||
} else {
|
||||
ast::Unsafe::No
|
||||
};
|
||||
|
||||
let path = this.parse_path(PathStyle::Mod)?;
|
||||
let args = this.parse_attr_args()?;
|
||||
Ok(ast::AttrItem { path, args, tokens: None })
|
||||
if is_unsafe {
|
||||
this.expect(&token::CloseDelim(Delimiter::Parenthesis))?;
|
||||
}
|
||||
Ok(ast::AttrItem { unsafety, path, args, tokens: None })
|
||||
};
|
||||
// Attr items don't have attributes
|
||||
if capture_tokens { self.collect_tokens_no_attrs(do_parse) } else { do_parse(self) }
|
||||
@ -375,10 +389,25 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
let lo = self.token.span;
|
||||
let is_unsafe = self.eat_keyword(kw::Unsafe);
|
||||
let unsafety = if is_unsafe {
|
||||
let unsafe_span = self.prev_token.span;
|
||||
self.psess.gated_spans.gate(sym::unsafe_attributes, unsafe_span);
|
||||
self.expect(&token::OpenDelim(Delimiter::Parenthesis))?;
|
||||
|
||||
ast::Unsafe::Yes(unsafe_span)
|
||||
} else {
|
||||
ast::Unsafe::No
|
||||
};
|
||||
|
||||
let path = self.parse_path(PathStyle::Mod)?;
|
||||
let kind = self.parse_meta_item_kind()?;
|
||||
if is_unsafe {
|
||||
self.expect(&token::CloseDelim(Delimiter::Parenthesis))?;
|
||||
}
|
||||
let span = lo.to(self.prev_token.span);
|
||||
Ok(ast::MetaItem { path, kind, span })
|
||||
|
||||
Ok(ast::MetaItem { unsafety, path, kind, span })
|
||||
}
|
||||
|
||||
pub(crate) fn parse_meta_item_kind(&mut self) -> PResult<'a, ast::MetaItemKind> {
|
||||
|
@ -42,6 +42,7 @@ pub fn check_attr(psess: &ParseSess, attr: &Attribute) {
|
||||
pub fn parse_meta<'a>(psess: &'a ParseSess, attr: &Attribute) -> PResult<'a, MetaItem> {
|
||||
let item = attr.get_normal_item();
|
||||
Ok(MetaItem {
|
||||
unsafety: item.unsafety,
|
||||
span: attr.span,
|
||||
path: item.path.clone(),
|
||||
kind: match &item.args {
|
||||
|
@ -1962,6 +1962,7 @@ symbols! {
|
||||
unreachable_display,
|
||||
unreachable_macro,
|
||||
unrestricted_attribute_tokens,
|
||||
unsafe_attributes,
|
||||
unsafe_block_in_unsafe_fn,
|
||||
unsafe_cell,
|
||||
unsafe_cell_raw_get,
|
||||
|
@ -1,6 +1,6 @@
|
||||
use super::*;
|
||||
|
||||
use rustc_ast::{MetaItemLit, Path, StrStyle};
|
||||
use rustc_ast::{MetaItemLit, Path, StrStyle, Unsafe};
|
||||
use rustc_span::create_default_session_globals_then;
|
||||
use rustc_span::symbol::{kw, Ident};
|
||||
use rustc_span::DUMMY_SP;
|
||||
@ -16,6 +16,7 @@ fn name_value_cfg(name: &str, value: &str) -> Cfg {
|
||||
|
||||
fn dummy_meta_item_word(name: &str) -> MetaItem {
|
||||
MetaItem {
|
||||
unsafety: Unsafe::No,
|
||||
path: Path::from_ident(Ident::from_str(name)),
|
||||
kind: MetaItemKind::Word,
|
||||
span: DUMMY_SP,
|
||||
@ -25,6 +26,7 @@ fn dummy_meta_item_word(name: &str) -> MetaItem {
|
||||
fn dummy_meta_item_name_value(name: &str, symbol: Symbol, kind: LitKind) -> MetaItem {
|
||||
let lit = MetaItemLit { symbol, suffix: None, kind, span: DUMMY_SP };
|
||||
MetaItem {
|
||||
unsafety: Unsafe::No,
|
||||
path: Path::from_ident(Ident::from_str(name)),
|
||||
kind: MetaItemKind::NameValue(lit),
|
||||
span: DUMMY_SP,
|
||||
@ -34,6 +36,7 @@ fn dummy_meta_item_name_value(name: &str, symbol: Symbol, kind: LitKind) -> Meta
|
||||
macro_rules! dummy_meta_item_list {
|
||||
($name:ident, [$($list:ident),* $(,)?]) => {
|
||||
MetaItem {
|
||||
unsafety: Unsafe::No,
|
||||
path: Path::from_ident(Ident::from_str(stringify!($name))),
|
||||
kind: MetaItemKind::List(thin_vec![
|
||||
$(
|
||||
@ -48,6 +51,7 @@ macro_rules! dummy_meta_item_list {
|
||||
|
||||
($name:ident, [$($list:expr),* $(,)?]) => {
|
||||
MetaItem {
|
||||
unsafety: Unsafe::No,
|
||||
path: Path::from_ident(Ident::from_str(stringify!($name))),
|
||||
kind: MetaItemKind::List(thin_vec![
|
||||
$(
|
||||
|
8
tests/ui/feature-gates/feature-gate-unsafe-attributes.rs
Normal file
8
tests/ui/feature-gates/feature-gate-unsafe-attributes.rs
Normal file
@ -0,0 +1,8 @@
|
||||
#[unsafe(no_mangle)] //~ ERROR [E0658]
|
||||
extern "C" fn foo() {
|
||||
|
||||
}
|
||||
|
||||
fn main() {
|
||||
foo();
|
||||
}
|
13
tests/ui/feature-gates/feature-gate-unsafe-attributes.stderr
Normal file
13
tests/ui/feature-gates/feature-gate-unsafe-attributes.stderr
Normal file
@ -0,0 +1,13 @@
|
||||
error[E0658]: `#[unsafe()]` markers for attributes are experimental
|
||||
--> $DIR/feature-gate-unsafe-attributes.rs:1:3
|
||||
|
|
||||
LL | #[unsafe(no_mangle)]
|
||||
| ^^^^^^
|
||||
|
|
||||
= note: see issue #123757 <https://github.com/rust-lang/rust/issues/123757> for more information
|
||||
= help: add `#![feature(unsafe_attributes)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
Loading…
Reference in New Issue
Block a user