Ltac unfold_localdef_name QQ Q :=
match Q with
| nil => idtac
| cons ?Qh ?Qt =>
match Qh with
| temp ?n _ => unfold n in QQ
| lvar ?n _ _ => unfold n in QQ
| _ => idtac
end;
unfold_localdef_name QQ Qt
end.
Ltac unify_for_go_lower :=
match goal with |- fold_right_PROP_SEP (VST_floyd_app ?A ?B) ?C = _ =>
repeat match B with context [(?x = ?y) :: _] =>
has_evar x; progress (unify x y)
end
end.
Ltac simply_msubst_extract_locals :=
unfold msubst_extract_locals, msubst_extract_local, VST_floyd_map;
cbv iota zeta beta;
simpl_PTree_get; simpl_eqb_type.
Ltac solve_clean_LOCAL_right :=
solve
[ simple apply clean_LOCAL_right_sep_lift
| simple apply clean_LOCAL_right_local_lift
| simple apply clean_LOCAL_right_prop
| simple apply clean_LOCAL_right_TT
| simple apply clean_LOCAL_right_FF
| try unfold tc_lvalue; simple apply clean_LOCAL_right_tc_lvalue
| try unfold tc_expr; simple apply clean_LOCAL_right_tc_expr
| try unfold tc_LR; simple apply clean_LOCAL_right_tc_LR
| try unfold tc_efield; simple apply clean_LOCAL_right_tc_efield
| try unfold tc_exprlist; simple apply clean_LOCAL_right_tc_exprlist
| simple apply clean_LOCAL_right_tc_expropt
| simple apply clean_LOCAL_right_canon;
simply_msubst_extract_locals;
unify_for_go_lower;
unfold VST_floyd_app;
unfold fold_right_PROP_SEP, fold_right_and_True;
unfold fold_right_sepcon; fold fold_right_sepcon; rewrite ?sepcon_emp;
reflexivity
| simple apply clean_LOCAL_right_eval_lvalue; solve_msubst_eval_lvalue
| simple apply clean_LOCAL_right_eval_expr; solve_msubst_eval_expr
| simple apply clean_LOCAL_right_andp; solve_clean_LOCAL_right
| simple apply clean_LOCAL_right_tc_andp; solve_clean_LOCAL_right
| simple apply clean_LOCAL_right_EX;
let a := fresh "a" in
intro a;
eexists;
split;
[ solve_clean_LOCAL_right
| match goal with
| |- ?t = _ => super_pattern t a; reflexivity
end
]
| fail 1000 "The right hand side is messed up; perhaps you inadvertently did something like 'simpl in *' that changes POSTCONDITION into a form that Floyd cannot recognize.  You may do 'unfold abbreviate in POSTCONDITION' in your previous proof steps to inspect it"
].
Ltac eapply_clean_LOCAL_right_spec_rec gv L :=
match goal with
| |- context [gv ?i] =>
match L with
| context [i] => fail 1
| _ => eapply_clean_LOCAL_right_spec_rec gv (@cons ident i L)
end
| _ := gv ?i |- _ =>
match L with
| context [i] => fail 1
| _ => eapply_clean_LOCAL_right_spec_rec gv (@cons ident i L)
end
| _ => match goal with
| |- _ |-- |==> _ => eapply (clean_LOCAL_right_bupd_spec L)
| _ => eapply (clean_LOCAL_right_spec L)
end
end.
Ltac eapply_clean_LOCAL_right_spec :=
match goal with
| |- context [gvars ?gv] => eapply_clean_LOCAL_right_spec_rec gv (@nil ident)
| _ => match goal with
| |- _ |-- |==> _ => eapply (clean_LOCAL_right_bupd_spec nil)
| _ => eapply (clean_LOCAL_right_spec nil)
end
end.
Ltac simpl_app_localdefs_tc :=
unfold localdefs_tc, localdef_tc;
unfold VST_floyd_map, VST_floyd_concat, VST_floyd_app;
cbv iota zeta beta;
simpl_temp_types_get;
cbv iota zeta beta.
Ltac clean_LOCAL_canon_mix :=
eapply_clean_LOCAL_right_spec;
[reflexivity | prove_local2ptree | solve_clean_LOCAL_right | simpl_app_localdefs_tc].

Lemma is_int_Vint_intro: forall sz sg v (P: Prop),
((exists i, v = Vint i /\ is_int sz sg (Vint i)) -> P) ->
(is_int sz sg v -> P).