diff --git a/src/plugins/wp/MemTyped.ml b/src/plugins/wp/MemTyped.ml
index 5320e25967110d07731d5cba700eddbd3e061e58..c8d82ca1aeeb11174fb1401795a77d809c7abeab 100644
--- a/src/plugins/wp/MemTyped.ml
+++ b/src/plugins/wp/MemTyped.ml
@@ -1062,14 +1062,15 @@ module Layout : sig
 
   val fits: dst:c_object -> src:c_object -> bool
   (* returns [true] in these cases:
-     - [dst] fits into [src]
-     - [dst] equals    [src] *)
+     - [dst] fits into [src] (exists cobj; [src] = [dst] concat cobj)
+     - [dst] equals    [src] ([dst] = [src]) *)
 end =
 struct
 
-  type atom = P of typ | I of c_int | F of c_float
+  type atom = P of typ | I of c_int | F of c_float | U of Cil_types.compinfo
 
   let pp_atom fmt = function
+    | U ci -> Format.fprintf fmt "union %a" Printer.pp_compinfo ci
     | P ty -> Printer.pp_typ fmt (TPtr(ty,[]))
     | I i -> Ctypes.pp_int fmt i
     | F f -> Ctypes.pp_float fmt f
@@ -1077,7 +1078,10 @@ struct
   let eqatom a1 a2 =
     match a1 , a2 with
     | P _ , P _ -> true
-    | _ -> (a1 = a2)
+    | U u1 , U u2 -> Compinfo.equal u1 u2
+    | I i1 , I i2 -> i1 = i2
+    | F f1 , F f2 -> f1 = f2
+    | _ -> false
 
   type block =
     | Str of atom * int
@@ -1124,12 +1128,13 @@ struct
     | C_int i -> add_atom (I i) w
     | C_float f -> add_atom (F f) w
     | C_pointer t -> add_atom (P t) w
+    | C_comp { cfields = [f] } ->
+        flayout w f (* unions containing only one field are
+                       considered as structures *)
     | C_comp c ->
         if c.cstruct
         then List.fold_left flayout w c.cfields
-        else
-          (* TODO: can be the longest common prefix *)
-          add_block Garbled w
+        else add_atom (U c) w (* unions with several fields *)
     | C_array { arr_flat = Some a } ->
         let ly = rlayout [] (Ctypes.object_of a.arr_cell) in
         if a.arr_cell_nbr = 1
@@ -1146,21 +1151,34 @@ struct
 
   let layout (obj : c_object) : layout = List.rev (rlayout [] obj)
 
-  type comparison = Fit | Equal | Mismatch
+  let add_compound (c: Cil_types.compinfo) w : layout =
+    List.fold_left flayout w (List.rev c.cfields)
+
+  let ulayout (c: Cil_types.compinfo) : layout = add_compound c []
+
+  type comparison = Srem of layout | Drem of layout | Equal | Mismatch
 
   let add_array ly n w =
     if n=1 then ly @ w else add_many ly n w
 
-  let rec compare ~dst ~src =
+  let rec equal_atom a b =
+    (eqatom a b) ||
+    (match a,b with
+     | U u1, U u2 -> (* for union, the layouts must be equal *)
+         (match compare ~dst:(ulayout u1) ~src:(ulayout u2) with
+          | Equal -> true
+          | _ -> false)
+     | _, _ -> false)
+  and compare ~dst ~src =
     match dst , src with
     | [] , [] -> Equal (* src = dst *)
-    | [] , _ -> Fit    (* exists obj ;  src = dst concat obj *)
-    | _ , [] -> Mismatch
+    | [] , obj -> Srem obj    (* src = dst @ obj *)
+    | obj , [] -> Drem obj    (* dst = src @ obj *)
     | p::w1 , q::w2 ->
         match p , q with
         | Garbled , _ | _ , Garbled -> Mismatch
         | Str(a,n) , Str(b,m) ->
-            if eqatom a b then
+            if equal_atom a b then
               if n < m then
                 let w2 = Str(a,m-n)::w2 in
                 compare w1 w2
@@ -1175,7 +1193,14 @@ struct
             begin
               match compare ~dst:u ~src:v with
               | Mismatch -> Mismatch
-              | Fit -> Mismatch
+              | Drem u' ->
+                    let w1 = u' @ add_array u (n-1) w1 in
+                    let w2 = add_array v (m-1) w2 in
+                    compare w1 w2
+              | Srem v' ->
+                    let w1 = add_array u (n-1) w1 in
+                    let w2 = v' @ add_array v (m-1) w2 in
+                    compare w1 w2
               | Equal ->
                   if n < m then
                     let w2 = add_array v (m-n) w2 in
@@ -1200,8 +1225,8 @@ struct
     | C_pointer _ , C_pointer _ -> true
     | _ ->
         match compare ~dst:(layout dst) ~src:(layout src) with
-        | Equal | Fit -> true
-        | Mismatch -> false
+        | Equal | Srem _ -> true
+        | Drem _ | Mismatch -> false
 
   let rec pretty fmt = function
     | C_pointer ty -> Format.fprintf fmt "%a*" pretty (Ctypes.object_of ty)
diff --git a/src/plugins/wp/tests/wp_typed/oracle/cast_fits.0.res.oracle b/src/plugins/wp/tests/wp_typed/oracle/cast_fits.0.res.oracle
index d9d935d41738a286acc33595f24e8552f1593e8f..56beccaf01fa52665901dd19e21253de0b119058 100644
--- a/src/plugins/wp/tests/wp_typed/oracle/cast_fits.0.res.oracle
+++ b/src/plugins/wp/tests/wp_typed/oracle/cast_fits.0.res.oracle
@@ -3,12 +3,6 @@
 [wp] Running WP plugin...
 [wp] Loading driver 'share/wp.driver'
 [wp] Warning: Missing RTE guards
-[wp] tests/wp_typed/cast_fits.i:39: Warning: 
-  Cast with incompatible pointers types (source: __anonstruct_L5_5*)
-     (target: __anonstruct_L6_6*)
-[wp] tests/wp_typed/cast_fits.i:47: Warning: 
-  Cast with incompatible pointers types (source: __anonunion_L7_7*)
-     (target: sint32*)
 [wp] tests/wp_typed/cast_fits.i:13: Warning: 
   Cast with incompatible pointers types (source: __anonstruct_L2_2*)
      (target: sint32*)
@@ -70,11 +64,7 @@ Prove: x_1 = x.
 ------------------------------------------------------------
 
 Goal Post-condition (file tests/wp_typed/cast_fits.i, line 37) in 'fits4':
-tests/wp_typed/cast_fits.i:39: warning from Typed Model:
- - Warning: Hide sub-term definition
-   Reason: Cast with incompatible pointers types (source: __anonstruct_L5_5*)
-   (target: __anonstruct_L6_6*)
-Let x = Mchar_0[shiftfield_F6_c6(q)].
+Let x = Mchar_0[shiftfield_F6_c6(p)].
 Let x_1 = Mchar_0
             [shiftfield_F3_c3(shift___anonstruct_L3_3(shiftfield_F5_ci5(p),
                                 1))].
@@ -91,11 +81,7 @@ Prove: x_1 = x.
 ------------------------------------------------------------
 
 Goal Post-condition (file tests/wp_typed/cast_fits.i, line 45) in 'fits5':
-tests/wp_typed/cast_fits.i:47: warning from Typed Model:
- - Warning: Hide sub-term definition
-   Reason: Cast with incompatible pointers types (source: __anonunion_L7_7*)
-   (target: sint32*)
-Let x = Mint_0[q].
+Let x = Mint_0[p].
 Let x_1 = Mint_0[shiftfield_F7_u7(p)].
 Assume {
   Type: is_sint32(x) /\ is_sint32(x_1).
diff --git a/src/plugins/wp/tests/wp_typed/oracle/cast_fits.1.res.oracle b/src/plugins/wp/tests/wp_typed/oracle/cast_fits.1.res.oracle
index 0fe3ebad7424b28bd8090d4916f8f1246f982ee9..cc8072d61ce0f259dd2e73a19b11d96f46c2512d 100644
--- a/src/plugins/wp/tests/wp_typed/oracle/cast_fits.1.res.oracle
+++ b/src/plugins/wp/tests/wp_typed/oracle/cast_fits.1.res.oracle
@@ -3,12 +3,6 @@
 [wp] Running WP plugin...
 [wp] Loading driver 'share/wp.driver'
 [wp] Warning: Missing RTE guards
-[wp] tests/wp_typed/cast_fits.i:39: Warning: 
-  Cast with incompatible pointers types (source: __anonstruct_L5_5*)
-     (target: __anonstruct_L6_6*)
-[wp] tests/wp_typed/cast_fits.i:47: Warning: 
-  Cast with incompatible pointers types (source: __anonunion_L7_7*)
-     (target: sint32*)
 [wp] tests/wp_typed/cast_fits.i:13: Warning: 
   Cast with incompatible pointers types (source: __anonstruct_L2_2*)
      (target: sint32*)
@@ -70,11 +64,7 @@ Prove: x_1 = x.
 ------------------------------------------------------------
 
 Goal Post-condition (file tests/wp_typed/cast_fits.i, line 37) in 'fits4':
-tests/wp_typed/cast_fits.i:39: warning from Typed Model:
- - Warning: Hide sub-term definition
-   Reason: Cast with incompatible pointers types (source: __anonstruct_L5_5*)
-   (target: __anonstruct_L6_6*)
-Let x = Mchar_0[shiftfield_F6_c6(q)].
+Let x = Mchar_0[shiftfield_F6_c6(p)].
 Let x_1 = Mchar_0
             [shiftfield_F3_c3(shift___anonstruct_L3_3(shiftfield_F5_ci5(p),
                                 1))].
@@ -91,11 +81,7 @@ Prove: x_1 = x.
 ------------------------------------------------------------
 
 Goal Post-condition (file tests/wp_typed/cast_fits.i, line 45) in 'fits5':
-tests/wp_typed/cast_fits.i:47: warning from Typed Model:
- - Warning: Hide sub-term definition
-   Reason: Cast with incompatible pointers types (source: __anonunion_L7_7*)
-   (target: sint32*)
-Let x = Mint_0[q].
+Let x = Mint_0[p].
 Let x_1 = Mint_0[shiftfield_F7_u7(p)].
 Assume {
   Type: is_sint32(x) /\ is_sint32(x_1).
diff --git a/src/plugins/wp/tests/wp_typed/oracle_qualif/cast_fits.0.report.json b/src/plugins/wp/tests/wp_typed/oracle_qualif/cast_fits.0.report.json
index 3003aaa8a860a03d7085e8098f82494f7239592f..193b5d5e58bebc238a27b6c45e343141affb683a 100644
--- a/src/plugins/wp/tests/wp_typed/oracle_qualif/cast_fits.0.report.json
+++ b/src/plugins/wp/tests/wp_typed/oracle_qualif/cast_fits.0.report.json
@@ -1,7 +1,7 @@
-{ "wp:global": { "alt-ergo": { "total": 8, "valid": 3, "unknown": 5,
-                               "rank": 7 },
-                 "wp:main": { "total": 8, "valid": 3, "unknown": 5,
-                              "rank": 7 } },
+{ "wp:global": { "alt-ergo": { "total": 8, "valid": 5, "unknown": 3,
+                               "rank": 8 },
+                 "wp:main": { "total": 8, "valid": 5, "unknown": 3,
+                              "rank": 8 } },
   "wp:functions": { "fits1": { "fits1_ensures": { "alt-ergo": { "total": 1,
                                                                 "valid": 1,
                                                                 "rank": 6 },
@@ -49,21 +49,29 @@
                                                             "valid": 1,
                                                             "rank": 7 } } },
                     "fits4": { "fits4_ensures": { "alt-ergo": { "total": 1,
-                                                                "unknown": 1 },
+                                                                "valid": 1,
+                                                                "rank": 8 },
                                                   "wp:main": { "total": 1,
-                                                               "unknown": 1 } },
+                                                               "valid": 1,
+                                                               "rank": 8 } },
                                "wp:section": { "alt-ergo": { "total": 1,
-                                                             "unknown": 1 },
+                                                             "valid": 1,
+                                                             "rank": 8 },
                                                "wp:main": { "total": 1,
-                                                            "unknown": 1 } } },
+                                                            "valid": 1,
+                                                            "rank": 8 } } },
                     "fits5": { "fits5_ensures": { "alt-ergo": { "total": 1,
-                                                                "unknown": 1 },
+                                                                "valid": 1,
+                                                                "rank": 6 },
                                                   "wp:main": { "total": 1,
-                                                               "unknown": 1 } },
+                                                               "valid": 1,
+                                                               "rank": 6 } },
                                "wp:section": { "alt-ergo": { "total": 1,
-                                                             "unknown": 1 },
+                                                             "valid": 1,
+                                                             "rank": 6 },
                                                "wp:main": { "total": 1,
-                                                            "unknown": 1 } } },
+                                                            "valid": 1,
+                                                            "rank": 6 } } },
                     "mismatch2": { "mismatch2_ensures": { "alt-ergo": 
                                                             { "total": 1,
                                                               "unknown": 1 },
diff --git a/src/plugins/wp/tests/wp_typed/oracle_qualif/cast_fits.res.oracle b/src/plugins/wp/tests/wp_typed/oracle_qualif/cast_fits.res.oracle
index 41a7947cd45a046af542b6bca6c43d115baa713c..6bc88bcb22a2bf7acb1f1acca3ffc64da2dca480 100644
--- a/src/plugins/wp/tests/wp_typed/oracle_qualif/cast_fits.res.oracle
+++ b/src/plugins/wp/tests/wp_typed/oracle_qualif/cast_fits.res.oracle
@@ -3,12 +3,6 @@
 [wp] Running WP plugin...
 [wp] Loading driver 'share/wp.driver'
 [wp] Warning: Missing RTE guards
-[wp] tests/wp_typed/cast_fits.i:39: Warning: 
-  Cast with incompatible pointers types (source: __anonstruct_L5_5*)
-     (target: __anonstruct_L6_6*)
-[wp] tests/wp_typed/cast_fits.i:47: Warning: 
-  Cast with incompatible pointers types (source: __anonunion_L7_7*)
-     (target: sint32*)
 [wp] tests/wp_typed/cast_fits.i:13: Warning: 
   Cast with incompatible pointers types (source: __anonstruct_L2_2*)
      (target: sint32*)
@@ -22,14 +16,14 @@
 [wp] [Alt-Ergo] Goal typed_fits1_ensures : Valid
 [wp] [Alt-Ergo] Goal typed_fits2_ensures : Valid
 [wp] [Alt-Ergo] Goal typed_fits3_ensures : Valid
-[wp] [Alt-Ergo] Goal typed_fits4_ensures : Unsuccess (Stronger)
-[wp] [Alt-Ergo] Goal typed_fits5_ensures : Unsuccess (Stronger)
+[wp] [Alt-Ergo] Goal typed_fits4_ensures : Valid
+[wp] [Alt-Ergo] Goal typed_fits5_ensures : Valid
 [wp] [Alt-Ergo] Goal typed_mismatch1_ensures : Unsuccess (Stronger)
 [wp] [Alt-Ergo] Goal typed_mismatch2_ensures : Unsuccess (Stronger)
 [wp] [Alt-Ergo] Goal typed_mismatch3_ensures : Unsuccess (Stronger)
-[wp] Proved goals:    3 / 8
+[wp] Proved goals:    5 / 8
   Qed:             0 
-  Alt-Ergo:        3  (unsuccess: 5)
+  Alt-Ergo:        5  (unsuccess: 3)
 [wp] Report in:  'tests/wp_typed/oracle_qualif/cast_fits.0.report.json'
 [wp] Report out: 'tests/wp_typed/result_qualif/cast_fits.0.report.json'
 -------------------------------------------------------------
@@ -38,8 +32,8 @@ fits1               -       1 (20..32)       1       100%
 mismatch1           -      -                 1       0.0%
 fits2               -       1 (20..32)       1       100%
 fits3               -       1 (24..36)       1       100%
-fits4               -      -                 1       0.0%
-fits5               -      -                 1       0.0%
+fits4               -       1 (28..40)       1       100%
+fits5               -       1 (20..32)       1       100%
 mismatch2           -      -                 1       0.0%
 mismatch3           -      -                 1       0.0%
 -------------------------------------------------------------