|
9 | 9 | /// \file
|
10 | 10 | /// ANSI-C Conversion / Type Checking
|
11 | 11 |
|
12 |
| -#include "c_typecheck_base.h" |
13 |
| - |
14 | 12 | #include <util/arith_tools.h>
|
15 | 13 | #include <util/byte_operators.h>
|
16 | 14 | #include <util/c_types.h>
|
|
22 | 20 | #include <util/string_constant.h>
|
23 | 21 |
|
24 | 22 | #include "anonymous_member.h"
|
| 23 | +#include "c_typecheck_base.h" |
| 24 | +#include "type2name.h" |
25 | 25 |
|
26 | 26 | void c_typecheck_baset::do_initializer(
|
27 | 27 | exprt &initializer,
|
@@ -240,13 +240,12 @@ void c_typecheck_baset::do_initializer(symbolt &symbol)
|
240 | 240 | typecheck_expr(symbol.value);
|
241 | 241 | do_initializer(symbol.value, symbol.type, true);
|
242 | 242 |
|
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()) |
248 | 248 | symbol.type = symbol.value.type();
|
249 |
| - } |
250 | 249 | }
|
251 | 250 |
|
252 | 251 | if(symbol.is_macro)
|
@@ -428,8 +427,6 @@ exprt::operandst::const_iterator c_typecheck_baset::do_designated_initializer(
|
428 | 427 | }
|
429 | 428 | dest->operands().resize(
|
430 | 429 | numeric_cast_v<std::size_t>(index) + 1, *zero);
|
431 |
| - |
432 |
| - // todo: adjust type! |
433 | 430 | }
|
434 | 431 | else
|
435 | 432 | {
|
@@ -1007,11 +1004,49 @@ exprt c_typecheck_baset::do_initializer_list(
|
1007 | 1004 | increment_designator(current_designator);
|
1008 | 1005 | }
|
1009 | 1006 |
|
1010 |
| - // make sure we didn't mess up index computation |
1011 | 1007 | if(full_type.id()==ID_struct)
|
1012 | 1008 | {
|
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 | + } |
1015 | 1050 | }
|
1016 | 1051 |
|
1017 | 1052 | if(full_type.id()==ID_array &&
|
|
0 commit comments