@@ -9,8 +9,6 @@ Author: Daniel Kroening, kroening@kroening.com
99// / \file
1010// / ANSI-C Conversion / Type Checking
1111
12- #include " c_typecheck_base.h"
13-
1412#include < util/arith_tools.h>
1513#include < util/byte_operators.h>
1614#include < util/c_types.h>
@@ -22,6 +20,8 @@ Author: Daniel Kroening, kroening@kroening.com
2220#include < util/string_constant.h>
2321
2422#include " anonymous_member.h"
23+ #include " c_typecheck_base.h"
24+ #include " type2name.h"
2525
2626void c_typecheck_baset::do_initializer (
2727 exprt &initializer,
@@ -240,13 +240,12 @@ void c_typecheck_baset::do_initializer(symbolt &symbol)
240240 typecheck_expr (symbol.value );
241241 do_initializer (symbol.value , symbol.type , true );
242242
243- // need to adjust size?
244- if (
245- !symbol. is_macro && symbol. type . id () == ID_array &&
246- to_array_type (symbol. type ). size (). is_nil ())
247- {
243+ // A flexible array may have been initialized, which entails a type change.
244+ // Note that the type equality test is important: we want to preserve
245+ // annotations like typedefs or const-ness when the type is otherwise the
246+ // same.
247+ if (!symbol. is_macro && symbol. type != symbol. value . type ())
248248 symbol.type = symbol.value .type ();
249- }
250249 }
251250
252251 if (symbol.is_macro )
@@ -428,8 +427,6 @@ exprt::operandst::const_iterator c_typecheck_baset::do_designated_initializer(
428427 }
429428 dest->operands ().resize (
430429 numeric_cast_v<std::size_t >(index) + 1 , *zero);
431-
432- // todo: adjust type!
433430 }
434431 else
435432 {
@@ -1007,11 +1004,49 @@ exprt c_typecheck_baset::do_initializer_list(
10071004 increment_designator (current_designator);
10081005 }
10091006
1010- // make sure we didn't mess up index computation
10111007 if (full_type.id ()==ID_struct)
10121008 {
1013- assert (result.operands ().size ()==
1014- to_struct_type (full_type).components ().size ());
1009+ const struct_typet &full_struct_type = to_struct_type (full_type);
1010+ const struct_typet::componentst &components = full_struct_type.components ();
1011+ // make sure we didn't mess up index computation
1012+ CHECK_RETURN (result.operands ().size () == components.size ());
1013+
1014+ if (
1015+ !components.empty () &&
1016+ components.back ().type ().get_bool (ID_C_flexible_array_member))
1017+ {
1018+ const auto array_size = numeric_cast<mp_integer>(
1019+ to_array_type (components.back ().type ()).size ());
1020+ array_exprt &init_array = to_array_expr (result.operands ().back ());
1021+ if (
1022+ !array_size.has_value () ||
1023+ (*array_size <= 1 && init_array.operands ().size () != *array_size))
1024+ {
1025+ struct_typet actual_struct_type = full_struct_type;
1026+ array_typet &actual_array_type =
1027+ to_array_type (actual_struct_type.components ().back ().type ());
1028+ actual_array_type.size () = from_integer (
1029+ init_array.operands ().size (), actual_array_type.index_type ());
1030+ actual_array_type.set (ID_C_flexible_array_member, true );
1031+ init_array.type () = actual_array_type;
1032+
1033+ // mimic bits of typecheck_compound_type to produce a new struct tag
1034+ actual_struct_type.remove (ID_tag);
1035+ type_symbolt compound_symbol{actual_struct_type};
1036+ compound_symbol.mode = mode;
1037+ compound_symbol.location = value.source_location ();
1038+ std::string typestr = type2name (compound_symbol.type , *this );
1039+ compound_symbol.base_name = " #anon#" + typestr;
1040+ compound_symbol.name = " tag-#anon#" + typestr;
1041+ irep_idt tag_identifier = compound_symbol.name ;
1042+
1043+ // We might already have the same anonymous struct, which is fine as it
1044+ // will be exactly the same type.
1045+ symbol_table.insert (std::move (compound_symbol));
1046+
1047+ result.type () = struct_tag_typet{tag_identifier};
1048+ }
1049+ }
10151050 }
10161051
10171052 if (full_type.id ()==ID_array &&
0 commit comments