about summary refs log tree commit diff
path: root/src/librustc_driver
diff options
context:
space:
mode:
Diffstat (limited to 'src/librustc_driver')
-rw-r--r--src/librustc_driver/lib.rs85
1 files changed, 80 insertions, 5 deletions
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index f872fd47546..6af7a23f66d 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -139,6 +139,19 @@ pub mod target_features {
 const BUG_REPORT_URL: &'static str = "https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.\
                                       md#bug-reports";
 
+const ICE_REPORT_COMPILER_FLAGS: &'static [&'static str] = &[
+    "Z",
+    "C",
+    "crate-type",
+];
+const ICE_REPORT_COMPILER_FLAGS_EXCLUDE: &'static [&'static str] = &[
+    "metadata",
+    "extra-filename",
+];
+const ICE_REPORT_COMPILER_FLAGS_STRIP_VALUE: &'static [&'static str] = &[
+    "incremental",
+];
+
 pub fn abort_on_err<T>(result: Result<T, CompileIncomplete>, sess: &Session) -> T {
     match result {
         Err(CompileIncomplete::Errored(ErrorReported)) => {
@@ -1431,6 +1444,57 @@ pub fn in_rustc_thread<F, R>(f: F) -> Result<R, Box<Any + Send>>
     thread.unwrap().join()
 }
 
+/// Get a list of extra command-line flags provided by the user, as strings.
+///
+/// This function is used during ICEs to show more information useful for
+/// debugging, since some ICEs only happens with non-default compiler flags
+/// (and the users don't always report them).
+fn extra_compiler_flags() -> Option<(Vec<String>, bool)> {
+    let mut args = Vec::new();
+    for arg in env::args_os() {
+        args.push(arg.to_string_lossy().to_string());
+    }
+
+    let matches = if let Some(matches) = handle_options(&args) {
+        matches
+    } else {
+        return None;
+    };
+
+    let mut result = Vec::new();
+    let mut excluded_cargo_defaults = false;
+    for flag in ICE_REPORT_COMPILER_FLAGS {
+        let prefix = if flag.len() == 1 { "-" } else { "--" };
+
+        for content in &matches.opt_strs(flag) {
+            // Split always returns the first element
+            let name = if let Some(first) = content.split('=').next() {
+                first
+            } else {
+                &content
+            };
+
+            let content = if ICE_REPORT_COMPILER_FLAGS_STRIP_VALUE.contains(&name) {
+                name
+            } else {
+                content
+            };
+
+            if !ICE_REPORT_COMPILER_FLAGS_EXCLUDE.contains(&name) {
+                result.push(format!("{}{} {}", prefix, flag, content));
+            } else {
+                excluded_cargo_defaults = true;
+            }
+        }
+    }
+
+    if result.len() > 0 {
+        Some((result, excluded_cargo_defaults))
+    } else {
+        None
+    }
+}
+
 /// Run a procedure which will detect panics in the compiler and print nicer
 /// error messages rather than just failing the test.
 ///
@@ -1462,11 +1526,22 @@ pub fn monitor<F: FnOnce() + Send + 'static>(f: F) {
                              errors::Level::Bug);
             }
 
-            let xs = ["the compiler unexpectedly panicked. this is a bug.".to_string(),
-                      format!("we would appreciate a bug report: {}", BUG_REPORT_URL),
-                      format!("rustc {} running on {}",
-                              option_env!("CFG_VERSION").unwrap_or("unknown_version"),
-                              config::host_triple())];
+            let mut xs = vec![
+                "the compiler unexpectedly panicked. this is a bug.".to_string(),
+                format!("we would appreciate a bug report: {}", BUG_REPORT_URL),
+                format!("rustc {} running on {}",
+                        option_env!("CFG_VERSION").unwrap_or("unknown_version"),
+                        config::host_triple()),
+            ];
+
+            if let Some((flags, excluded_cargo_defaults)) = extra_compiler_flags() {
+                xs.push(format!("compiler flags: {}", flags.join(" ")));
+
+                if excluded_cargo_defaults {
+                    xs.push("some of the compiler flags provided by cargo are hidden".to_string());
+                }
+            }
+
             for note in &xs {
                 handler.emit(&MultiSpan::new(),
                              &note,