diff --git a/src/analyses/goto_check_c.cpp b/src/analyses/goto_check_c.cpp index 7dffe9219f9..e3ab5331d2f 100644 --- a/src/analyses/goto_check_c.cpp +++ b/src/analyses/goto_check_c.cpp @@ -1621,7 +1621,7 @@ void goto_check_ct::bounds_check_index( ? to_array_type(array_type).size() : to_vector_type(array_type).size(); - if(size.is_nil()) + if(size.is_nil() && !array_type.get_bool(ID_C_flexible_array_member)) { // Linking didn't complete, we don't have a size. // Not clear what to do. @@ -1629,7 +1629,9 @@ void goto_check_ct::bounds_check_index( else if(size.id() == ID_infinity) { } - else if(size.is_zero() && expr.array().id() == ID_member) + else if( + expr.array().id() == ID_member && + (size.is_zero() || array_type.get_bool(ID_C_flexible_array_member))) { // a variable sized struct member // diff --git a/src/ansi-c/c_typecheck_type.cpp b/src/ansi-c/c_typecheck_type.cpp index 8366cc41b69..26bf7d194f0 100644 --- a/src/ansi-c/c_typecheck_type.cpp +++ b/src/ansi-c/c_typecheck_type.cpp @@ -1010,8 +1010,8 @@ void c_typecheck_baset::typecheck_compound_body( } // make it zero-length - c_type.id(ID_array); - c_type.set(ID_size, from_integer(0, c_index_type())); + to_array_type(c_type).size() = from_integer(0, c_index_type()); + c_type.set(ID_C_flexible_array_member, true); } } } diff --git a/src/util/irep_ids.def b/src/util/irep_ids.def index fc68a39cc33..2521ddc1de9 100644 --- a/src/util/irep_ids.def +++ b/src/util/irep_ids.def @@ -868,6 +868,7 @@ IREP_ID_ONE(bitreverse) IREP_ID_ONE(saturating_minus) IREP_ID_ONE(saturating_plus) IREP_ID_ONE(annotated_pointer_constant) +IREP_ID_TWO(C_flexible_array_member, #flexible_array_member) // Projects depending on this code base that wish to extend the list of // available ids should provide a file local_irep_ids.def in their source tree diff --git a/src/util/pointer_offset_size.cpp b/src/util/pointer_offset_size.cpp index 23b688eea44..0dcfe6c188d 100644 --- a/src/util/pointer_offset_size.cpp +++ b/src/util/pointer_offset_size.cpp @@ -368,6 +368,11 @@ optionalt size_of_expr(const typet &type, const namespacet &ns) if(bytes > 0) result = plus_exprt(result, from_integer(bytes, result.type())); } + else if(c.type().get_bool(ID_C_flexible_array_member)) + { + // flexible array members do not change the sizeof result + continue; + } else { DATA_INVARIANT( diff --git a/src/util/simplify_expr.cpp b/src/util/simplify_expr.cpp index b11fe680833..93589c19b29 100644 --- a/src/util/simplify_expr.cpp +++ b/src/util/simplify_expr.cpp @@ -1746,6 +1746,9 @@ simplify_exprt::simplify_byte_extract(const byte_extract_exprt &expr) if(comps.empty() || comps.back().type().id() != ID_array) return false; + if(comps.back().type().get_bool(ID_C_flexible_array_member)) + return true; + const auto size = numeric_cast(to_array_type(comps.back().type()).size()); return !size.has_value() || *size <= 1;