Skip to content

Commit c0b10d1

Browse files
Handle initializers for anonymous struct in unions (#184)
Co-authored-by: jprotopopov-ut <jprotopopov-ut@users.noreply.github.com> Co-authored-by: Jevgenijs Protopopovs <jevgenijs.protopopovs@ut.ee>
1 parent faeb7be commit c0b10d1

3 files changed

Lines changed: 168 additions & 13 deletions

File tree

src/frontc/cabs2cil.ml

Lines changed: 35 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2340,13 +2340,6 @@ let integerArrayLength (leno: exp option) : int =
23402340
d_exp len)
23412341
end
23422342

2343-
(* sm: I'm sure something like this already exists, but ... *)
2344-
let isNone (o : 'a option) : bool =
2345-
match o with
2346-
| None -> true
2347-
| Some _ -> false
2348-
2349-
23502343
let annonCompFieldNameId = ref 0
23512344
let annonCompFieldName = "__annonCompField"
23522345

@@ -5364,7 +5357,7 @@ and doInit
53645357
(* ISO 6.7.8 para 14: final NUL added only if no size specified, or
53655358
if there is room for it; btw, we can't rely on zero-init of
53665359
globals, since this array might be a local variable *)
5367-
if ((isNone leno) || ((String.length s) < (integerArrayLength leno)))
5360+
if ((Option.is_none leno) || ((String.length s) < (integerArrayLength leno)))
53685361
then ref [init Int64.zero]
53695362
else ref []
53705363
in
@@ -5426,7 +5419,7 @@ and doInit
54265419
(* ISO 6.7.8 para 14: final NUL added only if no size specified, or
54275420
if there is room for it; btw, we can't rely on zero-init of
54285421
globals, since this array might be a local variable *)
5429-
if ((isNone leno) || ((List.length s) < (integerArrayLength leno)))
5422+
if ((Option.is_none leno) || ((List.length s) < (integerArrayLength leno)))
54305423
then [init Int64.zero]
54315424
else [])
54325425
(*
@@ -5590,6 +5583,28 @@ and doInit
55905583

55915584
(* We have a designator *)
55925585
| _, (what, ie) :: restil when what != A.NEXT_INIT ->
5586+
let rec unrollDesignatorForNestedAnonymous (comp: compinfo) (designator: string) (whatnext: initwhat) =
5587+
let own_field = List.filter (fun fld -> fld.fname = designator) comp.cfields in
5588+
match own_field with
5589+
| fld :: _ -> (true, Some(A.INFIELD_INIT (designator, whatnext)))
5590+
| [] ->
5591+
let anonymous_compounds = List.filter_map (fun f ->
5592+
(* f.ftype need not be unrolled here, inner anonymous struct cannot be typdef'ed *)
5593+
match f.ftype with
5594+
| TComp(compinfo, _) when prefix annonCompFieldName f.fname -> Some (f, compinfo)
5595+
| _ -> None
5596+
) comp.cfields
5597+
in
5598+
let anonymous_compound_inits = List.filter_map (fun (comp_field, comp) ->
5599+
match unrollDesignatorForNestedAnonymous comp designator whatnext with
5600+
| _, Some(what) -> Some(comp_field, what)
5601+
| _, None -> None
5602+
) anonymous_compounds
5603+
in
5604+
match anonymous_compound_inits with
5605+
| [] -> (false, None)
5606+
| (comp_fld, compwhat) :: _ -> (false, Some(A.INFIELD_INIT (comp_fld.fname, compwhat)))
5607+
in
55935608
(* Process a designator and position to the designated subobject *)
55945609
let addressSubobj
55955610
(so: subobj)
@@ -5604,10 +5619,17 @@ and doInit
56045619
| A.INFIELD_INIT (fn, whatnext) -> begin
56055620
match unrollType so.soTyp with
56065621
TComp (comp, _) ->
5607-
let toinit = fieldsToInit comp (Some fn) in
5608-
so.stack <- InComp(so.soOff, comp, toinit) :: so.stack;
5609-
normalSubobj so;
5610-
address whatnext acc
5622+
let unrolledWhat = unrollDesignatorForNestedAnonymous comp fn whatnext in
5623+
begin
5624+
match unrolledWhat with
5625+
false, Some(unrolled) ->
5626+
address unrolled acc
5627+
| _ ->
5628+
let toinit = fieldsToInit comp (Some fn) in
5629+
so.stack <- InComp(so.soOff, comp, toinit) :: so.stack;
5630+
normalSubobj so;
5631+
address whatnext acc
5632+
end;
56115633

56125634
| _ -> E.s (error "Field designator %s not in a struct " fn)
56135635
end

test/small1/unioninit.c

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
#include "testharness.h"
2+
typedef union
3+
{
4+
struct
5+
{
6+
short leaf;
7+
};
8+
int raw;
9+
} un;
10+
11+
typedef unsigned int uint32_t;
12+
typedef unsigned long long int uint64_t;
13+
typedef union
14+
{
15+
struct
16+
{
17+
uint32_t leaf;
18+
uint32_t subleaf;
19+
};
20+
uint64_t raw;
21+
} cpuid_config_leaf_subleaf_t;
22+
typedef struct
23+
{
24+
cpuid_config_leaf_subleaf_t leaf_subleaf;
25+
} cpuid_lookup_t;
26+
extern const cpuid_lookup_t cpuid_lookup[68];
27+
const cpuid_lookup_t cpuid_lookup[68] = {
28+
[10] = { .leaf_subleaf = {.leaf = 0x0, .subleaf = 0xffffffff}}
29+
};
30+
31+
32+
un v = { .leaf = 13 };
33+
34+
typedef struct {
35+
struct {};
36+
struct {
37+
long a;
38+
};
39+
} b;
40+
41+
b c = { .a = 0 };
42+
43+
struct S1 {
44+
struct {
45+
int a;
46+
int x;
47+
};
48+
49+
struct {
50+
int b;
51+
int y;
52+
};
53+
54+
struct {
55+
int c;
56+
int z;
57+
};
58+
} s1 = {
59+
.a = 1,
60+
.b = 2,
61+
.c = 3,
62+
.x = 100,
63+
.y = 101,
64+
.z = 102
65+
};
66+
67+
struct S2 {
68+
union {
69+
int a;
70+
int b;
71+
};
72+
73+
union {
74+
struct {
75+
int c;
76+
int d;
77+
};
78+
79+
struct {
80+
int e;
81+
int f;
82+
};
83+
};
84+
} s2 = {
85+
.b = 100,
86+
.c = 500,
87+
.d = 600
88+
};
89+
90+
struct S2 s2_2 = {
91+
.a = 1,
92+
.e = 2,
93+
.f = 3
94+
};
95+
96+
97+
struct Complicated {
98+
struct {
99+
int a;
100+
} s1;
101+
struct {
102+
int a;
103+
};
104+
} c1 = {
105+
.s1 = { .a = 1 },
106+
.a = 2
107+
};
108+
109+
110+
111+
int main() {
112+
if(s2.b != 100 || s2.c != 500 || s2.d != 600) {
113+
E(1);
114+
}
115+
if(s2_2.a != 1 || s2_2.e != 2 || s2_2.f != 3) {
116+
E(2);
117+
}
118+
if(s1.a != 1 || s1.b != 2 || s1.c != 3 || s1.x != 100 || s1.y != 101 || s1.z != 102) {
119+
E(3);
120+
}
121+
if(c.a != 0) {
122+
E(4);
123+
}
124+
if(v.leaf != 13) {
125+
E(5);
126+
}
127+
if(c1.a != 2 || c1.s1.a != 1) {
128+
E(6);
129+
}
130+
SUCCESS;
131+
}

test/testcil.pl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,8 @@ sub addToGroup {
173173
addTest("test/apachebits");
174174
addTest("testrun/apachebuf");
175175

176+
addTest("testrun/unioninit");
177+
176178
addTest("testrun/apachefptr");
177179
addTest("testrun/asm1 _GNUCC=1");
178180
addTest("test/asm2 _GNUCC=1");

0 commit comments

Comments
 (0)