Skip to content

Commit

Permalink
add -C overflow-checks option
Browse files Browse the repository at this point in the history
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.

Fixes rust-lang#33134.
  • Loading branch information
froydnj committed Feb 22, 2017
1 parent fc6f092 commit ffc6ddd
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 14 deletions.
6 changes: 6 additions & 0 deletions src/librustc/session/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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],
Expand Down Expand Up @@ -2345,6 +2347,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());
Expand Down
5 changes: 5 additions & 0 deletions src/librustc/session/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 ||
Expand Down
3 changes: 1 addition & 2 deletions src/librustc_incremental/calculate_svh/svh_visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
9 changes: 2 additions & 7 deletions src/librustc_mir/hair/cx/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
6 changes: 1 addition & 5 deletions src/librustc_trans/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1132,11 +1132,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);

Expand Down
35 changes: 35 additions & 0 deletions src/test/run-pass/iter-sum-overflow-overflow-checks.rs
Original file line number Diff line number Diff line change
@@ -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());
}

0 comments on commit ffc6ddd

Please sign in to comment.