Skip to content

Commit 4adc967

Browse files
committed
mir: report when overflow checks would be missing cross-crate.
1 parent cab35ff commit 4adc967

File tree

4 files changed

+57
-23
lines changed

4 files changed

+57
-23
lines changed

src/librustc_mir/build/expr/as_rvalue.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
8080
ExprKind::Unary { op, arg } => {
8181
let arg = unpack!(block = this.as_operand(block, arg));
8282
// Check for -MIN on signed integers
83-
if op == UnOp::Neg && this.check_overflow() && expr.ty.is_signed() {
83+
if op == UnOp::Neg && expr.ty.is_signed() && this.check_overflow() {
8484
let bool_ty = this.hir.bool_ty();
8585

8686
let minval = this.minval_literal(expr_span, expr.ty);
@@ -247,7 +247,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
247247
lhs: Operand<'tcx>, rhs: Operand<'tcx>) -> BlockAnd<Rvalue<'tcx>> {
248248
let scope_id = self.innermost_scope_id();
249249
let bool_ty = self.hir.bool_ty();
250-
if self.check_overflow() && op.is_checkable() && ty.is_integral() {
250+
if op.is_checkable() && ty.is_integral() && self.check_overflow() {
251251
let result_tup = self.hir.tcx().mk_tup(vec![ty, bool_ty]);
252252
let result_value = self.temp(result_tup);
253253

src/librustc_mir/build/mod.rs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ pub struct Builder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
5555
cached_resume_block: Option<BasicBlock>,
5656
/// cached block with the RETURN terminator
5757
cached_return_block: Option<BasicBlock>,
58+
59+
has_warned_about_xcrate_overflows: bool
5860
}
5961

6062
struct CFG<'tcx> {
@@ -273,7 +275,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
273275
var_indices: FnvHashMap(),
274276
unit_temp: None,
275277
cached_resume_block: None,
276-
cached_return_block: None
278+
cached_return_block: None,
279+
has_warned_about_xcrate_overflows: false
277280
};
278281

279282
assert_eq!(builder.cfg.start_new_block(), START_BLOCK);
@@ -379,9 +382,19 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
379382
}
380383
}
381384

382-
pub fn check_overflow(&self) -> bool {
383-
self.hir.tcx().sess.opts.debugging_opts.force_overflow_checks.unwrap_or(
384-
self.hir.tcx().sess.opts.debug_assertions)
385+
pub fn check_overflow(&mut self) -> bool {
386+
let check = self.hir.tcx().sess.opts.debugging_opts.force_overflow_checks
387+
.unwrap_or(self.hir.tcx().sess.opts.debug_assertions);
388+
389+
if !check && self.hir.may_be_inlined_cross_crate() {
390+
if !self.has_warned_about_xcrate_overflows {
391+
self.hir.tcx().sess.span_warn(self.fn_span,
392+
"overflow checks would be missing when used from another crate");
393+
self.has_warned_about_xcrate_overflows = true;
394+
}
395+
}
396+
397+
check
385398
}
386399
}
387400

src/librustc_mir/hair/cx/mod.rs

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,32 +17,63 @@
1717

1818
use hair::*;
1919
use rustc::mir::repr::*;
20+
use rustc::mir::transform::MirSource;
2021

2122
use rustc::middle::const_val::ConstVal;
2223
use rustc_const_eval as const_eval;
2324
use rustc::hir::def_id::DefId;
25+
use rustc::hir::intravisit::FnKind;
26+
use rustc::hir::map::blocks::FnLikeNode;
2427
use rustc::infer::InferCtxt;
2528
use rustc::ty::subst::{Subst, Substs};
2629
use rustc::ty::{self, Ty, TyCtxt};
2730
use syntax::parse::token;
2831
use rustc::hir;
2932
use rustc_const_math::{ConstInt, ConstUsize};
33+
use syntax::attr;
3034

3135
#[derive(Copy, Clone)]
3236
pub struct Cx<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
3337
tcx: TyCtxt<'a, 'gcx, 'tcx>,
3438
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
35-
constness: hir::Constness
39+
constness: hir::Constness,
40+
41+
/// True if this MIR can get inlined in other crates.
42+
inline: bool
3643
}
3744

3845
impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
3946
pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
40-
constness: hir::Constness)
47+
src: MirSource)
4148
-> Cx<'a, 'gcx, 'tcx> {
49+
let (constness, inline) = match src {
50+
MirSource::Const(_) |
51+
MirSource::Static(..) => (hir::Constness::Const, false),
52+
MirSource::Fn(id) => {
53+
let def_id = infcx.tcx.map.local_def_id(id);
54+
let fn_like = FnLikeNode::from_node(infcx.tcx.map.get(id));
55+
match fn_like.map(|f| f.kind()) {
56+
Some(FnKind::ItemFn(_, _, _, c, _, _, attrs)) => {
57+
let scheme = infcx.tcx.lookup_item_type(def_id);
58+
let any_types = !scheme.generics.types.is_empty();
59+
(c, any_types || attr::requests_inline(attrs))
60+
}
61+
Some(FnKind::Method(_, m, _, attrs)) => {
62+
let scheme = infcx.tcx.lookup_item_type(def_id);
63+
let any_types = !scheme.generics.types.is_empty();
64+
(m.constness, any_types || attr::requests_inline(attrs))
65+
}
66+
_ => (hir::Constness::NotConst, true)
67+
}
68+
}
69+
MirSource::Promoted(..) => bug!()
70+
};
71+
4272
Cx {
4373
tcx: infcx.tcx,
4474
infcx: infcx,
4575
constness: constness,
76+
inline: inline
4677
}
4778
}
4879
}
@@ -154,6 +185,10 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
154185
pub fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> {
155186
self.tcx
156187
}
188+
189+
pub fn may_be_inlined_cross_crate(&self) -> bool {
190+
self.inline
191+
}
157192
}
158193

159194
mod block;

src/librustc_mir/mir_map.rs

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ use rustc::ty::subst::Substs;
3232
use rustc::util::nodemap::NodeMap;
3333
use rustc::hir;
3434
use rustc::hir::intravisit::{self, FnKind, Visitor};
35-
use rustc::hir::map::blocks::FnLikeNode;
3635
use syntax::ast;
3736
use syntax::codemap::Span;
3837

@@ -116,20 +115,7 @@ impl<'a, 'gcx, 'tcx> CxBuilder<'a, 'gcx, 'tcx> {
116115
{
117116
let src = self.src;
118117
let mir = self.infcx.enter(|infcx| {
119-
let constness = match src {
120-
MirSource::Const(_) |
121-
MirSource::Static(..) => hir::Constness::Const,
122-
MirSource::Fn(id) => {
123-
let fn_like = FnLikeNode::from_node(infcx.tcx.map.get(id));
124-
match fn_like.map(|f| f.kind()) {
125-
Some(FnKind::ItemFn(_, _, _, c, _, _, _)) => c,
126-
Some(FnKind::Method(_, m, _, _)) => m.constness,
127-
_ => hir::Constness::NotConst
128-
}
129-
}
130-
MirSource::Promoted(..) => bug!()
131-
};
132-
let (mut mir, scope_auxiliary) = f(Cx::new(&infcx, constness));
118+
let (mut mir, scope_auxiliary) = f(Cx::new(&infcx, src));
133119

134120
// Convert the Mir to global types.
135121
let mut globalizer = GlobalizeMir {

0 commit comments

Comments
 (0)