Skip to content

Commit 751dc42

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 203bb3c commit 751dc42

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>
@@ -518,13 +519,15 @@ exprt::operandst::const_iterator c_typecheck_baset::do_designated_initializer(
518519
{
519520
// Already right union component. We can initialize multiple submembers,
520521
// so do not overwrite this.
522+
dest = &(to_union_expr(*dest).op());
521523
}
522524
else
523525
{
524526
// The first component is not the maximum member, which the (default)
525527
// zero initializer prepared. Replace this by a component-specific
526528
// initializer; other bytes have an unspecified value (C Standard
527-
// 6.2.6.1(7)).
529+
// 6.2.6.1(7)). In practice, objects of static lifetime are fully zero
530+
// initialized.
528531
const auto zero =
529532
zero_initializer(component.type(), value.source_location(), *this);
530533
if(!zero.has_value())
@@ -534,12 +537,23 @@ exprt::operandst::const_iterator c_typecheck_baset::do_designated_initializer(
534537
<< to_string(component.type()) << "'" << eom;
535538
throw 0;
536539
}
537-
union_exprt union_expr(component.get_name(), *zero, type);
538-
union_expr.add_source_location()=value.source_location();
539-
*dest=union_expr;
540-
}
541540

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

0 commit comments

Comments
 (0)