1
1
// Copyright Kani Contributors
2
2
// SPDX-License-Identifier: Apache-2.0 OR MIT
3
3
4
- //! This file contains the code that acts as a wrapper to create the new assert and related statements
4
+ //! This module is the central location for handling assertions and assumptions in Kani.
5
+
6
+ use crate :: codegen_cprover_gotoc:: utils;
5
7
use crate :: codegen_cprover_gotoc:: GotocCtx ;
6
- use cbmc:: goto_program:: { Expr , Location , Stmt } ;
8
+ use cbmc:: goto_program:: { BuiltinFn , Expr , Location , Stmt } ;
9
+ use rustc_span:: Span ;
7
10
use std:: convert:: AsRef ;
8
11
use strum_macros:: { AsRefStr , EnumString } ;
9
12
@@ -39,6 +42,7 @@ impl PropertyClass {
39
42
}
40
43
41
44
impl < ' tcx > GotocCtx < ' tcx > {
45
+ /// Generates a CBMC assertion. Note: Does _NOT_ assume.
42
46
pub fn codegen_assert (
43
47
& self ,
44
48
cond : Expr ,
@@ -51,6 +55,7 @@ impl<'tcx> GotocCtx<'tcx> {
51
55
Stmt :: assert ( cond, property_name, message, loc)
52
56
}
53
57
58
+ /// Generates a CBMC assertion, followed by an assumption of the same condition.
54
59
pub fn codegen_assert_assume (
55
60
& self ,
56
61
cond : Expr ,
@@ -66,6 +71,7 @@ impl<'tcx> GotocCtx<'tcx> {
66
71
)
67
72
}
68
73
74
+ /// A shorthand for generating a CBMC assert-false. TODO: This should probably be eliminated!
69
75
pub fn codegen_assert_false (
70
76
& self ,
71
77
property_class : PropertyClass ,
@@ -76,4 +82,49 @@ impl<'tcx> GotocCtx<'tcx> {
76
82
let property_name = property_class. as_str ( ) ;
77
83
Stmt :: assert_false ( property_name, message, loc)
78
84
}
85
+
86
+ /// Kani hooks function calls to `panic` and calls this intead.
87
+ pub fn codegen_panic ( & self , span : Option < Span > , fargs : Vec < Expr > ) -> Stmt {
88
+ // CBMC requires that the argument to the assertion must be a string constant.
89
+ // If there is one in the MIR, use it; otherwise, explain that we can't.
90
+ assert ! ( !fargs. is_empty( ) , "Panic requires a string message" ) ;
91
+ let msg = utils:: extract_const_message ( & fargs[ 0 ] ) . unwrap_or ( String :: from (
92
+ "This is a placeholder message; Kani doesn't support message formatted at runtime" ,
93
+ ) ) ;
94
+
95
+ self . codegen_fatal_error ( PropertyClass :: Assertion , & msg, span)
96
+ }
97
+
98
+ /// Generate code for fatal error which should trigger an assertion failure and abort the
99
+ /// execution.
100
+ pub fn codegen_fatal_error (
101
+ & self ,
102
+ property_class : PropertyClass ,
103
+ msg : & str ,
104
+ span : Option < Span > ,
105
+ ) -> Stmt {
106
+ let loc = self . codegen_caller_span ( & span) ;
107
+ Stmt :: block (
108
+ vec ! [
109
+ self . codegen_assert_false( property_class, msg, loc) ,
110
+ BuiltinFn :: Abort . call( vec![ ] , loc) . as_stmt( loc) ,
111
+ ] ,
112
+ loc,
113
+ )
114
+ }
115
+
116
+ /// Generate code to cover the given condition at the current location
117
+ pub fn codegen_cover ( & self , cond : Expr , msg : & str , span : Option < Span > ) -> Stmt {
118
+ let loc = self . codegen_caller_span ( & span) ;
119
+ // Should use Stmt::cover, but currently this doesn't work with CBMC
120
+ // unless it is run with '--cover cover' (see
121
+ // https://github.com/diffblue/cbmc/issues/6613). So for now use
122
+ // assert(!cond).
123
+ self . codegen_assert ( cond. not ( ) , PropertyClass :: Cover , msg, loc)
124
+ }
125
+
126
+ /// Generate code to cover the current location
127
+ pub fn codegen_cover_loc ( & self , msg : & str , span : Option < Span > ) -> Stmt {
128
+ self . codegen_cover ( Expr :: bool_true ( ) , msg, span)
129
+ }
79
130
}
0 commit comments