mir: report when overflow checks would be missing cross-crate.
This commit is contained in:
parent
cab35ff4b8
commit
4adc967ed1
@ -80,7 +80,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
ExprKind::Unary { op, arg } => {
|
||||
let arg = unpack!(block = this.as_operand(block, arg));
|
||||
// Check for -MIN on signed integers
|
||||
if op == UnOp::Neg && this.check_overflow() && expr.ty.is_signed() {
|
||||
if op == UnOp::Neg && expr.ty.is_signed() && this.check_overflow() {
|
||||
let bool_ty = this.hir.bool_ty();
|
||||
|
||||
let minval = this.minval_literal(expr_span, expr.ty);
|
||||
@ -247,7 +247,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
lhs: Operand<'tcx>, rhs: Operand<'tcx>) -> BlockAnd<Rvalue<'tcx>> {
|
||||
let scope_id = self.innermost_scope_id();
|
||||
let bool_ty = self.hir.bool_ty();
|
||||
if self.check_overflow() && op.is_checkable() && ty.is_integral() {
|
||||
if op.is_checkable() && ty.is_integral() && self.check_overflow() {
|
||||
let result_tup = self.hir.tcx().mk_tup(vec![ty, bool_ty]);
|
||||
let result_value = self.temp(result_tup);
|
||||
|
||||
|
@ -55,6 +55,8 @@ pub struct Builder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
||||
cached_resume_block: Option<BasicBlock>,
|
||||
/// cached block with the RETURN terminator
|
||||
cached_return_block: Option<BasicBlock>,
|
||||
|
||||
has_warned_about_xcrate_overflows: bool
|
||||
}
|
||||
|
||||
struct CFG<'tcx> {
|
||||
@ -273,7 +275,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
var_indices: FnvHashMap(),
|
||||
unit_temp: None,
|
||||
cached_resume_block: None,
|
||||
cached_return_block: None
|
||||
cached_return_block: None,
|
||||
has_warned_about_xcrate_overflows: false
|
||||
};
|
||||
|
||||
assert_eq!(builder.cfg.start_new_block(), START_BLOCK);
|
||||
@ -379,9 +382,19 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn check_overflow(&self) -> bool {
|
||||
self.hir.tcx().sess.opts.debugging_opts.force_overflow_checks.unwrap_or(
|
||||
self.hir.tcx().sess.opts.debug_assertions)
|
||||
pub fn check_overflow(&mut self) -> bool {
|
||||
let check = self.hir.tcx().sess.opts.debugging_opts.force_overflow_checks
|
||||
.unwrap_or(self.hir.tcx().sess.opts.debug_assertions);
|
||||
|
||||
if !check && self.hir.may_be_inlined_cross_crate() {
|
||||
if !self.has_warned_about_xcrate_overflows {
|
||||
self.hir.tcx().sess.span_warn(self.fn_span,
|
||||
"overflow checks would be missing when used from another crate");
|
||||
self.has_warned_about_xcrate_overflows = true;
|
||||
}
|
||||
}
|
||||
|
||||
check
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,32 +17,63 @@
|
||||
|
||||
use hair::*;
|
||||
use rustc::mir::repr::*;
|
||||
use rustc::mir::transform::MirSource;
|
||||
|
||||
use rustc::middle::const_val::ConstVal;
|
||||
use rustc_const_eval as const_eval;
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::hir::intravisit::FnKind;
|
||||
use rustc::hir::map::blocks::FnLikeNode;
|
||||
use rustc::infer::InferCtxt;
|
||||
use rustc::ty::subst::{Subst, Substs};
|
||||
use rustc::ty::{self, Ty, TyCtxt};
|
||||
use syntax::parse::token;
|
||||
use rustc::hir;
|
||||
use rustc_const_math::{ConstInt, ConstUsize};
|
||||
use syntax::attr;
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Cx<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
||||
tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
|
||||
constness: hir::Constness
|
||||
constness: hir::Constness,
|
||||
|
||||
/// True if this MIR can get inlined in other crates.
|
||||
inline: bool
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
|
||||
pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
|
||||
constness: hir::Constness)
|
||||
src: MirSource)
|
||||
-> Cx<'a, 'gcx, 'tcx> {
|
||||
let (constness, inline) = match src {
|
||||
MirSource::Const(_) |
|
||||
MirSource::Static(..) => (hir::Constness::Const, false),
|
||||
MirSource::Fn(id) => {
|
||||
let def_id = infcx.tcx.map.local_def_id(id);
|
||||
let fn_like = FnLikeNode::from_node(infcx.tcx.map.get(id));
|
||||
match fn_like.map(|f| f.kind()) {
|
||||
Some(FnKind::ItemFn(_, _, _, c, _, _, attrs)) => {
|
||||
let scheme = infcx.tcx.lookup_item_type(def_id);
|
||||
let any_types = !scheme.generics.types.is_empty();
|
||||
(c, any_types || attr::requests_inline(attrs))
|
||||
}
|
||||
Some(FnKind::Method(_, m, _, attrs)) => {
|
||||
let scheme = infcx.tcx.lookup_item_type(def_id);
|
||||
let any_types = !scheme.generics.types.is_empty();
|
||||
(m.constness, any_types || attr::requests_inline(attrs))
|
||||
}
|
||||
_ => (hir::Constness::NotConst, true)
|
||||
}
|
||||
}
|
||||
MirSource::Promoted(..) => bug!()
|
||||
};
|
||||
|
||||
Cx {
|
||||
tcx: infcx.tcx,
|
||||
infcx: infcx,
|
||||
constness: constness,
|
||||
inline: inline
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -154,6 +185,10 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
|
||||
pub fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
self.tcx
|
||||
}
|
||||
|
||||
pub fn may_be_inlined_cross_crate(&self) -> bool {
|
||||
self.inline
|
||||
}
|
||||
}
|
||||
|
||||
mod block;
|
||||
|
@ -32,7 +32,6 @@ use rustc::ty::subst::Substs;
|
||||
use rustc::util::nodemap::NodeMap;
|
||||
use rustc::hir;
|
||||
use rustc::hir::intravisit::{self, FnKind, Visitor};
|
||||
use rustc::hir::map::blocks::FnLikeNode;
|
||||
use syntax::ast;
|
||||
use syntax::codemap::Span;
|
||||
|
||||
@ -116,20 +115,7 @@ impl<'a, 'gcx, 'tcx> CxBuilder<'a, 'gcx, 'tcx> {
|
||||
{
|
||||
let src = self.src;
|
||||
let mir = self.infcx.enter(|infcx| {
|
||||
let constness = match src {
|
||||
MirSource::Const(_) |
|
||||
MirSource::Static(..) => hir::Constness::Const,
|
||||
MirSource::Fn(id) => {
|
||||
let fn_like = FnLikeNode::from_node(infcx.tcx.map.get(id));
|
||||
match fn_like.map(|f| f.kind()) {
|
||||
Some(FnKind::ItemFn(_, _, _, c, _, _, _)) => c,
|
||||
Some(FnKind::Method(_, m, _, _)) => m.constness,
|
||||
_ => hir::Constness::NotConst
|
||||
}
|
||||
}
|
||||
MirSource::Promoted(..) => bug!()
|
||||
};
|
||||
let (mut mir, scope_auxiliary) = f(Cx::new(&infcx, constness));
|
||||
let (mut mir, scope_auxiliary) = f(Cx::new(&infcx, src));
|
||||
|
||||
// Convert the Mir to global types.
|
||||
let mut globalizer = GlobalizeMir {
|
||||
|
Loading…
x
Reference in New Issue
Block a user