Skip to content

Commit 5e1537a

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 5b41901 commit 5e1537a

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>
@@ -522,13 +523,15 @@ exprt::operandst::const_iterator c_typecheck_baset::do_designated_initializer(
522523
{
523524
// Already right union component. We can initialize multiple submembers,
524525
// so do not overwrite this.
526+
dest = &(to_union_expr(*dest).op());
525527
}
526528
else
527529
{
528530
// The first component is not the maximum member, which the (default)
529531
// zero initializer prepared. Replace this by a component-specific
530532
// initializer; other bytes have an unspecified value (C Standard
531-
// 6.2.6.1(7)).
533+
// 6.2.6.1(7)). In practice, objects of static lifetime are fully zero
534+
// initialized.
532535
const auto zero =
533536
zero_initializer(component.type(), value.source_location(), *this);
534537
if(!zero.has_value())
@@ -538,12 +541,23 @@ exprt::operandst::const_iterator c_typecheck_baset::do_designated_initializer(
538541
<< to_string(component.type()) << "'" << eom;
539542
throw 0;
540543
}
541-
union_exprt union_expr(component.get_name(), *zero, type);
542-
union_expr.add_source_location()=value.source_location();
543-
*dest=union_expr;
544-
}
545544

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

0 commit comments

Comments
 (0)