Inductive return_inner_gen (S: list mpred): option val -> (environ -> mpred) -> (environ -> mpred) -> Prop :=
| return_inner_gen_main: forall ov_gen P ts u,
return_inner_gen S ov_gen (main_post P ts u) (PROPx nil (LOCALx nil (SEPx (TT :: S))))
| return_inner_gen_canon_nil':
forall ov_gen P R,
return_inner_gen S ov_gen
(PROPx P (LOCALx nil (SEPx R)))
(PROPx P (LOCALx nil (SEPx (R ++ S))))
| return_inner_gen_canon_Some':
forall P v R v_gen,
return_inner_gen S (Some v_gen)
(PROPx P (LOCALx (temp ret_temp v :: nil) (SEPx R)))
(PROPx (P ++ (v_gen = v) :: nil) (LOCALx nil (SEPx (R ++ S))))
| return_inner_gen_EX':
forall ov_gen (A: Type) (post1 post2: A -> environ -> mpred),
(forall a: A, return_inner_gen S ov_gen (post1 a) (post2 a)) ->
return_inner_gen S ov_gen (exp post1) (exp post2).

Lemma semax_return_Some: forall {cs Espec} Delta Ppre Qpre Rpre Post1 sf SEPsf post2 post3 ret v_gen,
ENTAIL Delta, PROPx Ppre (LOCALx Qpre (SEPx Rpre)) |-- local (`(eq v_gen) (eval_expr (Ecast ret (ret_type Delta)))) ->
ENTAIL Delta, PROPx Ppre (LOCALx Qpre (SEPx Rpre)) |-- tc_expr Delta (Ecast ret (ret_type Delta)) ->
return_outer_gen Post1 (frame_ret_assert (function_body_ret_assert (ret_type Delta) post2) sf) ->
ENTAIL Delta, PROPx Ppre (LOCALx Qpre (SEPx SEPsf)) |-- sf ->
return_inner_gen SEPsf (Some v_gen) post2 post3 ->
ENTAIL Delta, PROPx Ppre (LOCALx Qpre (SEPx Rpre)) |-- post3 ->
@semax cs Espec Delta (PROPx Ppre (LOCALx Qpre (SEPx Rpre))) (Sreturn (Some ret)) Post1.