Skip to content

Commit 203bb3c

Browse files
authored
Merge pull request #5702 from tautschnig/union-excess
C front-end: ignore or reject excess union initializers
2 parents 8ea67e7 + ae6107b commit 203bb3c

File tree

4 files changed

+52
-5
lines changed

4 files changed

+52
-5
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#include <assert.h>
2+
3+
#ifndef _MSC_VER
4+
union U {
5+
int x;
6+
int y;
7+
} u = {1, 2};
8+
9+
int main()
10+
{
11+
// the excess initializer (2) is ignored
12+
assert(u.x == 1);
13+
}
14+
#else
15+
int main()
16+
{
17+
}
18+
#endif
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
main.c
3+
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL$
7+
--
8+
^warning: ignoring

scripts/expected_doxygen_warnings.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ warning: Included by graph for 'goto_functions.h' not generated, too many nodes
8585
warning: Included by graph for 'goto_model.h' not generated, too many nodes (109), threshold is 60. Consider increasing DOT_GRAPH_MAX_NODES.
8686
warning: Included by graph for 'arith_tools.h' not generated, too many nodes (181), threshold is 60. Consider increasing DOT_GRAPH_MAX_NODES.
8787
warning: Included by graph for 'c_types.h' not generated, too many nodes (110), threshold is 60. Consider increasing DOT_GRAPH_MAX_NODES.
88-
warning: Included by graph for 'config.h' not generated, too many nodes (83), threshold is 60. Consider increasing DOT_GRAPH_MAX_NODES.
88+
warning: Included by graph for 'config.h' not generated, too many nodes (84), threshold is 60. Consider increasing DOT_GRAPH_MAX_NODES.
8989
warning: Included by graph for 'exception_utils.h' not generated, too many nodes (61), threshold is 60. Consider increasing DOT_GRAPH_MAX_NODES.
9090
warning: Included by graph for 'expr.h' not generated, too many nodes (88), threshold is 60. Consider increasing DOT_GRAPH_MAX_NODES.
9191
warning: Included by graph for 'expr_util.h' not generated, too many nodes (60), threshold is 60. Consider increasing DOT_GRAPH_MAX_NODES.

src/ansi-c/c_typecheck_initializer.cpp

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ Author: Daniel Kroening, [email protected]
1313

1414
#include <util/arith_tools.h>
1515
#include <util/c_types.h>
16+
#include <util/config.h>
1617
#include <util/cprover_prefix.h>
1718
#include <util/expr_initializer.h>
1819
#include <util/prefix.h>
@@ -484,6 +485,22 @@ exprt::operandst::const_iterator c_typecheck_baset::do_designated_initializer(
484485
error() << "union member designator found for empty union" << eom;
485486
throw 0;
486487
}
488+
else if(init_it != initializer_list.operands().begin())
489+
{
490+
if(config.ansi_c.mode == configt::ansi_ct::flavourt::VISUAL_STUDIO)
491+
{
492+
error().source_location = value.source_location();
493+
error() << "too many initializers" << eom;
494+
throw 0;
495+
}
496+
else
497+
{
498+
warning().source_location = value.source_location();
499+
warning() << "excess elements in union initializer" << eom;
500+
501+
return ++init_it;
502+
}
503+
}
487504
else if(index >= components.size())
488505
{
489506
error().source_location = value.source_location();
@@ -494,16 +511,20 @@ exprt::operandst::const_iterator c_typecheck_baset::do_designated_initializer(
494511

495512
const union_typet::componentt &component = components[index];
496513

497-
if(dest->id()==ID_union &&
498-
dest->get(ID_component_name)==component.get_name())
514+
DATA_INVARIANT(
515+
dest->id() == ID_union, "union should be zero initialized");
516+
517+
if(dest->get(ID_component_name) == component.get_name())
499518
{
500519
// Already right union component. We can initialize multiple submembers,
501520
// so do not overwrite this.
502521
}
503522
else
504523
{
505-
// Note that gcc issues a warning if the union component is switched.
506-
// Build a union expression from given component.
524+
// The first component is not the maximum member, which the (default)
525+
// zero initializer prepared. Replace this by a component-specific
526+
// initializer; other bytes have an unspecified value (C Standard
527+
// 6.2.6.1(7)).
507528
const auto zero =
508529
zero_initializer(component.type(), value.source_location(), *this);
509530
if(!zero.has_value())

0 commit comments

Comments
 (0)