@@ -47,21 +47,26 @@ static bool stackinit_range_contains(char *haystack_start, size_t haystack_size,
47
47
#define DO_NOTHING_TYPE_SCALAR (var_type ) var_type
48
48
#define DO_NOTHING_TYPE_STRING (var_type ) void
49
49
#define DO_NOTHING_TYPE_STRUCT (var_type ) void
50
+ #define DO_NOTHING_TYPE_UNION (var_type ) void
50
51
51
52
#define DO_NOTHING_RETURN_SCALAR (ptr ) *(ptr)
52
53
#define DO_NOTHING_RETURN_STRING (ptr ) /**/
53
54
#define DO_NOTHING_RETURN_STRUCT (ptr ) /**/
55
+ #define DO_NOTHING_RETURN_UNION (ptr ) /**/
54
56
55
57
#define DO_NOTHING_CALL_SCALAR (var , name ) \
56
58
(var) = do_nothing_ ## name(&(var))
57
59
#define DO_NOTHING_CALL_STRING (var , name ) \
58
60
do_nothing_ ## name(var)
59
61
#define DO_NOTHING_CALL_STRUCT (var , name ) \
60
62
do_nothing_ ## name(&(var))
63
+ #define DO_NOTHING_CALL_UNION (var , name ) \
64
+ do_nothing_ ## name(&(var))
61
65
62
66
#define FETCH_ARG_SCALAR (var ) &var
63
67
#define FETCH_ARG_STRING (var ) var
64
68
#define FETCH_ARG_STRUCT (var ) &var
69
+ #define FETCH_ARG_UNION (var ) &var
65
70
66
71
/*
67
72
* On m68k, if the leaf function test variable is longer than 8 bytes,
@@ -77,6 +82,7 @@ static bool stackinit_range_contains(char *haystack_start, size_t haystack_size,
77
82
#define INIT_CLONE_SCALAR /**/
78
83
#define INIT_CLONE_STRING [FILL_SIZE_STRING]
79
84
#define INIT_CLONE_STRUCT /**/
85
+ #define INIT_CLONE_UNION /**/
80
86
81
87
#define ZERO_CLONE_SCALAR (zero ) memset(&(zero), 0x00, sizeof(zero))
82
88
#define ZERO_CLONE_STRING (zero ) memset(&(zero), 0x00, sizeof(zero))
@@ -92,6 +98,7 @@ static bool stackinit_range_contains(char *haystack_start, size_t haystack_size,
92
98
zero.three = 0; \
93
99
zero.four = 0; \
94
100
} while (0)
101
+ #define ZERO_CLONE_UNION (zero ) ZERO_CLONE_STRUCT(zero)
95
102
96
103
#define INIT_SCALAR_none (var_type ) /**/
97
104
#define INIT_SCALAR_zero (var_type ) = 0
@@ -147,6 +154,34 @@ static bool stackinit_range_contains(char *haystack_start, size_t haystack_size,
147
154
#define INIT_STRUCT_assigned_copy (var_type ) \
148
155
; var = *(arg)
149
156
157
+ /* Union initialization is the same as structs. */
158
+ #define INIT_UNION_none (var_type ) INIT_STRUCT_none(var_type)
159
+ #define INIT_UNION_zero (var_type ) INIT_STRUCT_zero(var_type)
160
+ #define INIT_UNION_old_zero (var_type ) INIT_STRUCT_old_zero(var_type)
161
+
162
+ #define INIT_UNION_static_partial (var_type ) \
163
+ INIT_STRUCT_static_partial(var_type)
164
+ #define INIT_UNION_static_all (var_type ) \
165
+ INIT_STRUCT_static_all(var_type)
166
+ #define INIT_UNION_dynamic_partial (var_type ) \
167
+ INIT_STRUCT_dynamic_partial(var_type)
168
+ #define INIT_UNION_dynamic_all (var_type ) \
169
+ INIT_STRUCT_dynamic_all(var_type)
170
+ #define INIT_UNION_runtime_partial (var_type ) \
171
+ INIT_STRUCT_runtime_partial(var_type)
172
+ #define INIT_UNION_runtime_all (var_type ) \
173
+ INIT_STRUCT_runtime_all(var_type)
174
+ #define INIT_UNION_assigned_static_partial (var_type ) \
175
+ INIT_STRUCT_assigned_static_partial(var_type)
176
+ #define INIT_UNION_assigned_static_all (var_type ) \
177
+ INIT_STRUCT_assigned_static_all(var_type)
178
+ #define INIT_UNION_assigned_dynamic_partial (var_type ) \
179
+ INIT_STRUCT_assigned_dynamic_partial(var_type)
180
+ #define INIT_UNION_assigned_dynamic_all (var_type ) \
181
+ INIT_STRUCT_assigned_dynamic_all(var_type)
182
+ #define INIT_UNION_assigned_copy (var_type ) \
183
+ INIT_STRUCT_assigned_copy(var_type)
184
+
150
185
/*
151
186
* @name: unique string name for the test
152
187
* @var_type: type to be tested for zeroing initialization
@@ -295,6 +330,33 @@ struct test_user {
295
330
unsigned long four ;
296
331
};
297
332
333
+ /* No padding: all members are the same size. */
334
+ union test_same_sizes {
335
+ unsigned long one ;
336
+ unsigned long two ;
337
+ unsigned long three ;
338
+ unsigned long four ;
339
+ };
340
+
341
+ /* Mismatched sizes, with one and two being small */
342
+ union test_small_start {
343
+ char one :1 ;
344
+ char two ;
345
+ short three ;
346
+ unsigned long four ;
347
+ struct big_struct {
348
+ unsigned long array [8 ];
349
+ } big ;
350
+ };
351
+
352
+ /* Mismatched sizes, with one and two being small */
353
+ union test_small_end {
354
+ short one ;
355
+ unsigned long two ;
356
+ char three :1 ;
357
+ char four ;
358
+ };
359
+
298
360
#define ALWAYS_PASS WANT_SUCCESS
299
361
#define ALWAYS_FAIL XFAIL
300
362
@@ -333,6 +395,11 @@ struct test_user {
333
395
struct test_ ## name, STRUCT, init, \
334
396
xfail)
335
397
398
+ #define DEFINE_UNION_TEST (name , init , xfail ) \
399
+ DEFINE_TEST(name ## _ ## init, \
400
+ union test_ ## name, STRUCT, init, \
401
+ xfail)
402
+
336
403
#define DEFINE_STRUCT_TESTS (init , xfail ) \
337
404
DEFINE_STRUCT_TEST(small_hole, init, xfail); \
338
405
DEFINE_STRUCT_TEST(big_hole, init, xfail); \
@@ -344,17 +411,35 @@ struct test_user {
344
411
xfail); \
345
412
DEFINE_STRUCT_TESTS(base ## _ ## all, xfail)
346
413
414
+ #define DEFINE_UNION_INITIALIZER_TESTS (base , xfail ) \
415
+ DEFINE_UNION_TESTS(base ## _ ## partial, \
416
+ xfail); \
417
+ DEFINE_UNION_TESTS(base ## _ ## all, xfail)
418
+
419
+ #define DEFINE_UNION_TESTS (init , xfail ) \
420
+ DEFINE_UNION_TEST(same_sizes, init, xfail); \
421
+ DEFINE_UNION_TEST(small_start, init, xfail); \
422
+ DEFINE_UNION_TEST(small_end, init, xfail);
423
+
347
424
/* These should be fully initialized all the time! */
348
425
DEFINE_SCALAR_TESTS (zero , ALWAYS_PASS );
349
426
DEFINE_STRUCT_TESTS (zero , ALWAYS_PASS );
350
427
DEFINE_STRUCT_TESTS (old_zero , ALWAYS_PASS );
428
+ DEFINE_UNION_TESTS (zero , ALWAYS_PASS );
429
+ DEFINE_UNION_TESTS (old_zero , ALWAYS_PASS );
351
430
/* Struct initializers: padding may be left uninitialized. */
352
431
DEFINE_STRUCT_INITIALIZER_TESTS (static , STRONG_PASS );
353
432
DEFINE_STRUCT_INITIALIZER_TESTS (dynamic , STRONG_PASS );
354
433
DEFINE_STRUCT_INITIALIZER_TESTS (runtime , STRONG_PASS );
355
434
DEFINE_STRUCT_INITIALIZER_TESTS (assigned_static , STRONG_PASS );
356
435
DEFINE_STRUCT_INITIALIZER_TESTS (assigned_dynamic , STRONG_PASS );
357
436
DEFINE_STRUCT_TESTS (assigned_copy , ALWAYS_FAIL );
437
+ DEFINE_UNION_INITIALIZER_TESTS (static , STRONG_PASS );
438
+ DEFINE_UNION_INITIALIZER_TESTS (dynamic , STRONG_PASS );
439
+ DEFINE_UNION_INITIALIZER_TESTS (runtime , STRONG_PASS );
440
+ DEFINE_UNION_INITIALIZER_TESTS (assigned_static , STRONG_PASS );
441
+ DEFINE_UNION_INITIALIZER_TESTS (assigned_dynamic , STRONG_PASS );
442
+ DEFINE_UNION_TESTS (assigned_copy , ALWAYS_FAIL );
358
443
/* No initialization without compiler instrumentation. */
359
444
DEFINE_SCALAR_TESTS (none , STRONG_PASS );
360
445
DEFINE_STRUCT_TESTS (none , BYREF_PASS );
@@ -438,14 +523,23 @@ DEFINE_TEST_DRIVER(switch_2_none, uint64_t, SCALAR, ALWAYS_FAIL);
438
523
KUNIT_CASE(test_trailing_hole_ ## init),\
439
524
KUNIT_CASE(test_packed_ ## init) \
440
525
526
+ #define KUNIT_test_unions (init ) \
527
+ KUNIT_CASE(test_same_sizes_ ## init), \
528
+ KUNIT_CASE(test_small_start_ ## init), \
529
+ KUNIT_CASE(test_small_end_ ## init) \
530
+
441
531
static struct kunit_case stackinit_test_cases [] = {
442
532
/* These are explicitly initialized and should always pass. */
443
533
KUNIT_test_scalars (zero ),
444
534
KUNIT_test_structs (zero ),
445
535
KUNIT_test_structs (old_zero ),
536
+ KUNIT_test_unions (zero ),
537
+ KUNIT_test_unions (old_zero ),
446
538
/* Padding here appears to be accidentally always initialized? */
447
539
KUNIT_test_structs (dynamic_partial ),
448
540
KUNIT_test_structs (assigned_dynamic_partial ),
541
+ KUNIT_test_unions (dynamic_partial ),
542
+ KUNIT_test_unions (assigned_dynamic_partial ),
449
543
/* Padding initialization depends on compiler behaviors. */
450
544
KUNIT_test_structs (static_partial ),
451
545
KUNIT_test_structs (static_all ),
@@ -455,8 +549,17 @@ static struct kunit_case stackinit_test_cases[] = {
455
549
KUNIT_test_structs (assigned_static_partial ),
456
550
KUNIT_test_structs (assigned_static_all ),
457
551
KUNIT_test_structs (assigned_dynamic_all ),
552
+ KUNIT_test_unions (static_partial ),
553
+ KUNIT_test_unions (static_all ),
554
+ KUNIT_test_unions (dynamic_all ),
555
+ KUNIT_test_unions (runtime_partial ),
556
+ KUNIT_test_unions (runtime_all ),
557
+ KUNIT_test_unions (assigned_static_partial ),
558
+ KUNIT_test_unions (assigned_static_all ),
559
+ KUNIT_test_unions (assigned_dynamic_all ),
458
560
/* Everything fails this since it effectively performs a memcpy(). */
459
561
KUNIT_test_structs (assigned_copy ),
562
+ KUNIT_test_unions (assigned_copy ),
460
563
/* STRUCTLEAK_BYREF_ALL should cover everything from here down. */
461
564
KUNIT_test_scalars (none ),
462
565
KUNIT_CASE (test_switch_1_none ),
0 commit comments