Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions kani-compiler/src/codegen_cprover_gotoc/codegen/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

use crate::codegen_cprover_gotoc::GotocCtx;
use rustc_middle::mir::{BasicBlock, BasicBlockData};
use tracing::debug;

impl<'tcx> GotocCtx<'tcx> {
/// Generates Goto-C for a basic block.
Expand All @@ -12,6 +13,7 @@ impl<'tcx> GotocCtx<'tcx> {
/// This function does not return a value, but mutates state with
/// `self.current_fn_mut().push_onto_block(...)`
pub fn codegen_block(&mut self, bb: BasicBlock, bbd: &BasicBlockData<'tcx>) {
debug!(?bb, "Codegen basicblock");
self.current_fn_mut().set_current_bb(bb);
let label: String = self.current_fn().find_label(&bb);
// the first statement should be labelled. if there is no statements, then the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use kani_queries::UserInput;
use rustc_ast::Attribute;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId;
use rustc_middle::mir::traversal::reverse_postorder;
use rustc_middle::mir::{Body, HasLocalDecls, Local};
use rustc_middle::ty::layout::FnAbiOf;
use rustc_middle::ty::{self, Instance};
Expand Down Expand Up @@ -88,7 +89,7 @@ impl<'tcx> GotocCtx<'tcx> {
self.codegen_function_prelude();
self.codegen_declare_variables();

mir.basic_blocks.iter_enumerated().for_each(|(bb, bbd)| self.codegen_block(bb, bbd));
reverse_postorder(mir).for_each(|(bb, bbd)| self.codegen_block(bb, bbd));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sweet.


let loc = self.codegen_span(&mir.span);
let stmts = self.current_fn_mut().extract_block();
Expand Down
20 changes: 20 additions & 0 deletions tests/kani/Loops/loop_free.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Copyright Kani Contributors
// SPDX-License-Identifier: Apache-2.0 OR MIT
//
//! Ensure that Kani identifies that there is not loop in this code.
//! This was related to https://github.com/model-checking/kani/issues/2164
fn loop_free<T: Default>(b: bool, other: T) -> T {
match b {
true => T::default(),
false => other,
}
}

/// Set the unwind to 1 so this test will fail instead of running forever.
#[kani::proof]
#[kani::unwind(1)]
fn check_no_loop() {
let b: bool = kani::any();
let result = loop_free(b, 5);
assert!(result == 5 || (b && result == 0))
}
23 changes: 23 additions & 0 deletions tests/kani/Loops/loop_with_drop.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright Kani Contributors
// SPDX-License-Identifier: Apache-2.0 OR MIT
//
//! Ensure that Kani correctly unwind the loop with drop instructions which may .
//! This was related to https://github.com/model-checking/kani/issues/2164
/// Dummy function with a for loop that only runs 2 iterations.
fn bounded_loop<T: Default>(b: bool, other: T) -> T {
let mut ret = other;
for i in 0..2 {
ret = match b {
true => T::default(),
false => ret,
};
}
return ret;
}

/// Harness that should succeed. We add a conservative loop bound.
#[kani::proof]
#[kani::unwind(3)]
fn harness() {
let _ = bounded_loop(kani::any(), ());
}