Rollup merge of #40037 - froydnj:overflow-checks, r=alexcrichton

add `-C overflow-checks` option

In addition to defining and handling the new option, we also add a method on librustc::Session for determining the necessity of overflow checks.  This method provides a single point to sort out the three (!) different ways for turning on overflow checks: -C debug-assertions, -C overflow-checks, and -Z force-overflow-checks.

I was seeing a [run-pass/issue-28950.rs](b1363a73ed/src/test/run-pass/issue-28950.rs) failure on my machine with these patches, but I was also seeing the failure without the changes to the core compiler.  We'll see what travis says.

Fixes #33134.  r? @alexcrichton
This commit is contained in:
Eduard-Mihai Burtescu 2017-02-25 14:13:38 +02:00 committed by GitHub
commit 582d5d9793
6 changed files with 50 additions and 14 deletions

View File

@ -804,6 +804,8 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options,
"save all temporary output files during compilation"),
rpath: bool = (false, parse_bool, [UNTRACKED],
"set rpath values in libs/exes"),
overflow_checks: Option<bool> = (None, parse_opt_bool, [TRACKED],
"use overflow checks for integer arithmetic"),
no_prepopulate_passes: bool = (false, parse_bool, [TRACKED],
"don't pre-populate the pass manager with a list of passes"),
no_vectorize_loops: bool = (false, parse_bool, [TRACKED],
@ -2348,6 +2350,10 @@ mod tests {
opts.cg.llvm_args = vec![String::from("1"), String::from("2")];
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.cg.overflow_checks = Some(true);
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.cg.no_prepopulate_passes = true;
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());

View File

@ -372,6 +372,11 @@ impl Session {
pub fn nonzeroing_move_hints(&self) -> bool {
self.opts.debugging_opts.enable_nonzeroing_move_hints
}
pub fn overflow_checks(&self) -> bool {
self.opts.cg.overflow_checks
.or(self.opts.debugging_opts.force_overflow_checks)
.unwrap_or(self.opts.debug_assertions)
}
pub fn must_not_eliminate_frame_pointers(&self) -> bool {
self.opts.debuginfo != DebugInfoLevel::NoDebugInfo ||

View File

@ -63,8 +63,7 @@ impl<'a, 'hash, 'tcx> StrictVersionHashVisitor<'a, 'hash, 'tcx> {
hash_spans: bool,
hash_bodies: bool)
-> Self {
let check_overflow = tcx.sess.opts.debugging_opts.force_overflow_checks
.unwrap_or(tcx.sess.opts.debug_assertions);
let check_overflow = tcx.sess.overflow_checks();
StrictVersionHashVisitor {
st: st,

View File

@ -59,13 +59,8 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
let mut check_overflow = attrs.iter()
.any(|item| item.check_name("rustc_inherit_overflow_checks"));
// Respect -Z force-overflow-checks=on and -C debug-assertions.
check_overflow |= infcx.tcx
.sess
.opts
.debugging_opts
.force_overflow_checks
.unwrap_or(infcx.tcx.sess.opts.debug_assertions);
// Respect -C overflow-checks.
check_overflow |= infcx.tcx.sess.overflow_checks();
// Constants and const fn's always need overflow checks.
check_overflow |= constness == hir::Constness::Const;

View File

@ -1139,11 +1139,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
let ty::CrateAnalysis { export_map, reachable, name, .. } = analysis;
let exported_symbols = find_exported_symbols(tcx, reachable);
let check_overflow = if let Some(v) = tcx.sess.opts.debugging_opts.force_overflow_checks {
v
} else {
tcx.sess.opts.debug_assertions
};
let check_overflow = tcx.sess.overflow_checks();
let link_meta = link::build_link_meta(incremental_hashes_map, &name);

View File

@ -0,0 +1,35 @@
// Copyright 2016 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.
// compile-flags: -C overflow-checks
use std::panic;
fn main() {
let r = panic::catch_unwind(|| {
[1, i32::max_value()].iter().sum::<i32>();
});
assert!(r.is_err());
let r = panic::catch_unwind(|| {
[2, i32::max_value()].iter().product::<i32>();
});
assert!(r.is_err());
let r = panic::catch_unwind(|| {
[1, i32::max_value()].iter().cloned().sum::<i32>();
});
assert!(r.is_err());
let r = panic::catch_unwind(|| {
[2, i32::max_value()].iter().cloned().product::<i32>();
});
assert!(r.is_err());
}