Ltac safe_subst x := subst x.Ltac safe_subst_any := subst_any.Ltac gvar_headptr_intro_case1 gv H i :=
         match goal with
         | _ := gv i |- _ => fail 1
         | H: isptr (gv i), H': headptr (gv i) |- _ => fail 1
         | _ => generalize (H i _ ltac:(first[reflexivity | eassumption])); fancy_intro true
         end.Ltac gvar_headptr_intro_case2 gv H x i :=
         match goal with
         | H: isptr x, H': headptr x |- _ => fail 1
         | _ => generalize ((H i _ ltac:(first[reflexivity | eassumption])): headptr x); fancy_intro true
         end.Ltac gvar_headptr_intro gv H:=
  repeat
     match goal with
     | x:= gv ?i |- _ =>
         gvar_headptr_intro_case2 gv H x i
     | |- context [gv ?i] =>
         gvar_headptr_intro_case1 gv H i
     | _: context [gv ?i] |- _ =>
         gvar_headptr_intro_case1 gv H i
     | x:= context [gv ?i] |- _ =>
         gvar_headptr_intro_case1 gv H i
     end.Fixpoint remove_localdef (x: localdef) (l: list localdef) : list localdef :=
  match l with
  | nil => nil
  | y :: l0 =>
     match x, y with
     | temp i u, temp j v =>
       if Pos.eqb i j
       then remove_localdef x l0
       else y :: remove_localdef x l0
     | lvar i ti u, lvar j tj v =>
       if Pos.eqb i j
       then remove_localdef x l0
       else y :: remove_localdef x l0
     | _, _ => y :: remove_localdef x l0
     end
  end.Definition localdefs_tc (Delta: tycontext) gvar_ident (Pre: list localdef): list Prop :=
  VST_floyd_concat (VST_floyd_map (localdef_tc Delta gvar_ident) Pre).Definition msubst_extract_locals (Delta: tycontext) (T1: PTree.t val) (T2: PTree.t (type * val)) (GV: option globals) := VST_floyd_map (msubst_extract_local Delta T1 T2 GV).

(* Specifications: *)
Lemma clean_LOCAL_right_TT {cs: compspecs} (Delta : tycontext) (T1 : PTree.t val) (T2 : PTree.t (type * val)) (GV : option globals): clean_LOCAL_right Delta T1 T2 GV TT TT.
Lemma clean_LOCAL_right_FF {cs: compspecs} (Delta : tycontext) (T1 : PTree.t val) (T2 : PTree.t (type * val)) (GV : option globals): clean_LOCAL_right Delta T1 T2 GV FF FF.
Lemma clean_LOCAL_right_canon {cs: compspecs} (Delta : tycontext) (T1 : PTree.t val) (T2 : PTree.t (type * val)) (GV : option globals): forall P Q R Res, (fold_right_PROP_SEP (VST_floyd_app P (msubst_extract_locals Delta T1 T2 GV Q)) R) = Res -> clean_LOCAL_right Delta T1 T2 GV (PROPx P (LOCALx Q (SEPx R))) Res.
Lemma clean_LOCAL_right_tc_andp {cs: compspecs} (Delta : tycontext) (T1 : PTree.t val) (T2 : PTree.t (type * val)) (GV : option globals): forall P1 P2 Q1 Q2, clean_LOCAL_right Delta T1 T2 GV (denote_tc_assert P1) Q1 -> clean_LOCAL_right Delta T1 T2 GV (denote_tc_assert P2) Q2 -> clean_LOCAL_right Delta T1 T2 GV (denote_tc_assert (tc_andp P1 P2)) (Q1 && Q2).
Lemma clean_LOCAL_right_EX: forall {cs: compspecs} (Delta: tycontext) (T1: PTree.t val) (T2: PTree.t (type * val)) (GV: option globals) A (P: A -> environ -> mpred) (Q: A -> mpred), (forall a, exists Q', clean_LOCAL_right Delta T1 T2 GV (P a) Q' /\ Q' = Q a) -> clean_LOCAL_right Delta T1 T2 GV (exp P) (exp Q).