diff options
| author | Mara Bos <m-ou.se@m-ou.se> | 2020-10-31 09:49:38 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-10-31 09:49:38 +0100 |
| commit | 841f0e7f2cd90747d6a7d0e699fac342cc6ee92b (patch) | |
| tree | 45ad3e8f8c464fe07833143704229d52251077a0 | |
| parent | c0f356d28fb2ea1712ee3b5b8cd4918933e3860e (diff) | |
| parent | b816e5dfb49b7a135813b204b9123bbc5f41be7a (diff) | |
| download | rust-841f0e7f2cd90747d6a7d0e699fac342cc6ee92b.tar.gz rust-841f0e7f2cd90747d6a7d0e699fac342cc6ee92b.zip | |
Rollup merge of #78577 - tmiasko:validate-aliasing, r=jonas-schievink
validator: Extend aliasing check to a call terminator
| -rw-r--r-- | compiler/rustc_mir/src/transform/validate.rs | 45 |
1 files changed, 40 insertions, 5 deletions
diff --git a/compiler/rustc_mir/src/transform/validate.rs b/compiler/rustc_mir/src/transform/validate.rs index 7b22d643ab6..ecdd0c517ef 100644 --- a/compiler/rustc_mir/src/transform/validate.rs +++ b/compiler/rustc_mir/src/transform/validate.rs @@ -10,8 +10,8 @@ use rustc_middle::mir::{ visit::{PlaceContext, Visitor}, }; use rustc_middle::mir::{ - AggregateKind, BasicBlock, Body, BorrowKind, Local, Location, MirPhase, Operand, Rvalue, - SourceScope, Statement, StatementKind, Terminator, TerminatorKind, VarDebugInfo, + AggregateKind, BasicBlock, Body, BorrowKind, Local, Location, MirPhase, Operand, PlaceRef, + Rvalue, SourceScope, Statement, StatementKind, Terminator, TerminatorKind, VarDebugInfo, }; use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation}; use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt}; @@ -46,8 +46,16 @@ impl<'tcx> MirPass<'tcx> for Validator { .iterate_to_fixpoint() .into_results_cursor(body); - TypeChecker { when: &self.when, body, tcx, param_env, mir_phase, storage_liveness } - .visit_body(body); + TypeChecker { + 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>, mir_phase: MirPhase, storage_liveness: ResultsCursor<'a, 'tcx, MaybeStorageLive>, + place_cache: Vec<PlaceRef<'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); } } - TerminatorKind::Call { func, destination, cleanup, .. } => { + TerminatorKind::Call { func, args, destination, cleanup, .. } => { let func_ty = func.ty(&self.body.local_decls, self.tcx); match func_ty.kind() { ty::FnPtr(..) | ty::FnDef(..) => {} @@ -406,6 +415,32 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { if let Some(cleanup) = cleanup { 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, .. } => { let cond_ty = cond.ty(&self.body.local_decls, self.tcx); |
