(** Non-separating conjunction *)
Program Definition mconj (P Q: massert) : massert := {|
m_pred := fun m => m_pred P m /\ m_pred Q m;
m_footprint := fun b ofs => m_footprint P b ofs \/ m_footprint Q b ofs
|}.
Next Obligation.
split.
apply (m_invar P) with m; auto. eapply Mem.unchanged_on_implies; eauto. simpl; auto.
apply (m_invar Q) with m; auto. eapply Mem.unchanged_on_implies; eauto. simpl; auto.
Qed.
Next Obligation.
destruct H0; [eapply (m_valid P) | eapply (m_valid Q)]; eauto.
Qed.

(* Specifications: *)
Lemma mconj_intro:
forall P Q R m,
m |= P ** R -> m |= Q ** R -> m |= mconj P Q ** R.
Lemma mconj_proj1:
forall P Q R m, m |= mconj P Q ** R -> m |= P ** R.
Lemma mconj_proj2:
forall P Q R m, m |= mconj P Q ** R -> m |= Q ** R.
Lemma frame_mconj:
forall P P' Q R m m',
m |= mconj P Q ** R ->
m' |= P' ** R ->
m' |= Q ->
m' |= mconj P' Q ** R.