diff --git a/src/plugins/wp/MemTyped.ml b/src/plugins/wp/MemTyped.ml
index 63c759f0498dc1021c47c79fc16be245a1fbaad4..fef9cc957168b581ed71df0c6b185dfa64a96762 100644
--- a/src/plugins/wp/MemTyped.ml
+++ b/src/plugins/wp/MemTyped.ml
@@ -503,6 +503,7 @@ let rec size_of_object = function
 and size_of_typ t = size_of_object (object_of t)
 and size_of_field f = size_of_typ f.ftype
 and size_of_comp c =
+  (* union field are considered as struct field *)
   List.fold_left
     (fun s f -> s + size_of_field f)
     0 c.cfields
@@ -1067,36 +1068,74 @@ module Layout : sig
 end =
 struct
 
-  type atom = P of typ | I of c_int | F of c_float | U of Cil_types.compinfo
+  type atom = P of typ | I of c_int | F of c_float
 
   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
 
-  let eqatom a1 a2 =
+  let eq_atom a1 a2 =
     match a1 , a2 with
     | P _ , P _ -> true
-    | U u1 , U u2 -> Compinfo.equal u1 u2
     | I i1 , I i2 -> i1 = i2
     | F f1 , F f2 -> f1 = f2
     | _ -> false
 
+  type slot = A of atom
+            | S of Cil_types.compinfo (* delayed layout of a C struct *)
+            | U of Cil_types.compinfo (* delayed layout of a C union *)
+
+  let pp_slot fmt = function
+    | A a -> pp_atom fmt a
+    | S s -> Format.fprintf fmt "{struct %a}" Printer.pp_compinfo s
+    | U u -> Format.fprintf fmt "{union %a}" Printer.pp_compinfo u
+
+  let eq_slot a1 a2 = (* syntactic equality *)
+    match a1 , a2 with
+    | A a1 , A a2 -> eq_atom a1 a2
+    | S c1 , S c2 | U c1, U c2 -> Compinfo.equal c1 c2
+    | _ -> false
+
+  let rec get_slot = function
+    | C_int i -> A (I i)
+    | C_float f -> A (F f)
+    | C_pointer t -> A (P t)
+    | C_comp ( { cfields = [f] } as c ) ->
+        begin (* union having only one field is equivalent to a struct *)
+          match Ctypes.object_of f.ftype with
+          | C_array _ -> (if c.cstruct then S c else U c)
+          | cobj -> get_slot cobj
+        end
+    | C_comp c -> if c.cstruct then S c else U c
+    | C_array _ -> assert false
+
   type block =
-    | Str of atom * int
-    | Arr of layout * int (* non-homogeneous, more than one *)
+    | Str of slot * int
+    | Arr of c_object * int (* delayed layout of a C type *)
     | Garbled
 
-  and layout = block list
-
-  let rec pp_block fmt = function
-    | Str(a,n) when n=1 -> pp_atom fmt a
-    | Str(a,n) -> Format.fprintf fmt "%a[%d]" pp_atom a n
-    | Arr(ly,n) -> Format.fprintf fmt "%a[%d]" pp_layout ly n
+  let pp_block fmt = function
+    | Str(a,n) when n=1 -> pp_slot fmt a
+    | Str(a,n) -> Format.fprintf fmt "%a[%d]" pp_slot a n
+    | Arr(o,n) -> Format.fprintf fmt "{ctype %a}[%d]" Ctypes.pretty o n
     | Garbled -> Format.fprintf fmt "..."
 
-  and pp_layout fmt = function
+  let add_slot a n w =
+    assert (n >= 1) ;
+    match w with
+    | Str(b,m) :: w when eq_slot a b -> Str(b,m+n)::w
+    | _ -> Str(a,n) :: w
+
+  let add_block p w =
+    match p , w with
+    | Str(a,n) , Str(b,m)::w when eq_slot a b -> Str(b,n+m)::w
+    | Garbled , Garbled::_ -> w
+    | _ -> p :: w
+
+  type layout = block list
+
+  let pp_layout fmt = function
     | [b] -> pp_block fmt b
     | bs ->
         begin
@@ -1105,100 +1144,100 @@ struct
           Format.fprintf fmt " }@]" ;
         end
 
-  let add_atom a ly =
-    match ly with
-    | Str(b,m) :: w when eqatom a b -> Str(b,m+1)::w
-    | _ -> Str(a,1) :: ly
-
-  let add_block p ly =
-    match p , ly with
-    | Str(a,n) , Str(b,m)::w when eqatom a b -> Str(b,n+m)::w
-    | Garbled , Garbled::_ -> ly
-    | _ -> p :: ly
-
   (* requires n > 1 *)
-  let add_many ly n w =
-    match ly with
-    | [] -> w
-    | [Str(a,m)] -> add_block (Str(a,n*m)) w
-    | Garbled::_ -> add_block Garbled w
-    | ly -> Arr(ly,n) :: w
-
-  let rec rlayout w = function
-    | 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 add_atom (U c) w (* unions with several fields *)
+  let rec add_many cobj n w = (* returns [layout obj]*n @ [w] *)
+    assert (n > 1) ;
+    match cobj, w with
+    | C_array { arr_flat = Some a }, _ when a.arr_cell_nbr = 1 ->
+        add_many (Ctypes.object_of a.arr_cell) n w
+    | C_array _, Arr(o, m)::w when 0 = compare_ptr_conflated o cobj -> Arr(o, m+n)::w
+    | C_array _, _ -> Arr(cobj, n)::w
+    | _  -> add_slot (get_slot cobj) n w
+
+  let rec rlayout w = function (* returns [layout obj] @ [w] *)
     | C_array { arr_flat = Some a } ->
-        let ly = rlayout [] (Ctypes.object_of a.arr_cell) in
+        let cobj = Ctypes.object_of a.arr_cell in
         if a.arr_cell_nbr = 1
-        then ly @ w (* ly is in reversed order *)
-        else add_many (List.rev ly) a.arr_cell_nbr w
+        then rlayout w cobj
+        else add_many cobj a.arr_cell_nbr w
     | C_array { arr_element = e } ->
         if Wp_parameters.ExternArrays.get () then
-          let ly = rlayout [] (Ctypes.object_of e) in
-          add_many (List.rev ly) max_int w
+          add_many (Ctypes.object_of e) max_int w
         else
           add_block Garbled w
+    | cobj -> add_slot (get_slot cobj) 1 w
 
-  and flayout w f = rlayout w (Ctypes.object_of f.ftype)
+  let layout (obj : c_object) : layout = rlayout [] obj
 
-  let layout (obj : c_object) : layout = List.rev (rlayout [] obj)
+  let clayout (c: Cil_types.compinfo) : layout =
+    let flayout w f = rlayout w (Ctypes.object_of f.ftype) in
+    List.fold_left flayout [] (List.rev c.cfields)
 
-  let add_compound (c: Cil_types.compinfo) w : layout =
-    List.fold_left flayout w (List.rev c.cfields)
+  type comparison = Srem of layout | Drem of layout | Equal | Mismatch
 
-  let ulayout (c: Cil_types.compinfo) : layout = add_compound c []
+  let add_array o n w =
+    assert (n > 0) ;
+    if n=1 then rlayout w o else Arr(o, n)::w
 
-  type comparison = Srem of layout | Drem of layout | Equal | Mismatch
+  let decr_slot a n w =
+    assert (n >= 1);
+    if n=1 then w else Str(a, n-1)::w
 
-  let add_array ly n w =
-    if n=1 then ly @ w else add_many ly n w
-
-  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)
+  let rec equal u v =
+    match compare ~dst:u ~src:v with
+    | Equal -> true
+    | _ -> false
+  and compare_slot ~dst ~src =
+    match dst, src with
+    | A a1, A a2 -> if eq_atom a1 a2 then Equal else Mismatch
+    | S c1, S c2 | U c1, U c2 when Compinfo.equal c1 c2 -> Equal
+    | S c1, _    -> compare ~dst:(clayout c1) ~src:[Str(src,1)]
+    |    _, S c2 -> compare ~dst:[Str(dst,1)] ~src:(clayout c2)
+    | U c1, U c2 ->  (* for union, the layouts must be equal *)
+        if equal (clayout c1) (clayout c2) then Equal else Mismatch
+    | U _, A _ -> Mismatch
+    | A _, U _ -> Mismatch
   and compare ~dst ~src =
     match dst , src with
-    | [] , [] -> Equal (* src = dst *)
-    | [] , obj -> Srem obj    (* src = dst @ obj *)
-    | obj , [] -> Drem obj    (* dst = src @ obj *)
+    | [] , [] -> Equal     (* src = dst *)
+    | [] , 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 equal_atom a b then
-              if n < m then
-                let w2 = Str(a,m-n)::w2 in
-                compare w1 w2
-              else if n > m then
-                let w1 = Str(a,n-m)::w1 in
-                compare w1 w2
-              else
-                (* n = m *)
-                compare w1 w2
-            else Mismatch
+            begin
+              match compare_slot a b with
+              | Mismatch -> Mismatch
+              | Drem a'->
+                  let w1 = a' @ decr_slot a n w1 in
+                  let w2 =      decr_slot b m w2 in
+                  compare w1 w2
+              | Srem b' ->
+                  let w1 =      decr_slot a n w1 in
+                  let w2 = b' @ decr_slot b m w2 in
+                  compare w1 w2
+              | Equal ->
+                  if n < m then
+                    let w2 = Str(a,m-n)::w2 in
+                    compare w1 w2
+                  else if n > m then
+                    let w1 = Str(a,n-m)::w1 in
+                    compare w1 w2
+                  else
+                    (* n = m *)
+                    compare w1 w2
+            end
         | Arr(u,n) , Arr(v,m) ->
             begin
-              match compare ~dst:u ~src:v with
+              match compare ~dst:(layout u) ~src:(layout v) with
               | Mismatch -> Mismatch
               | Drem u' ->
                   let w1 = u' @ add_array u (n-1) w1 in
-                  let w2 = add_array v (m-1) w2 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 w1 =      add_array u (n-1) w1 in
                   let w2 = v' @ add_array v (m-1) w2 in
                   compare w1 w2
               | Equal ->
@@ -1212,10 +1251,10 @@ struct
                     (* n = m *)
                     compare w1 w2
             end
-        | Arr(v,n) , Str _ ->
-            compare ~dst:(v @ add_array v (n-1) w1) ~src
+        | Arr(u,n) , Str _ ->
+            compare ~dst:((layout u) @ add_array u (n-1) w1) ~src
         | Str _ , Arr(v,n) ->
-            compare ~dst ~src:(v @ add_array v (n-1) w2)
+            compare ~dst ~src:((layout v) @ add_array v (n-1) w2)
 
   let rec repeated ~dst ~src =
     match dst , src with
@@ -1226,10 +1265,22 @@ struct
         match p , q with
         | Garbled , _ | _ , Garbled -> false
         | Str(a,n) , Str(b,m) -> (* dst =?= repeated(src,n/m) *)
-            equal_atom a b && n >= m && (n mod m = 0)
+            begin
+              match compare_slot ~dst:a ~src:b with
+              | Mismatch -> false
+              | Drem a' ->
+                  let w1 = a' @ decr_slot a n [] in
+                  let w2 =      decr_slot b m [] in
+                  let cmp = compare ~dst:w1 ~src:w2 in
+                  repeated_result ~src cmp
+              | Srem _ ->
+                  false
+              | Equal -> (* dst =?= repeated(src,n/m) *)
+                  n >= m && (n mod m = 0)
+            end
         | Arr(u,n) , Arr(v,m) ->
             begin
-              match compare ~dst:u ~src:v with
+              match compare ~dst:(layout u) ~src:(layout v) with
               | Mismatch -> false
               | Drem u' ->
                   let w1 = u' @ add_array u (n-1) [] in