Lint missing StorageDead when returning from functions
This commit is contained in:
parent
7a246ddd8e
commit
1d36e3ae03
2 changed files with 54 additions and 1 deletions
|
@ -18,13 +18,24 @@ pub fn lint_body<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, when: String) {
|
||||||
.iterate_to_fixpoint()
|
.iterate_to_fixpoint()
|
||||||
.into_results_cursor(body);
|
.into_results_cursor(body);
|
||||||
|
|
||||||
Lint { tcx, when, body, reachable_blocks, storage_liveness }.visit_body(body);
|
Lint {
|
||||||
|
tcx,
|
||||||
|
when,
|
||||||
|
body,
|
||||||
|
is_fn_like: tcx.def_kind(body.source.def_id()).is_fn_like(),
|
||||||
|
always_live_locals,
|
||||||
|
reachable_blocks,
|
||||||
|
storage_liveness,
|
||||||
|
}
|
||||||
|
.visit_body(body);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Lint<'a, 'tcx> {
|
struct Lint<'a, 'tcx> {
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
when: String,
|
when: String,
|
||||||
body: &'a Body<'tcx>,
|
body: &'a Body<'tcx>,
|
||||||
|
is_fn_like: bool,
|
||||||
|
always_live_locals: &'a BitSet<Local>,
|
||||||
reachable_blocks: BitSet<BasicBlock>,
|
reachable_blocks: BitSet<BasicBlock>,
|
||||||
storage_liveness: ResultsCursor<'a, 'tcx, MaybeStorageLive<'a>>,
|
storage_liveness: ResultsCursor<'a, 'tcx, MaybeStorageLive<'a>>,
|
||||||
}
|
}
|
||||||
|
@ -74,4 +85,27 @@ impl<'a, 'tcx> Visitor<'tcx> for Lint<'a, 'tcx> {
|
||||||
|
|
||||||
self.super_statement(statement, location);
|
self.super_statement(statement, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) {
|
||||||
|
match terminator.kind {
|
||||||
|
TerminatorKind::Return => {
|
||||||
|
if self.is_fn_like && self.reachable_blocks.contains(location.block) {
|
||||||
|
self.storage_liveness.seek_after_primary_effect(location);
|
||||||
|
for local in self.storage_liveness.get().iter() {
|
||||||
|
if !self.always_live_locals.contains(local) {
|
||||||
|
self.fail(
|
||||||
|
location,
|
||||||
|
format!(
|
||||||
|
"local {local:?} still has storage when returning from function"
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.super_terminator(terminator, location);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
19
tests/ui/mir/lint/storage-return.rs
Normal file
19
tests/ui/mir/lint/storage-return.rs
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
// compile-flags: -Zlint-mir -Ztreat-err-as-bug
|
||||||
|
// failure-status: 101
|
||||||
|
// dont-check-compiler-stderr
|
||||||
|
// error-pattern: has storage when returning
|
||||||
|
#![feature(custom_mir, core_intrinsics)]
|
||||||
|
extern crate core;
|
||||||
|
use core::intrinsics::mir::*;
|
||||||
|
|
||||||
|
#[custom_mir(dialect = "built")]
|
||||||
|
fn main() {
|
||||||
|
mir!(
|
||||||
|
let a: ();
|
||||||
|
{
|
||||||
|
StorageLive(a);
|
||||||
|
RET = a;
|
||||||
|
Return()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue