about summary refs log tree commit diff
path: root/compiler/rustc_parse
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2024-06-07 20:14:28 +0200
committerGitHub <noreply@github.com>2024-06-07 20:14:28 +0200
commit6e534c73c35f569492ed5fb5f349075d58ed8b7e (patch)
treedb013e765334eeeee9ac1f98c05131cf91371a47 /compiler/rustc_parse
parent0acb5b8513e727ebb4f63d8d8ee8cfa285342a89 (diff)
parentf9104f0dfb531581aa96b19b333835351a566b04 (diff)
downloadrust-6e534c73c35f569492ed5fb5f349075d58ed8b7e.tar.gz
rust-6e534c73c35f569492ed5fb5f349075d58ed8b7e.zip
Rollup merge of #124214 - carbotaniuman:parse_unsafe_attrs, r=michaelwoerister
Parse unsafe attributes

Initial parse implementation for #123757

This is the initial work to parse unsafe attributes, which is represented as an extra `unsafety` field in `MetaItem` and `AttrItem`. There's two areas in the code where it appears that parsing is done manually and not using the parser stuff, and I'm not sure how I'm supposed to thread the change there.
Diffstat (limited to 'compiler/rustc_parse')
-rw-r--r--compiler/rustc_parse/src/parser/attr.rs35
-rw-r--r--compiler/rustc_parse/src/validate_attr.rs1
2 files changed, 33 insertions, 3 deletions
diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs
index 4acc610d8c4..58fef9b6c45 100644
--- a/compiler/rustc_parse/src/parser/attr.rs
+++ b/compiler/rustc_parse/src/parser/attr.rs
@@ -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::Safety::Unsafe(unsafe_span)
+            } else {
+                ast::Safety::Default
+            };
+
             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::Safety::Unsafe(unsafe_span)
+        } else {
+            ast::Safety::Default
+        };
+
         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> {
diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs
index b91ef1ae1f3..58342ff8290 100644
--- a/compiler/rustc_parse/src/validate_attr.rs
+++ b/compiler/rustc_parse/src/validate_attr.rs
@@ -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 {