Local Open Scope logic.
Definition msubst_simpl_tc_assert (T1: PTree.t val): tc_assert -> tc_assert :=
fix msubst_simpl_tc_assert (tc: tc_assert): tc_assert :=
match tc with
| tc_andp' tc1 tc2 => tc_andp (msubst_simpl_tc_assert tc1) (msubst_simpl_tc_assert tc2)
| tc_orp' tc1 tc2 => tc_orp (msubst_simpl_tc_assert tc1) (msubst_simpl_tc_assert tc2)
| tc_initialized i _ => match T1 ! i with Some _ => tc_TT | None => tc_FF miscellaneous_typecheck_error end
| _ => tc
end.
Section MSUBST_DENOTE_TC_ASSERT.
Context {cs: compspecs} (Delta: tycontext) (T1: PTree.t val) (T2: PTree.t (type * val)) (GV: option globals).
Fixpoint msubst_denote_tc_assert (tc: tc_assert): mpred :=
match tc with
| tc_FF msg => !! (typecheck_error msg)
| tc_TT => TT
| tc_andp' b c => (msubst_denote_tc_assert b) && (msubst_denote_tc_assert c)
| tc_orp' b c => (msubst_denote_tc_assert b) || (msubst_denote_tc_assert c)
| tc_nonzero' e => denote_tc_nonzero (force_val (msubst_eval_expr Delta T1 T2 GV e))
| tc_isptr e => denote_tc_isptr (force_val (msubst_eval_expr Delta T1 T2 GV e))
| tc_isint e => denote_tc_isint (force_val (msubst_eval_expr Delta T1 T2 GV e))
| tc_islong e => denote_tc_islong (force_val (msubst_eval_expr Delta T1 T2 GV e))
| tc_test_eq' e1 e2 => denote_tc_test_eq (force_val (msubst_eval_expr Delta T1 T2 GV e1)) (force_val (msubst_eval_expr Delta T1 T2 GV e2))
| tc_test_order' e1 e2 => denote_tc_test_order (force_val (msubst_eval_expr Delta T1 T2 GV e1)) (force_val (msubst_eval_expr Delta T1 T2 GV e2))
| tc_ilt' e i => denote_tc_igt i (force_val (msubst_eval_expr Delta T1 T2 GV e))
| tc_llt' e i => denote_tc_lgt i (force_val (msubst_eval_expr Delta T1 T2 GV e))
| tc_Zle e z => denote_tc_Zge z (force_val (msubst_eval_expr Delta T1 T2 GV e))
| tc_Zge e z => denote_tc_Zle z (force_val (msubst_eval_expr Delta T1 T2 GV e))
| tc_samebase e1 e2 => denote_tc_samebase (force_val (msubst_eval_expr Delta T1 T2 GV e1)) (force_val (msubst_eval_expr Delta T1 T2 GV e2))
| tc_nodivover' v1 v2 => denote_tc_nodivover (force_val (msubst_eval_expr Delta T1 T2 GV v1)) (force_val (msubst_eval_expr Delta T1 T2 GV v2))
| tc_initialized id ty => FF
| tc_iszero' e => denote_tc_iszero (force_val (msubst_eval_expr Delta T1 T2 GV e))
| tc_nosignedover op e1 e2 => denote_tc_nosignedover op (force_val (msubst_eval_expr Delta T1 T2 GV e1)) (force_val (msubst_eval_expr Delta T1 T2 GV e2))
end.
Definition msubst_tc_lvalue (e: expr) :=
msubst_denote_tc_assert (msubst_simpl_tc_assert T1 (typecheck_lvalue Delta e)).
Definition msubst_tc_expr (e: expr) :=
msubst_denote_tc_assert (msubst_simpl_tc_assert T1 (typecheck_expr Delta e)).
Definition msubst_tc_LR (e: expr) (lr: LLRR) :=
msubst_denote_tc_assert (msubst_simpl_tc_assert T1 (typecheck_LR Delta e lr)).
Definition msubst_tc_efield (efs: list efield) :=
msubst_denote_tc_assert (msubst_simpl_tc_assert T1 (typecheck_efield Delta efs)).
Definition msubst_tc_exprlist (ts: list type) (es: list expr) :=
msubst_denote_tc_assert (msubst_simpl_tc_assert T1 (typecheck_exprlist Delta ts es)).
Definition msubst_tc_expropt (e: option expr) (t: type) :=
msubst_denote_tc_assert (msubst_simpl_tc_assert T1
(match e with
| None => tc_bool (eqb_type t Tvoid) wrong_signature
| Some e' => typecheck_expr Delta (Ecast e' t)
end)).
(* Soundness proof *)

Lemma msubst_denote_tc_assert_sound: forall P R tc,
local (tc_environ Delta) && PROPx P (LOCALx (LocalD T1 T2 GV) (SEPx R)) && `(msubst_denote_tc_assert tc) |--
denote_tc_assert tc.