Skip to content
Merged
48 changes: 35 additions & 13 deletions src/frontc/cabs2cil.ml
Original file line number Diff line number Diff line change
Expand Up @@ -2340,13 +2340,6 @@ let integerArrayLength (leno: exp option) : int =
d_exp len)
end

(* sm: I'm sure something like this already exists, but ... *)
let isNone (o : 'a option) : bool =
match o with
| None -> true
| Some _ -> false


let annonCompFieldNameId = ref 0
let annonCompFieldName = "__annonCompField"

Expand Down Expand Up @@ -5364,7 +5357,7 @@ and doInit
(* ISO 6.7.8 para 14: final NUL added only if no size specified, or
if there is room for it; btw, we can't rely on zero-init of
globals, since this array might be a local variable *)
if ((isNone leno) || ((String.length s) < (integerArrayLength leno)))
if ((Option.is_none leno) || ((String.length s) < (integerArrayLength leno)))
then ref [init Int64.zero]
else ref []
in
Expand Down Expand Up @@ -5426,7 +5419,7 @@ and doInit
(* ISO 6.7.8 para 14: final NUL added only if no size specified, or
if there is room for it; btw, we can't rely on zero-init of
globals, since this array might be a local variable *)
if ((isNone leno) || ((List.length s) < (integerArrayLength leno)))
if ((Option.is_none leno) || ((List.length s) < (integerArrayLength leno)))
then [init Int64.zero]
else [])
(*
Expand Down Expand Up @@ -5590,6 +5583,28 @@ and doInit

(* We have a designator *)
| _, (what, ie) :: restil when what != A.NEXT_INIT ->
let rec unrollDesignatorForNestedAnonymous (comp: compinfo) (designator: string) (whatnext: initwhat) =
let own_field = List.filter (fun fld -> fld.fname = designator) comp.cfields in
match own_field with
| fld :: _ -> (true, Some(A.INFIELD_INIT (designator, whatnext)))
| [] ->
let anonymous_compounds = List.filter_map (fun f ->
(* f.ftype need not be unrolled here, inner anonymous struct cannot be typdef'ed *)
match f.ftype with
| TComp(compinfo, _) when prefix annonCompFieldName f.fname -> Some (f, compinfo)
| _ -> None
) comp.cfields
in
let anonymous_compound_inits = List.filter_map (fun (comp_field, comp) ->
match unrollDesignatorForNestedAnonymous comp designator whatnext with
| _, Some(what) -> Some(comp_field, what)
| _, None -> None
) anonymous_compounds
in
match anonymous_compound_inits with
| [] -> (false, None)
| (comp_fld, compwhat) :: _ -> (false, Some(A.INFIELD_INIT (comp_fld.fname, compwhat)))
in
(* Process a designator and position to the designated subobject *)
let addressSubobj
(so: subobj)
Expand All @@ -5604,10 +5619,17 @@ and doInit
| A.INFIELD_INIT (fn, whatnext) -> begin
match unrollType so.soTyp with
TComp (comp, _) ->
let toinit = fieldsToInit comp (Some fn) in
so.stack <- InComp(so.soOff, comp, toinit) :: so.stack;
normalSubobj so;
address whatnext acc
let unrolledWhat = unrollDesignatorForNestedAnonymous comp fn whatnext in
begin
match unrolledWhat with
false, Some(unrolled) ->
address unrolled acc
| _ ->
let toinit = fieldsToInit comp (Some fn) in
so.stack <- InComp(so.soOff, comp, toinit) :: so.stack;
normalSubobj so;
address whatnext acc
end;

| _ -> E.s (error "Field designator %s not in a struct " fn)
end
Expand Down
131 changes: 131 additions & 0 deletions test/small1/unioninit.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
#include "testharness.h"
typedef union
{
struct
{
short leaf;
};
int raw;
} un;

typedef unsigned int uint32_t;
typedef unsigned long long int uint64_t;
typedef union
{
struct
{
uint32_t leaf;
uint32_t subleaf;
};
uint64_t raw;
} cpuid_config_leaf_subleaf_t;
typedef struct
{
cpuid_config_leaf_subleaf_t leaf_subleaf;
} cpuid_lookup_t;
extern const cpuid_lookup_t cpuid_lookup[68];
const cpuid_lookup_t cpuid_lookup[68] = {
[10] = { .leaf_subleaf = {.leaf = 0x0, .subleaf = 0xffffffff}}
};


un v = { .leaf = 13 };

typedef struct {
struct {};
struct {
long a;
};
} b;

b c = { .a = 0 };

struct S1 {
struct {
int a;
int x;
};

struct {
int b;
int y;
};

struct {
int c;
int z;
};
} s1 = {
.a = 1,
.b = 2,
.c = 3,
.x = 100,
.y = 101,
.z = 102
};

struct S2 {
union {
int a;
int b;
};

union {
struct {
int c;
int d;
};

struct {
int e;
int f;
};
};
} s2 = {
.b = 100,
.c = 500,
.d = 600
};

struct S2 s2_2 = {
.a = 1,
.e = 2,
.f = 3
};


struct Complicated {
struct {
int a;
} s1;
struct {
int a;
};
} c1 = {
.s1 = { .a = 1 },
.a = 2
};



int main() {
if(s2.b != 100 || s2.c != 500 || s2.d != 600) {
E(1);
}
if(s2_2.a != 1 || s2_2.e != 2 || s2_2.f != 3) {
E(2);
}
if(s1.a != 1 || s1.b != 2 || s1.c != 3 || s1.x != 100 || s1.y != 101 || s1.z != 102) {
E(3);
}
if(c.a != 0) {
E(4);
}
if(v.leaf != 13) {
E(5);
}
if(c1.a != 2 || c1.s1.a != 1) {
E(6);
}
SUCCESS;
}
2 changes: 2 additions & 0 deletions test/testcil.pl
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,8 @@ sub addToGroup {
addTest("test/apachebits");
addTest("testrun/apachebuf");

addTest("testrun/unioninit");

addTest("testrun/apachefptr");
addTest("testrun/asm1 _GNUCC=1");
addTest("test/asm2 _GNUCC=1");
Expand Down