validator: Extend aliasing check to a call terminator
This commit is contained in:
parent
388ef34904
commit
b816e5dfb4
@ -10,8 +10,8 @@ use rustc_middle::mir::{
|
|||||||
visit::{PlaceContext, Visitor},
|
visit::{PlaceContext, Visitor},
|
||||||
};
|
};
|
||||||
use rustc_middle::mir::{
|
use rustc_middle::mir::{
|
||||||
AggregateKind, BasicBlock, Body, BorrowKind, Local, Location, MirPhase, Operand, Rvalue,
|
AggregateKind, BasicBlock, Body, BorrowKind, Local, Location, MirPhase, Operand, PlaceRef,
|
||||||
SourceScope, Statement, StatementKind, Terminator, TerminatorKind, VarDebugInfo,
|
Rvalue, SourceScope, Statement, StatementKind, Terminator, TerminatorKind, VarDebugInfo,
|
||||||
};
|
};
|
||||||
use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
|
use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
|
||||||
use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt};
|
use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt};
|
||||||
@ -46,8 +46,16 @@ impl<'tcx> MirPass<'tcx> for Validator {
|
|||||||
.iterate_to_fixpoint()
|
.iterate_to_fixpoint()
|
||||||
.into_results_cursor(body);
|
.into_results_cursor(body);
|
||||||
|
|
||||||
TypeChecker { when: &self.when, body, tcx, param_env, mir_phase, storage_liveness }
|
TypeChecker {
|
||||||
.visit_body(body);
|
when: &self.when,
|
||||||
|
body,
|
||||||
|
tcx,
|
||||||
|
param_env,
|
||||||
|
mir_phase,
|
||||||
|
storage_liveness,
|
||||||
|
place_cache: Vec::new(),
|
||||||
|
}
|
||||||
|
.visit_body(body);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,6 +158,7 @@ struct TypeChecker<'a, 'tcx> {
|
|||||||
param_env: ParamEnv<'tcx>,
|
param_env: ParamEnv<'tcx>,
|
||||||
mir_phase: MirPhase,
|
mir_phase: MirPhase,
|
||||||
storage_liveness: ResultsCursor<'a, 'tcx, MaybeStorageLive>,
|
storage_liveness: ResultsCursor<'a, 'tcx, MaybeStorageLive>,
|
||||||
|
place_cache: Vec<PlaceRef<'tcx>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||||
@ -391,7 +400,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
|||||||
self.check_edge(location, *unwind, EdgeKind::Unwind);
|
self.check_edge(location, *unwind, EdgeKind::Unwind);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TerminatorKind::Call { func, destination, cleanup, .. } => {
|
TerminatorKind::Call { func, args, destination, cleanup, .. } => {
|
||||||
let func_ty = func.ty(&self.body.local_decls, self.tcx);
|
let func_ty = func.ty(&self.body.local_decls, self.tcx);
|
||||||
match func_ty.kind() {
|
match func_ty.kind() {
|
||||||
ty::FnPtr(..) | ty::FnDef(..) => {}
|
ty::FnPtr(..) | ty::FnDef(..) => {}
|
||||||
@ -406,6 +415,32 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
|||||||
if let Some(cleanup) = cleanup {
|
if let Some(cleanup) = cleanup {
|
||||||
self.check_edge(location, *cleanup, EdgeKind::Unwind);
|
self.check_edge(location, *cleanup, EdgeKind::Unwind);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The call destination place and Operand::Move place used as an argument might be
|
||||||
|
// passed by a reference to the callee. Consequently they must be non-overlapping.
|
||||||
|
// Currently this simply checks for duplicate places.
|
||||||
|
self.place_cache.clear();
|
||||||
|
if let Some((destination, _)) = destination {
|
||||||
|
self.place_cache.push(destination.as_ref());
|
||||||
|
}
|
||||||
|
for arg in args {
|
||||||
|
if let Operand::Move(place) = arg {
|
||||||
|
self.place_cache.push(place.as_ref());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let all_len = self.place_cache.len();
|
||||||
|
self.place_cache.sort_unstable();
|
||||||
|
self.place_cache.dedup();
|
||||||
|
let has_duplicates = all_len != self.place_cache.len();
|
||||||
|
if has_duplicates {
|
||||||
|
self.fail(
|
||||||
|
location,
|
||||||
|
format!(
|
||||||
|
"encountered overlapping memory in `Call` terminator: {:?}",
|
||||||
|
terminator.kind,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
TerminatorKind::Assert { cond, target, cleanup, .. } => {
|
TerminatorKind::Assert { cond, target, cleanup, .. } => {
|
||||||
let cond_ty = cond.ty(&self.body.local_decls, self.tcx);
|
let cond_ty = cond.ty(&self.body.local_decls, self.tcx);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user