Inductive empty_type : Type := .
Definition withtype_of_NDfunspec fs := match fs with
mk_funspec _ _ (rmaps.ConstType A) _ _ _ _ => A | _ => empty_type end.
Definition withtype_of_funspec fs := match fs with
mk_funspec _ _ A _ _ _ _ => A end.

(* Specifications: *)
Lemma tc_val_sem_cast':
forall {CS: compspecs} t2 e2 rho Delta,
typecheck_environ Delta rho ->
denote_tc_assert (typecheck_expr Delta e2) rho
&&  denote_tc_assert (isCastResultType (typeof e2) t2  e2) rho
|-- !! tc_val t2 (force_val (sem_cast (typeof e2) t2 (eval_expr e2 rho))).
Lemma subsume_funspec_refl:
forall fs, subsume_funspec fs fs.
Lemma sepcon_ENTAIL:
forall Delta P Q P' Q',
ENTAIL Delta, P |-- P' ->
ENTAIL Delta, Q |-- Q' ->
ENTAIL Delta, P * Q |-- P' * Q'.
Lemma subsume_funspec_trans:
forall fs1 fs2 fs3,
subsume_funspec fs1 fs2 ->
subsume_funspec fs2 fs3 ->
subsume_funspec fs1 fs3.
Lemma NDsubsume_funspec_refl:
forall fsig cc A P Q,
NDsubsume_funspec (NDmk_funspec fsig cc A P Q) (NDmk_funspec fsig cc A P Q).
Lemma NDsubsume_funspec_trans:
forall fsig1 cc1 A1 P1 Q1 fsig2 cc2 A2 P2 Q2 fsig3 cc3 A3 P3 Q3,
NDsubsume_funspec (NDmk_funspec fsig1 cc1 A1 P1 Q1) (NDmk_funspec fsig2 cc2 A2 P2 Q2) ->
NDsubsume_funspec (NDmk_funspec fsig2 cc2 A2 P2 Q2) (NDmk_funspec fsig3 cc3 A3 P3 Q3) ->
NDsubsume_funspec (NDmk_funspec fsig1 cc1 A1 P1 Q1) (NDmk_funspec fsig3 cc3 A3 P3 Q3).
Lemma tc_environ_make_args':
forall {CS: compspecs} argsig retsig bl rho Delta,
tc_environ Delta rho ->
tc_exprlist Delta (snd (split argsig)) bl rho
|-- !! tc_environ (funsig_tycontext (argsig, retsig))
(make_args' (argsig, retsig)
(eval_exprlist (snd (split argsig)) bl) rho).
Lemma later_exp'' (A: Type) (ND: NatDed A)(Indir: Indir A):
forall T : Type,
(exists x: T, True) ->
forall F : T -> A,
|> (EX x : _, F x) = EX x : T, |> F x.
Lemma semax_call_subsume:
forall (fs1: funspec) A P Q NEP NEQ argsig retsig cc,
subsume_funspec fs1 (mk_funspec  (argsig,retsig) cc A P Q NEP NEQ)  ->
forall {CS: compspecs} {Espec: OracleKind} Delta  ts x (F: environ -> mpred) ret  a bl,
Cop.classify_fun (typeof a) =
Cop.fun_case_f (type_of_params argsig) retsig cc ->
(retsig = Tvoid -> ret = None) ->
tc_fn_return Delta ret retsig ->
@semax CS Espec Delta
((|>((tc_expr Delta a) && (tc_exprlist Delta (snd (split argsig)) bl)))  &&
(`(func_ptr fs1) (eval_expr a) &&
|>(F * `(P ts x: environ -> mpred) (make_args' (argsig,retsig) (eval_exprlist (snd (split argsig)) bl)))))
(Scall ret a bl)
(normal_ret_assert
(EX old:val, substopt ret (`old) F * maybe_retval (Q ts x) retsig ret)).
Lemma semax_call_NDsubsume :
forall (fs1: funspec) A P Q argsig retsig cc,
NDsubsume_funspec fs1
(NDmk_funspec  (argsig,retsig) cc A P Q)  ->
forall {CS: compspecs} {Espec: OracleKind},
forall  Delta  x (F: environ -> mpred) ret a bl,
Cop.classify_fun (typeof a) =
Cop.fun_case_f (type_of_params argsig) retsig cc ->
(retsig = Tvoid -> ret = None) ->
tc_fn_return Delta ret retsig ->
@semax CS Espec Delta
((|>((tc_expr Delta a) && (tc_exprlist Delta (snd (split argsig)) bl)))  &&
(`(func_ptr fs1) (eval_expr a) &&
|>(F * `(P x: environ -> mpred) (make_args' (argsig,retsig) (eval_exprlist (snd (split argsig)) bl)))))
(Scall ret a bl)
(normal_ret_assert
(EX old:val, substopt ret (`old) F * maybe_retval (Q x) retsig ret)).