@@ -231,6 +231,34 @@ void smt2_convt::write_footer()
231
231
<< " \n " ;
232
232
}
233
233
234
+ // / Returns true iff \p type has effective width of zero bits.
235
+ static bool is_zero_width (const typet &type, const namespacet &ns)
236
+ {
237
+ if (type.id () == ID_empty)
238
+ return true ;
239
+ else if (type.id () == ID_struct_tag)
240
+ return is_zero_width (ns.follow_tag (to_struct_tag_type (type)), ns);
241
+ else if (type.id () == ID_union_tag)
242
+ return is_zero_width (ns.follow_tag (to_union_tag_type (type)), ns);
243
+ else if (type.id () == ID_struct || type.id () == ID_union)
244
+ {
245
+ for (const auto &comp : to_struct_union_type (type).components ())
246
+ {
247
+ if (!is_zero_width (comp.type (), ns))
248
+ return false ;
249
+ }
250
+ return true ;
251
+ }
252
+ else if (auto array_type = type_try_dynamic_cast<array_typet>(type))
253
+ {
254
+ // we ignore array_type->size().is_zero() for now as there may be
255
+ // out-of-bounds accesses that we need to model
256
+ return is_zero_width (array_type->element_type (), ns);
257
+ }
258
+ else
259
+ return false ;
260
+ }
261
+
234
262
void smt2_convt::define_object_size (
235
263
const irep_idt &id,
236
264
const object_size_exprt &expr)
@@ -584,14 +612,21 @@ smt2_convt::parse_struct(const irept &src, const struct_typet &type)
584
612
{
585
613
// Structs look like:
586
614
// (mk-struct.1 <component0> <component1> ... <componentN>)
587
-
588
- if (src.get_sub ().size ()!=components.size ()+1 )
589
- return result; // give up
590
-
615
+ std::size_t j = 1 ;
591
616
for (std::size_t i=0 ; i<components.size (); i++)
592
617
{
593
618
const struct_typet::componentt &c=components[i];
594
- result.operands ()[i]=parse_rec (src.get_sub ()[i+1 ], c.type ());
619
+ if (is_zero_width (components[i].type (), ns))
620
+ {
621
+ result.operands ()[i] = nil_exprt{};
622
+ }
623
+ else
624
+ {
625
+ DATA_INVARIANT (
626
+ src.get_sub ().size () > j, " insufficient number of component values" );
627
+ result.operands ()[i] = parse_rec (src.get_sub ()[j], c.type ());
628
+ ++j;
629
+ }
595
630
}
596
631
}
597
632
else
@@ -609,6 +644,9 @@ smt2_convt::parse_struct(const irept &src, const struct_typet &type)
609
644
610
645
for (std::size_t i=0 ; i<components.size (); i++)
611
646
{
647
+ if (is_zero_width (components[i].type (), ns))
648
+ continue ;
649
+
612
650
std::size_t component_width=boolbv_width (components[i].type ());
613
651
614
652
INVARIANT (
@@ -972,28 +1010,6 @@ std::string smt2_convt::convert_identifier(const irep_idt &identifier)
972
1010
return result;
973
1011
}
974
1012
975
- // / Returns true iff \p type has effective width of zero bits.
976
- static bool is_zero_width (const typet &type, const namespacet &ns)
977
- {
978
- if (type.id () == ID_empty)
979
- return true ;
980
- else if (type.id () == ID_struct_tag)
981
- return is_zero_width (ns.follow_tag (to_struct_tag_type (type)), ns);
982
- else if (type.id () == ID_union_tag)
983
- return is_zero_width (ns.follow_tag (to_union_tag_type (type)), ns);
984
- else if (type.id () == ID_struct || type.id () == ID_union)
985
- {
986
- for (const auto &comp : to_struct_union_type (type).components ())
987
- {
988
- if (!is_zero_width (comp.type (), ns))
989
- return false ;
990
- }
991
- return true ;
992
- }
993
- else
994
- return false ;
995
- }
996
-
997
1013
std::string smt2_convt::type2id (const typet &type) const
998
1014
{
999
1015
if (type.id ()==ID_floatbv)
@@ -3224,6 +3240,8 @@ void smt2_convt::convert_struct(const struct_exprt &expr)
3224
3240
it!=components.end ();
3225
3241
it++, i++)
3226
3242
{
3243
+ if (is_zero_width (it->type (), ns))
3244
+ continue ;
3227
3245
out << " " ;
3228
3246
convert_expr (expr.operands ()[i]);
3229
3247
}
@@ -3246,9 +3264,16 @@ void smt2_convt::convert_struct(const struct_exprt &expr)
3246
3264
else
3247
3265
{
3248
3266
// SMT-LIB 2 concat is binary only
3267
+ std::size_t n_concat = 0 ;
3249
3268
for (std::size_t i=components.size (); i>1 ; i--)
3250
3269
{
3251
- out << " (concat " ;
3270
+ if (is_zero_width (components[i - 1 ].type (), ns))
3271
+ continue ;
3272
+ else if (i > 2 || !is_zero_width (components[0 ].type (), ns))
3273
+ {
3274
+ ++n_concat;
3275
+ out << " (concat " ;
3276
+ }
3252
3277
3253
3278
exprt op=expr.operands ()[i-1 ];
3254
3279
@@ -3263,10 +3288,10 @@ void smt2_convt::convert_struct(const struct_exprt &expr)
3263
3288
out << " " ;
3264
3289
}
3265
3290
3266
- convert_expr (expr.op0 ());
3291
+ if (!is_zero_width (components[0 ].type (), ns))
3292
+ convert_expr (expr.op0 ());
3267
3293
3268
- for (std::size_t i=1 ; i<components.size (); i++)
3269
- out << " )" ;
3294
+ out << std::string (n_concat, ' )' );
3270
3295
}
3271
3296
}
3272
3297
}
@@ -4701,19 +4726,30 @@ void smt2_convt::flatten2bv(const exprt &expr)
4701
4726
struct_type.components ();
4702
4727
4703
4728
// SMT-LIB 2 concat is binary only
4729
+ std::size_t n_concat = 0 ;
4704
4730
for (std::size_t i=components.size (); i>1 ; i--)
4705
4731
{
4706
- out << " (concat (" << smt_typename << " ."
4707
- << components[i-1 ].get_name () << " ?sflop)" ;
4732
+ if (is_zero_width (components[i - 1 ].type (), ns))
4733
+ continue ;
4734
+ else if (i > 2 || !is_zero_width (components[0 ].type (), ns))
4735
+ {
4736
+ ++n_concat;
4737
+ out << " (concat " ;
4738
+ }
4739
+
4740
+ out << " (" << smt_typename << " ." << components[i - 1 ].get_name ()
4741
+ << " ?sflop)" ;
4708
4742
4709
4743
out << " " ;
4710
4744
}
4711
4745
4712
- out << " (" << smt_typename << " ."
4713
- << components[0 ].get_name () << " ?sflop)" ;
4746
+ if (!is_zero_width (components[0 ].type (), ns))
4747
+ {
4748
+ out << " (" << smt_typename << " ." << components[0 ].get_name ()
4749
+ << " ?sflop)" ;
4750
+ }
4714
4751
4715
- for (std::size_t i=1 ; i<components.size (); i++)
4716
- out << " )" ; // concat
4752
+ out << std::string (n_concat, ' )' ); // concat
4717
4753
4718
4754
out << " )" ; // let
4719
4755
}
@@ -4812,6 +4848,9 @@ void smt2_convt::unflatten(
4812
4848
it!=components.end ();
4813
4849
it++, i++)
4814
4850
{
4851
+ if (is_zero_width (it->type (), ns))
4852
+ continue ;
4853
+
4815
4854
std::size_t member_width=boolbv_width (it->type ());
4816
4855
4817
4856
out << " " ;
@@ -5037,6 +5076,9 @@ exprt smt2_convt::prepare_for_convert_expr(const exprt &expr)
5037
5076
5038
5077
void smt2_convt::find_symbols (const exprt &expr)
5039
5078
{
5079
+ if (is_zero_width (expr.type (), ns))
5080
+ return ;
5081
+
5040
5082
// recursive call on type
5041
5083
find_symbols (expr.type ());
5042
5084
@@ -5821,6 +5863,9 @@ void smt2_convt::find_symbols_rec(
5821
5863
5822
5864
for (const auto &component : components)
5823
5865
{
5866
+ if (is_zero_width (component.type (), ns))
5867
+ continue ;
5868
+
5824
5869
out << " (" << smt_typename << " ." << component.get_name ()
5825
5870
<< " " ;
5826
5871
convert_type (component.type ());
@@ -5849,6 +5894,9 @@ void smt2_convt::find_symbols_rec(
5849
5894
it!=components.end ();
5850
5895
++it)
5851
5896
{
5897
+ if (is_zero_width (it->type (), ns))
5898
+ continue ;
5899
+
5852
5900
const struct_union_typet::componentt &component=*it;
5853
5901
out << " (define-fun update-" << smt_typename << " ."
5854
5902
<< component.get_name () << " "
@@ -5866,7 +5914,7 @@ void smt2_convt::find_symbols_rec(
5866
5914
{
5867
5915
if (it==it2)
5868
5916
out << " v " ;
5869
- else
5917
+ else if (! is_zero_width (it2-> type (), ns))
5870
5918
{
5871
5919
out << " (" << smt_typename << " ."
5872
5920
<< it2->get_name () << " s) " ;
0 commit comments