Skip to content

Commit 9fec06a

Browse files
authored
Merge pull request #6598 from tautschnig/cleanup/annotated-pointer-constant
Add annotated_pointer_constant_exprt
2 parents 7157df5 + b497f6b commit 9fec06a

File tree

11 files changed

+200
-130
lines changed

11 files changed

+200
-130
lines changed

jbmc/src/java_bytecode/java_trace_validation.cpp

Lines changed: 39 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ bool valid_rhs_expr_high_level(const exprt &rhs)
6868
{
6969
return can_cast_expr<struct_exprt>(rhs) || can_cast_expr<array_exprt>(rhs) ||
7070
can_cast_expr<constant_exprt>(rhs) ||
71+
can_cast_expr<annotated_pointer_constant_exprt>(rhs) ||
7172
can_cast_expr<address_of_exprt>(rhs) ||
7273
can_cast_expr<symbol_exprt>(rhs) ||
7374
can_cast_expr<array_list_exprt>(rhs) ||
@@ -96,14 +97,21 @@ bool check_struct_structure(const struct_exprt &expr)
9697
return false;
9798
if(const auto sub_struct = expr_try_dynamic_cast<struct_exprt>(expr.op0()))
9899
check_struct_structure(*sub_struct);
99-
else if(!can_cast_expr<constant_exprt>(expr.op0()))
100+
else if(
101+
!can_cast_expr<constant_exprt>(expr.op0()) &&
102+
!can_cast_expr<annotated_pointer_constant_exprt>(expr.op0()))
103+
{
100104
return false;
105+
}
101106
if(
102-
expr.operands().size() > 1 &&
103-
std::any_of(
104-
++expr.operands().begin(),
105-
expr.operands().end(),
106-
[&](const exprt &operand) { return operand.id() != ID_constant; }))
107+
expr.operands().size() > 1 && std::any_of(
108+
++expr.operands().begin(),
109+
expr.operands().end(),
110+
[&](const exprt &operand) {
111+
return operand.id() != ID_constant &&
112+
operand.id() !=
113+
ID_annotated_pointer_constant;
114+
}))
107115
{
108116
return false;
109117
}
@@ -119,17 +127,21 @@ bool check_address_structure(const address_of_exprt &address)
119127
bool check_constant_structure(const constant_exprt &constant_expr)
120128
{
121129
if(constant_expr.has_operands())
122-
{
123-
const auto &operand = skip_typecast(constant_expr.operands()[0]);
124-
return can_cast_expr<constant_exprt>(operand) ||
125-
can_cast_expr<address_of_exprt>(operand) ||
126-
can_cast_expr<plus_exprt>(operand);
127-
}
130+
return false;
128131
// All value types used in Java must be non-empty except string_typet:
129132
return !constant_expr.get_value().empty() ||
130133
constant_expr.type() == string_typet();
131134
}
132135

136+
static bool check_annotated_pointer_constant_structure(
137+
const annotated_pointer_constant_exprt &constant_expr)
138+
{
139+
const auto &operand = skip_typecast(constant_expr.symbolic_pointer());
140+
return can_cast_expr<constant_exprt>(operand) ||
141+
can_cast_expr<address_of_exprt>(operand) ||
142+
can_cast_expr<plus_exprt>(operand);
143+
}
144+
133145
static void check_lhs_assumptions(
134146
const exprt &lhs,
135147
const namespacet &ns,
@@ -253,8 +265,21 @@ static void check_rhs_assumptions(
253265
check_constant_structure(*constant_expr),
254266
"RHS",
255267
rhs.pretty(),
256-
"Expecting the first operand of a constant expression to be a constant, "
257-
"address_of or plus expression, or no operands and a non-empty value.");
268+
"Expecting a constant expression to have no operands and a non-empty "
269+
"value.");
270+
}
271+
// check pointer constant rhs structure
272+
else if(
273+
const auto constant_expr =
274+
expr_try_dynamic_cast<annotated_pointer_constant_exprt>(rhs))
275+
{
276+
DATA_CHECK_WITH_DIAGNOSTICS(
277+
vm,
278+
check_annotated_pointer_constant_structure(*constant_expr),
279+
"RHS",
280+
rhs.pretty(),
281+
"Expecting the operand of an annotated pointer constant expression "
282+
"to be a constant, address_of, or plus expression.");
258283
}
259284
// check byte extract rhs structure
260285
else if(const auto byte = expr_try_dynamic_cast<byte_extract_exprt>(rhs))

src/ansi-c/expr2c.cpp

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1994,23 +1994,11 @@ std::string expr2ct::convert_constant(
19941994
if(to_pointer_type(type).base_type().id() != ID_empty)
19951995
dest="(("+convert(type)+")"+dest+")";
19961996
}
1997-
else if(src.operands().size() == 1)
1997+
else if(
1998+
value == "INVALID" || has_prefix(id2string(value), "INVALID-") ||
1999+
value == "NULL+offset")
19982000
{
1999-
const auto &annotation = to_unary_expr(src).op();
2000-
2001-
if(annotation.id() == ID_constant)
2002-
{
2003-
const irep_idt &op_value = to_constant_expr(annotation).get_value();
2004-
2005-
if(op_value=="INVALID" ||
2006-
has_prefix(id2string(op_value), "INVALID-") ||
2007-
op_value=="NULL+offset")
2008-
dest=id2string(op_value);
2009-
else
2010-
return convert_norep(src, precedence);
2011-
}
2012-
else
2013-
return convert_with_precedence(annotation, precedence);
2001+
dest = id2string(value);
20142002
}
20152003
else
20162004
{
@@ -2029,6 +2017,15 @@ std::string expr2ct::convert_constant(
20292017
return dest;
20302018
}
20312019

2020+
std::string expr2ct::convert_annotated_pointer_constant(
2021+
const annotated_pointer_constant_exprt &src,
2022+
unsigned &precedence)
2023+
{
2024+
const auto &annotation = src.symbolic_pointer();
2025+
2026+
return convert_with_precedence(annotation, precedence);
2027+
}
2028+
20322029
/// To get the C-like representation of a given boolean value.
20332030
/// \param boolean_value: The value of the constant bool expression
20342031
/// \return Returns a C-like representation of the boolean value, e.g. TRUE or
@@ -3888,6 +3885,12 @@ std::string expr2ct::convert_with_precedence(
38883885
else if(src.id()==ID_constant)
38893886
return convert_constant(to_constant_expr(src), precedence);
38903887

3888+
else if(src.id() == ID_annotated_pointer_constant)
3889+
{
3890+
return convert_annotated_pointer_constant(
3891+
to_annotated_pointer_constant_expr(src), precedence);
3892+
}
3893+
38913894
else if(src.id()==ID_string_constant)
38923895
return '"' + MetaString(id2string(to_string_constant(src).get_value())) +
38933896
'"';

src/ansi-c/expr2c_class.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ Author: Daniel Kroening, [email protected]
2323
#include <util/mathematical_expr.h>
2424
#include <util/std_code.h>
2525

26+
class annotated_pointer_constant_exprt;
2627
class qualifierst;
2728
class namespacet;
2829

@@ -257,6 +258,9 @@ class expr2ct
257258
// NOLINTNEXTLINE(whitespace/line_length)
258259
virtual std::string convert_constant(const constant_exprt &src, unsigned &precedence);
259260
virtual std::string convert_constant_bool(bool boolean_value);
261+
virtual std::string convert_annotated_pointer_constant(
262+
const annotated_pointer_constant_exprt &src,
263+
unsigned &precedence);
260264

261265
std::string convert_norep(const exprt &src, unsigned &precedence);
262266

src/goto-programs/goto_trace.h

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -296,32 +296,4 @@ void show_goto_trace(
296296
if(cmdline.isset("stack-trace")) \
297297
options.set_option("stack-trace", true);
298298

299-
/// Variety of constant expression only used in the context of a GOTO trace, to
300-
/// give both the numeric value and the symbolic value of a pointer,
301-
/// e.g. numeric value "0xabcd0004" but symbolic value "&some_object + 4". The
302-
/// numeric value is stored in the `constant_exprt`'s usual value slot (see
303-
/// \ref constant_exprt::get_value) and the symbolic value is accessed using the
304-
/// `symbolic_pointer` method introduced by this class.
305-
class goto_trace_constant_pointer_exprt : public constant_exprt
306-
{
307-
public:
308-
const exprt &symbolic_pointer() const
309-
{
310-
return static_cast<const exprt &>(operands()[0]);
311-
}
312-
};
313-
314-
template <>
315-
inline bool can_cast_expr<goto_trace_constant_pointer_exprt>(const exprt &base)
316-
{
317-
return can_cast_expr<constant_exprt>(base) && base.operands().size() == 1;
318-
}
319-
320-
inline const goto_trace_constant_pointer_exprt &
321-
to_goto_trace_constant_pointer_expr(const exprt &expr)
322-
{
323-
PRECONDITION(can_cast_expr<goto_trace_constant_pointer_exprt>(expr));
324-
return static_cast<const goto_trace_constant_pointer_exprt &>(expr);
325-
}
326-
327299
#endif // CPROVER_GOTO_PROGRAMS_GOTO_TRACE_H

src/goto-programs/json_expr.cpp

Lines changed: 42 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -31,24 +31,7 @@ Author: Peter Schrammel
3131

3232
static exprt simplify_json_expr(const exprt &src)
3333
{
34-
if(src.id() == ID_constant)
35-
{
36-
if(src.type().id() == ID_pointer)
37-
{
38-
const constant_exprt &c = to_constant_expr(src);
39-
40-
if(
41-
c.get_value() != ID_NULL &&
42-
(!c.value_is_zero_string() || !config.ansi_c.NULL_is_zero) &&
43-
src.operands().size() == 1 &&
44-
to_unary_expr(src).op().id() != ID_constant)
45-
// try to simplify the constant pointer
46-
{
47-
return simplify_json_expr(to_unary_expr(src).op());
48-
}
49-
}
50-
}
51-
else if(src.id() == ID_typecast)
34+
if(src.id() == ID_typecast)
5235
{
5336
return simplify_json_expr(to_typecast_expr(src).op());
5437
}
@@ -303,25 +286,8 @@ json_objectt json(const exprt &expr, const namespacet &ns, const irep_idt &mode)
303286
{
304287
result["name"] = json_stringt("pointer");
305288
result["type"] = json_stringt(type_string);
306-
exprt simpl_expr = simplify_json_expr(expr);
307-
if(
308-
simpl_expr.get(ID_value) == ID_NULL ||
309-
// remove typecast on NULL
310-
(simpl_expr.id() == ID_constant &&
311-
simpl_expr.type().id() == ID_pointer &&
312-
to_unary_expr(simpl_expr).op().get(ID_value) == ID_NULL))
313-
{
289+
if(constant_expr.get_value() == ID_NULL)
314290
result["data"] = json_stringt(value_string);
315-
}
316-
else if(simpl_expr.id() == ID_symbol)
317-
{
318-
const irep_idt &ptr_id = to_symbol_expr(simpl_expr).get_identifier();
319-
identifiert identifier(id2string(ptr_id));
320-
DATA_INVARIANT(
321-
!identifier.components.empty(),
322-
"pointer identifier should have non-empty components");
323-
result["data"] = json_stringt(identifier.components.back());
324-
}
325291
}
326292
else if(type.id() == ID_bool)
327293
{
@@ -339,6 +305,46 @@ json_objectt json(const exprt &expr, const namespacet &ns, const irep_idt &mode)
339305
result["name"] = json_stringt("unknown");
340306
}
341307
}
308+
else if(expr.id() == ID_annotated_pointer_constant)
309+
{
310+
const annotated_pointer_constant_exprt &c =
311+
to_annotated_pointer_constant_expr(expr);
312+
exprt simpl_expr = simplify_json_expr(c.symbolic_pointer());
313+
314+
if(simpl_expr.id() == ID_symbol)
315+
{
316+
result["name"] = json_stringt("pointer");
317+
318+
const typet &type = expr.type();
319+
320+
std::unique_ptr<languaget> lang;
321+
if(mode != ID_unknown)
322+
lang = std::unique_ptr<languaget>(get_language_from_mode(mode));
323+
if(!lang)
324+
lang = std::unique_ptr<languaget>(get_default_language());
325+
326+
const typet &underlying_type =
327+
type.id() == ID_c_bit_field
328+
? to_c_bit_field_type(type).underlying_type()
329+
: type;
330+
331+
std::string type_string;
332+
bool error = lang->from_type(underlying_type, type_string, ns);
333+
CHECK_RETURN(!error);
334+
result["type"] = json_stringt(type_string);
335+
336+
const irep_idt &ptr_id = to_symbol_expr(simpl_expr).get_identifier();
337+
identifiert identifier(id2string(ptr_id));
338+
DATA_INVARIANT(
339+
!identifier.components.empty(),
340+
"pointer identifier should have non-empty components");
341+
result["data"] = json_stringt(identifier.components.back());
342+
}
343+
else if(simpl_expr.id() == ID_constant)
344+
return json(simpl_expr, ns, mode);
345+
else
346+
result["name"] = json_stringt("unknown");
347+
}
342348
else if(expr.id() == ID_array)
343349
{
344350
result["name"] = json_stringt("array");

src/solvers/flattening/boolbv_constant.cpp

Lines changed: 1 addition & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -22,29 +22,7 @@ bvt boolbvt::convert_constant(const constant_exprt &expr)
2222

2323
const typet &expr_type=expr.type();
2424

25-
if(expr_type.id()==ID_array)
26-
{
27-
std::size_t op_width=width/expr.operands().size();
28-
std::size_t offset=0;
29-
30-
forall_operands(it, expr)
31-
{
32-
const bvt &tmp=convert_bv(*it);
33-
34-
DATA_INVARIANT_WITH_DIAGNOSTICS(
35-
tmp.size() == op_width,
36-
"convert_constant: unexpected operand width",
37-
irep_pretty_diagnosticst{expr});
38-
39-
for(std::size_t j=0; j<op_width; j++)
40-
bv[offset+j]=tmp[j];
41-
42-
offset+=op_width;
43-
}
44-
45-
return bv;
46-
}
47-
else if(expr_type.id()==ID_string)
25+
if(expr_type.id() == ID_string)
4826
{
4927
// we use the numbering for strings
5028
std::size_t number = string_numbering.number(expr.get_value());

src/solvers/flattening/bv_pointers.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -805,10 +805,8 @@ exprt bv_pointerst::bv_get_rec(
805805
numeric_cast_v<std::size_t>(binary2integer(value_addr, false));
806806
pointer.offset=binary2integer(value_offset, true);
807807

808-
// we add the elaborated expression as operand
809-
result.copy_to_operands(pointer_logic.pointer_expr(pointer, pt));
810-
811-
return std::move(result);
808+
return annotated_pointer_constant_exprt{
809+
bvrep, pointer_logic.pointer_expr(pointer, pt)};
812810
}
813811

814812
bvt bv_pointerst::encode(std::size_t addr, const pointer_typet &type) const

src/util/format_expr.cpp

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -189,13 +189,6 @@ static std::ostream &format_rec(std::ostream &os, const constant_exprt &src)
189189
{
190190
return os << "INVALID-POINTER";
191191
}
192-
else if(src.operands().size() == 1)
193-
{
194-
const auto &unary_expr = to_unary_expr(src);
195-
const auto &pointer_type = to_pointer_type(src.type());
196-
return os << "pointer(" << format(unary_expr.op()) << ", "
197-
<< format(pointer_type.base_type()) << ')';
198-
}
199192
else
200193
{
201194
const auto &pointer_type = to_pointer_type(src.type());
@@ -308,6 +301,12 @@ void format_expr_configt::setup()
308301
return format_rec(os, to_constant_expr(expr));
309302
};
310303

304+
expr_map[ID_annotated_pointer_constant] =
305+
[](std::ostream &os, const exprt &expr) -> std::ostream & {
306+
const auto &annotated_pointer = to_annotated_pointer_constant_expr(expr);
307+
return os << format(annotated_pointer.symbolic_pointer());
308+
};
309+
311310
expr_map[ID_typecast] =
312311
[](std::ostream &os, const exprt &expr) -> std::ostream & {
313312
return os << "cast(" << format(to_typecast_expr(expr).op()) << ", "

src/util/irep_ids.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -867,6 +867,7 @@ IREP_ID_ONE(empty_union)
867867
IREP_ID_ONE(bitreverse)
868868
IREP_ID_ONE(saturating_minus)
869869
IREP_ID_ONE(saturating_plus)
870+
IREP_ID_ONE(annotated_pointer_constant)
870871

871872
// Projects depending on this code base that wish to extend the list of
872873
// available ids should provide a file local_irep_ids.def in their source tree

0 commit comments

Comments
 (0)