Ltac valid_nested_field_rec f a T :=
let H := fresh "H" in
let t := fresh "t" in
let ofs := fresh "ofs" in
simpl in T; destruct (nested_field_rec f a) as [[ofs t]|] eqn:H; [|inversion T].
Ltac auto_destruct_above_line :=
repeat (
let H1 := fresh "H" in
let H2 := fresh "H" in
let x := fresh "x" in
match goal with
| H: _ /\ _ |- _ => destruct H as [H1 H2]
| H: prod _ _ |- _ => destruct H as [H1 H2]
| H: @ex _ _ |- _ => destruct H as [x H1]
| H: sigT _ |- _ => destruct H as [x H1]
end).
(* Lemma legal_nested_field_nested_field_rec_None_conflict: forall t gfs P, legal_nested_field t gfs -> nested_field_rec t gfs = None -> P.  Lemma nested_field_rec_cons_eq_Some_lemma: forall t gf gfs ofs0 t0, nested_field_rec t (gf :: gfs) = Some (ofs0, t0) <-> match gf, nested_field_rec t gfs with | ArraySubsc i0, Some (ofs, Tarray t1 n a) => ofs0 = ofs + sizeof t0 * i0 /\ t0 = t1 | StructField i, Some (ofs, Tstruct id a) => in_members i (co_members (get_co id)) /\ co_su (get_co id) = Struct /\ t0 = field_type2 i (co_members (get_co id)) /\ ofs0 = ofs + field_offset2 cenv_cs i (co_members (get_co id)) | UnionField i, Some (ofs, Tunion id a) => in_members i (co_members (get_co id)) /\ co_su (get_co id) = Union /\ t0 = field_type2 i (co_members (get_co id)) /\ ofs0 = ofs | _, _ => False end.  Ltac solve_legal_nested_field_cons H := let HH := fresh "HH" in let Heq := fresh "Heq" in let HeqNFT := fresh "Heq" in let H1 := fresh "H" in let H2 := fresh "H" in let H3 := fresh "H" in let id := fresh "id" in let co := fresh "co" in let CO := fresh "CO" in match type of H with | (legal_nested_field ?T (?A :: ?GFS)) => destruct (legal_nested_field_cons_lemma T A GFS) as [HH _]; specialize (HH H); destruct A eqn:Heq; destruct (nested_field_type2 T GFS) as [ | | | | | | | id ? | id ? ] eqn:HeqNFT; try solve [destruct HH as [_ HH]; inversion HH] end; [try solve [inversion Heq]; destruct HH as [H1 H2] |try solve [inversion Heq]; destruct HH as [H1 H2]; destruct (cenv_cs ! id) as [co |] eqn:CO; [| inversion H2]; destruct H2 as [H2 H3] |try solve [inversion Heq]; destruct HH as [H1 H2]; destruct (cenv_cs ! id) as [co |] eqn:CO; [| inversion H2]; destruct H2 as [H2 H3]].  Ltac solve_nested_field_rec_cons_eq_Some H := let HH := fresh "HH" in let HeqA := fresh "Heq" in let HeqNFT := fresh "Heq" in let H1 := fresh "H" in let H2 := fresh "H" in let H3 := fresh "H" in let H4 := fresh "H" in let ofs := fresh "ofs" in let id := fresh "id" in let co := fresh "co" in let CO := fresh "CO" in match type of H with | (nested_field_rec ?T (?A :: ?GFS) = Some (?OFS, ?T0)) => destruct (nested_field_rec_cons_eq_Some_lemma T A GFS OFS T0) as [HH _]; specialize (HH H); destruct A eqn:HeqA; destruct (nested_field_rec T GFS) as [[ofs [ | | | | | | | id ? | id ? ]]|] eqn:HeqNFT; try solve [inversion HH] end; [try solve [inversion HeqA]; destruct HH as [H1 H2] |try solve [inversion HeqA]; destruct (cenv_cs ! id) as [co |] eqn:CO; [| inversion HH]; destruct HH as [H1 [H2 [H3 H4]]] |try solve [inversion HeqA]; destruct (cenv_cs ! id) as [co |] eqn:CO; [| inversion HH]; destruct HH as [H1 [H2 [H3 H4]]]].  Ltac solve_legal_nested_field := first [ solve [apply legal_nested_field_nil_lemma] | apply legal_nested_field_cons_lemma; simpl; split; [solve_legal_nested_field | auto]].  Global Opaque legal_nested_field. *)
Definition legal_nested_field_dec: forall t gfs,
{legal_nested_field t gfs} + {~ legal_nested_field t gfs}.
Definition legal_nested_field0_dec: forall t gfs,
{legal_nested_field0 t gfs} + {~ legal_nested_field0 t gfs}.
Definition field_compatible t gfs p :=
isptr p /\
complete_legal_cosu_type t = true /\
size_compatible t p /\
align_compatible t p /\
legal_nested_field t gfs.
Definition field_compatible0 t gfs p :=
isptr p /\
complete_legal_cosu_type t = true /\
size_compatible t p /\
align_compatible t p /\
legal_nested_field0 t gfs.

Lemma field_compatible_cons: forall t gf gfs p,
field_compatible t (gf :: gfs) p <->
match nested_field_type t gfs, gf with
| Tstruct id _, StructField i => in_members i (co_members (get_co id)) /\ field_compatible t gfs p
| Tunion id _, UnionField i => in_members i (co_members (get_co id)) /\ field_compatible t gfs p
| Tarray _ n _, ArraySubsc i => 0 <= i < n /\ field_compatible t gfs p
| _, _ => False
end.