diff --git a/src/frontc/cabs2cil.ml b/src/frontc/cabs2cil.ml index 707612f6b..7fbe8db5f 100644 --- a/src/frontc/cabs2cil.ml +++ b/src/frontc/cabs2cil.ml @@ -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" @@ -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 @@ -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 []) (* @@ -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) @@ -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 diff --git a/test/small1/unioninit.c b/test/small1/unioninit.c new file mode 100644 index 000000000..04d9a9d03 --- /dev/null +++ b/test/small1/unioninit.c @@ -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; +} diff --git a/test/testcil.pl b/test/testcil.pl index b4a23d806..8a3ab3940 100644 --- a/test/testcil.pl +++ b/test/testcil.pl @@ -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");