Skip to content

Commit 266f00b

Browse files
committed
Separate and refactor checking member
Only clang-format, inline expr-construction, and for-each loop.
1 parent d74ef71 commit 266f00b

File tree

1 file changed

+56
-41
lines changed

1 file changed

+56
-41
lines changed

src/analyses/goto_check.cpp

+56-41
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,18 @@ class goto_checkt
111111
/// the) if-condition for recursively calls)
112112
void check_rec_if(const if_exprt &if_expr, guardt &guard);
113113

114+
/// Check that a member expression is valid:
115+
/// - check the structure this expression is a member of (via pointer of its
116+
/// dereference)
117+
/// - run pointer-validity check on `*(s+member_offset)' instead of
118+
/// `s->member' to avoid checking safety of `s'
119+
/// - check all operands of the expression
120+
/// \param member: the expression to be checked
121+
/// \param guard: the condition for the check (unmodified here)
122+
/// \return true if no more checks are required for \p member or its
123+
/// sub-expressions
124+
bool check_rec_member(const member_exprt &member, guardt &guard);
125+
114126
void check_rec(const exprt &expr, guardt &guard);
115127
void check(const exprt &expr);
116128

@@ -1546,6 +1558,46 @@ void goto_checkt::check_rec_if(const if_exprt &if_expr, guardt &guard)
15461558
}
15471559
}
15481560

1561+
bool goto_checkt::check_rec_member(const member_exprt &member, guardt &guard)
1562+
{
1563+
const dereference_exprt &deref = to_dereference_expr(member.struct_op());
1564+
1565+
check_rec(deref.pointer(), guard);
1566+
1567+
// avoid building the following expressions when pointer_validity_check
1568+
// would return immediately anyway
1569+
if(!enable_pointer_check)
1570+
return true;
1571+
1572+
// we rewrite s->member into *(s+member_offset)
1573+
// to avoid requiring memory safety of the entire struct
1574+
auto member_offset_opt = member_offset_expr(member, ns);
1575+
1576+
if(member_offset_opt.has_value())
1577+
{
1578+
pointer_typet new_pointer_type = to_pointer_type(deref.pointer().type());
1579+
new_pointer_type.subtype() = member.type();
1580+
1581+
const exprt char_pointer = typecast_exprt::conditional_cast(
1582+
deref.pointer(), pointer_type(char_type()));
1583+
1584+
const exprt new_address_casted = typecast_exprt::conditional_cast(
1585+
typecast_exprt{
1586+
plus_exprt{char_pointer,
1587+
typecast_exprt::conditional_cast(
1588+
member_offset_opt.value(), pointer_diff_type())},
1589+
char_pointer.type()},
1590+
new_pointer_type);
1591+
1592+
dereference_exprt new_deref{new_address_casted};
1593+
new_deref.add_source_location() = deref.source_location();
1594+
pointer_validity_check(new_deref, guard);
1595+
1596+
return true;
1597+
}
1598+
return false;
1599+
}
1600+
15491601
void goto_checkt::check_rec(const exprt &expr, guardt &guard)
15501602
{
15511603
// we don't look into quantifiers
@@ -1568,49 +1620,12 @@ void goto_checkt::check_rec(const exprt &expr, guardt &guard)
15681620
check_rec_if(to_if_expr(expr), guard);
15691621
return;
15701622
}
1571-
else if(expr.id()==ID_member &&
1572-
to_member_expr(expr).struct_op().id()==ID_dereference)
1623+
else if(
1624+
expr.id() == ID_member &&
1625+
to_member_expr(expr).struct_op().id() == ID_dereference)
15731626
{
1574-
const member_exprt &member=to_member_expr(expr);
1575-
const dereference_exprt &deref=
1576-
to_dereference_expr(member.struct_op());
1577-
1578-
check_rec(deref.pointer(), guard);
1579-
1580-
// avoid building the following expressions when pointer_validity_check
1581-
// would return immediately anyway
1582-
if(!enable_pointer_check)
1583-
return;
1584-
1585-
// we rewrite s->member into *(s+member_offset)
1586-
// to avoid requiring memory safety of the entire struct
1587-
auto member_offset_opt = member_offset_expr(member, ns);
1588-
1589-
if(member_offset_opt.has_value())
1590-
{
1591-
pointer_typet new_pointer_type = to_pointer_type(deref.pointer().type());
1592-
new_pointer_type.subtype() = expr.type();
1593-
1594-
const exprt char_pointer =
1595-
typecast_exprt::conditional_cast(
1596-
deref.pointer(), pointer_type(char_type()));
1597-
1598-
const exprt new_address = typecast_exprt(
1599-
plus_exprt(
1600-
char_pointer,
1601-
typecast_exprt::conditional_cast(
1602-
member_offset_opt.value(), pointer_diff_type())),
1603-
char_pointer.type());
1604-
1605-
const exprt new_address_casted =
1606-
typecast_exprt::conditional_cast(new_address, new_pointer_type);
1607-
1608-
dereference_exprt new_deref{new_address_casted};
1609-
new_deref.add_source_location() = deref.source_location();
1610-
pointer_validity_check(new_deref, guard);
1611-
1627+
if(check_rec_member(to_member_expr(expr), guard))
16121628
return;
1613-
}
16141629
}
16151630

16161631
forall_operands(it, expr)

0 commit comments

Comments
 (0)