parse: Use string literal parsing in the asm
macro
This commit is contained in:
parent
b85a3da421
commit
a699f17483
4 changed files with 56 additions and 59 deletions
|
@ -1073,6 +1073,22 @@ impl<'a> Parser<'a> {
|
||||||
self.maybe_recover_from_bad_qpath(expr, true)
|
self.maybe_recover_from_bad_qpath(expr, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn parse_str_lit(&mut self) -> Result<ast::StrLit, Option<Lit>> {
|
||||||
|
match self.parse_opt_lit() {
|
||||||
|
Some(lit) => match lit.kind {
|
||||||
|
ast::LitKind::Str(symbol_unescaped, style) => Ok(ast::StrLit {
|
||||||
|
style,
|
||||||
|
symbol: lit.token.symbol,
|
||||||
|
suffix: lit.token.suffix,
|
||||||
|
span: lit.span,
|
||||||
|
symbol_unescaped,
|
||||||
|
}),
|
||||||
|
_ => Err(Some(lit)),
|
||||||
|
}
|
||||||
|
None => Err(None),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(super) fn parse_lit(&mut self) -> PResult<'a, Lit> {
|
pub(super) fn parse_lit(&mut self) -> PResult<'a, Lit> {
|
||||||
self.parse_opt_lit().ok_or_else(|| {
|
self.parse_opt_lit().ok_or_else(|| {
|
||||||
let msg = format!("unexpected token: {}", self.this_token_descr());
|
let msg = format!("unexpected token: {}", self.this_token_descr());
|
||||||
|
|
|
@ -3,9 +3,9 @@ use super::diagnostics::{Error, dummy_arg, ConsumeClosingDelim};
|
||||||
|
|
||||||
use crate::maybe_whole;
|
use crate::maybe_whole;
|
||||||
|
|
||||||
use syntax::ast::{self, Abi, DUMMY_NODE_ID, Ident, Attribute, AttrKind, AttrStyle, AnonConst, Item};
|
use syntax::ast::{self, DUMMY_NODE_ID, Ident, Attribute, AttrKind, AttrStyle, AnonConst, Item};
|
||||||
use syntax::ast::{ItemKind, ImplItem, ImplItemKind, TraitItem, TraitItemKind, UseTree, UseTreeKind};
|
use syntax::ast::{ItemKind, ImplItem, ImplItemKind, TraitItem, TraitItemKind, UseTree, UseTreeKind};
|
||||||
use syntax::ast::{PathSegment, IsAuto, Constness, IsAsync, Unsafety, Defaultness};
|
use syntax::ast::{PathSegment, IsAuto, Constness, IsAsync, Unsafety, Defaultness, Extern, StrLit};
|
||||||
use syntax::ast::{Visibility, VisibilityKind, Mutability, FnHeader, ForeignItem, ForeignItemKind};
|
use syntax::ast::{Visibility, VisibilityKind, Mutability, FnHeader, ForeignItem, ForeignItemKind};
|
||||||
use syntax::ast::{Ty, TyKind, Generics, TraitRef, EnumDef, VariantData, StructField};
|
use syntax::ast::{Ty, TyKind, Generics, TraitRef, EnumDef, VariantData, StructField};
|
||||||
use syntax::ast::{Mac, MacDelimiter, Block, BindingMode, FnDecl, FnSig, SelfKind, Param};
|
use syntax::ast::{Mac, MacDelimiter, Block, BindingMode, FnDecl, FnSig, SelfKind, Param};
|
||||||
|
@ -105,7 +105,7 @@ impl<'a> Parser<'a> {
|
||||||
return Ok(Some(self.parse_item_extern_crate(lo, vis, attrs)?));
|
return Ok(Some(self.parse_item_extern_crate(lo, vis, attrs)?));
|
||||||
}
|
}
|
||||||
|
|
||||||
let abi = self.parse_opt_abi();
|
let abi = self.parse_abi();
|
||||||
|
|
||||||
if self.eat_keyword(kw::Fn) {
|
if self.eat_keyword(kw::Fn) {
|
||||||
// EXTERN FUNCTION ITEM
|
// EXTERN FUNCTION ITEM
|
||||||
|
|
|
@ -15,8 +15,8 @@ use crate::{Directory, DirectoryOwnership};
|
||||||
use crate::lexer::UnmatchedBrace;
|
use crate::lexer::UnmatchedBrace;
|
||||||
|
|
||||||
use syntax::ast::{
|
use syntax::ast::{
|
||||||
self, DUMMY_NODE_ID, AttrStyle, Attribute, CrateSugar, Extern, Ident,
|
self, DUMMY_NODE_ID, AttrStyle, Attribute, CrateSugar, Extern, Ident, StrLit,
|
||||||
IsAsync, MacDelimiter, Mutability, StrStyle, Visibility, VisibilityKind, Unsafety,
|
IsAsync, MacDelimiter, Mutability, Visibility, VisibilityKind, Unsafety,
|
||||||
};
|
};
|
||||||
|
|
||||||
use syntax::print::pprust;
|
use syntax::print::pprust;
|
||||||
|
@ -1214,34 +1214,32 @@ impl<'a> Parser<'a> {
|
||||||
/// Parses `extern string_literal?`.
|
/// Parses `extern string_literal?`.
|
||||||
fn parse_extern(&mut self) -> PResult<'a, Extern> {
|
fn parse_extern(&mut self) -> PResult<'a, Extern> {
|
||||||
Ok(if self.eat_keyword(kw::Extern) {
|
Ok(if self.eat_keyword(kw::Extern) {
|
||||||
Extern::from_abi(self.parse_opt_abi())
|
Extern::from_abi(self.parse_abi())
|
||||||
} else {
|
} else {
|
||||||
Extern::None
|
Extern::None
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses a string literal as an ABI spec.
|
/// Parses a string literal as an ABI spec.
|
||||||
fn parse_opt_abi(&mut self) -> Option<StrLit> {
|
fn parse_abi(&mut self) -> Option<StrLit> {
|
||||||
if let Some(ast::Lit { token: token::Lit { symbol, suffix, .. }, span, kind })
|
match self.parse_str_lit() {
|
||||||
= self.parse_opt_lit() {
|
Ok(str_lit) => Some(str_lit),
|
||||||
match kind {
|
Err(Some(lit)) => match lit.kind {
|
||||||
ast::LitKind::Str(symbol_unescaped, style) => return Some(StrLit {
|
ast::LitKind::Err(_) => None,
|
||||||
style, symbol, suffix, span, symbol_unescaped,
|
|
||||||
}),
|
|
||||||
ast::LitKind::Err(_) => {}
|
|
||||||
_ => {
|
_ => {
|
||||||
self.struct_span_err(span, "non-string ABI literal")
|
self.struct_span_err(lit.span, "non-string ABI literal")
|
||||||
.span_suggestion(
|
.span_suggestion(
|
||||||
span,
|
lit.span,
|
||||||
"specify the ABI with a string literal",
|
"specify the ABI with a string literal",
|
||||||
"\"C\"".to_string(),
|
"\"C\"".to_string(),
|
||||||
Applicability::MaybeIncorrect,
|
Applicability::MaybeIncorrect,
|
||||||
)
|
)
|
||||||
.emit();
|
.emit();
|
||||||
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Err(None) => None,
|
||||||
}
|
}
|
||||||
None
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// We are parsing `async fn`. If we are on Rust 2015, emit an error.
|
/// We are parsing `async fn`. If we are on Rust 2015, emit an error.
|
||||||
|
@ -1333,34 +1331,6 @@ impl<'a> Parser<'a> {
|
||||||
self.look_ahead(1, |t| *t == token::OpenDelim(token::Brace) ||
|
self.look_ahead(1, |t| *t == token::OpenDelim(token::Brace) ||
|
||||||
*t == token::BinOp(token::Star))
|
*t == token::BinOp(token::Star))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_optional_str(&mut self) -> Option<(Symbol, ast::StrStyle, Option<ast::Name>)> {
|
|
||||||
let ret = match self.token.kind {
|
|
||||||
token::Literal(token::Lit { kind: token::Str, symbol, suffix }) =>
|
|
||||||
(symbol, ast::StrStyle::Cooked, suffix),
|
|
||||||
token::Literal(token::Lit { kind: token::StrRaw(n), symbol, suffix }) =>
|
|
||||||
(symbol, ast::StrStyle::Raw(n), suffix),
|
|
||||||
_ => return None
|
|
||||||
};
|
|
||||||
self.bump();
|
|
||||||
Some(ret)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn parse_str(&mut self) -> PResult<'a, (Symbol, StrStyle)> {
|
|
||||||
match self.parse_optional_str() {
|
|
||||||
Some((s, style, suf)) => {
|
|
||||||
let sp = self.prev_span;
|
|
||||||
self.expect_no_suffix(sp, "a string literal", suf);
|
|
||||||
Ok((s, style))
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
let msg = "expected string literal";
|
|
||||||
let mut err = self.fatal(msg);
|
|
||||||
err.span_label(self.token.span, msg);
|
|
||||||
Err(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn make_unclosed_delims_error(
|
crate fn make_unclosed_delims_error(
|
||||||
|
|
|
@ -2,19 +2,17 @@
|
||||||
//
|
//
|
||||||
use State::*;
|
use State::*;
|
||||||
|
|
||||||
|
use errors::{DiagnosticBuilder, PResult};
|
||||||
use rustc_data_structures::thin_vec::ThinVec;
|
use rustc_data_structures::thin_vec::ThinVec;
|
||||||
|
use rustc_parse::parser::Parser;
|
||||||
use errors::DiagnosticBuilder;
|
use syntax_expand::base::*;
|
||||||
|
use syntax_pos::Span;
|
||||||
use syntax::ast;
|
use syntax::{span_err, struct_span_err};
|
||||||
use syntax_expand::base::{self, *};
|
use syntax::ast::{self, AsmDialect};
|
||||||
use syntax::token::{self, Token};
|
|
||||||
use syntax::ptr::P;
|
use syntax::ptr::P;
|
||||||
use syntax::symbol::{kw, sym, Symbol};
|
use syntax::symbol::{kw, sym, Symbol};
|
||||||
use syntax::ast::AsmDialect;
|
use syntax::token::{self, Token};
|
||||||
use syntax_pos::Span;
|
|
||||||
use syntax::tokenstream::{self, TokenStream};
|
use syntax::tokenstream::{self, TokenStream};
|
||||||
use syntax::{span_err, struct_span_err};
|
|
||||||
|
|
||||||
use rustc_error_codes::*;
|
use rustc_error_codes::*;
|
||||||
|
|
||||||
|
@ -45,7 +43,7 @@ const OPTIONS: &[Symbol] = &[sym::volatile, sym::alignstack, sym::intel];
|
||||||
pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt<'_>,
|
pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt<'_>,
|
||||||
sp: Span,
|
sp: Span,
|
||||||
tts: TokenStream)
|
tts: TokenStream)
|
||||||
-> Box<dyn base::MacResult + 'cx> {
|
-> Box<dyn MacResult + 'cx> {
|
||||||
let mut inline_asm = match parse_inline_asm(cx, sp, tts) {
|
let mut inline_asm = match parse_inline_asm(cx, sp, tts) {
|
||||||
Ok(Some(inline_asm)) => inline_asm,
|
Ok(Some(inline_asm)) => inline_asm,
|
||||||
Ok(None) => return DummyResult::any(sp),
|
Ok(None) => return DummyResult::any(sp),
|
||||||
|
@ -69,6 +67,19 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt<'_>,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_asm_str<'a>(p: &mut Parser<'a>) -> PResult<'a, Symbol> {
|
||||||
|
match p.parse_str_lit() {
|
||||||
|
Ok(str_lit) => Ok(str_lit.symbol_unescaped),
|
||||||
|
Err(opt_lit) => {
|
||||||
|
let span = opt_lit.map_or(p.token.span, |lit| lit.span);
|
||||||
|
let msg = "expected string literal";
|
||||||
|
let mut err = p.sess.span_diagnostic.struct_span_fatal(span, msg);
|
||||||
|
err.span_label(span, msg);
|
||||||
|
Err(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_inline_asm<'a>(
|
fn parse_inline_asm<'a>(
|
||||||
cx: &mut ExtCtxt<'a>,
|
cx: &mut ExtCtxt<'a>,
|
||||||
sp: Span,
|
sp: Span,
|
||||||
|
@ -144,7 +155,7 @@ fn parse_inline_asm<'a>(
|
||||||
p.eat(&token::Comma);
|
p.eat(&token::Comma);
|
||||||
}
|
}
|
||||||
|
|
||||||
let (constraint, _) = p.parse_str()?;
|
let constraint = parse_asm_str(&mut p)?;
|
||||||
|
|
||||||
let span = p.prev_span;
|
let span = p.prev_span;
|
||||||
|
|
||||||
|
@ -189,7 +200,7 @@ fn parse_inline_asm<'a>(
|
||||||
p.eat(&token::Comma);
|
p.eat(&token::Comma);
|
||||||
}
|
}
|
||||||
|
|
||||||
let (constraint, _) = p.parse_str()?;
|
let constraint = parse_asm_str(&mut p)?;
|
||||||
|
|
||||||
if constraint.as_str().starts_with("=") {
|
if constraint.as_str().starts_with("=") {
|
||||||
span_err!(cx, p.prev_span, E0662,
|
span_err!(cx, p.prev_span, E0662,
|
||||||
|
@ -212,7 +223,7 @@ fn parse_inline_asm<'a>(
|
||||||
p.eat(&token::Comma);
|
p.eat(&token::Comma);
|
||||||
}
|
}
|
||||||
|
|
||||||
let (s, _) = p.parse_str()?;
|
let s = parse_asm_str(&mut p)?;
|
||||||
|
|
||||||
if OPTIONS.iter().any(|&opt| s == opt) {
|
if OPTIONS.iter().any(|&opt| s == opt) {
|
||||||
cx.span_warn(p.prev_span, "expected a clobber, found an option");
|
cx.span_warn(p.prev_span, "expected a clobber, found an option");
|
||||||
|
@ -225,7 +236,7 @@ fn parse_inline_asm<'a>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Options => {
|
Options => {
|
||||||
let (option, _) = p.parse_str()?;
|
let option = parse_asm_str(&mut p)?;
|
||||||
|
|
||||||
if option == sym::volatile {
|
if option == sym::volatile {
|
||||||
// Indicates that the inline assembly has side effects
|
// Indicates that the inline assembly has side effects
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue