Local Open Scope logic.
(* PROOF AUTOMATION FOR SEMAX *)
Hint Extern 3 (inlist _ _ = false) => (compute; reflexivity).
Ltac compute_neq := solve [let H := fresh in intro H; inversion H].
Hint Rewrite arguments_gss : args.
Hint Rewrite arguments_gso using compute_neq : args.
Ltac call_tac := unfold call; simpl; autorewrite with args; simpl.
Ltac funassert_tac :=
match goal with
| |-   ?A && ?B |-- _ =>
match A with context [funassert _] => apply andp_left1; funassert_tac  end ||
match B with context [funassert _] => apply andp_left2; funassert_tac  end
| |- funassert _ |-- _ => apply funassert_e; simpl; reflexivity
end.
Ltac func_tac :=
apply semax_func_cons;
[ compute; reflexivity | compute; reflexivity | compute; reflexivity
|  (*eapply semax_pre; [intro ; call_tac; apply derives_refl | ] *)
| ].
Ltac rewrite' H := eapply semax_pre; [ intro; rewrite H; apply derives_refl | ].
(* This tactic works but introduces magic wands, which is undesirable *)
Ltac forward_magic :=
match goal with |- semax _ ?G ?P (Assign (Mem ?e1) ?e2 ?c) =>
let v := fresh "v" in
(evar (v:adr);
apply semax_pre with (P' := fun s => mapsto (eval e1 s) v * (mapsto (eval e1 s) v -* P s));
[intro | apply semax_store; auto  ] );
unfold v; clear v
end.
Hint Resolve now_later sepcon_derives.
Definition semax_body (G: funspecs) (spec: funspec) (f: list var * control) :=
semax (fst f) G (fun s => call spec (map s (fst f))) (snd f).

Lemma semax_store_next: forall x y v c vars G (Q P: assert),
expcheck vars x = true ->
expcheck vars y = true ->
Q = (fun s => next (eval x s) v  * P s) ->
semax vars G (fun s => next (eval x s) (eval y s) * P s) c ->
semax vars G Q  (Do Mem x  := y ; c).