about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-09-20 04:55:41 +0000
committerbors <bors@rust-lang.org>2014-09-20 04:55:41 +0000
commitf7fb0f5a172bcde42293bf64ffafd1e5df4bd0f8 (patch)
tree6f9513f09a30e3aae088a378d86a2c842ce8dd1e /src
parentaef6c4b1382dcf2f943bd5872656625f935c0b7c (diff)
parent5b42f79ff088bf3f9136f6f668a481097e22bed9 (diff)
downloadrust-f7fb0f5a172bcde42293bf64ffafd1e5df4bd0f8.tar.gz
rust-f7fb0f5a172bcde42293bf64ffafd1e5df4bd0f8.zip
auto merge of #17319 : kmcallister/rust/method-macro-bt, r=pcwalton
We were leaving these on the stack, causing spurious backtraces.
Diffstat (limited to 'src')
-rw-r--r--src/compiletest/header.rs15
-rw-r--r--src/compiletest/runtest.rs40
-rw-r--r--src/libsyntax/ext/expand.rs5
-rw-r--r--src/test/compile-fail/method-macro-backtrace.rs37
4 files changed, 83 insertions, 14 deletions
diff --git a/src/compiletest/header.rs b/src/compiletest/header.rs
index 9ad2582dec8..cc765695cb7 100644
--- a/src/compiletest/header.rs
+++ b/src/compiletest/header.rs
@@ -42,6 +42,8 @@ pub struct TestProps {
     pub pretty_mode: String,
     // Only compare pretty output and don't try compiling
     pub pretty_compare_only: bool,
+    // Patterns which must not appear in the output of a cfail test.
+    pub forbid_output: Vec<String>,
 }
 
 // Load any test directives embedded in the file
@@ -59,6 +61,7 @@ pub fn load_props(testfile: &Path) -> TestProps {
     let mut no_pretty_expanded = false;
     let mut pretty_mode = None;
     let mut pretty_compare_only = false;
+    let mut forbid_output = Vec::new();
     iter_header(testfile, |ln| {
         match parse_error_pattern(ln) {
           Some(ep) => error_patterns.push(ep),
@@ -116,6 +119,11 @@ pub fn load_props(testfile: &Path) -> TestProps {
             None => ()
         };
 
+        match parse_forbid_output(ln) {
+            Some(of) => forbid_output.push(of),
+            None => (),
+        }
+
         true
     });
 
@@ -132,7 +140,8 @@ pub fn load_props(testfile: &Path) -> TestProps {
         no_prefer_dynamic: no_prefer_dynamic,
         no_pretty_expanded: no_pretty_expanded,
         pretty_mode: pretty_mode.unwrap_or("normal".to_string()),
-        pretty_compare_only: pretty_compare_only
+        pretty_compare_only: pretty_compare_only,
+        forbid_output: forbid_output,
     }
 }
 
@@ -210,6 +219,10 @@ fn parse_error_pattern(line: &str) -> Option<String> {
     parse_name_value_directive(line, "error-pattern")
 }
 
+fn parse_forbid_output(line: &str) -> Option<String> {
+    parse_name_value_directive(line, "forbid-output")
+}
+
 fn parse_aux_build(line: &str) -> Option<String> {
     parse_name_value_directive(line, "aux-build")
 }
diff --git a/src/compiletest/runtest.rs b/src/compiletest/runtest.rs
index 40acb7da175..d64d3317e2e 100644
--- a/src/compiletest/runtest.rs
+++ b/src/compiletest/runtest.rs
@@ -71,6 +71,14 @@ pub fn run_metrics(config: Config, testfile: String, mm: &mut MetricMap) {
     }
 }
 
+fn get_output(props: &TestProps, proc_res: &ProcRes) -> String {
+    if props.check_stdout {
+        format!("{}{}", proc_res.stdout, proc_res.stderr)
+    } else {
+        proc_res.stderr.clone()
+    }
+}
+
 fn run_cfail_test(config: &Config, props: &TestProps, testfile: &Path) {
     let proc_res = compile_test(config, props, testfile);
 
@@ -81,6 +89,11 @@ fn run_cfail_test(config: &Config, props: &TestProps, testfile: &Path) {
 
     check_correct_failure_status(&proc_res);
 
+    if proc_res.status.success() {
+        fatal("process did not return an error status");
+    }
+
+    let output_to_check = get_output(props, &proc_res);
     let expected_errors = errors::load_errors(&config.cfail_regex, testfile);
     if !expected_errors.is_empty() {
         if !props.error_patterns.is_empty() {
@@ -88,9 +101,10 @@ fn run_cfail_test(config: &Config, props: &TestProps, testfile: &Path) {
         }
         check_expected_errors(expected_errors, testfile, &proc_res);
     } else {
-        check_error_patterns(props, testfile, &proc_res);
+        check_error_patterns(props, testfile, output_to_check.as_slice(), &proc_res);
     }
     check_no_compiler_crash(&proc_res);
+    check_forbid_output(props, output_to_check.as_slice(), &proc_res);
 }
 
 fn run_rfail_test(config: &Config, props: &TestProps, testfile: &Path) {
@@ -112,8 +126,9 @@ fn run_rfail_test(config: &Config, props: &TestProps, testfile: &Path) {
         fatal_proc_rec("run-fail test isn't valgrind-clean!", &proc_res);
     }
 
+    let output_to_check = get_output(props, &proc_res);
     check_correct_failure_status(&proc_res);
-    check_error_patterns(props, testfile, &proc_res);
+    check_error_patterns(props, testfile, output_to_check.as_slice(), &proc_res);
 }
 
 fn check_correct_failure_status(proc_res: &ProcRes) {
@@ -834,24 +849,15 @@ fn check_debugger_output(debugger_run_result: &ProcRes, check_lines: &[String])
 
 fn check_error_patterns(props: &TestProps,
                         testfile: &Path,
+                        output_to_check: &str,
                         proc_res: &ProcRes) {
     if props.error_patterns.is_empty() {
         fatal(format!("no error pattern specified in {}",
                       testfile.display()).as_slice());
     }
-
-    if proc_res.status.success() {
-        fatal("process did not return an error status");
-    }
-
     let mut next_err_idx = 0u;
     let mut next_err_pat = &props.error_patterns[next_err_idx];
     let mut done = false;
-    let output_to_check = if props.check_stdout {
-        format!("{}{}", proc_res.stdout, proc_res.stderr)
-    } else {
-        proc_res.stderr.clone()
-    };
     for line in output_to_check.as_slice().lines() {
         if line.contains(next_err_pat.as_slice()) {
             debug!("found error pattern {}", next_err_pat);
@@ -890,6 +896,16 @@ fn check_no_compiler_crash(proc_res: &ProcRes) {
     }
 }
 
+fn check_forbid_output(props: &TestProps,
+                       output_to_check: &str,
+                       proc_res: &ProcRes) {
+    for pat in props.forbid_output.iter() {
+        if output_to_check.contains(pat.as_slice()) {
+            fatal_proc_rec("forbidden pattern found in compiler output", proc_res);
+        }
+    }
+}
+
 fn check_expected_errors(expected_errors: Vec<errors::ExpectedError> ,
                          testfile: &Path,
                          proc_res: &ProcRes) {
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index e173b93e468..70cf41d5e17 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -895,7 +895,10 @@ fn expand_method(m: P<ast::Method>, fld: &mut MacroExpander) -> SmallVector<P<as
             };
 
             // expand again if necessary
-            new_methods.into_iter().flat_map(|m| fld.fold_method(m).into_iter()).collect()
+            let new_methods = new_methods.move_iter()
+                                  .flat_map(|m| fld.fold_method(m).into_iter()).collect();
+            fld.cx.bt_pop();
+            new_methods
         }
     })
 }
diff --git a/src/test/compile-fail/method-macro-backtrace.rs b/src/test/compile-fail/method-macro-backtrace.rs
new file mode 100644
index 00000000000..dc41e2e02a8
--- /dev/null
+++ b/src/test/compile-fail/method-macro-backtrace.rs
@@ -0,0 +1,37 @@
+// Copyright 2014 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.
+
+// forbid-output: in expansion of
+
+#![feature(macro_rules)]
+
+macro_rules! make_method ( ($name:ident) => (
+    fn $name(&self) { }
+))
+
+struct S;
+
+impl S {
+    // We had a bug where these wouldn't clean up macro backtrace frames.
+    make_method!(foo1)
+    make_method!(foo2)
+    make_method!(foo3)
+    make_method!(foo4)
+    make_method!(foo5)
+    make_method!(foo6)
+    make_method!(foo7)
+    make_method!(foo8)
+
+    // Cause an error. It shouldn't have any macro backtrace frames.
+    fn bar(&self) { }
+    fn bar(&self) { } //~ ERROR duplicate definition
+}
+
+fn main() { }