xref: /llvm-project/clang/test/Sema/init-randomized-struct.c (revision f2639cf3fe46c30ad450cc2533c81eacd4788c33)
1 // RUN: %clang_cc1 -triple=x86_64-unknown-linux -frandomize-layout-seed=1234567890abcded \
2 // RUN:  -verify -fsyntax-only -Werror %s
3 
4 // NOTE: The current seed (1234567890abcded) is specifically chosen because it
5 // uncovered a bug in diagnostics. With it the randomization of "t9" places the
6 // "a" element at the end of the record. When that happens, the clang complains
7 // about excessive initializers, which is confusing, because there aren't
8 // excessive initializers. It should instead complain about using a
9 // non-designated initializer on a raqndomized struct.
10 
11 // Initializing a randomized structure requires a designated initializer,
12 // otherwise the element ordering will be off. The only exceptions to this rule
13 // are:
14 //
15 //    - A structure with only one element, and
16 //    - A structure initialized with "{0}".
17 //
18 // These are well-defined situations where the field ordering doesn't affect
19 // the result.
20 
21 typedef void (*func_ptr)();
22 
23 void foo(void);
24 void bar(void);
25 void baz(void);
26 void gaz(void);
27 
28 struct test {
29   func_ptr a;
30   func_ptr b;
31   func_ptr c;
32   func_ptr d;
33   func_ptr e;
34   func_ptr f;
35   func_ptr g;
36 } __attribute__((randomize_layout));
37 
38 struct test t1 = {}; // This should be fine per WG14 N2900 (in C23) + our extension handling of it in earlier modes
39 struct test t2 = { 0 }; // This should also be fine per C99 6.7.8p19
40 struct test t3 = { .f = baz, .b = bar, .g = gaz, .a = foo }; // Okay
41 struct test t4 = { .a = foo, bar, baz }; // expected-error {{a randomized struct can only be initialized with a designated initializer}}
42 
43 struct other_test {
44   func_ptr a;
45   func_ptr b[3];
46   func_ptr c;
47 } __attribute__((randomize_layout));
48 
49 struct other_test t5 = { .a = foo, .b[0] = foo }; // Okay
50 struct other_test t6 = { .a = foo, .b[0] = foo, bar, baz }; // Okay
51 struct other_test t7 = { .a = foo, .b = { foo, bar, baz } }; // Okay
52 struct other_test t8 = { baz, bar, gaz, foo }; // expected-error {{a randomized struct can only be initialized with a designated initializer}}
53 struct other_test t9 = { .a = foo, .b[0] = foo, bar, baz, gaz }; // expected-error {{a randomized struct can only be initialized with a designated initializer}}
54 
55 struct empty_test {
56 } __attribute__((randomize_layout));
57 
58 struct empty_test t10 = {}; // Okay
59 
60 struct degen_test {
61   func_ptr a;
62 } __attribute__((randomize_layout));
63 
64 struct degen_test t11 = { foo }; // Okay
65 
66 struct static_assert_test {
67   int f;
68   _Static_assert(sizeof(int) == 4, "oh no!");
69 } __attribute__((randomize_layout));
70 
71 struct static_assert_test t12 = { 42 }; // Okay
72 
73 struct enum_decl_test {
74   enum e { BORK = 42, FORK = 9 } f;
75 } __attribute__((randomize_layout));
76 
77 struct enum_decl_test t13 = { BORK }; // Okay
78