Tactic Notation "forward_while" constr(Inv) :=
repeat (apply -> seq_assoc; abbreviate_semax);
lazymatch goal with |- semax _ _ (Ssequence _ _) _ => idtac | _ => apply <- semax_seq_skip end;
first [ignore (Inv: environ->mpred)
| fail 1 "Invariant (first argument to forward_while) must have type (environ->mpred)"];
apply semax_pre with Inv;
[ unfold_function_derives_right
| repeat match goal with
| |- semax _ (exp _) _ _ => fail 1
| |- semax _ (PROPx _ _) _ _ => fail 1
| |- semax _ ?Pre _ _ => match Pre with context [ ?F ] => unfold F end
end;
match goal with
| |- semax _ (exp (fun a1 => _)) _ _ =>
let a := fresh a1 in pose (a := EXP_NAME)
| |- semax _ (PROPx ?P ?QR) _ _ =>
let a := fresh "u" in pose (a := EXP_UNIT);
rewrite (trivial_exp (PROPx P QR))
end;
repeat match goal with |- semax _ (exp (fun a1 => (exp (fun a2 => _)))) _ _ =>
let a := fresh a2 in pose (a := EXP_NAME);
rewrite exp_uncurry
end;
eapply semax_seq;
[match goal with |- semax ?Delta ?Pre (Swhile ?e _) _ =>
(* the following line was before: eapply semax_while_3g1; *)
match goal with [ |- semax _ (@exp _ _ ?A _) _ _ ] => eapply (@semax_while_3g1 _ _ A) end;
(* check if we can revert back to the previous version with coq 8.5. (as of December 2015 with compcert 2.6 the above fix is still necessary) The bug happens when we destruct the existential variable of the loop invariant:  (* example.c program: *)
int main(){int i=0; while(i);}
(* verif_example.v file (+you have to Require Import the example.v file produced by clightgen) *)
Instance CompSpecs : compspecs. Proof. make_compspecs prog. Defined.
Local Open Scope logic.

(* Specifications: *)
Lemma body_main : semax_body [] [] f_main
(DECLARE _main WITH u : unit
PRE  [] main_pre prog u
POST [ tint ] main_post prog u).