Ltac hint_msg_aux R1 A :=
lazymatch A with
| data_at => idtac
| field_at => idtac
| data_at_ => idtac
| field_at_ => idtac
| memory_block => idtac
| @exp _ _ _ _  => idtac "
Or, perhaps you need to do [Intros x] to introduce the EXistential" R1 "in your SEP clause."
| _ _ => idtac
| _ => idtac "
Or, perhaps the definition [" A "] needs to be unfolded so that your SEP conjuct" R1 "can be used effectively."
end.
Ltac hint_msg_aux2 R p2 :=
match R with
| nil => idtac
| ?R1 :: ?R' =>
lazymatch R1 with
| ?A _ _ _ _ _ _ _ _ _ _ p2 => hint_msg_aux R1 A
| ?A _ _ _ _ _ _ _ _ _ p2 => hint_msg_aux R1 A
| ?A _ _ _ _ _ _ _ _ p2 => hint_msg_aux R1 A
| ?A _ _ _ _ _ _ _ p2 => hint_msg_aux R1 A
| ?A _ _ _ _ _ _ p2 => hint_msg_aux R1 A
| ?A _ _ _ _ _ p2 => hint_msg_aux R1 A
| ?A _ _ _ _ p2 => hint_msg_aux R1 A
| ?A _ _ _ p2 => hint_msg_aux R1 A
| ?A _ _ p2 => hint_msg_aux R1 A
| ?A _ p2 => hint_msg_aux R1 A
| ?A p2 => hint_msg_aux R1 A
| context [p2] => hint_msg_aux R1 R1
| _ => idtac
end;
hint_msg_aux2 R' p2
end.
Ltac hint_msg LOCAL2PTREE Delta e :=
match goal with |- semax _ (|> PROPx _ (LOCALx _ (SEPx ?R))) _ _ =>
eapply (hint_msg_lemma Delta e);
[ exact LOCAL2PTREE
| reflexivity
| solve_msubst_eval_lvalue
| solve_msubst_eval_LR
| solve_msubst_efield_denote
| econstructor
| solve_field_address_gen
| ];
match goal with
| |- ?eq1 /\ ?eq2 /\ False =>
match eq1 with ?p1 = field_address _ _ ?p =>
try match p1 with offset_val _ ?p2 => hint_msg_aux2 R p2 end;
first [ constr_eq eq1 eq2;
fail 1000 "
It is not obvious how to move forward here.  One way:
Find a SEP clause of the form [data_at _ _ _ " p"] (or field_at, data_at_, field_at_),
then use assert_PROP to prove an equality of the form" eq1 ", then try [forward] again."
| fail 1000 "
It is not obvious how to move forward here.  One way:
Find a SEP clause of the form [data_at _ _ _ " p"] (or field_at, data_at_, field_at_),
then use assert_PROP to prove an equality of the form" eq1
"or if this does not hold, prove an equality of the form" eq2 ", then try [forward] again."
]
end
end
end.
Section SEMAX_PTREE.
Context {cs: compspecs}.

(* Specifications: *)
Lemma semax_PTree_set:
forall {Espec: OracleKind},
forall Delta id P Q R T1 T2 GV (e2: expr) t v,
local2ptree Q = (T1, T2, nil, GV) ->
typeof_temp Delta id = Some t ->
is_neutral_cast (implicit_deref (typeof e2)) t = true ->
msubst_eval_expr Delta T1 T2 GV e2 = Some v ->
ENTAIL Delta, PROPx P (LOCALx Q (SEPx R)) |--
(tc_expr Delta e2) ->
semax Delta (|>PROPx P (LOCALx Q (SEPx R)))
(Sset id e2)
(normal_ret_assert
(PROPx P
(LOCALx (temp id v :: remove_localdef_temp id Q)
(SEPx R)))).
Lemma semax_PTree_field_load_no_hint:
forall {Espec: OracleKind},
forall n Rn Delta sh id P Q R (e: expr) t
T1 T2 GV e_root (efs: list efield) lr
t_root_from_e gfs_from_e p_from_e
(t_root: type) (gfs0 gfs1 gfs: list gfield) (p: val)
(v : val) (v' : reptype (nested_field_type t_root gfs0)),
local2ptree Q = (T1, T2, nil, GV) ->
compute_nested_efield e = (e_root, efs, lr) ->
typeof_temp Delta id = Some t ->
is_neutral_cast (typeof e) t = true ->
type_is_volatile (typeof e) = false ->
msubst_eval_LR Delta T1 T2 GV e_root lr = Some p_from_e ->
msubst_efield_denote Delta T1 T2 GV efs gfs_from_e ->
compute_root_type (typeof e_root) lr t_root_from_e ->
field_address_gen (t_root_from_e, gfs_from_e, p_from_e) (t_root, gfs, p) ->
find_nth_preds (fun Rn => Rn = field_at sh t_root gfs0 v' p /\ gfs = gfs1 ++ gfs0) R (Some (n, Rn)) ->
readable_share sh ->
JMeq (proj_reptype (nested_field_type t_root gfs0) gfs1 v') v ->
ENTAIL Delta, PROPx P (LOCALx Q (SEPx R)) |--
!! (legal_nested_field (nested_field_type t_root gfs0) gfs1) ->
ENTAIL Delta, PROPx P (LOCALx Q (SEPx R)) |--
local `(tc_val (typeof e) v) ->
ENTAIL Delta, PROPx P (LOCALx Q (SEPx R)) |--
denote_tc_assert
(tc_andp (typecheck_LR Delta e_root lr) (typecheck_efield Delta efs)) ->
semax Delta (|>PROPx P (LOCALx Q (SEPx R)))
(Sset id e)
(normal_ret_assert
(PROPx P
(LOCALx (temp id v :: remove_localdef_temp id Q)
(SEPx R)))).
Lemma semax_PTree_field_load_with_hint:
forall {Espec: OracleKind},
forall n Rn Delta sh id P Q R (e: expr) t
T1 T2 GV p_from_e
(t_root: type) (gfs0 gfs1 gfs: list gfield) (p: val)
(v_val : val) (v_reptype : reptype (nested_field_type t_root gfs0)),
local2ptree Q = (T1, T2, nil, GV) ->
typeof_temp Delta id = Some t ->
is_neutral_cast (typeof e) t = true ->
type_is_volatile (typeof e) = false ->
msubst_eval_lvalue Delta T1 T2 GV e = Some p_from_e ->
p_from_e = field_address t_root gfs p ->
typeof e = nested_field_type t_root gfs ->
find_nth_preds (fun Rn => Rn = field_at sh t_root gfs0 v_reptype p /\ gfs = gfs1 ++ gfs0) R (Some (n, Rn)) ->
readable_share sh ->
JMeq (proj_reptype (nested_field_type t_root gfs0) gfs1 v_reptype) v_val ->
ENTAIL Delta, PROPx P (LOCALx Q (SEPx R)) |--
local (`(tc_val (typeof e) v_val)) ->
ENTAIL Delta, PROPx P (LOCALx Q (SEPx R)) |--
tc_lvalue Delta e ->
@semax cs Espec Delta (|> PROPx P (LOCALx Q (SEPx R)))
(Sset id e)
(normal_ret_assert
(PROPx P
(LOCALx (temp id v_val :: remove_localdef_temp id Q)
(SEPx R)))).
Lemma semax_PTree_field_cast_load_no_hint:
forall {Espec: OracleKind},
forall n Rn Delta sh id P Q R (e: expr) t
T1 T2 GV e_root (efs: list efield) lr
t_root_from_e gfs_from_e p_from_e
(t_root: type) (gfs0 gfs1 gfs: list gfield) (p: val)
(v : val) (v' : reptype (nested_field_type t_root gfs0)),
local2ptree Q = (T1, T2, nil, GV) ->
compute_nested_efield e = (e_root, efs, lr) ->
typeof_temp Delta id = Some t ->
type_is_by_value (typeof e) = true ->
type_is_volatile (typeof e) = false ->
cast_pointer_to_bool (typeof e) t = false ->
msubst_eval_LR Delta T1 T2 GV e_root lr = Some p_from_e ->
msubst_efield_denote Delta T1 T2 GV efs gfs_from_e ->
compute_root_type (typeof e_root) lr t_root_from_e ->
field_address_gen (t_root_from_e, gfs_from_e, p_from_e) (t_root, gfs, p) ->
find_nth_preds (fun Rn => Rn = field_at sh t_root gfs0 v' p /\ gfs = gfs1 ++ gfs0) R (Some (n, Rn)) ->
readable_share sh ->
JMeq (proj_reptype (nested_field_type t_root gfs0) gfs1 v') v ->
ENTAIL Delta, PROPx P (LOCALx Q (SEPx R)) |--
!! (legal_nested_field (nested_field_type t_root gfs0) gfs1) ->
ENTAIL Delta, PROPx P (LOCALx Q (SEPx R)) |--
local `(tc_val t (eval_cast (typeof e) t v)) ->
ENTAIL Delta, PROPx P (LOCALx Q (SEPx R)) |--
denote_tc_assert
(tc_andp (typecheck_LR Delta e_root lr) (typecheck_efield Delta efs)) ->
semax Delta (|>PROPx P (LOCALx Q (SEPx R)))
(Sset id (Ecast e t))
(normal_ret_assert
(PROPx P
(LOCALx (temp id (eval_cast (typeof e) t v) :: remove_localdef_temp id Q)
(SEPx R)))).
Lemma semax_PTree_field_cast_load_with_hint:
forall {Espec: OracleKind},
forall n Rn Delta sh id P Q R (e: expr) t
T1 T2 GV p_from_e
(t_root: type) (gfs0 gfs1 gfs: list gfield) (p: val)
(v_val : val) (v_reptype : reptype (nested_field_type t_root gfs0)),
local2ptree Q = (T1, T2, nil, GV) ->
typeof_temp Delta id = Some t ->
type_is_by_value (typeof e) = true ->
type_is_volatile (typeof e) = false ->
cast_pointer_to_bool (typeof e) t = false ->
msubst_eval_lvalue Delta T1 T2 GV e = Some p_from_e ->
p_from_e = field_address t_root gfs p ->
typeof e = nested_field_type t_root gfs ->
find_nth_preds (fun Rn => Rn = field_at sh t_root gfs0 v_reptype p /\ gfs = gfs1 ++ gfs0) R (Some (n, Rn)) ->
readable_share sh ->
JMeq (proj_reptype (nested_field_type t_root gfs0) gfs1 v_reptype) v_val ->
ENTAIL Delta, PROPx P (LOCALx Q (SEPx R)) |--
local (`(tc_val t (eval_cast (typeof e) t v_val))) ->
ENTAIL Delta, PROPx P (LOCALx Q (SEPx R)) |--
tc_lvalue Delta e ->
@semax cs Espec Delta (|> PROPx P (LOCALx Q (SEPx R)))
(Sset id (Ecast e t))
(normal_ret_assert
(PROPx P
(LOCALx (temp id (eval_cast (typeof e) t v_val) :: remove_localdef_temp id Q)
(SEPx R)))).
Lemma semax_PTree_field_store_no_hint:
forall {Espec: OracleKind},
forall n Rn Delta sh P Q R (e1 e2 : expr)
T1 T2 GV e_root (efs: list efield) lr
t_root_from_e gfs_from_e p_from_e
(t_root: type) (gfs0 gfs1 gfs: list gfield) (p: val)
(v0: reptype (nested_field_type (nested_field_type t_root gfs0) gfs1))
(v0_val: val) Rv (v v_new: reptype (nested_field_type t_root gfs0)),
local2ptree Q = (T1, T2, nil, GV) ->
compute_nested_efield e1 = (e_root, efs, lr) ->
type_is_by_value (typeof e1) = true ->
type_is_volatile (typeof e1) = false ->
msubst_eval_expr Delta T1 T2 GV (Ecast e2 (typeof e1)) = Some v0_val ->
msubst_eval_LR Delta T1 T2 GV e_root lr = Some p_from_e ->
msubst_efield_denote Delta T1 T2 GV efs gfs_from_e ->
compute_root_type (typeof e_root) lr t_root_from_e ->
field_address_gen (t_root_from_e, gfs_from_e, p_from_e) (t_root, gfs, p) ->
find_nth_preds (fun Rn => (Rn = Rv v /\ (Rv = fun v => field_at sh t_root gfs0 v p)) /\ gfs = gfs1 ++ gfs0) R (Some (n, Rn)) ->
writable_share sh ->
JMeq v0_val v0 ->
data_equal (upd_reptype (nested_field_type t_root gfs0) gfs1 v v0) v_new ->
ENTAIL Delta, PROPx P (LOCALx Q (SEPx R)) |--
denote_tc_assert
(tc_andp (typecheck_LR Delta e_root lr)
(tc_andp (typecheck_expr Delta (Ecast e2 (typeof e1)))
(typecheck_efield Delta efs))) ->
ENTAIL Delta, PROPx P (LOCALx Q (SEPx R)) |--
!! (legal_nested_field (nested_field_type t_root gfs0) gfs1) ->
semax Delta (|>PROPx P (LOCALx Q (SEPx R)))
(Sassign e1 e2)
(normal_ret_assert
(PROPx P
(LOCALx Q
(SEPx
(replace_nth n R (Rv v_new)))))).
Lemma semax_PTree_field_store_with_hint:
forall {Espec: OracleKind},
forall n Rn Delta sh P Q R (e1 e2 : expr)
T1 T2 GV p_from_e
(t_root: type) (gfs0 gfs1 gfs: list gfield) (p: val)
(v0: reptype (nested_field_type (nested_field_type t_root gfs0) gfs1))
(v0_val: val) Rv (v v_new: reptype (nested_field_type t_root gfs0)),
local2ptree Q = (T1, T2, nil, GV) ->
type_is_by_value (typeof e1) = true ->
type_is_volatile (typeof e1) = false ->
msubst_eval_expr Delta T1 T2 GV (Ecast e2 (typeof e1)) = Some v0_val ->
msubst_eval_lvalue Delta T1 T2 GV e1 = Some p_from_e ->
p_from_e = field_address t_root gfs p ->
typeof e1 = nested_field_type t_root gfs ->
find_nth_preds (fun Rn => (Rn = Rv v /\ (Rv = fun v => field_at sh t_root gfs0 v p)) /\ gfs = gfs1 ++ gfs0) R (Some (n, Rn)) ->
writable_share sh ->
JMeq v0_val v0 ->
data_equal (upd_reptype (nested_field_type t_root gfs0) gfs1 v v0) v_new ->
ENTAIL Delta, PROPx P (LOCALx Q (SEPx R)) |--
denote_tc_assert
(tc_andp (typecheck_lvalue Delta e1) (typecheck_expr Delta (Ecast e2 (typeof e1)))) ->
semax Delta (|>PROPx P (LOCALx Q (SEPx R)))
(Sassign e1 e2)
(normal_ret_assert
(PROPx P
(LOCALx Q
(SEPx
(replace_nth n R
(field_at sh t_root gfs0 v_new p)))))).