Skip to content

Commit

Permalink
Check macro definition and do not expand invalid macros
Browse files Browse the repository at this point in the history
  • Loading branch information
sanxiyn committed Nov 14, 2015
1 parent 289b1b4 commit cce7b8b
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 4 deletions.
25 changes: 22 additions & 3 deletions src/libsyntax/ext/tt/macro_rules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

use ast::{self, TokenTree};
use codemap::{Span, DUMMY_SP};
use ext::base::{ExtCtxt, MacResult, SyntaxExtension};
use ext::base::{DummyResult, ExtCtxt, MacResult, SyntaxExtension};
use ext::base::{NormalTT, TTMacroExpander};
use ext::tt::macro_parser::{Success, Error, Failure};
use ext::tt::macro_parser::{MatchedSeq, MatchedNonterminal};
Expand Down Expand Up @@ -131,6 +131,7 @@ struct MacroRulesMacroExpander {
imported_from: Option<ast::Ident>,
lhses: Vec<TokenTree>,
rhses: Vec<TokenTree>,
valid: bool,
}

impl TTMacroExpander for MacroRulesMacroExpander {
Expand All @@ -139,6 +140,9 @@ impl TTMacroExpander for MacroRulesMacroExpander {
sp: Span,
arg: &[TokenTree])
-> Box<MacResult+'cx> {
if !self.valid {
return DummyResult::any(sp);
}
generic_extension(cx,
sp,
self.name,
Expand Down Expand Up @@ -171,15 +175,15 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt,
for (i, lhs) in lhses.iter().enumerate() { // try each arm's matchers
let lhs_tt = match *lhs {
TokenTree::Delimited(_, ref delim) => &delim.tts[..],
_ => panic!(cx.span_fatal(sp, "malformed macro lhs"))
_ => cx.span_bug(sp, "malformed macro lhs")
};

match TokenTree::parse(cx, lhs_tt, arg) {
Success(named_matches) => {
let rhs = match rhses[i] {
// ignore delimiters
TokenTree::Delimited(_, ref delimed) => delimed.tts.clone(),
_ => panic!(cx.span_fatal(sp, "macro rhs must be delimited")),
_ => cx.span_bug(sp, "malformed macro rhs"),
};
// rhs has holes ( `$id` and `$(...)` that need filled)
let trncbr = new_tt_reader(&cx.parse_sess().span_diagnostic,
Expand Down Expand Up @@ -271,6 +275,8 @@ pub fn compile<'cx>(cx: &'cx mut ExtCtxt,
}
};

let mut valid = true;

// Extract the arguments:
let lhses = match **argument_map.get(&lhs_nm.name).unwrap() {
MatchedSeq(ref s, _) => {
Expand All @@ -296,11 +302,16 @@ pub fn compile<'cx>(cx: &'cx mut ExtCtxt,
_ => cx.span_bug(def.span, "wrong-structured rhs")
};

for rhs in &rhses {
valid &= check_rhs(cx, rhs);
}

let exp: Box<_> = Box::new(MacroRulesMacroExpander {
name: def.ident,
imported_from: def.imported_from,
lhses: lhses,
rhses: rhses,
valid: valid,
});

NormalTT(exp, Some(def.span), def.allow_internal_unstable)
Expand All @@ -323,6 +334,14 @@ fn check_lhs_nt_follows(cx: &mut ExtCtxt, lhs: &TokenTree, sp: Span) {
// after parsing/expansion. we can report every error in every macro this way.
}

fn check_rhs(cx: &mut ExtCtxt, rhs: &TokenTree) -> bool {
match *rhs {
TokenTree::Delimited(..) => return true,
_ => cx.span_err(rhs.get_span(), "macro rhs must be delimited")
}
false
}

// returns the last token that was checked, for TokenTree::Sequence. this gets used later on.
fn check_matcher<'a, I>(cx: &mut ExtCtxt, matcher: I, follow: &Token)
-> Option<(Span, Token)> where I: Iterator<Item=&'a TokenTree> {
Expand Down
19 changes: 19 additions & 0 deletions src/test/compile-fail/macro-error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// Check that we report errors at macro definition, not expansion.

macro_rules! foo {
($a:expr) => $a; //~ ERROR macro rhs must be delimited
}

fn main() {
foo!(0);
}
2 changes: 1 addition & 1 deletion src/test/compile-fail/type-macros-fail.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
// except according to those terms.

macro_rules! Id {
{ $T:tt } => $T
($T:tt) => ($T);
}

struct Foo<T> {
Expand Down

0 comments on commit cce7b8b

Please sign in to comment.