about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorSeo Sanghyeon <sanxiyn@gmail.com>2015-11-14 19:50:46 +0900
committerSeo Sanghyeon <sanxiyn@gmail.com>2015-11-14 19:50:46 +0900
commitcce7b8bd25484a882a2be5472d6a2aadd84e9539 (patch)
treecaa3cf0d28c9a88e3469081743deb44caed3fbec /src/libsyntax
parent289b1b400a01f9cc8a6b75b3083341c1a2170831 (diff)
downloadrust-cce7b8bd25484a882a2be5472d6a2aadd84e9539.tar.gz
rust-cce7b8bd25484a882a2be5472d6a2aadd84e9539.zip
Check macro definition and do not expand invalid macros
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/ext/tt/macro_rules.rs25
1 files changed, 22 insertions, 3 deletions
diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs
index c5cbb95aeeb..323cc53ecef 100644
--- a/src/libsyntax/ext/tt/macro_rules.rs
+++ b/src/libsyntax/ext/tt/macro_rules.rs
@@ -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};
@@ -131,6 +131,7 @@ struct MacroRulesMacroExpander {
     imported_from: Option<ast::Ident>,
     lhses: Vec<TokenTree>,
     rhses: Vec<TokenTree>,
+    valid: bool,
 }
 
 impl TTMacroExpander for MacroRulesMacroExpander {
@@ -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,
@@ -171,7 +175,7 @@ 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) {
@@ -179,7 +183,7 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt,
                 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,
@@ -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, _) => {
@@ -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)
@@ -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> {