Skip to content

Commit 3d299a5

Browse files
committed
Verify member expressions
This checks that the component they refer to really exists, and the expression and component's types match (are base_type_eq).
1 parent c049004 commit 3d299a5

File tree

3 files changed

+52
-1
lines changed

3 files changed

+52
-1
lines changed

src/util/std_expr.cpp

+33
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ Author: Daniel Kroening, [email protected]
1515
#include "c_types.h"
1616
#include "expr_util.h"
1717
#include "mathematical_types.h"
18+
#include "namespace.h"
1819
#include "pointer_offset_size.h"
1920

2021
bool constant_exprt::value_is_zero_string() const
@@ -223,3 +224,35 @@ const exprt &object_descriptor_exprt::root_object() const
223224

224225
return *p;
225226
}
227+
228+
void member_exprt::validate(
229+
const exprt &expr,
230+
const namespacet &ns,
231+
const validation_modet vm)
232+
{
233+
check(expr, vm);
234+
235+
const auto &member_expr = to_member_expr(expr);
236+
237+
const typet &compound_type = ns.follow(member_expr.compound().type());
238+
DATA_CHECK(
239+
vm,
240+
can_cast_type<struct_union_typet>(compound_type),
241+
"member must address a struct, union or compatible type");
242+
243+
const auto &component =
244+
to_struct_union_type(compound_type).get_component(
245+
member_expr.get_component_name());
246+
247+
DATA_CHECK(
248+
vm,
249+
component.is_not_nil(),
250+
"member component '" + id2string(member_expr.get_component_name()) +
251+
"' must exist on addressed type");
252+
253+
DATA_CHECK(
254+
vm,
255+
base_type_eq(component.type(), member_expr.type(), ns),
256+
"member expression's type must match the addressed struct or union "
257+
"component");
258+
}

src/util/std_expr.h

+15-1
Original file line numberDiff line numberDiff line change
@@ -3897,6 +3897,21 @@ class member_exprt:public unary_exprt
38973897
{
38983898
return op0();
38993899
}
3900+
3901+
static void check(
3902+
const exprt &expr,
3903+
const validation_modet vm = validation_modet::INVARIANT)
3904+
{
3905+
DATA_CHECK(
3906+
vm,
3907+
expr.operands().size() == 1,
3908+
"member expression must have one operand");
3909+
}
3910+
3911+
static void validate(
3912+
const exprt &expr,
3913+
const namespacet &ns,
3914+
const validation_modet vm = validation_modet::INVARIANT);
39003915
};
39013916

39023917
/// \brief Cast an exprt to a \ref member_exprt
@@ -3933,7 +3948,6 @@ inline void validate_expr(const member_exprt &value)
39333948
validate_operands(value, 1, "Extract member must have one operand");
39343949
}
39353950

3936-
39373951
/// \brief Evaluates to true if the operand is NaN
39383952
class isnan_exprt:public unary_predicate_exprt
39393953
{

src/util/validate_expressions.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ void call_on_expr(const exprt &expr, Args &&... args)
3737
{
3838
CALL_ON_EXPR(ssa_exprt);
3939
}
40+
else if(expr.id() == ID_member)
41+
{
42+
CALL_ON_EXPR(member_exprt);
43+
}
4044
else
4145
{
4246
#ifdef REPORT_UNIMPLEMENTED_EXPRESSION_CHECKS

0 commit comments

Comments
 (0)