Skip to content

Commit

Permalink
Don't panic for fatal errors in attribute parsing.
Browse files Browse the repository at this point in the history
  • Loading branch information
eefriedman committed Oct 28, 2015
1 parent c141f47 commit de95857
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 54 deletions.
2 changes: 1 addition & 1 deletion src/libsyntax/ext/cfg.rs
Expand Up @@ -26,7 +26,7 @@ pub fn expand_cfg<'cx>(cx: &mut ExtCtxt,
tts: &[ast::TokenTree])
-> Box<base::MacResult+'static> {
let mut p = cx.new_parser_from_tts(tts);
let cfg = p.parse_meta_item();
let cfg = panictry!(p.parse_meta_item());

if !panictry!(p.eat(&token::Eof)){
cx.span_err(sp, "expected 1 cfg-pattern");
Expand Down
2 changes: 1 addition & 1 deletion src/libsyntax/ext/tt/macro_parser.rs
Expand Up @@ -526,7 +526,7 @@ pub fn parse_nt(p: &mut Parser, sp: Span, name: &str) -> Nonterminal {
"path" => {
token::NtPath(Box::new(panictry!(p.parse_path(LifetimeAndTypesWithoutColons))))
},
"meta" => token::NtMeta(p.parse_meta_item()),
"meta" => token::NtMeta(panictry!(p.parse_meta_item())),
_ => {
panic!(p.span_fatal_help(sp,
&format!("invalid fragment specifier `{}`", name),
Expand Down
69 changes: 35 additions & 34 deletions src/libsyntax/parse/attr.rs
Expand Up @@ -12,20 +12,21 @@ use attr;
use ast;
use codemap::{spanned, Spanned, mk_sp, Span};
use parse::common::*; //resolve bug?
use parse::PResult;
use parse::token;
use parse::parser::{Parser, TokenType};
use ptr::P;

impl<'a> Parser<'a> {
/// Parse attributes that appear before an item
pub fn parse_outer_attributes(&mut self) -> Vec<ast::Attribute> {
pub fn parse_outer_attributes(&mut self) -> PResult<Vec<ast::Attribute>> {
let mut attrs: Vec<ast::Attribute> = Vec::new();
loop {
debug!("parse_outer_attributes: self.token={:?}",
self.token);
match self.token {
token::Pound => {
attrs.push(self.parse_attribute(false));
attrs.push(try!(self.parse_attribute(false)));
}
token::DocComment(s) => {
let attr = ::attr::mk_sugared_doc_attr(
Expand All @@ -35,32 +36,32 @@ impl<'a> Parser<'a> {
self.span.hi
);
if attr.node.style != ast::AttrStyle::Outer {
panic!(self.fatal("expected outer comment"));
return Err(self.fatal("expected outer comment"));
}
attrs.push(attr);
panictry!(self.bump());
try!(self.bump());
}
_ => break
}
}
return attrs;
return Ok(attrs);
}

/// Matches `attribute = # ! [ meta_item ]`
///
/// If permit_inner is true, then a leading `!` indicates an inner
/// attribute
fn parse_attribute(&mut self, permit_inner: bool) -> ast::Attribute {
fn parse_attribute(&mut self, permit_inner: bool) -> PResult<ast::Attribute> {
debug!("parse_attributes: permit_inner={:?} self.token={:?}",
permit_inner, self.token);
let (span, value, mut style) = match self.token {
token::Pound => {
let lo = self.span.lo;
panictry!(self.bump());
try!(self.bump());

if permit_inner { self.expected_tokens.push(TokenType::Token(token::Not)); }
let style = if self.token == token::Not {
panictry!(self.bump());
try!(self.bump());
if !permit_inner {
let span = self.span;
self.span_err(span,
Expand All @@ -74,43 +75,43 @@ impl<'a> Parser<'a> {
ast::AttrStyle::Outer
};

panictry!(self.expect(&token::OpenDelim(token::Bracket)));
let meta_item = self.parse_meta_item();
try!(self.expect(&token::OpenDelim(token::Bracket)));
let meta_item = try!(self.parse_meta_item());
let hi = self.span.hi;
panictry!(self.expect(&token::CloseDelim(token::Bracket)));
try!(self.expect(&token::CloseDelim(token::Bracket)));

(mk_sp(lo, hi), meta_item, style)
}
_ => {
let token_str = self.this_token_to_string();
panic!(self.fatal(&format!("expected `#`, found `{}`", token_str)));
return Err(self.fatal(&format!("expected `#`, found `{}`", token_str)));
}
};

if permit_inner && self.token == token::Semi {
panictry!(self.bump());
try!(self.bump());
self.span_warn(span, "this inner attribute syntax is deprecated. \
The new syntax is `#![foo]`, with a bang and no semicolon");
style = ast::AttrStyle::Inner;
}

return Spanned {
Ok(Spanned {
span: span,
node: ast::Attribute_ {
id: attr::mk_attr_id(),
style: style,
value: value,
is_sugared_doc: false
}
};
})
}

/// Parse attributes that appear after the opening of an item. These should
/// be preceded by an exclamation mark, but we accept and warn about one
/// terminated by a semicolon.

/// matches inner_attrs*
pub fn parse_inner_attributes(&mut self) -> Vec<ast::Attribute> {
pub fn parse_inner_attributes(&mut self) -> PResult<Vec<ast::Attribute>> {
let mut attrs: Vec<ast::Attribute> = vec![];
loop {
match self.token {
Expand All @@ -120,7 +121,7 @@ impl<'a> Parser<'a> {
break;
}

let attr = self.parse_attribute(true);
let attr = try!(self.parse_attribute(true));
assert!(attr.node.style == ast::AttrStyle::Inner);
attrs.push(attr);
}
Expand All @@ -131,21 +132,21 @@ impl<'a> Parser<'a> {
let attr = attr::mk_sugared_doc_attr(attr::mk_attr_id(), str, lo, hi);
if attr.node.style == ast::AttrStyle::Inner {
attrs.push(attr);
panictry!(self.bump());
try!(self.bump());
} else {
break;
}
}
_ => break
}
}
attrs
Ok(attrs)
}

/// matches meta_item = IDENT
/// | IDENT = lit
/// | IDENT meta_seq
pub fn parse_meta_item(&mut self) -> P<ast::MetaItem> {
pub fn parse_meta_item(&mut self) -> PResult<P<ast::MetaItem>> {
let nt_meta = match self.token {
token::Interpolated(token::NtMeta(ref e)) => {
Some(e.clone())
Expand All @@ -155,19 +156,19 @@ impl<'a> Parser<'a> {

match nt_meta {
Some(meta) => {
panictry!(self.bump());
return meta;
try!(self.bump());
return Ok(meta);
}
None => {}
}

let lo = self.span.lo;
let ident = panictry!(self.parse_ident());
let ident = try!(self.parse_ident());
let name = self.id_to_interned_str(ident);
match self.token {
token::Eq => {
panictry!(self.bump());
let lit = panictry!(self.parse_lit());
try!(self.bump());
let lit = try!(self.parse_lit());
// FIXME #623 Non-string meta items are not serialized correctly;
// just forbid them for now
match lit.node {
Expand All @@ -179,25 +180,25 @@ impl<'a> Parser<'a> {
}
}
let hi = self.span.hi;
P(spanned(lo, hi, ast::MetaNameValue(name, lit)))
Ok(P(spanned(lo, hi, ast::MetaNameValue(name, lit))))
}
token::OpenDelim(token::Paren) => {
let inner_items = self.parse_meta_seq();
let inner_items = try!(self.parse_meta_seq());
let hi = self.span.hi;
P(spanned(lo, hi, ast::MetaList(name, inner_items)))
Ok(P(spanned(lo, hi, ast::MetaList(name, inner_items))))
}
_ => {
let hi = self.last_span.hi;
P(spanned(lo, hi, ast::MetaWord(name)))
Ok(P(spanned(lo, hi, ast::MetaWord(name))))
}
}
}

/// matches meta_seq = ( COMMASEP(meta_item) )
fn parse_meta_seq(&mut self) -> Vec<P<ast::MetaItem>> {
panictry!(self.parse_seq(&token::OpenDelim(token::Paren),
&token::CloseDelim(token::Paren),
seq_sep_trailing_allowed(token::Comma),
|p| Ok(p.parse_meta_item()))).node
fn parse_meta_seq(&mut self) -> PResult<Vec<P<ast::MetaItem>>> {
self.parse_unspanned_seq(&token::OpenDelim(token::Paren),
&token::CloseDelim(token::Paren),
seq_sep_trailing_allowed(token::Comma),
|p| p.parse_meta_item())
}
}
7 changes: 4 additions & 3 deletions src/libsyntax/parse/mod.rs
Expand Up @@ -82,7 +82,8 @@ pub fn parse_crate_attrs_from_file(
cfg: ast::CrateConfig,
sess: &ParseSess
) -> Vec<ast::Attribute> {
new_parser_from_file(sess, cfg, input).parse_inner_attributes()
// FIXME: maybe_aborted?
panictry!(new_parser_from_file(sess, cfg, input).parse_inner_attributes())
}

pub fn parse_crate_from_source_str(name: String,
Expand All @@ -106,7 +107,7 @@ pub fn parse_crate_attrs_from_source_str(name: String,
cfg,
name,
source);
maybe_aborted(p.parse_inner_attributes(), p)
maybe_aborted(panictry!(p.parse_inner_attributes()), p)
}

pub fn parse_expr_from_source_str(name: String,
Expand All @@ -133,7 +134,7 @@ pub fn parse_meta_from_source_str(name: String,
sess: &ParseSess)
-> P<ast::MetaItem> {
let mut p = new_parser_from_source_str(sess, cfg, name, source);
maybe_aborted(p.parse_meta_item(), p)
maybe_aborted(panictry!(p.parse_meta_item()), p)
}

pub fn parse_stmt_from_source_str(name: String,
Expand Down
30 changes: 15 additions & 15 deletions src/libsyntax/parse/parser.rs
Expand Up @@ -1174,7 +1174,7 @@ impl<'a> Parser<'a> {
seq_sep_none(),
|p| -> PResult<P<TraitItem>> {
maybe_whole!(no_clone p, NtTraitItem);
let mut attrs = p.parse_outer_attributes();
let mut attrs = try!(p.parse_outer_attributes());
let lo = p.span.lo;

let (name, node) = if try!(p.eat_keyword(keywords::Type)) {
Expand Down Expand Up @@ -2956,7 +2956,7 @@ impl<'a> Parser<'a> {
pub fn parse_arm_nopanic(&mut self) -> PResult<Arm> {
maybe_whole!(no_clone self, NtArm);

let attrs = self.parse_outer_attributes();
let attrs = try!(self.parse_outer_attributes());
let pats = try!(self.parse_pats());
let mut guard = None;
if try!(self.eat_keyword(keywords::If) ){
Expand Down Expand Up @@ -3465,7 +3465,7 @@ impl<'a> Parser<'a> {
}
}

let attrs = self.parse_outer_attributes();
let attrs = try!(self.parse_outer_attributes());
let lo = self.span.lo;

Ok(Some(if self.check_keyword(keywords::Let) {
Expand Down Expand Up @@ -3607,7 +3607,7 @@ impl<'a> Parser<'a> {

let lo = self.span.lo;
try!(self.expect(&token::OpenDelim(token::Brace)));
Ok((self.parse_inner_attributes(),
Ok((try!(self.parse_inner_attributes()),
try!(self.parse_block_tail(lo, DefaultBlock))))
}

Expand Down Expand Up @@ -4431,7 +4431,7 @@ impl<'a> Parser<'a> {
pub fn parse_impl_item(&mut self) -> PResult<P<ImplItem>> {
maybe_whole!(no_clone self, NtImplItem);

let mut attrs = self.parse_outer_attributes();
let mut attrs = try!(self.parse_outer_attributes());
let lo = self.span.lo;
let vis = try!(self.parse_visibility());
let (name, node) = if try!(self.eat_keyword(keywords::Type)) {
Expand Down Expand Up @@ -4608,7 +4608,7 @@ impl<'a> Parser<'a> {
generics.where_clause = try!(self.parse_where_clause());

try!(self.expect(&token::OpenDelim(token::Brace)));
let attrs = self.parse_inner_attributes();
let attrs = try!(self.parse_inner_attributes());

let mut impl_items = vec![];
while !try!(self.eat(&token::CloseDelim(token::Brace))) {
Expand Down Expand Up @@ -4727,7 +4727,7 @@ impl<'a> Parser<'a> {
&token::CloseDelim(token::Paren),
seq_sep_trailing_allowed(token::Comma),
|p| {
let attrs = p.parse_outer_attributes();
let attrs = try!(p.parse_outer_attributes());
let lo = p.span.lo;
let struct_field_ = ast::StructField_ {
kind: UnnamedField(try!(p.parse_visibility())),
Expand Down Expand Up @@ -4769,7 +4769,7 @@ impl<'a> Parser<'a> {
/// Parse an element of a struct definition
fn parse_struct_decl_field(&mut self, allow_pub: bool) -> PResult<StructField> {

let attrs = self.parse_outer_attributes();
let attrs = try!(self.parse_outer_attributes());

if try!(self.eat_keyword(keywords::Pub) ){
if !allow_pub {
Expand Down Expand Up @@ -4841,7 +4841,7 @@ impl<'a> Parser<'a> {
let mod_inner_lo = self.span.lo;
let old_owns_directory = self.owns_directory;
self.owns_directory = true;
let attrs = self.parse_inner_attributes();
let attrs = try!(self.parse_inner_attributes());
let m = try!(self.parse_mod_items(&token::CloseDelim(token::Brace), mod_inner_lo));
self.owns_directory = old_owns_directory;
self.pop_mod_path();
Expand Down Expand Up @@ -4990,7 +4990,7 @@ impl<'a> Parser<'a> {
Some(name),
id_sp);
let mod_inner_lo = p0.span.lo;
let mod_attrs = p0.parse_inner_attributes();
let mod_attrs = try!(p0.parse_inner_attributes());
let m0 = try!(p0.parse_mod_items(&token::Eof, mod_inner_lo));
self.sess.included_mod_stack.borrow_mut().pop();
Ok((ast::ItemMod(m0), mod_attrs))
Expand Down Expand Up @@ -5093,7 +5093,7 @@ impl<'a> Parser<'a> {

let abi = opt_abi.unwrap_or(abi::C);

attrs.extend(self.parse_inner_attributes());
attrs.extend(try!(self.parse_inner_attributes()));

let mut foreign_items = vec![];
while let Some(item) = try!(self.parse_foreign_item()) {
Expand Down Expand Up @@ -5143,7 +5143,7 @@ impl<'a> Parser<'a> {
let mut all_nullary = true;
let mut any_disr = None;
while self.token != token::CloseDelim(token::Brace) {
let variant_attrs = self.parse_outer_attributes();
let variant_attrs = try!(self.parse_outer_attributes());
let vlo = self.span.lo;

let struct_def;
Expand Down Expand Up @@ -5505,7 +5505,7 @@ impl<'a> Parser<'a> {

/// Parse a foreign item.
fn parse_foreign_item(&mut self) -> PResult<Option<P<ForeignItem>>> {
let attrs = self.parse_outer_attributes();
let attrs = try!(self.parse_outer_attributes());
let lo = self.span.lo;
let visibility = try!(self.parse_visibility());

Expand Down Expand Up @@ -5605,7 +5605,7 @@ impl<'a> Parser<'a> {
}

pub fn parse_item_nopanic(&mut self) -> PResult<Option<P<Item>>> {
let attrs = self.parse_outer_attributes();
let attrs = try!(self.parse_outer_attributes());
self.parse_item_(attrs, true)
}

Expand Down Expand Up @@ -5724,7 +5724,7 @@ impl<'a> Parser<'a> {
pub fn parse_crate_mod(&mut self) -> PResult<Crate> {
let lo = self.span.lo;
Ok(ast::Crate {
attrs: self.parse_inner_attributes(),
attrs: try!(self.parse_inner_attributes()),
module: try!(self.parse_mod_items(&token::Eof, lo)),
config: self.cfg.clone(),
span: mk_sp(lo, self.span.lo),
Expand Down

0 comments on commit de95857

Please sign in to comment.