Definition can_assume_funcptr cs Delta P Q R a fs :=
forall Espec c Post,
@semax cs Espec Delta ((EX v: val, (lift0 (func_ptr fs v) && local (`(eq v) (eval_expr a)))) &&
PROPx P (LOCALx Q (SEPx R))) c Post ->
@semax cs Espec Delta (PROPx P (LOCALx Q (SEPx R))) c Post.
Definition call_setup1
(cs: compspecs) Qtemp Qvar GV a Delta P Q R R'
fs argsig retty cc (A: rmaps.TypeTree)  Pre Post NEPre NEPost
(bl: list expr) (vl : list val)
(Qactuals : PTree.t _)
:=
local2ptree Q = (Qtemp, Qvar, nil, GV) /\
subsume_funspec fs (mk_funspec (argsig,retty) cc A Pre Post NEPre NEPost) /\
can_assume_funcptr  cs Delta P Q R' a fs /\
PROPx P (LOCALx Q (SEPx R')) |-- |> PROPx P (LOCALx Q (SEPx R)) /\
Cop.classify_fun (typeof a) = Cop.fun_case_f (type_of_params argsig) retty cc /\
ENTAIL Delta, PROPx P (LOCALx Q (SEPx R))
|-- (tc_expr Delta a)  /\
ENTAIL Delta, PROPx P (LOCALx Q (SEPx R))
|--  (tc_exprlist Delta (argtypes argsig) bl) /\
force_list (map (msubst_eval_expr Delta Qtemp Qvar GV)
(explicit_cast_exprlist (argtypes argsig) bl))
= Some vl /\
pTree_from_elements (List.combine (var_names argsig) vl) = Qactuals.

(* Specifications: *)
Lemma call_setup1_i:
forall (cs: compspecs) Delta P Q R R' (a: expr) (bl: list expr)
Qtemp Qvar GV (v: val)
fs argsig retty cc (A: rmaps.TypeTree)  Pre Post NEPre NEPost
(vl : list val)
(Qactuals : PTree.t _),
local2ptree Q = (Qtemp, Qvar, nil, GV) ->
msubst_eval_expr Delta Qtemp Qvar GV a = Some v ->
fold_right_sepcon R' |--  func_ptr fs v ->
subsume_funspec fs (mk_funspec (argsig,retty) cc A Pre Post NEPre NEPost) ->
fold_right_sepcon R' |-- |> fold_right_sepcon R ->
Cop.classify_fun (typeof a) = Cop.fun_case_f (type_of_params argsig) retty cc ->
ENTAIL Delta, PROPx P (LOCALx Q (SEPx R))
|-- (tc_expr Delta a)  ->
ENTAIL Delta, PROPx P (LOCALx Q (SEPx R))
|--  (tc_exprlist Delta (argtypes argsig) bl) ->
force_list (map (msubst_eval_expr Delta Qtemp Qvar GV)
(explicit_cast_exprlist (argtypes argsig) bl))
= Some vl ->
pTree_from_elements (List.combine (var_names argsig) vl) = Qactuals ->
call_setup1 cs Qtemp Qvar GV a Delta P Q R R' fs argsig retty cc A Pre Post NEPre NEPost bl vl Qactuals.
Lemma call_setup1_i2:
forall (cs: compspecs) Delta P Q R R' (id: ident) (ty: type) (bl: list expr)
Qtemp Qvar GV
fs argsig retty cc (A: rmaps.TypeTree)  Pre Post NEPre NEPost
(vl : list val)
(Qactuals : PTree.t _),
local2ptree Q = (Qtemp, Qvar, nil, GV) ->
can_assume_funcptr  cs Delta P Q R' (Evar id ty) fs ->
subsume_funspec fs (mk_funspec (argsig,retty) cc A Pre Post NEPre NEPost) ->
PROPx P (LOCALx Q (SEPx R')) |-- |> PROPx P (LOCALx Q (SEPx R)) ->
Cop.classify_fun ty = Cop.fun_case_f (type_of_params argsig) retty cc ->
ENTAIL Delta, PROPx P (LOCALx Q (SEPx R))
|-- (tc_expr Delta (Evar id ty))  ->
ENTAIL Delta, PROPx P (LOCALx Q (SEPx R))
|--  (tc_exprlist Delta (argtypes argsig) bl) ->
force_list (map (msubst_eval_expr Delta Qtemp Qvar GV)
(explicit_cast_exprlist (argtypes argsig) bl))
= Some vl ->
pTree_from_elements (List.combine (var_names argsig) vl) = Qactuals ->
call_setup1 cs Qtemp Qvar GV (Evar id ty) Delta P Q R R' fs argsig retty cc A Pre Post NEPre NEPost bl vl Qactuals.
Lemma can_assume_funcptr1:
forall  cs Delta P Q R a fs v Qtemp Qvar GV,
local2ptree Q = (Qtemp, Qvar, nil, GV) ->
msubst_eval_expr Delta Qtemp Qvar GV a = Some v ->
ENTAIL Delta, PROPx P (LOCALx Q (SEPx R)) |-- lift0(func_ptr fs v) ->
can_assume_funcptr cs Delta P Q R a fs.
Lemma can_assume_funcptr2:
forall id ty cs Delta P Q R fs ,
(var_types Delta) ! id = None ->
(glob_specs Delta) ! id = Some fs ->
(glob_types Delta) ! id = Some (type_of_funspec fs) ->
ty = (type_of_funspec fs) ->
can_assume_funcptr cs Delta P Q R (Evar id ty) fs.