Skip to content

Commit 2fbbd09

Browse files
committed
Initialise union of static lifetime with zeros
The C standard does not specify the value of bytes that do not belong to the object representation of a member referred to in an initializer list, but compilers seem to ensure those bytes are zero (possibly by using the .bss section).
1 parent 7b566e5 commit 2fbbd09

File tree

2 files changed

+21
-7
lines changed

2 files changed

+21
-7
lines changed

regression/cbmc/union1/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
KNOWNBUG
1+
CORE
22
main.c
33

44
^EXIT=0$

src/ansi-c/c_typecheck_initializer.cpp

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ Author: Daniel Kroening, [email protected]
1212
#include "c_typecheck_base.h"
1313

1414
#include <util/arith_tools.h>
15+
#include <util/byte_operators.h>
1516
#include <util/c_types.h>
1617
#include <util/config.h>
1718
#include <util/cprover_prefix.h>
@@ -520,13 +521,15 @@ exprt::operandst::const_iterator c_typecheck_baset::do_designated_initializer(
520521
{
521522
// Already right union component. We can initialize multiple submembers,
522523
// so do not overwrite this.
524+
dest = &(to_union_expr(*dest).op());
523525
}
524526
else
525527
{
526528
// The first component is not the maximum member, which the (default)
527529
// zero initializer prepared. Replace this by a component-specific
528530
// initializer; other bytes have an unspecified value (C Standard
529-
// 6.2.6.1(7)).
531+
// 6.2.6.1(7)). In practice, objects of static lifetime are fully zero
532+
// initialized.
530533
const auto zero =
531534
zero_initializer(component.type(), value.source_location(), *this);
532535
if(!zero.has_value())
@@ -536,12 +539,23 @@ exprt::operandst::const_iterator c_typecheck_baset::do_designated_initializer(
536539
<< to_string(component.type()) << "'" << eom;
537540
throw 0;
538541
}
539-
union_exprt union_expr(component.get_name(), *zero, type);
540-
union_expr.add_source_location()=value.source_location();
541-
*dest=union_expr;
542-
}
543542

544-
dest = &(to_union_expr(*dest).op());
543+
if(current_symbol.is_static_lifetime)
544+
{
545+
byte_update_exprt byte_update{
546+
byte_update_id(), *dest, from_integer(0, index_type()), *zero};
547+
byte_update.add_source_location() = value.source_location();
548+
*dest = std::move(byte_update);
549+
dest = &(to_byte_update_expr(*dest).op2());
550+
}
551+
else
552+
{
553+
union_exprt union_expr(component.get_name(), *zero, type);
554+
union_expr.add_source_location() = value.source_location();
555+
*dest = std::move(union_expr);
556+
dest = &(to_union_expr(*dest).op());
557+
}
558+
}
545559
}
546560
else
547561
UNREACHABLE;

0 commit comments

Comments
 (0)