@@ -231,6 +231,34 @@ void smt2_convt::write_footer()
231231 << " \n " ;
232232}
233233
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+
234262void smt2_convt::define_object_size (
235263 const irep_idt &id,
236264 const object_size_exprt &expr)
@@ -584,14 +612,21 @@ smt2_convt::parse_struct(const irept &src, const struct_typet &type)
584612 {
585613 // Structs look like:
586614 // (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 ;
591616 for (std::size_t i=0 ; i<components.size (); i++)
592617 {
593618 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+ }
595630 }
596631 }
597632 else
@@ -609,6 +644,9 @@ smt2_convt::parse_struct(const irept &src, const struct_typet &type)
609644
610645 for (std::size_t i=0 ; i<components.size (); i++)
611646 {
647+ if (is_zero_width (components[i].type (), ns))
648+ continue ;
649+
612650 std::size_t component_width=boolbv_width (components[i].type ());
613651
614652 INVARIANT (
@@ -972,28 +1010,6 @@ std::string smt2_convt::convert_identifier(const irep_idt &identifier)
9721010 return result;
9731011}
9741012
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-
9971013std::string smt2_convt::type2id (const typet &type) const
9981014{
9991015 if (type.id ()==ID_floatbv)
@@ -3224,6 +3240,8 @@ void smt2_convt::convert_struct(const struct_exprt &expr)
32243240 it!=components.end ();
32253241 it++, i++)
32263242 {
3243+ if (is_zero_width (it->type (), ns))
3244+ continue ;
32273245 out << " " ;
32283246 convert_expr (expr.operands ()[i]);
32293247 }
@@ -3246,9 +3264,16 @@ void smt2_convt::convert_struct(const struct_exprt &expr)
32463264 else
32473265 {
32483266 // SMT-LIB 2 concat is binary only
3267+ std::size_t n_concat = 0 ;
32493268 for (std::size_t i=components.size (); i>1 ; i--)
32503269 {
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+ }
32523277
32533278 exprt op=expr.operands ()[i-1 ];
32543279
@@ -3263,10 +3288,10 @@ void smt2_convt::convert_struct(const struct_exprt &expr)
32633288 out << " " ;
32643289 }
32653290
3266- convert_expr (expr.op0 ());
3291+ if (!is_zero_width (components[0 ].type (), ns))
3292+ convert_expr (expr.op0 ());
32673293
3268- for (std::size_t i=1 ; i<components.size (); i++)
3269- out << " )" ;
3294+ out << std::string (n_concat, ' )' );
32703295 }
32713296 }
32723297}
@@ -4701,19 +4726,30 @@ void smt2_convt::flatten2bv(const exprt &expr)
47014726 struct_type.components ();
47024727
47034728 // SMT-LIB 2 concat is binary only
4729+ std::size_t n_concat = 0 ;
47044730 for (std::size_t i=components.size (); i>1 ; i--)
47054731 {
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)" ;
47084742
47094743 out << " " ;
47104744 }
47114745
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+ }
47144751
4715- for (std::size_t i=1 ; i<components.size (); i++)
4716- out << " )" ; // concat
4752+ out << std::string (n_concat, ' )' ); // concat
47174753
47184754 out << " )" ; // let
47194755 }
@@ -4812,6 +4848,9 @@ void smt2_convt::unflatten(
48124848 it!=components.end ();
48134849 it++, i++)
48144850 {
4851+ if (is_zero_width (it->type (), ns))
4852+ continue ;
4853+
48154854 std::size_t member_width=boolbv_width (it->type ());
48164855
48174856 out << " " ;
@@ -5037,6 +5076,9 @@ exprt smt2_convt::prepare_for_convert_expr(const exprt &expr)
50375076
50385077void smt2_convt::find_symbols (const exprt &expr)
50395078{
5079+ if (is_zero_width (expr.type (), ns))
5080+ return ;
5081+
50405082 // recursive call on type
50415083 find_symbols (expr.type ());
50425084
@@ -5821,6 +5863,9 @@ void smt2_convt::find_symbols_rec(
58215863
58225864 for (const auto &component : components)
58235865 {
5866+ if (is_zero_width (component.type (), ns))
5867+ continue ;
5868+
58245869 out << " (" << smt_typename << " ." << component.get_name ()
58255870 << " " ;
58265871 convert_type (component.type ());
@@ -5849,6 +5894,9 @@ void smt2_convt::find_symbols_rec(
58495894 it!=components.end ();
58505895 ++it)
58515896 {
5897+ if (is_zero_width (it->type (), ns))
5898+ continue ;
5899+
58525900 const struct_union_typet::componentt &component=*it;
58535901 out << " (define-fun update-" << smt_typename << " ."
58545902 << component.get_name () << " "
@@ -5866,7 +5914,7 @@ void smt2_convt::find_symbols_rec(
58665914 {
58675915 if (it==it2)
58685916 out << " v " ;
5869- else
5917+ else if (! is_zero_width (it2-> type (), ns))
58705918 {
58715919 out << " (" << smt_typename << " ."
58725920 << it2->get_name () << " s) " ;
0 commit comments