diff --git a/src/analyses/goto_check.cpp b/src/analyses/goto_check.cpp
index b54831c7962..99a28ebfaad 100644
--- a/src/analyses/goto_check.cpp
+++ b/src/analyses/goto_check.cpp
@@ -79,6 +79,11 @@ class goto_checkt
const irep_idt &function_identifier,
goto_functiont &goto_function);
+ /// Fill the list of allocations \ref allocationst with
for
+ /// every allocation instruction. Also check that each allocation is
+ /// well-formed.
+ /// \param goto_functions: goto functions from which the allocations are to be
+ /// collected
void collect_allocations(const goto_functionst &goto_functions);
protected:
@@ -87,10 +92,63 @@ class goto_checkt
goto_programt::const_targett current_target;
guard_managert guard_manager;
- void check_rec(
- const exprt &expr,
- guardt &guard,
- bool address);
+ /// Check an address-of expression:
+ /// if it is a dereference then check the pointer
+ /// if it is an index then address-check the array and then check the index
+ /// \param expr: the expression to be checked
+ /// \param guard: the condition for the check (unmodified here)
+ void check_rec_address(const exprt &expr, guardt &guard);
+
+ /// Check a logical operation: check each operand in separation while
+ /// extending the guarding condition as follows.
+ /// a /\ b /\ c ==> check(a, TRUE), check(b, a), check (c, a /\ b)
+ /// a \/ b \/ c ==> check(a, TRUE), check(b, ~a), check (c, ~a /\ ~b)
+ /// \param expr: the expression to be checked
+ /// \param guard: the condition for the check (extended with the previous
+ /// operands (or their negations) for recursively calls)
+ void check_rec_logical_op(const exprt &expr, guardt &guard);
+
+ /// Check an if expression: check the if-condition alone, and then check the
+ /// true/false-cases with the guard extended with if-condition and it's
+ /// negation, respectively.
+ /// \param if_expr: the expression to be checked
+ /// \param guard: the condition for the check (extended with the (negation of
+ /// the) if-condition for recursively calls)
+ void check_rec_if(const if_exprt &if_expr, guardt &guard);
+
+ /// Check that a member expression is valid:
+ /// - check the structure this expression is a member of (via pointer of its
+ /// dereference)
+ /// - run pointer-validity check on `*(s+member_offset)' instead of
+ /// `s->member' to avoid checking safety of `s'
+ /// - check all operands of the expression
+ /// \param member: the expression to be checked
+ /// \param guard: the condition for the check (unmodified here)
+ /// \return true if no more checks are required for \p member or its
+ /// sub-expressions
+ bool check_rec_member(const member_exprt &member, guardt &guard);
+
+ /// Check that a division is valid: check for division by zero, overflow and
+ /// NaN (for floating point numbers).
+ /// \param div_expr: the expression to be checked
+ /// \param guard: the condition for the check (unmodified here)
+ void check_rec_div(const div_exprt &div_expr, guardt &guard);
+
+ /// Check that an arithmetic operation is valid: overflow check, NaN-check
+ /// (for floating point numbers), and pointer overflow check.
+ /// \param expr: the expression to be checked
+ /// \param guard: the condition for the check (unmodified here)
+ void check_rec_arithmetic_op(const exprt &expr, guardt &guard);
+
+ /// Recursively descend into \p expr and run the appropriate check for each
+ /// sub-expression, while collecting the condition for the check in \p
+ /// guard.
+ /// \param expr: the expression to be checked
+ /// \param guard: the condition for when the check should be made
+ void check_rec(const exprt &expr, guardt &guard);
+
+ /// Initiate the recursively analysis of \p expr with its `guard' set to TRUE.
+ /// \param expr: the expression to be checked
void check(const exprt &expr);
struct conditiont
@@ -123,11 +181,19 @@ class goto_checkt
std::string array_name(const exprt &);
- void add_guarded_claim(
- const exprt &expr,
+ /// Include the \p asserted_expr in the code conditioned by the \p guard.
+ /// \param asserted_expr: expression to be asserted
+ /// \param comment: human readable comment
+ /// \param property_class: classification of the property
+ /// \param source_location: the source location of the original expression
+ /// \param src_expr: the original expression to be included in the comment
+ /// \param guard: the condition under which the asserted expression should be
+ /// taken into account
+ void add_guarded_property(
+ const exprt &asserted_expr,
const std::string &comment,
const std::string &property_class,
- const source_locationt &,
+ const source_locationt &source_location,
const exprt &src_expr,
const guardt &guard);
@@ -135,6 +201,10 @@ class goto_checkt
typedef std::set assertionst;
assertionst assertions;
+ /// Remove all assertions containing the symbol in \p lhs as well as all
+ /// assertions containing dereference.
+ /// \param lhs: the left-hand-side expression whose symbol should be
+ /// invalidated
void invalidate(const exprt &lhs);
bool enable_bounds_check;
@@ -208,21 +278,14 @@ void goto_checkt::invalidate(const exprt &lhs)
else if(lhs.id()==ID_symbol)
{
// clear all assertions about 'symbol'
- find_symbols_sett find_symbols_set;
- find_symbols_set.insert(to_symbol_expr(lhs).get_identifier());
+ find_symbols_sett find_symbols_set{to_symbol_expr(lhs).get_identifier()};
- for(assertionst::iterator
- it=assertions.begin();
- it!=assertions.end();
- ) // no it++
+ for(auto it = assertions.begin(); it != assertions.end();)
{
- assertionst::iterator next=it;
- next++;
-
if(has_symbol(*it, find_symbols_set) || has_subexpr(*it, ID_dereference))
- assertions.erase(it);
-
- it=next;
+ it = assertions.erase(it);
+ else
+ ++it;
}
}
else
@@ -244,7 +307,7 @@ void goto_checkt::div_by_zero_check(
exprt zero=from_integer(0, expr.op1().type());
const notequal_exprt inequality(expr.op1(), std::move(zero));
- add_guarded_claim(
+ add_guarded_property(
inequality,
"division by zero",
"division-by-zero",
@@ -270,7 +333,7 @@ void goto_checkt::undefined_shift_check(
binary_relation_exprt inequality(
expr.distance(), ID_ge, from_integer(0, distance_type));
- add_guarded_claim(
+ add_guarded_property(
inequality,
"shift distance is negative",
"undefined-shift",
@@ -286,7 +349,7 @@ void goto_checkt::undefined_shift_check(
exprt width_expr=
from_integer(to_bitvector_type(op_type).get_width(), distance_type);
- add_guarded_claim(
+ add_guarded_property(
binary_relation_exprt(expr.distance(), ID_lt, std::move(width_expr)),
"shift distance too large",
"undefined-shift",
@@ -299,7 +362,7 @@ void goto_checkt::undefined_shift_check(
binary_relation_exprt inequality(
expr.op(), ID_ge, from_integer(0, op_type));
- add_guarded_claim(
+ add_guarded_property(
inequality,
"shift operand is negative",
"undefined-shift",
@@ -310,7 +373,7 @@ void goto_checkt::undefined_shift_check(
}
else
{
- add_guarded_claim(
+ add_guarded_property(
false_exprt(),
"shift of non-integer type",
"undefined-shift",
@@ -332,7 +395,7 @@ void goto_checkt::mod_by_zero_check(
exprt zero=from_integer(0, expr.op1().type());
const notequal_exprt inequality(expr.op1(), std::move(zero));
- add_guarded_claim(
+ add_guarded_property(
inequality,
"division by zero",
"division-by-zero",
@@ -362,7 +425,7 @@ void goto_checkt::mod_overflow_check(const mod_exprt &expr, const guardt &guard)
notequal_exprt minus_one_neq(
expr.op1(), from_integer(-1, expr.op1().type()));
- add_guarded_claim(
+ add_guarded_property(
or_exprt(int_min_neq, minus_one_neq),
"result of signed mod is not representable",
"overflow",
@@ -413,7 +476,7 @@ void goto_checkt::conversion_check(
const binary_relation_exprt no_overflow_lower(
expr.op0(), ID_ge, from_integer(-power(2, new_width - 1), old_type));
- add_guarded_claim(
+ add_guarded_property(
and_exprt(no_overflow_lower, no_overflow_upper),
"arithmetic overflow on signed type conversion",
"overflow",
@@ -432,7 +495,7 @@ void goto_checkt::conversion_check(
ID_le,
from_integer(power(2, new_width - 1) - 1, old_type));
- add_guarded_claim(
+ add_guarded_property(
no_overflow_upper,
"arithmetic overflow on unsigned to signed type conversion",
"overflow",
@@ -453,7 +516,7 @@ void goto_checkt::conversion_check(
const binary_relation_exprt no_overflow_lower(
expr.op0(), ID_gt, lower.to_expr());
- add_guarded_claim(
+ add_guarded_property(
and_exprt(no_overflow_lower, no_overflow_upper),
"arithmetic overflow on float to signed integer type conversion",
"overflow",
@@ -476,7 +539,7 @@ void goto_checkt::conversion_check(
const binary_relation_exprt no_overflow_lower(
expr.op0(), ID_ge, from_integer(0, old_type));
- add_guarded_claim(
+ add_guarded_property(
no_overflow_lower,
"arithmetic overflow on signed to unsigned type conversion",
"overflow",
@@ -493,7 +556,7 @@ void goto_checkt::conversion_check(
const binary_relation_exprt no_overflow_lower(
expr.op0(), ID_ge, from_integer(0, old_type));
- add_guarded_claim(
+ add_guarded_property(
and_exprt(no_overflow_lower, no_overflow_upper),
"arithmetic overflow on signed to unsigned type conversion",
"overflow",
@@ -511,7 +574,7 @@ void goto_checkt::conversion_check(
const binary_relation_exprt no_overflow_upper(
expr.op0(), ID_le, from_integer(power(2, new_width) - 1, old_type));
- add_guarded_claim(
+ add_guarded_property(
no_overflow_upper,
"arithmetic overflow on unsigned to unsigned type conversion",
"overflow",
@@ -532,7 +595,7 @@ void goto_checkt::conversion_check(
const binary_relation_exprt no_overflow_lower(
expr.op0(), ID_gt, lower.to_expr());
- add_guarded_claim(
+ add_guarded_property(
and_exprt(no_overflow_lower, no_overflow_upper),
"arithmetic overflow on float to unsigned integer type conversion",
"overflow",
@@ -576,7 +639,7 @@ void goto_checkt::integer_overflow_check(
equal_exprt minus_one_eq(
expr.op1(), from_integer(-1, type));
- add_guarded_claim(
+ add_guarded_property(
not_exprt(and_exprt(int_min_eq, minus_one_eq)),
"arithmetic overflow on signed division",
"overflow",
@@ -597,7 +660,7 @@ void goto_checkt::integer_overflow_check(
equal_exprt int_min_eq(
expr.op0(), to_signedbv_type(type).smallest_expr());
- add_guarded_claim(
+ add_guarded_property(
not_exprt(int_min_eq),
"arithmetic overflow on signed unary minus",
"overflow",
@@ -696,7 +759,7 @@ void goto_checkt::integer_overflow_check(
// a shift that's too far isn't an overflow;
// a shift of zero isn't overflow;
// else check the top bits
- add_guarded_claim(
+ add_guarded_property(
disjunction({neg_value_shift,
neg_dist_shift,
dist_too_large,
@@ -739,9 +802,9 @@ void goto_checkt::integer_overflow_check(
std::string kind=
type.id()==ID_unsignedbv?"unsigned":"signed";
- add_guarded_claim(
+ add_guarded_property(
not_exprt(overflow),
- "arithmetic overflow on "+kind+" "+expr.id_string(),
+ "arithmetic overflow on " + kind + " " + expr.id_string(),
"overflow",
expr.find_source_location(),
expr,
@@ -753,9 +816,9 @@ void goto_checkt::integer_overflow_check(
std::string kind=
type.id()==ID_unsignedbv?"unsigned":"signed";
- add_guarded_claim(
+ add_guarded_property(
not_exprt(overflow),
- "arithmetic overflow on "+kind+" "+expr.id_string(),
+ "arithmetic overflow on " + kind + " " + expr.id_string(),
"overflow",
expr.find_source_location(),
expr,
@@ -792,7 +855,7 @@ void goto_checkt::float_overflow_check(
or_exprt overflow_check(op0_inf, not_exprt(new_inf));
- add_guarded_claim(
+ add_guarded_property(
overflow_check,
"arithmetic overflow on floating-point typecast",
"overflow",
@@ -805,7 +868,7 @@ void goto_checkt::float_overflow_check(
// non-float-to-float
const isinf_exprt new_inf(expr);
- add_guarded_claim(
+ add_guarded_property(
not_exprt(new_inf),
"arithmetic overflow on floating-point typecast",
"overflow",
@@ -826,7 +889,7 @@ void goto_checkt::float_overflow_check(
or_exprt overflow_check(op0_inf, not_exprt(new_inf));
- add_guarded_claim(
+ add_guarded_property(
overflow_check,
"arithmetic overflow on floating-point division",
"overflow",
@@ -863,9 +926,9 @@ void goto_checkt::float_overflow_check(
expr.id()==ID_minus?"subtraction":
expr.id()==ID_mult?"multiplication":"";
- add_guarded_claim(
+ add_guarded_property(
overflow_check,
- "arithmetic overflow on floating-point "+kind,
+ "arithmetic overflow on floating-point " + kind,
"overflow",
expr.find_source_location(),
expr,
@@ -983,7 +1046,7 @@ void goto_checkt::nan_check(
else
UNREACHABLE;
- add_guarded_claim(
+ add_guarded_property(
boolean_negate(isnan),
"NaN on " + expr.id_string(),
"NaN",
@@ -1011,7 +1074,7 @@ void goto_checkt::pointer_rel_check(
{
exprt same_object=::same_object(expr.op0(), expr.op1());
- add_guarded_claim(
+ add_guarded_property(
same_object,
"same object violation",
"pointer",
@@ -1039,7 +1102,7 @@ void goto_checkt::pointer_overflow_check(
exprt overflow("overflow-" + expr.id_string(), bool_typet());
overflow.operands() = expr.operands();
- add_guarded_claim(
+ add_guarded_property(
not_exprt(overflow),
"pointer arithmetic overflow on " + expr.id_string(),
"overflow",
@@ -1064,9 +1127,9 @@ void goto_checkt::pointer_validity_check(
for(const auto &c : conditions)
{
- add_guarded_claim(
+ add_guarded_property(
c.assertion,
- "dereference failure: "+c.description,
+ "dereference failure: " + c.description,
"pointer dereference",
expr.find_source_location(),
expr,
@@ -1263,9 +1326,9 @@ void goto_checkt::bounds_check(
binary_relation_exprt inequality(
effective_offset, ID_ge, std::move(zero));
- add_guarded_claim(
+ add_guarded_property(
inequality,
- name+" lower bound",
+ name + " lower bound",
"array bounds",
expr.find_source_location(),
expr,
@@ -1320,9 +1383,9 @@ void goto_checkt::bounds_check(
and_exprt(dynamic_object(pointer), not_exprt(malloc_object(pointer, ns))),
inequality);
- add_guarded_claim(
+ add_guarded_property(
precond,
- name+" dynamic object upper bound",
+ name + " dynamic object upper bound",
"array bounds",
expr.find_source_location(),
expr,
@@ -1381,7 +1444,7 @@ void goto_checkt::bounds_check(
ID_lt,
type_size_opt.value());
- add_guarded_claim(
+ add_guarded_property(
implies_exprt(type_matches_size, inequality),
name + " upper bound",
"array bounds",
@@ -1397,9 +1460,9 @@ void goto_checkt::bounds_check(
inequality.op1() = typecast_exprt::conditional_cast(
inequality.op1(), inequality.op0().type());
- add_guarded_claim(
+ add_guarded_property(
implies_exprt(type_matches_size, inequality),
- name+" upper bound",
+ name + " upper bound",
"array bounds",
expr.find_source_location(),
expr,
@@ -1407,189 +1470,213 @@ void goto_checkt::bounds_check(
}
}
-void goto_checkt::add_guarded_claim(
- const exprt &_expr,
+void goto_checkt::add_guarded_property(
+ const exprt &asserted_expr,
const std::string &comment,
const std::string &property_class,
const source_locationt &source_location,
const exprt &src_expr,
const guardt &guard)
{
- exprt expr(_expr);
-
// first try simplifier on it
- if(enable_simplify)
- simplify(expr, ns);
+ exprt simplified_expr =
+ enable_simplify ? simplify_expr(asserted_expr, ns) : asserted_expr;
// throw away trivial properties?
- if(!retain_trivial && expr.is_true())
+ if(!retain_trivial && simplified_expr.is_true())
return;
// add the guard
+ exprt guarded_expr =
+ guard.is_true()
+ ? std::move(simplified_expr)
+ : implies_exprt{guard.as_expr(), std::move(simplified_expr)};
- exprt new_expr;
-
- if(guard.is_true())
- new_expr.swap(expr);
- else
- new_expr = implies_exprt(guard.as_expr(), std::move(expr));
-
- if(assertions.insert(new_expr).second)
+ if(assertions.insert(guarded_expr).second)
{
- goto_program_instruction_typet type=
- enable_assert_to_assume?ASSUME:ASSERT;
-
- goto_programt::targett t = new_code.add(goto_programt::instructiont(
- static_cast(get_nil_irep()),
- source_location,
- type,
- std::move(new_expr),
- {}));
+ auto t = new_code.add(
+ enable_assert_to_assume ? goto_programt::make_assumption(
+ std::move(guarded_expr), source_location)
+ : goto_programt::make_assertion(
+ std::move(guarded_expr), source_location));
std::string source_expr_string;
get_language_from_mode(mode)->from_expr(src_expr, source_expr_string, ns);
- t->source_location.set_comment(comment+" in "+source_expr_string);
+ t->source_location.set_comment(comment + " in " + source_expr_string);
t->source_location.set_property_class(property_class);
}
}
-void goto_checkt::check_rec(const exprt &expr, guardt &guard, bool address)
+void goto_checkt::check_rec_address(const exprt &expr, guardt &guard)
{
// we don't look into quantifiers
- if(expr.id()==ID_exists || expr.id()==ID_forall)
+ if(expr.id() == ID_exists || expr.id() == ID_forall)
return;
- if(address)
+ if(expr.id() == ID_dereference)
{
- if(expr.id()==ID_dereference)
- {
- assert(expr.operands().size()==1);
- check_rec(expr.op0(), guard, false);
- }
- else if(expr.id()==ID_index)
- {
- assert(expr.operands().size()==2);
- check_rec(expr.op0(), guard, true);
- check_rec(expr.op1(), guard, false);
- }
- else
- {
- forall_operands(it, expr)
- check_rec(*it, guard, true);
- }
- return;
+ check_rec(to_dereference_expr(expr).pointer(), guard);
}
-
- if(expr.id()==ID_address_of)
+ else if(expr.id() == ID_index)
{
- assert(expr.operands().size()==1);
- check_rec(expr.op0(), guard, true);
- return;
+ const index_exprt &index_expr = to_index_expr(expr);
+ check_rec_address(index_expr.array(), guard);
+ check_rec(index_expr.index(), guard);
}
- else if(expr.id()==ID_and || expr.id()==ID_or)
+ else
{
- if(!expr.is_boolean())
- throw "`"+expr.id_string()+"' must be Boolean, but got "+
- expr.pretty();
+ for(const auto &operand : expr.operands())
+ check_rec_address(operand, guard);
+ }
+}
- guardt old_guard=guard;
+void goto_checkt::check_rec_logical_op(const exprt &expr, guardt &guard)
+{
+ INVARIANT(
+ expr.is_boolean(),
+ "`" + expr.id_string() + "' must be Boolean, but got " + expr.pretty());
- for(const auto &op : expr.operands())
- {
- if(!op.is_boolean())
- throw "`"+expr.id_string()+"' takes Boolean operands only, but got "+
- op.pretty();
+ guardt old_guard = guard;
- check_rec(op, guard, false);
+ for(const auto &op : expr.operands())
+ {
+ INVARIANT(
+ op.is_boolean(),
+ "`" + expr.id_string() + "' takes Boolean operands only, but got " +
+ op.pretty());
- if(expr.id()==ID_or)
- guard.add(not_exprt(op));
- else
- guard.add(op);
- }
+ check_rec(op, guard);
+ guard.add(expr.id() == ID_or ? boolean_negate(op) : op);
+ }
+
+ guard = std::move(old_guard);
+}
+
+void goto_checkt::check_rec_if(const if_exprt &if_expr, guardt &guard)
+{
+ INVARIANT(
+ if_expr.cond().is_boolean(),
+ "first argument of if must be boolean, but got " + if_expr.cond().pretty());
+ check_rec(if_expr.cond(), guard);
+
+ {
+ guardt old_guard = guard;
+ guard.add(if_expr.cond());
+ check_rec(if_expr.true_case(), guard);
guard = std::move(old_guard);
- return;
}
- else if(expr.id()==ID_if)
+
{
- if(expr.operands().size()!=3)
- throw "if takes three arguments";
+ guardt old_guard = guard;
+ guard.add(not_exprt{if_expr.cond()});
+ check_rec(if_expr.false_case(), guard);
+ guard = std::move(old_guard);
+ }
+}
- if(!expr.op0().is_boolean())
- {
- std::string msg=
- "first argument of if must be boolean, but got "
- +expr.op0().pretty();
- throw msg;
- }
+bool goto_checkt::check_rec_member(const member_exprt &member, guardt &guard)
+{
+ const dereference_exprt &deref = to_dereference_expr(member.struct_op());
- check_rec(expr.op0(), guard, false);
+ check_rec(deref.pointer(), guard);
- {
- guardt old_guard=guard;
- guard.add(expr.op0());
- check_rec(expr.op1(), guard, false);
- guard = std::move(old_guard);
- }
+ // avoid building the following expressions when pointer_validity_check
+ // would return immediately anyway
+ if(!enable_pointer_check)
+ return true;
- {
- guardt old_guard=guard;
- guard.add(not_exprt(expr.op0()));
- check_rec(expr.op2(), guard, false);
- guard = std::move(old_guard);
- }
+ // we rewrite s->member into *(s+member_offset)
+ // to avoid requiring memory safety of the entire struct
+ auto member_offset_opt = member_offset_expr(member, ns);
- return;
- }
- else if(expr.id()==ID_member &&
- to_member_expr(expr).struct_op().id()==ID_dereference)
+ if(member_offset_opt.has_value())
{
- const member_exprt &member=to_member_expr(expr);
- const dereference_exprt &deref=
- to_dereference_expr(member.struct_op());
+ pointer_typet new_pointer_type = to_pointer_type(deref.pointer().type());
+ new_pointer_type.subtype() = member.type();
- check_rec(deref.pointer(), guard, false);
+ const exprt char_pointer = typecast_exprt::conditional_cast(
+ deref.pointer(), pointer_type(char_type()));
- // avoid building the following expressions when pointer_validity_check
- // would return immediately anyway
- if(!enable_pointer_check)
- return;
+ const exprt new_address_casted = typecast_exprt::conditional_cast(
+ typecast_exprt{
+ plus_exprt{char_pointer,
+ typecast_exprt::conditional_cast(
+ member_offset_opt.value(), pointer_diff_type())},
+ char_pointer.type()},
+ new_pointer_type);
- // we rewrite s->member into *(s+member_offset)
- // to avoid requiring memory safety of the entire struct
- auto member_offset_opt = member_offset_expr(member, ns);
+ dereference_exprt new_deref{new_address_casted};
+ new_deref.add_source_location() = deref.source_location();
+ pointer_validity_check(new_deref, guard);
- if(member_offset_opt.has_value())
- {
- pointer_typet new_pointer_type = to_pointer_type(deref.pointer().type());
- new_pointer_type.subtype() = expr.type();
+ return true;
+ }
+ return false;
+}
- const exprt char_pointer =
- typecast_exprt::conditional_cast(
- deref.pointer(), pointer_type(char_type()));
+void goto_checkt::check_rec_div(const div_exprt &div_expr, guardt &guard)
+{
+ div_by_zero_check(to_div_expr(div_expr), guard);
- const exprt new_address = typecast_exprt(
- plus_exprt(
- char_pointer,
- typecast_exprt::conditional_cast(
- member_offset_opt.value(), pointer_diff_type())),
- char_pointer.type());
+ if(div_expr.type().id() == ID_signedbv)
+ integer_overflow_check(div_expr, guard);
+ else if(div_expr.type().id() == ID_floatbv)
+ {
+ nan_check(div_expr, guard);
+ float_overflow_check(div_expr, guard);
+ }
+}
- const exprt new_address_casted =
- typecast_exprt::conditional_cast(new_address, new_pointer_type);
+void goto_checkt::check_rec_arithmetic_op(const exprt &expr, guardt &guard)
+{
+ if(expr.type().id() == ID_signedbv || expr.type().id() == ID_unsignedbv)
+ {
+ integer_overflow_check(expr, guard);
+ }
+ else if(expr.type().id() == ID_floatbv)
+ {
+ nan_check(expr, guard);
+ float_overflow_check(expr, guard);
+ }
+ else if(expr.type().id() == ID_pointer)
+ {
+ pointer_overflow_check(expr, guard);
+ }
+}
- dereference_exprt new_deref{new_address_casted};
- new_deref.add_source_location() = deref.source_location();
- pointer_validity_check(new_deref, guard);
+void goto_checkt::check_rec(const exprt &expr, guardt &guard)
+{
+ // we don't look into quantifiers
+ if(expr.id() == ID_exists || expr.id() == ID_forall)
+ return;
+ if(expr.id() == ID_address_of)
+ {
+ check_rec_address(to_address_of_expr(expr).object(), guard);
+ return;
+ }
+ else if(expr.id() == ID_and || expr.id() == ID_or)
+ {
+ check_rec_logical_op(expr, guard);
+ return;
+ }
+ else if(expr.id() == ID_if)
+ {
+ check_rec_if(to_if_expr(expr), guard);
+ return;
+ }
+ else if(
+ expr.id() == ID_member &&
+ to_member_expr(expr).struct_op().id() == ID_dereference)
+ {
+ if(check_rec_member(to_member_expr(expr), guard))
return;
- }
}
forall_operands(it, expr)
- check_rec(*it, guard, false);
+ check_rec(*it, guard);
if(expr.id()==ID_index)
{
@@ -1597,15 +1684,7 @@ void goto_checkt::check_rec(const exprt &expr, guardt &guard, bool address)
}
else if(expr.id()==ID_div)
{
- div_by_zero_check(to_div_expr(expr), guard);
-
- if(expr.type().id()==ID_signedbv)
- integer_overflow_check(expr, guard);
- else if(expr.type().id()==ID_floatbv)
- {
- nan_check(expr, guard);
- float_overflow_check(expr, guard);
- }
+ check_rec_div(to_div_expr(expr), guard);
}
else if(expr.id()==ID_shl || expr.id()==ID_ashr || expr.id()==ID_lshr)
{
@@ -1623,20 +1702,7 @@ void goto_checkt::check_rec(const exprt &expr, guardt &guard, bool address)
expr.id()==ID_mult ||
expr.id()==ID_unary_minus)
{
- if(expr.type().id()==ID_signedbv ||
- expr.type().id()==ID_unsignedbv)
- {
- integer_overflow_check(expr, guard);
- }
- else if(expr.type().id()==ID_floatbv)
- {
- nan_check(expr, guard);
- float_overflow_check(expr, guard);
- }
- else if(expr.type().id()==ID_pointer)
- {
- pointer_overflow_check(expr, guard);
- }
+ check_rec_arithmetic_op(expr, guard);
}
else if(expr.id()==ID_typecast)
conversion_check(expr, guard);
@@ -1652,7 +1718,7 @@ void goto_checkt::check_rec(const exprt &expr, guardt &guard, bool address)
void goto_checkt::check(const exprt &expr)
{
guardt guard{true_exprt{}, guard_manager};
- check_rec(expr, guard, false);
+ check_rec(expr, guard);
}
/// expand the r_ok and w_ok predicates
@@ -1798,15 +1864,10 @@ void goto_checkt::goto_check(
{
if(std::find(i.labels.begin(), i.labels.end(), label)!=i.labels.end())
{
- goto_program_instruction_typet type=
- enable_assert_to_assume?ASSUME:ASSERT;
-
- goto_programt::targett t = new_code.add(goto_programt::instructiont(
- static_cast(get_nil_irep()),
- i.source_location,
- type,
- false_exprt(),
- {}));
+ auto t = new_code.add(
+ enable_assert_to_assume
+ ? goto_programt::make_assumption(false_exprt{}, i.source_location)
+ : goto_programt::make_assertion(false_exprt{}, i.source_location));
t->source_location.set_property_class("error label");
t->source_location.set_comment("error label "+label);
@@ -1873,7 +1934,7 @@ void goto_checkt::goto_check(
pointer,
null_pointer_exprt(to_pointer_type(pointer.type())));
- add_guarded_claim(
+ add_guarded_property(
not_eq_null,
"this is null on method invocation",
"pointer dereference",
@@ -1922,7 +1983,7 @@ void goto_checkt::goto_check(
const notequal_exprt not_eq_null(
pointer, null_pointer_exprt(to_pointer_type(pointer.type())));
- add_guarded_claim(
+ add_guarded_property(
not_eq_null,
"throwing null",
"pointer dereference",
@@ -1997,7 +2058,7 @@ void goto_checkt::goto_check(
equal_exprt eq(
leak_expr,
null_pointer_exprt(to_pointer_type(leak.type)));
- add_guarded_claim(
+ add_guarded_property(
eq,
"dynamically allocated memory never freed",
"memory-leak",