make panictry! private to libsyntax

This commit completely removes usage of the `panictry!` macro from
outside libsyntax. The macro causes parse errors to be fatal, so using
it in libsyntax_ext caused parse failures *within* a syntax extension to
be fatal, which is probably not intended.

Furthermore, this commit adds spans to diagnostics emitted by empty
extensions if they were missing, à la #56491.
This commit is contained in:
Andy Russell
2018-12-04 14:10:32 -05:00
parent cae164753f
commit 0a6fb84738
22 changed files with 451 additions and 134 deletions

View File

@@ -4,6 +4,7 @@ use self::State::*;
use rustc_data_structures::thin_vec::ThinVec;
use errors::DiagnosticBuilder;
use syntax::ast;
use syntax::ext::base;
use syntax::ext::base::*;
@@ -51,6 +52,34 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt,
feature_gate::EXPLAIN_ASM);
}
let mut inline_asm = match parse_inline_asm(cx, sp, tts) {
Ok(Some(inline_asm)) => inline_asm,
Ok(None) => return DummyResult::expr(sp),
Err(mut err) => {
err.emit();
return DummyResult::expr(sp);
}
};
// If there are no outputs, the inline assembly is executed just for its side effects,
// so ensure that it is volatile
if inline_asm.outputs.is_empty() {
inline_asm.volatile = true;
}
MacEager::expr(P(ast::Expr {
id: ast::DUMMY_NODE_ID,
node: ast::ExprKind::InlineAsm(P(inline_asm)),
span: sp,
attrs: ThinVec::new(),
}))
}
fn parse_inline_asm<'a>(
cx: &mut ExtCtxt<'a>,
sp: Span,
tts: &[tokenstream::TokenTree],
) -> Result<Option<ast::InlineAsm>, DiagnosticBuilder<'a>> {
// Split the tts before the first colon, to avoid `asm!("x": y)` being
// parsed as `asm!(z)` with `z = "x": y` which is type ascription.
let first_colon = tts.iter()
@@ -80,22 +109,33 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt,
if asm_str_style.is_some() {
// If we already have a string with instructions,
// ending up in Asm state again is an error.
span_err!(cx, sp, E0660, "malformed inline assembly");
return DummyResult::expr(sp);
return Err(struct_span_err!(
cx.parse_sess.span_diagnostic,
sp,
E0660,
"malformed inline assembly"
));
}
// Nested parser, stop before the first colon (see above).
let mut p2 = cx.new_parser_from_tts(&tts[..first_colon]);
let (s, style) = match expr_to_string(cx,
panictry!(p2.parse_expr()),
"inline assembly must be a string literal") {
Some((s, st)) => (s, st),
// let compilation continue
None => return DummyResult::expr(sp),
};
if p2.token == token::Eof {
let mut err =
cx.struct_span_err(sp, "macro requires a string literal as an argument");
err.span_label(sp, "string literal required");
return Err(err);
}
let expr = p2.parse_expr()?;
let (s, style) =
match expr_to_string(cx, expr, "inline assembly must be a string literal") {
Some((s, st)) => (s, st),
None => return Ok(None),
};
// This is most likely malformed.
if p2.token != token::Eof {
let mut extra_tts = panictry!(p2.parse_all_token_trees());
let mut extra_tts = p2.parse_all_token_trees()?;
extra_tts.extend(tts[first_colon..].iter().cloned());
p = parse::stream_to_parser(cx.parse_sess, extra_tts.into_iter().collect());
}
@@ -105,18 +145,17 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt,
}
Outputs => {
while p.token != token::Eof && p.token != token::Colon && p.token != token::ModSep {
if !outputs.is_empty() {
p.eat(&token::Comma);
}
let (constraint, _str_style) = panictry!(p.parse_str());
let (constraint, _) = p.parse_str()?;
let span = p.prev_span;
panictry!(p.expect(&token::OpenDelim(token::Paren)));
let out = panictry!(p.parse_expr());
panictry!(p.expect(&token::CloseDelim(token::Paren)));
p.expect(&token::OpenDelim(token::Paren))?;
let expr = p.parse_expr()?;
p.expect(&token::CloseDelim(token::Paren))?;
// Expands a read+write operand into two operands.
//
@@ -143,7 +182,7 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt,
let is_indirect = constraint_str.contains("*");
outputs.push(ast::InlineAsmOutput {
constraint: output.unwrap_or(constraint),
expr: out,
expr,
is_rw,
is_indirect,
});
@@ -151,12 +190,11 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt,
}
Inputs => {
while p.token != token::Eof && p.token != token::Colon && p.token != token::ModSep {
if !inputs.is_empty() {
p.eat(&token::Comma);
}
let (constraint, _str_style) = panictry!(p.parse_str());
let (constraint, _) = p.parse_str()?;
if constraint.as_str().starts_with("=") {
span_err!(cx, p.prev_span, E0662,
@@ -166,21 +204,20 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt,
"input operand constraint contains '+'");
}
panictry!(p.expect(&token::OpenDelim(token::Paren)));
let input = panictry!(p.parse_expr());
panictry!(p.expect(&token::CloseDelim(token::Paren)));
p.expect(&token::OpenDelim(token::Paren))?;
let input = p.parse_expr()?;
p.expect(&token::CloseDelim(token::Paren))?;
inputs.push((constraint, input));
}
}
Clobbers => {
while p.token != token::Eof && p.token != token::Colon && p.token != token::ModSep {
if !clobs.is_empty() {
p.eat(&token::Comma);
}
let (s, _str_style) = panictry!(p.parse_str());
let (s, _) = p.parse_str()?;
if OPTIONS.iter().any(|&opt| s == opt) {
cx.span_warn(p.prev_span, "expected a clobber, found an option");
@@ -193,7 +230,7 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt,
}
}
Options => {
let (option, _str_style) = panictry!(p.parse_str());
let (option, _) = p.parse_str()?;
if option == "volatile" {
// Indicates that the inline assembly has side effects
@@ -234,26 +271,15 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt,
}
}
// If there are no outputs, the inline assembly is executed just for its side effects,
// so ensure that it is volatile
if outputs.is_empty() {
volatile = true;
}
MacEager::expr(P(ast::Expr {
id: ast::DUMMY_NODE_ID,
node: ast::ExprKind::InlineAsm(P(ast::InlineAsm {
asm,
asm_str_style: asm_str_style.unwrap(),
outputs,
inputs,
clobbers: clobs,
volatile,
alignstack,
dialect,
ctxt: cx.backtrace(),
})),
span: sp,
attrs: ThinVec::new(),
Ok(Some(ast::InlineAsm {
asm,
asm_str_style: asm_str_style.unwrap(),
outputs,
inputs,
clobbers: clobs,
volatile,
alignstack,
dialect,
ctxt: cx.backtrace(),
}))
}