Section VAL_CASTED.
Inductive val_casted: val -> type -> Prop :=
| val_casted_int: forall sz si attr n,
cast_int_int sz si n = n ->
val_casted (Vint n) (Tint sz si attr)
| val_casted_float: forall attr n,
val_casted (Vfloat n) (Tfloat F64 attr)
| val_casted_single: forall attr n,
val_casted (Vsingle n) (Tfloat F32 attr)
| val_casted_long: forall si attr n,
val_casted (Vlong n) (Tlong si attr)
| val_casted_ptr_ptr: forall b ofs ty attr,
val_casted (Vptr b ofs) (Tpointer ty attr)
| val_casted_int_ptr: forall n ty attr,
Archi.ptr64 = false -> val_casted (Vint n) (Tpointer ty attr)
| val_casted_ptr_int: forall b ofs si attr,
Archi.ptr64 = false -> val_casted (Vptr b ofs) (Tint I32 si attr)
| val_casted_long_ptr: forall n ty attr,
Archi.ptr64 = true -> val_casted (Vlong n) (Tpointer ty attr)
| val_casted_ptr_long: forall b ofs si attr,
Archi.ptr64 = true -> val_casted (Vptr b ofs) (Tlong si attr)
| val_casted_struct: forall id attr b ofs,
val_casted (Vptr b ofs) (Tstruct id attr)
| val_casted_union: forall id attr b ofs,
val_casted (Vptr b ofs) (Tunion id attr)
| val_casted_void: forall v,
val_casted v Tvoid.
Local Hint Constructors val_casted : core.
Remark cast_int_int_idem:
forall sz sg i, cast_int_int sz sg (cast_int_int sz sg i) = cast_int_int sz sg i.
Ltac DestructCases :=
match goal with
| [H: match match ?x with _ => _ end with _ => _ end = Some _ |- _ ] => destruct x eqn:?; DestructCases
| [H: match ?x with _ => _ end = Some _ |- _ ] => destruct x eqn:?; DestructCases
| [H: Some _ = Some _ |- _ ] => inv H; DestructCases
| [H: None = Some _ |- _ ] => discriminate H
| [H: @eq intsize _ _ |- _ ] => discriminate H || (clear H; DestructCases)
| [ |- val_casted (Vint (if ?x then Int.zero else Int.one)) _ ] =>
try (constructor; destruct x; reflexivity)
| [ |- val_casted (Vint _) (Tint ?sz ?sg _) ] =>
try (constructor; apply (cast_int_int_idem sz sg))
| _ => idtac
end.
End VAL_CASTED.
(** As a consequence, casting twice is equivalent to casting once. *)

Lemma cast_idempotent:
forall v ty ty' v' m, sem_cast v ty ty' m = Some v' -> sem_cast v' ty' ty' m = Some v'.