Ltac ghost_alloc G :=
  match goal with |-semax _ (PROPx ?P (LOCALx ?Q (SEPx ?R))) _ _ =>
    apply (semax_pre_bupd (PROPx P (LOCALx Q (SEPx ((EX g : _, G g) :: R)))));
  [go_lower; rewrite !prop_true_andp by (repeat (split; auto));
   rewrite <- emp_sepcon at 1; eapply derives_trans, bupd_frame_r;
   apply sepcon_derives, derives_refl; apply own_alloc; auto; simpl; auto with init|] end.(* weak view shift for use in funspecs *)
(* This could be replaced with P -* |==> Q. *)
Program Definition weak_view_shift (P Q: mpred): mpred :=
  fun w => predicates_hered.derives (approx (S (level w)) P) (own.bupd (approx (S (level w)) Q)).

(* Specifications: *)
Lemma view_shift_nonexpansive: forall P Q n, approx n (weak_view_shift P Q) = approx n (weak_view_shift (approx n P) (approx n Q)).
Lemma view_shift_nonexpansive_l: forall P Q n, approx n (weak_view_shift P Q) = approx n (weak_view_shift (approx n P) Q).
Lemma view_shift_nonexpansive_R: forall P Q n, approx n (weak_view_shift P Q) = approx n (weak_view_shift P (approx n Q)).