1
Fork 0

Parse unsafe attributes

This commit is contained in:
carbotaniuman 2024-04-20 23:54:50 -05:00
parent 76e7a0849c
commit 67f5dd1ef1
19 changed files with 173 additions and 27 deletions

View file

@ -488,6 +488,7 @@ pub struct Crate {
/// E.g., `#[test]`, `#[derive(..)]`, `#[rustfmt::skip]` or `#[feature = "foo"]`. /// E.g., `#[test]`, `#[derive(..)]`, `#[rustfmt::skip]` or `#[feature = "foo"]`.
#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)] #[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
pub struct MetaItem { pub struct MetaItem {
pub unsafety: Unsafe,
pub path: Path, pub path: Path,
pub kind: MetaItemKind, pub kind: MetaItemKind,
pub span: Span, pub span: Span,
@ -2823,7 +2824,12 @@ pub struct NormalAttr {
impl NormalAttr { impl NormalAttr {
pub fn from_ident(ident: Ident) -> Self { pub fn from_ident(ident: Ident) -> Self {
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, tokens: None,
} }
} }
@ -2831,6 +2837,7 @@ impl NormalAttr {
#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)] #[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
pub struct AttrItem { pub struct AttrItem {
pub unsafety: Unsafe,
pub path: Path, pub path: Path,
pub args: AttrArgs, pub args: AttrArgs,
// Tokens for the meta item, e.g. just the `foo` within `#[foo]` or `#![foo]`. // Tokens for the meta item, e.g. just the `foo` within `#[foo]` or `#![foo]`.

View file

@ -1,6 +1,8 @@
//! Functions dealing with attributes and meta items. //! 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::{DelimArgs, Expr, ExprKind, LitKind, MetaItemLit};
use crate::ast::{MetaItem, MetaItemKind, NestedMetaItem, NormalAttr}; use crate::ast::{MetaItem, MetaItemKind, NestedMetaItem, NormalAttr};
use crate::ast::{Path, PathSegment, DUMMY_NODE_ID}; use crate::ast::{Path, PathSegment, DUMMY_NODE_ID};
@ -238,7 +240,12 @@ impl AttrItem {
} }
pub fn meta(&self, span: Span) -> Option<MetaItem> { 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> { pub fn meta_kind(&self) -> Option<MetaItemKind> {
@ -371,7 +378,8 @@ impl MetaItem {
_ => path.span.hi(), _ => path.span.hi(),
}; };
let span = path.span.with_hi(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( pub fn mk_attr(
g: &AttrIdGenerator, g: &AttrIdGenerator,
style: AttrStyle, style: AttrStyle,
unsafety: Unsafe,
path: Path, path: Path,
args: AttrArgs, args: AttrArgs,
span: Span, span: Span,
) -> Attribute { ) -> 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( 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 path = Path::from_ident(Ident::new(name, span));
let args = AttrArgs::Empty; 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( pub fn mk_attr_nested_word(
g: &AttrIdGenerator, g: &AttrIdGenerator,
style: AttrStyle, style: AttrStyle,
unsafety: Unsafe,
outer: Symbol, outer: Symbol,
inner: Symbol, inner: Symbol,
span: Span, span: Span,
@ -601,12 +617,13 @@ pub fn mk_attr_nested_word(
delim: Delimiter::Parenthesis, delim: Delimiter::Parenthesis,
tokens: inner_tokens, 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( pub fn mk_attr_name_value_str(
g: &AttrIdGenerator, g: &AttrIdGenerator,
style: AttrStyle, style: AttrStyle,
unsafety: Unsafe,
name: Symbol, name: Symbol,
val: Symbol, val: Symbol,
span: Span, span: Span,
@ -621,7 +638,7 @@ pub fn mk_attr_name_value_str(
}); });
let path = Path::from_ident(Ident::new(name, span)); let path = Path::from_ident(Ident::new(name, span));
let args = AttrArgs::Eq(span, AttrArgsEq::Ast(expr)); 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> { pub fn filter_by_name(attrs: &[Attribute], name: Symbol) -> impl Iterator<Item = &Attribute> {

View file

@ -647,8 +647,10 @@ fn noop_visit_attribute<T: MutVisitor>(attr: &mut Attribute, vis: &mut T) {
let Attribute { kind, id: _, style: _, span } = attr; let Attribute { kind, id: _, style: _, span } = attr;
match kind { match kind {
AttrKind::Normal(normal) => { AttrKind::Normal(normal) => {
let NormalAttr { item: AttrItem { path, args, tokens }, tokens: attr_tokens } = let NormalAttr {
&mut **normal; item: AttrItem { unsafety: _, path, args, tokens },
tokens: attr_tokens,
} = &mut **normal;
vis.visit_path(path); vis.visit_path(path);
visit_attr_args(args, vis); visit_attr_args(args, vis);
visit_lazy_tts(tokens, 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) { 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 { match kind {
MetaItemKind::Word => {} MetaItemKind::Word => {}
MetaItemKind::List(mis) => visit_thin_vec(mis, |mi| vis.visit_meta_list_item(mi)), 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::NtTy(ty) => vis.visit_ty(ty),
token::NtLiteral(expr) => vis.visit_expr(expr), token::NtLiteral(expr) => vis.visit_expr(expr),
token::NtMeta(item) => { token::NtMeta(item) => {
let AttrItem { path, args, tokens } = item.deref_mut(); let AttrItem { unsafety: _, path, args, tokens } = item.deref_mut();
vis.visit_path(path); vis.visit_path(path);
visit_attr_args(args, vis); visit_attr_args(args, vis);
visit_lazy_tts(tokens, vis); visit_lazy_tts(tokens, vis);

View file

@ -1801,6 +1801,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let attr = attr::mk_attr_nested_word( let attr = attr::mk_attr_nested_word(
&self.tcx.sess.psess.attr_id_generator, &self.tcx.sess.psess.attr_id_generator,
AttrStyle::Outer, AttrStyle::Outer,
Unsafe::No,
sym::allow, sym::allow,
sym::unreachable_code, sym::unreachable_code,
self.lower_span(span), self.lower_span(span),

View file

@ -911,6 +911,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let kind = match attr.kind { let kind = match attr.kind {
AttrKind::Normal(ref normal) => AttrKind::Normal(P(NormalAttr { AttrKind::Normal(ref normal) => AttrKind::Normal(P(NormalAttr {
item: AttrItem { item: AttrItem {
unsafety: normal.item.unsafety,
path: normal.item.path.clone(), path: normal.item.path.clone(),
args: self.lower_attr_args(&normal.item.args), args: self.lower_attr_args(&normal.item.args),
tokens: None, tokens: None,

View file

@ -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!(mut_ref, "mutable by-reference bindings are experimental");
gate_all!(precise_capturing, "precise captures on `impl Trait` are experimental"); gate_all!(precise_capturing, "precise captures on `impl Trait` are experimental");
gate_all!(global_registration, "global registration is 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 !visitor.features.never_patterns {
if let Some(spans) = spans.get(&sym::never_patterns) { if let Some(spans) = spans.get(&sym::never_patterns) {

View file

@ -16,7 +16,7 @@ use rustc_ast::token::{self, BinOpToken, CommentKind, Delimiter, Nonterminal, To
use rustc_ast::tokenstream::{Spacing, TokenStream, TokenTree}; use rustc_ast::tokenstream::{Spacing, TokenStream, TokenTree};
use rustc_ast::util::classify; use rustc_ast::util::classify;
use rustc_ast::util::comments::{Comment, CommentStyle}; 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::{attr, BindingMode, ByRef, DelimArgs, RangeEnd, RangeSyntax, Term};
use rustc_ast::{GenericArg, GenericBound, SelfKind}; use rustc_ast::{GenericArg, GenericBound, SelfKind};
use rustc_ast::{InlineAsmOperand, InlineAsmRegOrRegClass}; use rustc_ast::{InlineAsmOperand, InlineAsmRegOrRegClass};
@ -249,6 +249,7 @@ pub fn print_crate<'a>(
let fake_attr = attr::mk_attr_nested_word( let fake_attr = attr::mk_attr_nested_word(
g, g,
ast::AttrStyle::Inner, ast::AttrStyle::Inner,
Unsafe::No,
sym::feature, sym::feature,
sym::prelude_import, sym::prelude_import,
DUMMY_SP, DUMMY_SP,
@ -259,7 +260,8 @@ pub fn print_crate<'a>(
// root, so this is not needed, and actually breaks things. // root, so this is not needed, and actually breaks things.
if edition.is_rust_2015() { if edition.is_rust_2015() {
// `#![no_std]` // `#![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); s.print_attribute(&fake_attr);
} }
} }

View file

@ -17,7 +17,7 @@ pub fn inject(krate: &mut ast::Crate, psess: &ParseSess, attrs: &[String]) {
)); ));
let start_span = parser.token.span; 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, Ok(ai) => ai,
Err(err) => { Err(err) => {
err.emit(); err.emit();
@ -33,6 +33,7 @@ pub fn inject(krate: &mut ast::Crate, psess: &ParseSess, attrs: &[String]) {
krate.attrs.push(mk_attr( krate.attrs.push(mk_attr(
&psess.attr_id_generator, &psess.attr_id_generator,
AttrStyle::Inner, AttrStyle::Inner,
unsafety,
path, path,
args, args,
start_span.to(end_span), start_span.to(end_span),

View file

@ -203,6 +203,7 @@ impl<'a> MutVisitor for EntryPointCleaner<'a> {
let allow_dead_code = attr::mk_attr_nested_word( let allow_dead_code = attr::mk_attr_nested_word(
&self.sess.psess.attr_id_generator, &self.sess.psess.attr_id_generator,
ast::AttrStyle::Outer, ast::AttrStyle::Outer,
ast::Unsafe::No,
sym::allow, sym::allow,
sym::dead_code, sym::dead_code,
self.def_site, self.def_site,

View file

@ -666,7 +666,7 @@ impl<'a> ExtCtxt<'a> {
// Builds `#[name]`. // Builds `#[name]`.
pub fn attr_word(&self, name: Symbol, span: Span) -> ast::Attribute { pub fn attr_word(&self, name: Symbol, span: Span) -> ast::Attribute {
let g = &self.sess.psess.attr_id_generator; 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]`. // Builds `#[name = val]`.
@ -674,12 +674,12 @@ impl<'a> ExtCtxt<'a> {
// Note: `span` is used for both the identifier and the value. // 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 { pub fn attr_name_value_str(&self, name: Symbol, val: Symbol, span: Span) -> ast::Attribute {
let g = &self.sess.psess.attr_id_generator; 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)]`. // Builds `#[outer(inner)]`.
pub fn attr_nested_word(&self, outer: Symbol, inner: Symbol, span: Span) -> ast::Attribute { pub fn attr_nested_word(&self, outer: Symbol, inner: Symbol, span: Span) -> ast::Attribute {
let g = &self.sess.psess.attr_id_generator; 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)
} }
} }

View file

@ -778,7 +778,13 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
if let SyntaxExtensionKind::Derive(..) = ext { if let SyntaxExtensionKind::Derive(..) = ext {
self.gate_proc_macro_input(&item); 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) { let items = match expander.expand(self.cx, span, &meta, item, is_const) {
ExpandResult::Ready(items) => items, ExpandResult::Ready(items) => items,
ExpandResult::Retry(item) => { ExpandResult::Retry(item) => {

View file

@ -59,6 +59,17 @@ pub enum AttributeType {
CrateLevel, 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)] #[derive(Clone, Copy)]
pub enum AttributeGate { pub enum AttributeGate {
/// Is gated by a given feature gate, reason /// Is gated by a given feature gate, reason
@ -177,6 +188,18 @@ macro_rules! ungated {
name: sym::$attr, name: sym::$attr,
encode_cross_crate: $encode_cross_crate, encode_cross_crate: $encode_cross_crate,
type_: $typ, 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, template: $tpl,
gate: Ungated, gate: Ungated,
duplicates: $duplicates, duplicates: $duplicates,
@ -190,6 +213,7 @@ macro_rules! gated {
name: sym::$attr, name: sym::$attr,
encode_cross_crate: $encode_cross_crate, encode_cross_crate: $encode_cross_crate,
type_: $typ, type_: $typ,
safety: AttributeSafety::Normal,
template: $tpl, template: $tpl,
duplicates: $duplicates, duplicates: $duplicates,
gate: Gated(Stability::Unstable, sym::$gate, $msg, cfg_fn!($gate)), gate: Gated(Stability::Unstable, sym::$gate, $msg, cfg_fn!($gate)),
@ -200,6 +224,29 @@ macro_rules! gated {
name: sym::$attr, name: sym::$attr,
encode_cross_crate: $encode_cross_crate, encode_cross_crate: $encode_cross_crate,
type_: $typ, 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, template: $tpl,
duplicates: $duplicates, duplicates: $duplicates,
gate: Gated(Stability::Unstable, sym::$attr, $msg, cfg_fn!($attr)), gate: Gated(Stability::Unstable, sym::$attr, $msg, cfg_fn!($attr)),
@ -228,6 +275,7 @@ macro_rules! rustc_attr {
name: sym::$attr, name: sym::$attr,
encode_cross_crate: $encode_cross_crate, encode_cross_crate: $encode_cross_crate,
type_: $typ, type_: $typ,
safety: AttributeSafety::Normal,
template: $tpl, template: $tpl,
duplicates: $duplicates, duplicates: $duplicates,
gate: Gated(Stability::Unstable, sym::rustc_attrs, $msg, cfg_fn!(rustc_attrs)), 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. /// Otherwise, it can only be used in the local crate.
pub encode_cross_crate: EncodeCrossCrate, pub encode_cross_crate: EncodeCrossCrate,
pub type_: AttributeType, pub type_: AttributeType,
pub safety: AttributeSafety,
pub template: AttributeTemplate, pub template: AttributeTemplate,
pub duplicates: AttributeDuplicates, pub duplicates: AttributeDuplicates,
pub gate: AttributeGate, pub gate: AttributeGate,
@ -375,9 +424,9 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
), ),
ungated!(no_link, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No), ungated!(no_link, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No),
ungated!(repr, Normal, template!(List: "C"), DuplicatesOk, EncodeCrossCrate::No), ungated!(repr, Normal, template!(List: "C"), DuplicatesOk, EncodeCrossCrate::No),
ungated!(export_name, Normal, template!(NameValueStr: "name"), FutureWarnPreceding, EncodeCrossCrate::No), ungated!(unsafe export_name, Normal, template!(NameValueStr: "name"), FutureWarnPreceding, EncodeCrossCrate::No),
ungated!(link_section, Normal, template!(NameValueStr: "name"), FutureWarnPreceding, EncodeCrossCrate::No), ungated!(unsafe link_section, Normal, template!(NameValueStr: "name"), FutureWarnPreceding, EncodeCrossCrate::No),
ungated!(no_mangle, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No), ungated!(unsafe no_mangle, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No),
ungated!(used, Normal, template!(Word, List: "compiler|linker"), WarnFollowing, EncodeCrossCrate::No), ungated!(used, Normal, template!(Word, List: "compiler|linker"), WarnFollowing, EncodeCrossCrate::No),
ungated!(link_ordinal, Normal, template!(List: "ordinal"), ErrorPreceding, EncodeCrossCrate::Yes), 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`. // FIXME: This can be `true` once we always use `tcx.is_diagnostic_item`.
encode_cross_crate: EncodeCrossCrate::Yes, encode_cross_crate: EncodeCrossCrate::Yes,
type_: Normal, type_: Normal,
safety: AttributeSafety::Normal,
template: template!(NameValueStr: "name"), template: template!(NameValueStr: "name"),
duplicates: ErrorFollowing, duplicates: ErrorFollowing,
gate: Gated( gate: Gated(

View file

@ -623,6 +623,7 @@ declare_features! (
/// Allows unsafe on extern declarations and safety qualifiers over internal items. /// Allows unsafe on extern declarations and safety qualifiers over internal items.
(unstable, unsafe_extern_blocks, "CURRENT_RUSTC_VERSION", Some(123743)), (unstable, unsafe_extern_blocks, "CURRENT_RUSTC_VERSION", Some(123743)),
/// Allows unsized fn parameters. /// Allows unsized fn parameters.
(unstable, unsafe_attributes, "CURRENT_RUSTC_VERSION", Some(123757)),
(unstable, unsized_fn_params, "1.49.0", Some(48055)), (unstable, unsized_fn_params, "1.49.0", Some(48055)),
/// Allows unsized rvalues at arguments and parameters. /// Allows unsized rvalues at arguments and parameters.
(incomplete, unsized_locals, "1.30.0", Some(48055)), (incomplete, unsized_locals, "1.30.0", Some(48055)),

View file

@ -7,7 +7,7 @@ use rustc_ast as ast;
use rustc_ast::attr; use rustc_ast::attr;
use rustc_ast::token::{self, Delimiter}; use rustc_ast::token::{self, Delimiter};
use rustc_errors::{codes::*, Diag, PResult}; 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 thin_vec::ThinVec;
use tracing::debug; use tracing::debug;
@ -252,9 +252,23 @@ impl<'a> Parser<'a> {
maybe_whole!(self, NtMeta, |attr| attr.into_inner()); maybe_whole!(self, NtMeta, |attr| attr.into_inner());
let do_parse = |this: &mut Self| { 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 path = this.parse_path(PathStyle::Mod)?;
let args = this.parse_attr_args()?; 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 // Attr items don't have attributes
if capture_tokens { self.collect_tokens_no_attrs(do_parse) } else { do_parse(self) } 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 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 path = self.parse_path(PathStyle::Mod)?;
let kind = self.parse_meta_item_kind()?; let kind = self.parse_meta_item_kind()?;
if is_unsafe {
self.expect(&token::CloseDelim(Delimiter::Parenthesis))?;
}
let span = lo.to(self.prev_token.span); 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> { pub(crate) fn parse_meta_item_kind(&mut self) -> PResult<'a, ast::MetaItemKind> {

View file

@ -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> { pub fn parse_meta<'a>(psess: &'a ParseSess, attr: &Attribute) -> PResult<'a, MetaItem> {
let item = attr.get_normal_item(); let item = attr.get_normal_item();
Ok(MetaItem { Ok(MetaItem {
unsafety: item.unsafety,
span: attr.span, span: attr.span,
path: item.path.clone(), path: item.path.clone(),
kind: match &item.args { kind: match &item.args {

View file

@ -1962,6 +1962,7 @@ symbols! {
unreachable_display, unreachable_display,
unreachable_macro, unreachable_macro,
unrestricted_attribute_tokens, unrestricted_attribute_tokens,
unsafe_attributes,
unsafe_block_in_unsafe_fn, unsafe_block_in_unsafe_fn,
unsafe_cell, unsafe_cell,
unsafe_cell_raw_get, unsafe_cell_raw_get,

View file

@ -1,6 +1,6 @@
use super::*; 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::create_default_session_globals_then;
use rustc_span::symbol::{kw, Ident}; use rustc_span::symbol::{kw, Ident};
use rustc_span::DUMMY_SP; 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 { fn dummy_meta_item_word(name: &str) -> MetaItem {
MetaItem { MetaItem {
unsafety: Unsafe::No,
path: Path::from_ident(Ident::from_str(name)), path: Path::from_ident(Ident::from_str(name)),
kind: MetaItemKind::Word, kind: MetaItemKind::Word,
span: DUMMY_SP, 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 { fn dummy_meta_item_name_value(name: &str, symbol: Symbol, kind: LitKind) -> MetaItem {
let lit = MetaItemLit { symbol, suffix: None, kind, span: DUMMY_SP }; let lit = MetaItemLit { symbol, suffix: None, kind, span: DUMMY_SP };
MetaItem { MetaItem {
unsafety: Unsafe::No,
path: Path::from_ident(Ident::from_str(name)), path: Path::from_ident(Ident::from_str(name)),
kind: MetaItemKind::NameValue(lit), kind: MetaItemKind::NameValue(lit),
span: DUMMY_SP, 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 { macro_rules! dummy_meta_item_list {
($name:ident, [$($list:ident),* $(,)?]) => { ($name:ident, [$($list:ident),* $(,)?]) => {
MetaItem { MetaItem {
unsafety: Unsafe::No,
path: Path::from_ident(Ident::from_str(stringify!($name))), path: Path::from_ident(Ident::from_str(stringify!($name))),
kind: MetaItemKind::List(thin_vec![ kind: MetaItemKind::List(thin_vec![
$( $(
@ -48,6 +51,7 @@ macro_rules! dummy_meta_item_list {
($name:ident, [$($list:expr),* $(,)?]) => { ($name:ident, [$($list:expr),* $(,)?]) => {
MetaItem { MetaItem {
unsafety: Unsafe::No,
path: Path::from_ident(Ident::from_str(stringify!($name))), path: Path::from_ident(Ident::from_str(stringify!($name))),
kind: MetaItemKind::List(thin_vec![ kind: MetaItemKind::List(thin_vec![
$( $(

View file

@ -0,0 +1,8 @@
#[unsafe(no_mangle)] //~ ERROR [E0658]
extern "C" fn foo() {
}
fn main() {
foo();
}

View 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`.