Module SortBodyProof := Mergesort.Sort(BodyProofOrder).
Definition Gprog_of_proof (p: semax_body_proof) :=
match p with
| @mk_body _ G _ _ _ _ _ => G
| @mk_external _ _ _ _ _ _ _ _ _ _ => nil
end.
Fixpoint delete_dups' id f (al: funspecs) : funspecs :=
match al with
| (id',f')::al' => if ident_eq id id' then delete_dups' id f al'
else (id,f)::delete_dups' id' f' al'
| nil => (id,f)::nil
end.
Definition delete_dups (al: funspecs) : funspecs :=
match al with
| (id,f)::al' => delete_dups' id f al'
| nil => nil
end.
Definition merge_Gprogs_of (module: list semax_body_proof) :=
delete_dups
(SortFunspec.sort
(List.fold_right (fun m G => Gprog_of_proof m ++ G) (nil: funspecs) module)).
Ltac apply_semax_body L :=
eapply (@semax_body_subsumption' _ _ _ _ _ _ _ _ L);
[first [ apply cspecs_sub_refl
| split3; red; apply @sub_option_get;
repeat (apply Forall_cons; [reflexivity | ]);  apply Forall_nil ]
| repeat (apply Forall_cons; [ reflexivity | ]); apply Forall_nil
| simple apply tycontext_sub_refl ||
(apply tycontext_sub_i99;
[ apply sub_option_get;  repeat (apply Forall_cons; [reflexivity | ]);  apply Forall_nil
| apply subsume_spec_get;
repeat (apply Forall_cons; [apply subsumespec_refl | ]); apply Forall_nil])].
Ltac semax_func_cons' L H :=
repeat (eapply semax_func_cons_ext_vacuous; [reflexivity | reflexivity | LookupID | LookupB |]);
first [eapply semax_func_cons;
[ reflexivity
| repeat apply Forall_cons; try apply Forall_nil; try computable; reflexivity
| unfold var_sizes_ok; repeat constructor; try (simpl; rep_omega)
| reflexivity | LookupID | LookupB |
(* next line not needed in alphaconvert branch simpl; precondition_closed | *)
apply_semax_body L
| ]
| eapply semax_func_cons_ext;
[reflexivity | reflexivity | reflexivity | reflexivity | reflexivity
| apply H | LookupID | LookupB | apply L |
]
];
repeat (eapply semax_func_cons_ext_vacuous; [reflexivity | reflexivity | LookupID | LookupB |]).
Ltac do_semax_body_proofs x :=
let x := eval hnf in x in
match x with
| mk_external _ _ ?H ?P :: ?y => semax_func_cons' P H; [do_semax_body_proofs y]
| mk_body ?P :: ?y => semax_func_cons' P I; [do_semax_body_proofs y]
| nil =>  apply semax_func_nil
| _ => pose (jj := x)
end.

Lemma closed_wrt_FF:
forall {cs: compspecs} S, closed_wrt_vars S FF.