Local Open Scope logic.
Definition NDfunspec_sub (f1 f2 : funspec) :=
let Delta := (funsig_tycontext (funsig_of_funspec f1)) in
match f1 with
| mk_funspec fsig1 cc1 (rmaps.ConstType A1) P1 Q1 _ _ =>
match f2 with
| mk_funspec fsig2 cc2 (rmaps.ConstType A2) P2 Q2 _ _ =>
fsig1 = fsig2 /\ cc1 = cc2 /\  forall x2,
ENTAIL Delta, P2 nil x2 |-- EX x1:_, EX F:mpred,
((`F * P1 nil x1) &&
(!! (ENTAIL (ret0_tycon Delta), `F * Q1 nil x1
|-- Q2 nil x2)))
| _ => False end
| _ => False end.
Definition is_NDfunspec (fs: funspec) :=
match fs with
| mk_funspec _ _ (rmaps.ConstType A) P Q _ _ =>
(forall ts, P ts = P nil /\ Q ts = Q nil)
| _ => False
end.
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.

Lemma semax_call_NDsubsume :
forall (fs1: funspec) A P Q argsig retsig cc,
NDfunspec_sub 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)).