about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/driver/driver.rs6
-rw-r--r--src/librustdoc/astsrv.rs2
-rw-r--r--src/libsyntax/ext/expand.rs101
-rw-r--r--src/test/run-pass/conditional-debug-macro-off.rs17
-rw-r--r--src/test/run-pass/conditional-debug-macro-on.rs21
5 files changed, 104 insertions, 43 deletions
diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs
index e8ef95b811e..d41c1167c70 100644
--- a/src/librustc/driver/driver.rs
+++ b/src/librustc/driver/driver.rs
@@ -194,6 +194,10 @@ pub fn compile_rest(sess: Session,
         //   mod bar { macro_rules! baz!(() => {{}}) }
         //
         // baz! should not use this definition unless foo is enabled.
+        crate = time(time_passes, ~"std macros injection", ||
+                     syntax::ext::expand::inject_std_macros(sess.parse_sess, copy cfg,
+                                                             crate));
+
         crate = time(time_passes, ~"configuration 1", ||
                      front::config::strip_unconfigured_items(crate));
 
@@ -214,7 +218,7 @@ pub fn compile_rest(sess: Session,
     assert!(phases.from != cu_no_trans);
 
     let (llcx, llmod, link_meta) = {
-        crate = time(time_passes, ~"extra injection", ||
+        crate = time(time_passes, ~"std injection", ||
                      front::std_inject::maybe_inject_libstd_ref(sess, crate));
 
         let ast_map = time(time_passes, ~"ast indexing", ||
diff --git a/src/librustdoc/astsrv.rs b/src/librustdoc/astsrv.rs
index 9c586ae95d1..559186d316e 100644
--- a/src/librustdoc/astsrv.rs
+++ b/src/librustdoc/astsrv.rs
@@ -113,6 +113,8 @@ fn build_ctxt(sess: Session,
 
     use rustc::front::config;
 
+    let ast = syntax::ext::expand::inject_std_macros(sess.parse_sess,
+                                                     copy sess.opts.cfg, ast);
     let ast = config::strip_unconfigured_items(ast);
     let ast = syntax::ext::expand::expand_crate(sess.parse_sess,
                                                 copy sess.opts.cfg, ast);
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index b45cde6a8e3..d63d914edd3 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -8,15 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use ast::{blk_, attribute_, attr_outer, meta_word};
-use ast::{crate, expr_, expr_mac, mac_invoc_tt};
+use ast::{blk_, crate, expr_, expr_mac, mac_invoc_tt};
 use ast::{item_mac, stmt_, stmt_mac, stmt_expr, stmt_semi};
 use ast::{illegal_ctxt};
 use ast;
 use ast_util::{new_rename, new_mark, resolve};
 use attr;
 use codemap;
-use codemap::{span, ExpnInfo, NameAndSpan, spanned};
+use codemap::{span, ExpnInfo, NameAndSpan};
 use ext::base::*;
 use fold::*;
 use parse;
@@ -452,9 +451,11 @@ pub fn new_span(cx: @ExtCtxt, sp: span) -> span {
 // the default compilation environment. It would be much nicer to use
 // a mechanism like syntax_quote to ensure hygiene.
 
-pub fn core_macros() -> @str {
+pub fn std_macros() -> @str {
     return
-@"pub mod macros {
+@"pub mod __std_macros {
+    #[macro_escape];
+
     macro_rules! ignore (($($x:tt)*) => (()))
 
     macro_rules! error (
@@ -484,7 +485,9 @@ pub fn core_macros() -> @str {
         )
     )
 
-    macro_rules! debug (
+    // conditionally define debug!, but keep it type checking even
+    // in non-debug builds.
+    macro_rules! __debug (
         ($arg:expr) => (
             __log(4u32, fmt!( \"%?\", $arg ))
         );
@@ -493,6 +496,22 @@ pub fn core_macros() -> @str {
         )
     )
 
+    #[cfg(debug)]
+    #[macro_escape]
+    mod debug_macro {
+        macro_rules! debug (($($arg:expr),*) => {
+            __debug!($($arg),*)
+        })
+    }
+
+    #[cfg(not(debug))]
+    #[macro_escape]
+    mod debug_macro {
+        macro_rules! debug (($($arg:expr),*) => {
+            if false { __debug!($($arg),*) }
+        })
+    }
+
     macro_rules! fail(
         () => (
             fail!(\"explicit failure\")
@@ -668,6 +687,35 @@ pub fn core_macros() -> @str {
 }";
 }
 
+// add a bunch of macros as though they were placed at the head of the
+// program (ick). This should run before cfg stripping.
+pub fn inject_std_macros(parse_sess: @mut parse::ParseSess,
+                         cfg: ast::crate_cfg, c: &crate) -> @crate {
+    let sm = match parse_item_from_source_str(@"<std-macros>",
+                                              std_macros(),
+                                              copy cfg,
+                                              ~[],
+                                              parse_sess) {
+        Some(item) => item,
+        None => fail!("expected core macros to parse correctly")
+    };
+
+    let injecter = @AstFoldFns {
+        fold_mod: |modd, _| {
+            // just inject the std macros at the start of the first
+            // module in the crate (i.e the crate file itself.)
+            let items = vec::append(~[sm], modd.items);
+            ast::_mod {
+                items: items,
+                // FIXME #2543: Bad copy.
+                .. copy *modd
+            }
+        },
+        .. *default_ast_fold()
+    };
+    @make_fold(injecter).fold_crate(c)
+}
+
 pub fn expand_crate(parse_sess: @mut parse::ParseSess,
                     cfg: ast::crate_cfg, c: &crate) -> @crate {
     // adding *another* layer of indirection here so that the block
@@ -692,33 +740,6 @@ pub fn expand_crate(parse_sess: @mut parse::ParseSess,
         new_span: |a| new_span(cx, a),
         .. *afp};
     let f = make_fold(f_pre);
-    // add a bunch of macros as though they were placed at the
-    // head of the program (ick).
-    let attrs = ~[
-        spanned {
-            span: codemap::dummy_sp(),
-            node: attribute_ {
-                style: attr_outer,
-                value: @spanned {
-                    node: meta_word(@"macro_escape"),
-                    span: codemap::dummy_sp(),
-                },
-                is_sugared_doc: false,
-            }
-        }
-    ];
-
-    let cm = match parse_item_from_source_str(@"<core-macros>",
-                                              core_macros(),
-                                              copy cfg,
-                                              attrs,
-                                              parse_sess) {
-        Some(item) => item,
-        None => cx.bug("expected core macros to parse correctly")
-    };
-    // This is run for its side-effects on the expander env,
-    // as it registers all the core macros as expanders.
-    f.fold_item(cm);
 
     @f.fold_crate(c)
 }
@@ -789,6 +810,8 @@ mod test {
             @"<test>",
             src,
             ~[],sess);
+        let crate_ast = inject_std_macros(sess, ~[], crate_ast);
+        // don't bother with striping, doesn't affect fail!.
         expand_crate(sess,~[],crate_ast);
     }
 
@@ -836,20 +859,14 @@ mod test {
         expand_crate(sess,~[],crate_ast);
     }
 
-    #[test] fn core_macros_must_parse () {
-        let src = @"
-  pub mod macros {
-    macro_rules! ignore (($($x:tt)*) => (()))
-
-    macro_rules! error ( ($( $arg:expr ),+) => (
-        log(::core::error, fmt!( $($arg),+ )) ))
-}";
+    #[test] fn std_macros_must_parse () {
+        let src = super::std_macros();
         let sess = parse::new_parse_sess(None);
         let cfg = ~[];
         let item_ast = parse::parse_item_from_source_str(
             @"<test>",
             src,
-            cfg,~[make_dummy_attr (@"macro_escape")],sess);
+            cfg,~[],sess);
         match item_ast {
             Some(_) => (), // success
             None => fail!("expected this to parse")
diff --git a/src/test/run-pass/conditional-debug-macro-off.rs b/src/test/run-pass/conditional-debug-macro-off.rs
new file mode 100644
index 00000000000..f40c8112e0b
--- /dev/null
+++ b/src/test/run-pass/conditional-debug-macro-off.rs
@@ -0,0 +1,17 @@
+// Copyright 2012 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.
+
+// xfail-fast exec-env directive doesn't work for check-fast
+// exec-env:RUST_LOG=conditional-debug-macro-off=4
+
+fn main() {
+    // only fails if debug! evaluates its argument.
+    debug!({ if true { fail!() } });
+}
\ No newline at end of file
diff --git a/src/test/run-pass/conditional-debug-macro-on.rs b/src/test/run-pass/conditional-debug-macro-on.rs
new file mode 100644
index 00000000000..65b751a5826
--- /dev/null
+++ b/src/test/run-pass/conditional-debug-macro-on.rs
@@ -0,0 +1,21 @@
+// Copyright 2012 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.
+
+// xfail-fast compile-flags directive doesn't work for check-fast
+// compile-flags: --cfg debug
+// exec-env:RUST_LOG=conditional-debug-macro-on=4
+
+fn main() {
+    // exits early if debug! evaluates its arguments, otherwise it
+    // will hit the fail.
+    debug!({ if true { return; } });
+
+    fail!();
+}
\ No newline at end of file