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.
Proof.
  intros.
  unfold legal_nested_field in H.
  rewrite H0 in H.
  simpl in H.
  tauto.
Qed.

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.
Proof.
  intros.
  simpl (nested_field_rec t (gf :: gfs)).
  unfold nested_field_type2.
  destruct (nested_field_rec t gfs) as [[? tt]| ]; [destruct tt |]; destruct gf;
  (split; intro H; auto_destruct_above_line);
  try solve[inversion H | inversion H0 | inversion H1 | inversion H2].
  + inversion H; subst.
    auto.
  + subst. auto.
  + unfold destruct (cenv_cs ! i); [| inversion H].
    destruct (co_su c); [| inversion H].
    destruct_in_members i0 (co_members c); [| inversion H].
    inversion H.
    auto.
  + destruct (cenv_cs ! i); [| inversion H].
    auto_destruct_above_line.
    apply compute_in_members_true_iff in H0.
    rewrite H, H0.
    subst; auto.
  + destruct (cenv_cs ! i); [| inversion H].
    destruct (co_su c); [inversion H |].
    destruct_in_members i0 (co_members c); [| inversion H].
    inversion H.
    auto.
  + destruct (cenv_cs ! i); [| inversion H].
    auto_destruct_above_line.
    apply compute_in_members_true_iff in H0.
    rewrite H, H0.
    subst; auto.
Qed.

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.