Refactor Sil.exp to Exp.t

Summary: Create Exp module and refactor Sil.exp to Exp.t

Reviewed By: cristianoc

Differential Revision: D3669394

fbshipit-source-id: 1f52a90
master
Josh Berdine 8 years ago committed by Facebook Github Bot 8
parent 6ffe204252
commit 701eb20f83

@ -347,7 +347,7 @@ let module Node = {
switch instr { switch instr {
| Sil.Call _ exp _ _ _ => | Sil.Call _ exp _ _ _ =>
switch exp { switch exp {
| Sil.Const (Const.Cfun procname) => [procname, ...callees] | Exp.Const (Const.Cfun procname) => [procname, ...callees]
| _ => callees | _ => callees
} }
| _ => callees | _ => callees
@ -656,7 +656,7 @@ let module Node = {
let convert_pvar pvar => Pvar.mk (Pvar.get_name pvar) resolved_proc_name; let convert_pvar pvar => Pvar.mk (Pvar.get_name pvar) resolved_proc_name;
let convert_exp = let convert_exp =
fun fun
| Sil.Lvar origin_pvar => Sil.Lvar (convert_pvar origin_pvar) | Exp.Lvar origin_pvar => Exp.Lvar (convert_pvar origin_pvar)
| exp => exp; | exp => exp;
let extract_class_name = let extract_class_name =
fun fun
@ -670,7 +670,7 @@ let module Node = {
}; };
let convert_instr instrs => let convert_instr instrs =>
fun fun
| Sil.Letderef id (Sil.Lvar origin_pvar as origin_exp) origin_typ loc => { | Sil.Letderef id (Exp.Lvar origin_pvar as origin_exp) origin_typ loc => {
let (_, specialized_typ) = { let (_, specialized_typ) = {
let pvar_name = Pvar.get_name origin_pvar; let pvar_name = Pvar.get_name origin_pvar;
try (IList.find (fun (n, _) => Mangled.equal n pvar_name) substitutions) { try (IList.find (fun (n, _) => Mangled.equal n pvar_name) substitutions) {
@ -680,7 +680,7 @@ let module Node = {
subst_map := Ident.IdentMap.add id specialized_typ !subst_map; subst_map := Ident.IdentMap.add id specialized_typ !subst_map;
[Sil.Letderef id (convert_exp origin_exp) specialized_typ loc, ...instrs] [Sil.Letderef id (convert_exp origin_exp) specialized_typ loc, ...instrs]
} }
| Sil.Letderef id (Sil.Var origin_id as origin_exp) origin_typ loc => { | Sil.Letderef id (Exp.Var origin_id as origin_exp) origin_typ loc => {
let updated_typ = let updated_typ =
switch (Ident.IdentMap.find origin_id !subst_map) { switch (Ident.IdentMap.find origin_id !subst_map) {
| Typ.Tptr typ _ => typ | Typ.Tptr typ _ => typ
@ -700,8 +700,8 @@ let module Node = {
} }
| Sil.Call | Sil.Call
return_ids return_ids
(Sil.Const (Const.Cfun (Procname.Java callee_pname_java))) (Exp.Const (Const.Cfun (Procname.Java callee_pname_java)))
[(Sil.Var id, _), ...origin_args] [(Exp.Var id, _), ...origin_args]
loc loc
call_flags call_flags
when call_flags.CallFlags.cf_virtual && redirected_class_name id != None => { when call_flags.CallFlags.cf_virtual && redirected_class_name id != None => {
@ -711,10 +711,10 @@ let module Node = {
(Procname.Java callee_pname_java) (extract_class_name redirected_typ) (Procname.Java callee_pname_java) (extract_class_name redirected_typ)
and args = { and args = {
let other_args = IList.map (fun (exp, typ) => (convert_exp exp, typ)) origin_args; let other_args = IList.map (fun (exp, typ) => (convert_exp exp, typ)) origin_args;
[(Sil.Var id, redirected_typ), ...other_args] [(Exp.Var id, redirected_typ), ...other_args]
}; };
let call_instr = let call_instr =
Sil.Call return_ids (Sil.Const (Const.Cfun redirected_pname)) args loc call_flags; Sil.Call return_ids (Exp.Const (Const.Cfun redirected_pname)) args loc call_flags;
[call_instr, ...instrs] [call_instr, ...instrs]
} }
| Sil.Call return_ids origin_call_exp origin_args loc call_flags => { | Sil.Call return_ids origin_call_exp origin_args loc call_flags => {
@ -871,7 +871,7 @@ let get_name_of_objc_static_locals (curr_f: Procdesc.t) p => {
let local_static e => let local_static e =>
switch e { switch e {
/* is a local static if it's a global and it has a static local name */ /* is a local static if it's a global and it has a static local name */
| Sil.Lvar pvar when Pvar.is_global pvar && Sil.is_static_local_name pname pvar => [pvar] | Exp.Lvar pvar when Pvar.is_global pvar && Sil.is_static_local_name pname pvar => [pvar]
| _ => [] | _ => []
}; };
let hpred_local_static hpred => let hpred_local_static hpred =>
@ -887,7 +887,7 @@ let get_name_of_objc_static_locals (curr_f: Procdesc.t) p => {
let get_name_of_objc_block_locals p => { let get_name_of_objc_block_locals p => {
let local_blocks e => let local_blocks e =>
switch e { switch e {
| Sil.Lvar pvar when Sil.is_block_pvar pvar => [pvar] | Exp.Lvar pvar when Sil.is_block_pvar pvar => [pvar]
| _ => [] | _ => []
}; };
let hpred_local_blocks hpred => let hpred_local_blocks hpred =>
@ -906,7 +906,7 @@ let remove_abducted_retvars p =>
let (sigma, pi) = (Prop.get_sigma p, Prop.get_pi p); let (sigma, pi) = (Prop.get_sigma p, Prop.get_pi p);
let rec collect_exps exps => let rec collect_exps exps =>
fun fun
| Sil.Eexp (Sil.Exn e) _ => Sil.ExpSet.add e exps | Sil.Eexp (Exp.Exn e) _ => Sil.ExpSet.add e exps
| Sil.Eexp e _ => Sil.ExpSet.add e exps | Sil.Eexp e _ => Sil.ExpSet.add e exps
| Sil.Estruct flds _ => | Sil.Estruct flds _ =>
IList.fold_left (fun exps (_, strexp) => collect_exps exps strexp) exps flds IList.fold_left (fun exps (_, strexp) => collect_exps exps strexp) exps flds
@ -951,11 +951,11 @@ let remove_abducted_retvars p =>
let rec exp_contains = let rec exp_contains =
fun fun
| exp when Sil.ExpSet.mem exp reach_exps => true | exp when Sil.ExpSet.mem exp reach_exps => true
| Sil.UnOp _ e _ | Exp.UnOp _ e _
| Sil.Cast _ e | Exp.Cast _ e
| Sil.Lfield e _ _ => exp_contains e | Exp.Lfield e _ _ => exp_contains e
| Sil.BinOp _ e0 e1 | Exp.BinOp _ e0 e1
| Sil.Lindex e0 e1 => exp_contains e0 || exp_contains e1 | Exp.Lindex e0 e1 => exp_contains e0 || exp_contains e1
| _ => false; | _ => false;
IList.filter IList.filter
( (
@ -975,7 +975,7 @@ let remove_abducted_retvars p =>
( (
fun pvars hpred => fun pvars hpred =>
switch hpred { switch hpred {
| Sil.Hpointsto (Sil.Lvar pvar) _ _ => | Sil.Hpointsto (Exp.Lvar pvar) _ _ =>
let (abducteds, normal_pvars) = pvars; let (abducteds, normal_pvars) = pvars;
if (Pvar.is_abducted pvar) { if (Pvar.is_abducted pvar) {
([pvar, ...abducteds], normal_pvars) ([pvar, ...abducteds], normal_pvars)
@ -990,7 +990,7 @@ let remove_abducted_retvars p =>
let (_, p') = Prop.deallocate_stack_vars p abducteds; let (_, p') = Prop.deallocate_stack_vars p abducteds;
let normal_pvar_set = let normal_pvar_set =
IList.fold_left IList.fold_left
(fun normal_pvar_set pvar => Sil.ExpSet.add (Sil.Lvar pvar) normal_pvar_set) (fun normal_pvar_set pvar => Sil.ExpSet.add (Exp.Lvar pvar) normal_pvar_set)
Sil.ExpSet.empty Sil.ExpSet.empty
normal_pvars; normal_pvars;
/* walk forward from non-abducted pvars, keep everything reachable. remove everything else */ /* walk forward from non-abducted pvars, keep everything reachable. remove everything else */
@ -1053,7 +1053,7 @@ let remove_locals_formals (curr_f: Procdesc.t) p => {
let remove_seed_vars (prop: Prop.t 'a) :Prop.t Prop.normal => { let remove_seed_vars (prop: Prop.t 'a) :Prop.t Prop.normal => {
let hpred_not_seed = let hpred_not_seed =
fun fun
| Sil.Hpointsto (Sil.Lvar pv) _ _ => not (Pvar.is_seed pv) | Sil.Hpointsto (Exp.Lvar pv) _ _ => not (Pvar.is_seed pv)
| _ => true; | _ => true;
let sigma = Prop.get_sigma prop; let sigma = Prop.get_sigma prop;
let sigma' = IList.filter hpred_not_seed sigma; let sigma' = IList.filter hpred_not_seed sigma;
@ -1107,7 +1107,7 @@ let remove_seed_captured_vars_block captured_vars prop => {
let is_captured pname vn => Mangled.equal pname vn; let is_captured pname vn => Mangled.equal pname vn;
let hpred_seed_captured = let hpred_seed_captured =
fun fun
| Sil.Hpointsto (Sil.Lvar pv) _ _ => { | Sil.Hpointsto (Exp.Lvar pv) _ _ => {
let pname = Pvar.get_name pv; let pname = Pvar.get_name pv;
Pvar.is_seed pv && IList.mem is_captured pname captured_vars Pvar.is_seed pv && IList.mem is_captured pname captured_vars
} }
@ -1194,33 +1194,33 @@ let inline_synthetic_method ret_ids etl proc_desc loc_call :option Sil.instr =>
let do_instr _ instr => let do_instr _ instr =>
switch (instr, ret_ids, etl) { switch (instr, ret_ids, etl) {
| ( | (
Sil.Letderef _ (Sil.Lfield (Sil.Var _) fn ft) bt _, Sil.Letderef _ (Exp.Lfield (Exp.Var _) fn ft) bt _,
[ret_id], [ret_id],
[(e1, _)] /* getter for fields */ [(e1, _)] /* getter for fields */
) => ) =>
let instr' = Sil.Letderef ret_id (Sil.Lfield e1 fn ft) bt loc_call; let instr' = Sil.Letderef ret_id (Exp.Lfield e1 fn ft) bt loc_call;
found instr instr' found instr instr'
| (Sil.Letderef _ (Sil.Lfield (Sil.Lvar pvar) fn ft) bt _, [ret_id], []) | (Sil.Letderef _ (Exp.Lfield (Exp.Lvar pvar) fn ft) bt _, [ret_id], [])
when Pvar.is_global pvar => when Pvar.is_global pvar =>
/* getter for static fields */ /* getter for static fields */
let instr' = Sil.Letderef ret_id (Sil.Lfield (Sil.Lvar pvar) fn ft) bt loc_call; let instr' = Sil.Letderef ret_id (Exp.Lfield (Exp.Lvar pvar) fn ft) bt loc_call;
found instr instr' found instr instr'
| ( | (
Sil.Set (Sil.Lfield _ fn ft) bt _ _, Sil.Set (Exp.Lfield _ fn ft) bt _ _,
_, _,
[(e1, _), (e2, _)] /* setter for fields */ [(e1, _), (e2, _)] /* setter for fields */
) => ) =>
let instr' = Sil.Set (Sil.Lfield e1 fn ft) bt e2 loc_call; let instr' = Sil.Set (Exp.Lfield e1 fn ft) bt e2 loc_call;
found instr instr' found instr instr'
| (Sil.Set (Sil.Lfield (Sil.Lvar pvar) fn ft) bt _ _, _, [(e1, _)]) when Pvar.is_global pvar => | (Sil.Set (Exp.Lfield (Exp.Lvar pvar) fn ft) bt _ _, _, [(e1, _)]) when Pvar.is_global pvar =>
/* setter for static fields */ /* setter for static fields */
let instr' = Sil.Set (Sil.Lfield (Sil.Lvar pvar) fn ft) bt e1 loc_call; let instr' = Sil.Set (Exp.Lfield (Exp.Lvar pvar) fn ft) bt e1 loc_call;
found instr instr' found instr instr'
| (Sil.Call ret_ids' (Sil.Const (Const.Cfun pn)) etl' _ cf, _, _) | (Sil.Call ret_ids' (Exp.Const (Const.Cfun pn)) etl' _ cf, _, _)
when IList.length ret_ids == IList.length ret_ids' && IList.length etl' == IList.length etl => when IList.length ret_ids == IList.length ret_ids' && IList.length etl' == IList.length etl =>
let instr' = Sil.Call ret_ids (Sil.Const (Const.Cfun pn)) etl loc_call cf; let instr' = Sil.Call ret_ids (Exp.Const (Const.Cfun pn)) etl loc_call cf;
found instr instr' found instr instr'
| (Sil.Call ret_ids' (Sil.Const (Const.Cfun pn)) etl' _ cf, _, _) | (Sil.Call ret_ids' (Exp.Const (Const.Cfun pn)) etl' _ cf, _, _)
when when
IList.length ret_ids == IList.length ret_ids' && IList.length ret_ids == IList.length ret_ids' &&
IList.length etl' + 1 == IList.length etl => IList.length etl' + 1 == IList.length etl =>
@ -1230,7 +1230,7 @@ let inline_synthetic_method ret_ids etl proc_desc loc_call :option Sil.instr =>
| [_, ...l] => IList.rev l | [_, ...l] => IList.rev l
| [] => assert false | [] => assert false
}; };
let instr' = Sil.Call ret_ids (Sil.Const (Const.Cfun pn)) etl1 loc_call cf; let instr' = Sil.Call ret_ids (Exp.Const (Const.Cfun pn)) etl1 loc_call cf;
found instr instr' found instr instr'
| _ => () | _ => ()
}; };
@ -1243,7 +1243,7 @@ let inline_synthetic_method ret_ids etl proc_desc loc_call :option Sil.instr =>
let proc_inline_synthetic_methods cfg proc_desc :unit => { let proc_inline_synthetic_methods cfg proc_desc :unit => {
let instr_inline_synthetic_method = let instr_inline_synthetic_method =
fun fun
| Sil.Call ret_ids (Sil.Const (Const.Cfun pn)) etl loc _ => | Sil.Call ret_ids (Exp.Const (Const.Cfun pn)) etl loc _ =>
switch (Procdesc.find_from_name cfg pn) { switch (Procdesc.find_from_name cfg pn) {
| Some pd => | Some pd =>
let is_access = Procname.java_is_access_method pn; let is_access = Procname.java_is_access_method pn;

@ -331,4 +331,4 @@ let remove_seed_captured_vars_block: list Mangled.t => Prop.t Prop.normal => Pro
(name, typ) where name is a parameter. The resulting procdesc is isomorphic but (name, typ) where name is a parameter. The resulting procdesc is isomorphic but
all the type of the parameters are replaced in the instructions according to the list. all the type of the parameters are replaced in the instructions according to the list.
The virtual calls are also replaced to match the parameter types */ The virtual calls are also replaced to match the parameter types */
let specialize_types: Procdesc.t => Procname.t => list (Sil.exp, Typ.t) => Procdesc.t; let specialize_types: Procdesc.t => Procname.t => list (Exp.t, Typ.t) => Procdesc.t;

@ -0,0 +1,52 @@
/*
* vim: set ft=rust:
* vim: set ft=reason:
*
* Copyright (c) 2009 - 2013 Monoidics ltd.
* Copyright (c) 2013 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
open! Utils;
/** The Smallfoot Intermediate Language: Expressions */
let module L = Logging;
let module F = Format;
type closure = {name: Procname.t, captured_vars: list (t, Pvar.t, Typ.t)}
/** dynamically determined length of an array value, if any */
and dynamic_length = option t
/** Program expressions. */
and t =
/** Pure variable: it is not an lvalue */
| Var of Ident.t
/** Unary operator with type of the result if known */
| UnOp of Unop.t t (option Typ.t)
/** Binary operator */
| BinOp of Binop.t t t
/** Exception */
| Exn of t
/** Anonymous function */
| Closure of closure
/** Constants */
| Const of Const.t
/** Type cast */
| Cast of Typ.t t
/** The address of a program variable */
| Lvar of Pvar.t
/** A field offset, the type is the surrounding struct type */
| Lfield of t Ident.fieldname Typ.t
/** An array index offset: [exp1\[exp2\]] */
| Lindex of t t
/** A sizeof expression. [Sizeof (Tarray elt (Some static_length)) (Some dynamic_length)]
represents the size of an array value consisting of [dynamic_length] elements of type [elt].
The [dynamic_length], tracked by symbolic execution, may differ from the [static_length]
obtained from the type definition, e.g. when an array is over-allocated. For struct types,
the [dynamic_length] is that of the final extensible array, if any. */
| Sizeof of Typ.t dynamic_length Subtype.t;

@ -0,0 +1,52 @@
/*
* vim: set ft=rust:
* vim: set ft=reason:
*
* Copyright (c) 2009 - 2013 Monoidics ltd.
* Copyright (c) 2013 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
open! Utils;
/** The Smallfoot Intermediate Language: Expressions */
let module L = Logging;
let module F = Format;
type closure = {name: Procname.t, captured_vars: list (t, Pvar.t, Typ.t)}
/** dynamically determined length of an array value, if any */
and dynamic_length = option t
/** Program expressions. */
and t =
/** Pure variable: it is not an lvalue */
| Var of Ident.t
/** Unary operator with type of the result if known */
| UnOp of Unop.t t (option Typ.t)
/** Binary operator */
| BinOp of Binop.t t t
/** Exception */
| Exn of t
/** Anonymous function */
| Closure of closure
/** Constants */
| Const of Const.t
/** Type cast */
| Cast of Typ.t t
/** The address of a program variable */
| Lvar of Pvar.t
/** A field offset, the type is the surrounding struct type */
| Lfield of t Ident.fieldname Typ.t
/** An array index offset: [exp1\[exp2\]] */
| Lindex of t t
/** A sizeof expression. [Sizeof (Tarray elt (Some static_length)) (Some dynamic_length)]
represents the size of an array value consisting of [dynamic_length] elements of type [elt].
The [dynamic_length], tracked by symbolic execution, may differ from the [static_length]
obtained from the type definition, e.g. when an array is over-allocated. For struct types,
the [dynamic_length] is that of the final extensible array, if any. */
| Sizeof of Typ.t dynamic_length Subtype.t;

@ -114,38 +114,6 @@ type attribute =
/** denotes an object unsubscribed from observers of a notification center */ /** denotes an object unsubscribed from observers of a notification center */
| Aunsubscribed_observer; | Aunsubscribed_observer;
type closure = {name: Procname.t, captured_vars: list (exp, Pvar.t, Typ.t)}
/** dynamically determined length of an array value, if any */
and dynamic_length = option exp
/** Program expressions. */
and exp =
/** Pure variable: it is not an lvalue */
| Var of Ident.t
/** Unary operator with type of the result if known */
| UnOp of Unop.t exp (option Typ.t)
/** Binary operator */
| BinOp of Binop.t exp exp
/** Exception */
| Exn of exp
/** Anonymous function */
| Closure of closure
/** Constants */
| Const of Const.t
/** Type cast */
| Cast of Typ.t exp
/** The address of a program variable */
| Lvar of Pvar.t
/** A field offset, the type is the surrounding struct type */
| Lfield of exp Ident.fieldname Typ.t
/** An array index offset: [exp1\[exp2\]] */
| Lindex of exp exp
/** A sizeof expression. [Sizeof (Tarray elt (Some static_length)) (Some dynamic_length)]
represents the size of an array value consisting of [dynamic_length] elements of type [elt].
The [dynamic_length], tracked by symbolic execution, may differ from the [static_length]
obtained from the type definition, e.g. when an array is over-allocated. For struct types,
the [dynamic_length] is that of the final extensible array, if any. */
| Sizeof of Typ.t dynamic_length Subtype.t;
/** Kind of prune instruction */ /** Kind of prune instruction */
type if_kind = type if_kind =
@ -170,15 +138,15 @@ type instr =
/** declaration [let x = *lexp:typ] where [typ] is the root type of [lexp] */ /** declaration [let x = *lexp:typ] where [typ] is the root type of [lexp] */
/* note for frontend writers: [x] must be used in a subsequent instruction, otherwise the entire /* note for frontend writers: [x] must be used in a subsequent instruction, otherwise the entire
`Letderef` instruction may be eliminated by copy-propagation */ `Letderef` instruction may be eliminated by copy-propagation */
| Letderef of Ident.t exp Typ.t Location.t | Letderef of Ident.t Exp.t Typ.t Location.t
/** assignment [*lexp1:typ = exp2] where [typ] is the root type of [lexp1] */ /** assignment [*lexp1:typ = exp2] where [typ] is the root type of [lexp1] */
| Set of exp Typ.t exp Location.t | Set of Exp.t Typ.t Exp.t Location.t
/** prune the state based on [exp=1], the boolean indicates whether true branch */ /** prune the state based on [exp=1], the boolean indicates whether true branch */
| Prune of exp Location.t bool if_kind | Prune of Exp.t Location.t bool if_kind
/** [Call (ret_id1..ret_idn, e_fun, arg_ts, loc, call_flags)] represents an instructions /** [Call (ret_id1..ret_idn, e_fun, arg_ts, loc, call_flags)] represents an instructions
[ret_id1..ret_idn = e_fun(arg_ts);] [ret_id1..ret_idn = e_fun(arg_ts);]
where n = 0 for void return and n > 1 for struct return */ where n = 0 for void return and n > 1 for struct return */
| Call of (list Ident.t) exp (list (exp, Typ.t)) Location.t CallFlags.t | Call of (list Ident.t) Exp.t (list (Exp.t, Typ.t)) Location.t CallFlags.t
/** nullify stack variable */ /** nullify stack variable */
| Nullify of Pvar.t Location.t | Nullify of Pvar.t Location.t
| Abstract of Location.t /** apply abstraction */ | Abstract of Location.t /** apply abstraction */
@ -202,16 +170,16 @@ let instr_is_auxiliary =
/** offset for an lvalue */ /** offset for an lvalue */
type offset = | Off_fld of Ident.fieldname Typ.t | Off_index of exp; type offset = | Off_fld of Ident.fieldname Typ.t | Off_index of Exp.t;
/** {2 Components of Propositions} */ /** {2 Components of Propositions} */
/** an atom is a pure atomic formula */ /** an atom is a pure atomic formula */
type atom = type atom =
| Aeq of exp exp /** equality */ | Aeq of Exp.t Exp.t /** equality */
| Aneq of exp exp /** disequality */ | Aneq of Exp.t Exp.t /** disequality */
| Apred of attribute (list exp) /** predicate symbol applied to exps */ | Apred of attribute (list Exp.t) /** predicate symbol applied to exps */
| Anpred of attribute (list exp) /** negated predicate symbol applied to exps */; | Anpred of attribute (list Exp.t) /** negated predicate symbol applied to exps */;
/** kind of lseg or dllseg predicates */ /** kind of lseg or dllseg predicates */
@ -247,7 +215,7 @@ type inst =
/** structured expressions represent a value of structured type, such as an array or a struct. */ /** structured expressions represent a value of structured type, such as an array or a struct. */
type strexp = type strexp =
| Eexp of exp inst /** Base case: expression with instrumentation */ | Eexp of Exp.t inst /** Base case: expression with instrumentation */
| Estruct of (list (Ident.fieldname, strexp)) inst /** C structure */ | Estruct of (list (Ident.fieldname, strexp)) inst /** C structure */
/** Array of given length /** Array of given length
There are two conditions imposed / used in the array case. There are two conditions imposed / used in the array case.
@ -256,20 +224,20 @@ type strexp =
For instance, x |->[10 | e1: v1] implies that e1 <= 9. For instance, x |->[10 | e1: v1] implies that e1 <= 9.
Second, if two indices appear in an array, they should be different. Second, if two indices appear in an array, they should be different.
For instance, x |->[10 | e1: v1, e2: v2] implies that e1 != e2. */ For instance, x |->[10 | e1: v1, e2: v2] implies that e1 != e2. */
| Earray of exp (list (exp, strexp)) inst; | Earray of Exp.t (list (Exp.t, strexp)) inst;
/** an atomic heap predicate */ /** an atomic heap predicate */
type hpred = type hpred =
| Hpointsto of exp strexp exp | Hpointsto of Exp.t strexp Exp.t
/** represents [exp|->strexp:typexp] where [typexp] /** represents [exp|->strexp:typexp] where [typexp]
is an expression representing a type, e.h. [sizeof(t)]. */ is an expression representing a type, e.h. [sizeof(t)]. */
| Hlseg of lseg_kind hpara exp exp (list exp) | Hlseg of lseg_kind hpara Exp.t Exp.t (list Exp.t)
/** higher - order predicate for singly - linked lists. /** higher - order predicate for singly - linked lists.
Should ensure that exp1!= exp2 implies that exp1 is allocated. Should ensure that exp1!= exp2 implies that exp1 is allocated.
This assumption is used in the rearrangement. The last [exp list] parameter This assumption is used in the rearrangement. The last [exp list] parameter
is used to denote the shared links by all the nodes in the list. */ is used to denote the shared links by all the nodes in the list. */
| Hdllseg of lseg_kind hpara_dll exp exp exp exp (list exp) | Hdllseg of lseg_kind hpara_dll Exp.t Exp.t Exp.t Exp.t (list Exp.t)
/** higher-order predicate for doubly-linked lists. */ /** higher-order predicate for doubly-linked lists. */
/** parameter for the higher-order singly-linked list predicate. /** parameter for the higher-order singly-linked list predicate.
Means "lambda (root,next,svars). Exists evars. body". Means "lambda (root,next,svars). Exists evars. body".
@ -318,9 +286,9 @@ let has_objc_ref_counter hpred =>
/** Returns the zero value of a type, for int, float and ptr types, None othwewise */ /** Returns the zero value of a type, for int, float and ptr types, None othwewise */
let zero_value_of_numerical_type_option typ => let zero_value_of_numerical_type_option typ =>
switch typ { switch typ {
| Typ.Tint _ => Some (Const (Cint IntLit.zero)) | Typ.Tint _ => Some (Exp.Const (Cint IntLit.zero))
| Typ.Tfloat _ => Some (Const (Cfloat 0.0)) | Typ.Tfloat _ => Some (Exp.Const (Cfloat 0.0))
| Typ.Tptr _ => Some (Const (Cint IntLit.null)) | Typ.Tptr _ => Some (Exp.Const (Cint IntLit.null))
| _ => None | _ => None
}; };
@ -346,17 +314,17 @@ let is_static_local_name pname pvar =>
let exp_is_zero = let exp_is_zero =
fun fun
| Const (Cint n) => IntLit.iszero n | Exp.Const (Cint n) => IntLit.iszero n
| _ => false; | _ => false;
let exp_is_null_literal = let exp_is_null_literal =
fun fun
| Const (Cint n) => IntLit.isnull n | Exp.Const (Cint n) => IntLit.isnull n
| _ => false; | _ => false;
let exp_is_this = let exp_is_this =
fun fun
| Lvar pvar => Pvar.is_this pvar | Exp.Lvar pvar => Pvar.is_this pvar
| _ => false; | _ => false;
@ -364,7 +332,7 @@ let exp_is_this =
with respect to the first argument. It returns an expression [e'] such that with respect to the first argument. It returns an expression [e'] such that
BinOp([binop], [e'], [exp1]) = [exp2]. If the [binop] operation is not invertible, BinOp([binop], [e'], [exp1]) = [exp2]. If the [binop] operation is not invertible,
the function raises an exception by calling "assert false". */ the function raises an exception by calling "assert false". */
let binop_invert bop e1 e2 => BinOp (Binop.invert bop) e2 e1; let binop_invert bop e1 e2 => Exp.BinOp (Binop.invert bop) e2 e1;
let path_pos_compare (pn1, nid1) (pn2, nid2) => { let path_pos_compare (pn1, nid1) (pn2, nid2) => {
let n = Procname.compare pn1 pn2; let n = Procname.compare pn1 pn2;
@ -550,7 +518,7 @@ let attribute_compare (att1: attribute) (att2: attribute) :int =>
/** Compare epressions. Variables come before other expressions. */ /** Compare epressions. Variables come before other expressions. */
let rec exp_compare (e1: exp) (e2: exp) :int => let rec exp_compare (e1: Exp.t) (e2: Exp.t) :int =>
switch (e1, e2) { switch (e1, e2) {
| (Var id1, Var id2) => Ident.compare id2 id1 | (Var id1, Var id2) => Ident.compare id2 id1
| (Var _, _) => (-1) | (Var _, _) => (-1)
@ -667,7 +635,7 @@ let exp_equal e1 e2 => exp_compare e1 e2 == 0;
let rec exp_is_array_index_of exp1 exp2 => let rec exp_is_array_index_of exp1 exp2 =>
switch exp1 { switch exp1 {
| Lindex exp _ => exp_is_array_index_of exp exp2 | Exp.Lindex exp _ => exp_is_array_index_of exp exp2
| _ => exp_equal exp1 exp2 | _ => exp_equal exp1 exp2
}; };
@ -912,12 +880,12 @@ let hpara_dll_equal hpara1 hpara2 => hpara_dll_compare hpara1 hpara2 == 0;
/** {2 Sets of expressions} */ /** {2 Sets of expressions} */
let module ExpSet = Set.Make { let module ExpSet = Set.Make {
type t = exp; type t = Exp.t;
let compare = exp_compare; let compare = exp_compare;
}; };
let module ExpMap = Map.Make { let module ExpMap = Map.Make {
type t = exp; type t = Exp.t;
let compare = exp_compare; let compare = exp_compare;
}; };
@ -1066,7 +1034,7 @@ let rec _pp_exp pe0 pp_t f e0 => {
}; };
if (not (exp_equal e0 e)) { if (not (exp_equal e0 e)) {
switch e { switch e {
| Lvar pvar => Pvar.pp_value pe f pvar | Exp.Lvar pvar => Pvar.pp_value pe f pvar
| _ => assert false | _ => assert false
} }
} else { } else {
@ -1083,17 +1051,17 @@ let rec _pp_exp pe0 pp_t f e0 => {
| Ge => F.fprintf f "(%a %s %a)" pp_exp e2 (Binop.str pe Le) pp_exp e1 | Ge => F.fprintf f "(%a %s %a)" pp_exp e2 (Binop.str pe Le) pp_exp e1
| _ => F.fprintf f "(%a %s %a)" pp_exp e1 (Binop.str pe op) pp_exp e2 | _ => F.fprintf f "(%a %s %a)" pp_exp e1 (Binop.str pe op) pp_exp e2
}; };
switch e { switch (e: Exp.t) {
| Var id => (Ident.pp pe) f id | Var id => (Ident.pp pe) f id
| Const c => F.fprintf f "%a" (Const.pp pe) c | Const c => F.fprintf f "%a" (Const.pp pe) c
| Cast typ e => F.fprintf f "(%a)%a" pp_t typ pp_exp e | Cast typ e => F.fprintf f "(%a)%a" pp_t typ pp_exp e
| UnOp op e _ => F.fprintf f "%s%a" (Unop.str op) pp_exp e | UnOp op e _ => F.fprintf f "%s%a" (Unop.str op) pp_exp e
| BinOp op (Const c) e2 when Config.smt_output => print_binop_stm_output (Const c) op e2 | BinOp op (Const c) e2 when Config.smt_output => print_binop_stm_output (Exp.Const c) op e2
| BinOp op e1 e2 => F.fprintf f "(%a %s %a)" pp_exp e1 (Binop.str pe op) pp_exp e2 | BinOp op e1 e2 => F.fprintf f "(%a %s %a)" pp_exp e1 (Binop.str pe op) pp_exp e2
| Exn e => F.fprintf f "EXN %a" pp_exp e | Exn e => F.fprintf f "EXN %a" pp_exp e
| Closure {name, captured_vars} => | Closure {name, captured_vars} =>
let id_exps = IList.map (fun (id_exp, _, _) => id_exp) captured_vars; let id_exps = IList.map (fun (id_exp, _, _) => id_exp) captured_vars;
F.fprintf f "(%a)" (pp_comma_seq pp_exp) [Const (Cfun name), ...id_exps] F.fprintf f "(%a)" (pp_comma_seq pp_exp) [Exp.Const (Cfun name), ...id_exps]
| Lvar pv => Pvar.pp pe f pv | Lvar pv => Pvar.pp pe f pv
| Lfield e fld _ => F.fprintf f "%a.%a" pp_exp e Ident.pp_fieldname fld | Lfield e fld _ => F.fprintf f "%a.%a" pp_exp e Ident.pp_fieldname fld
| Lindex e1 e2 => F.fprintf f "%a[%a]" pp_exp e1 pp_exp e2 | Lindex e1 e2 => F.fprintf f "%a[%a]" pp_exp e1 pp_exp e2
@ -1113,7 +1081,7 @@ let exp_to_string e => pp_to_string (pp_exp pe_text) e;
/** dump an expression. */ /** dump an expression. */
let d_exp (e: exp) => L.add_print_action (L.PTexp, Obj.repr e); let d_exp (e: Exp.t) => L.add_print_action (L.PTexp, Obj.repr e);
/** Pretty print a list of expressions. */ /** Pretty print a list of expressions. */
@ -1121,11 +1089,11 @@ let pp_exp_list pe f expl => (pp_seq (pp_exp pe)) f expl;
/** dump a list of expressions. */ /** dump a list of expressions. */
let d_exp_list (el: list exp) => L.add_print_action (L.PTexp_list, Obj.repr el); let d_exp_list (el: list Exp.t) => L.add_print_action (L.PTexp_list, Obj.repr el);
let pp_texp pe f => let pp_texp pe f =>
fun fun
| Sizeof t l s => { | Exp.Sizeof t l s => {
let pp_len f l => Option.map_default (F.fprintf f "[%a]" (pp_exp pe)) () l; let pp_len f l => Option.map_default (F.fprintf f "[%a]" (pp_exp pe)) () l;
F.fprintf f "%a%a%a" (Typ.pp pe) t pp_len l Subtype.pp s F.fprintf f "%a%a%a" (Typ.pp pe) t pp_len l Subtype.pp s
} }
@ -1135,7 +1103,7 @@ let pp_texp pe f =>
/** Pretty print a type with all the details. */ /** Pretty print a type with all the details. */
let pp_texp_full pe f => let pp_texp_full pe f =>
fun fun
| Sizeof t l s => { | Exp.Sizeof t l s => {
let pp_len f l => Option.map_default (F.fprintf f "[%a]" (pp_exp pe)) () l; let pp_len f l => Option.map_default (F.fprintf f "[%a]" (pp_exp pe)) () l;
F.fprintf f "%a%a%a" (Typ.pp_full pe) t pp_len l Subtype.pp s F.fprintf f "%a%a%a" (Typ.pp_full pe) t pp_len l Subtype.pp s
} }
@ -1143,7 +1111,7 @@ let pp_texp_full pe f =>
/** Dump a type expression with all the details. */ /** Dump a type expression with all the details. */
let d_texp_full (te: exp) => L.add_print_action (L.PTtexp_full, Obj.repr te); let d_texp_full (te: Exp.t) => L.add_print_action (L.PTtexp_full, Obj.repr te);
/** Pretty print an offset */ /** Pretty print an offset */
@ -1188,13 +1156,13 @@ let instr_get_loc =
/** get the expressions occurring in the instruction */ /** get the expressions occurring in the instruction */
let instr_get_exps = let instr_get_exps =
fun fun
| Letderef id e _ _ => [Var id, e] | Letderef id e _ _ => [Exp.Var id, e]
| Set e1 _ e2 _ => [e1, e2] | Set e1 _ e2 _ => [e1, e2]
| Prune cond _ _ _ => [cond] | Prune cond _ _ _ => [cond]
| Call ret_ids e _ _ _ => [e, ...(IList.map (fun id => Var id)) ret_ids] | Call ret_ids e _ _ _ => [e, ...(IList.map (fun id => Exp.Var id)) ret_ids]
| Nullify pvar _ => [Lvar pvar] | Nullify pvar _ => [Exp.Lvar pvar]
| Abstract _ => [] | Abstract _ => []
| Remove_temps temps _ => IList.map (fun id => Var id) temps | Remove_temps temps _ => IList.map (fun id => Exp.Var id) temps
| Stackop _ => [] | Stackop _ => []
| Declare_locals _ => []; | Declare_locals _ => [];
@ -1270,8 +1238,8 @@ let pp_atom pe0 f a => {
| Aeq (BinOp op e1 e2) (Const (Cint i)) when IntLit.isone i => | Aeq (BinOp op e1 e2) (Const (Cint i)) when IntLit.isone i =>
switch pe.pe_kind { switch pe.pe_kind {
| PP_TEXT | PP_TEXT
| PP_HTML => F.fprintf f "%a" (pp_exp pe) (BinOp op e1 e2) | PP_HTML => F.fprintf f "%a" (pp_exp pe) (Exp.BinOp op e1 e2)
| PP_LATEX => F.fprintf f "%a" (pp_exp pe) (BinOp op e1 e2) | PP_LATEX => F.fprintf f "%a" (pp_exp pe) (Exp.BinOp op e1 e2)
} }
| Aeq e1 e2 => | Aeq e1 e2 =>
switch pe.pe_kind { switch pe.pe_kind {
@ -1855,7 +1823,7 @@ let d_hpred (hpred: hpred) => L.add_print_action (L.PThpred, Obj.repr hpred);
/** {2 Functions for traversing SIL data types} */ /** {2 Functions for traversing SIL data types} */
let rec strexp_expmap (f: (exp, option inst) => (exp, option inst)) => { let rec strexp_expmap (f: (Exp.t, option inst) => (Exp.t, option inst)) => {
let fe e => fst (f (e, None)); let fe e => fst (f (e, None));
let fei (e, inst) => let fei (e, inst) =>
switch (f (e, Some inst)) { switch (f (e, Some inst)) {
@ -1881,7 +1849,7 @@ let rec strexp_expmap (f: (exp, option inst) => (exp, option inst)) => {
} }
}; };
let hpred_expmap (f: (exp, option inst) => (exp, option inst)) => { let hpred_expmap (f: (Exp.t, option inst) => (Exp.t, option inst)) => {
let fe e => fst (f (e, None)); let fe e => fst (f (e, None));
fun fun
| Hpointsto e se te => { | Hpointsto e se te => {
@ -1934,17 +1902,17 @@ and hpred_instmap (fn: inst => inst) (hpred: hpred) :hpred =>
| Hdllseg k hpar_dll e f g h el => Hdllseg k (hpara_dll_instmap fn hpar_dll) e f g h el | Hdllseg k hpar_dll e f g h el => Hdllseg k (hpara_dll_instmap fn hpar_dll) e f g h el
}; };
let hpred_list_expmap (f: (exp, option inst) => (exp, option inst)) (hlist: list hpred) => let hpred_list_expmap (f: (Exp.t, option inst) => (Exp.t, option inst)) (hlist: list hpred) =>
IList.map (hpred_expmap f) hlist; IList.map (hpred_expmap f) hlist;
let atom_expmap (f: exp => exp) => let atom_expmap (f: Exp.t => Exp.t) =>
fun fun
| Aeq e1 e2 => Aeq (f e1) (f e2) | Aeq e1 e2 => Aeq (f e1) (f e2)
| Aneq e1 e2 => Aneq (f e1) (f e2) | Aneq e1 e2 => Aneq (f e1) (f e2)
| Apred a es => Apred a (IList.map f es) | Apred a es => Apred a (IList.map f es)
| Anpred a es => Anpred a (IList.map f es); | Anpred a es => Anpred a (IList.map f es);
let atom_list_expmap (f: exp => exp) (alist: list atom) => IList.map (atom_expmap f) alist; let atom_list_expmap (f: Exp.t => Exp.t) (alist: list atom) => IList.map (atom_expmap f) alist;
/** {2 Function for computing lexps in sigma} */ /** {2 Function for computing lexps in sigma} */
@ -1954,7 +1922,7 @@ let hpred_get_lexp acc =>
| Hlseg _ _ e _ _ => [e, ...acc] | Hlseg _ _ e _ _ => [e, ...acc]
| Hdllseg _ _ e1 _ _ e2 _ => [e1, e2, ...acc]; | Hdllseg _ _ e1 _ _ e2 _ => [e1, e2, ...acc];
let hpred_list_get_lexps (filter: exp => bool) (hlist: list hpred) :list exp => { let hpred_list_get_lexps (filter: Exp.t => bool) (hlist: list hpred) :list Exp.t => {
let lexps = IList.fold_left hpred_get_lexp [] hlist; let lexps = IList.fold_left hpred_get_lexp [] hlist;
IList.filter filter lexps IList.filter filter lexps
}; };
@ -1965,13 +1933,13 @@ let hpred_list_get_lexps (filter: exp => bool) (hlist: list hpred) :list exp =>
If not a sizeof, return the default type if given, otherwise raise an exception */ If not a sizeof, return the default type if given, otherwise raise an exception */
let texp_to_typ default_opt => let texp_to_typ default_opt =>
fun fun
| Sizeof t _ _ => t | Exp.Sizeof t _ _ => t
| _ => Typ.unsome "texp_to_typ" default_opt; | _ => Typ.unsome "texp_to_typ" default_opt;
/** Return the root of [lexp]. */ /** Return the root of [lexp]. */
let rec root_of_lexp lexp => let rec root_of_lexp lexp =>
switch lexp { switch (lexp: Exp.t) {
| Var _ => lexp | Var _ => lexp
| Const _ => lexp | Const _ => lexp
| Cast _ e => root_of_lexp e | Cast _ e => root_of_lexp e
@ -1990,12 +1958,12 @@ let rec root_of_lexp lexp =>
Currently, catches array - indexing expressions such as a[i] only. */ Currently, catches array - indexing expressions such as a[i] only. */
let rec exp_pointer_arith = let rec exp_pointer_arith =
fun fun
| Lfield e _ _ => exp_pointer_arith e | Exp.Lfield e _ _ => exp_pointer_arith e
| Lindex _ => true | Exp.Lindex _ => true
| _ => false; | _ => false;
let exp_get_undefined footprint => let exp_get_undefined footprint =>
Var ( Exp.Var (
Ident.create_fresh ( Ident.create_fresh (
if footprint { if footprint {
Ident.kfootprint Ident.kfootprint
@ -2007,11 +1975,11 @@ let exp_get_undefined footprint =>
/** Create integer constant */ /** Create integer constant */
let exp_int i => Const (Cint i); let exp_int i => Exp.Const (Cint i);
/** Create float constant */ /** Create float constant */
let exp_float v => Const (Cfloat v); let exp_float v => Exp.Const (Cfloat v);
/** Integer constant 0 */ /** Integer constant 0 */
@ -2040,24 +2008,24 @@ let exp_bool b =>
/** Create expresstion [e1 == e2] */ /** Create expresstion [e1 == e2] */
let exp_eq e1 e2 => BinOp Eq e1 e2; let exp_eq e1 e2 => Exp.BinOp Eq e1 e2;
/** Create expresstion [e1 != e2] */ /** Create expresstion [e1 != e2] */
let exp_ne e1 e2 => BinOp Ne e1 e2; let exp_ne e1 e2 => Exp.BinOp Ne e1 e2;
/** Create expression [e1 <= e2] */ /** Create expression [e1 <= e2] */
let exp_le e1 e2 => BinOp Le e1 e2; let exp_le e1 e2 => Exp.BinOp Le e1 e2;
/** Create expression [e1 < e2] */ /** Create expression [e1 < e2] */
let exp_lt e1 e2 => BinOp Lt e1 e2; let exp_lt e1 e2 => Exp.BinOp Lt e1 e2;
/** {2 Functions for computing program variables} */ /** {2 Functions for computing program variables} */
let rec exp_fpv = let rec exp_fpv e =>
fun switch (e: Exp.t) {
| Var _ => [] | Var _ => []
| Exn e => exp_fpv e | Exn e => exp_fpv e
| Closure {captured_vars} => IList.map (fun (_, pvar, _) => pvar) captured_vars | Closure {captured_vars} => IList.map (fun (_, pvar, _) => pvar) captured_vars
@ -2071,7 +2039,8 @@ let rec exp_fpv =
/* TODO: Sizeof length expressions may contain variables, do not ignore them. */ /* TODO: Sizeof length expressions may contain variables, do not ignore them. */
/* | Sizeof _ None _ => [] */ /* | Sizeof _ None _ => [] */
/* | Sizeof _ (Some l) _ => exp_fpv l */ /* | Sizeof _ (Some l) _ => exp_fpv l */
| Sizeof _ _ _ => []; | Sizeof _ _ _ => []
};
let exp_list_fpv el => IList.flatten (IList.map exp_fpv el); let exp_list_fpv el => IList.flatten (IList.map exp_fpv el);
@ -2251,28 +2220,27 @@ let fav_subset_ident fav1 fav2 => ident_sorted_list_subset (fav_to_list fav1) (f
let fav_mem fav id => IList.exists (Ident.equal id) !fav; let fav_mem fav id => IList.exists (Ident.equal id) !fav;
let rec exp_fav_add fav => let rec exp_fav_add fav e =>
fun switch (e: Exp.t) {
| Var id => fav ++ id | Var id => fav ++ id
| Exn e => exp_fav_add fav e | Exn e => exp_fav_add fav e
| Closure {captured_vars} => IList.iter (fun (e, _, _) => exp_fav_add fav e) captured_vars | Closure {captured_vars} => IList.iter (fun (e, _, _) => exp_fav_add fav e) captured_vars
| Const (Cint _ | Cfun _ | Cstr _ | Cfloat _ | Cclass _ | Cptr_to_fld _) => () | Const (Cint _ | Cfun _ | Cstr _ | Cfloat _ | Cclass _ | Cptr_to_fld _) => ()
| Cast _ e | Cast _ e
| UnOp _ e _ => exp_fav_add fav e | UnOp _ e _ => exp_fav_add fav e
| BinOp _ e1 e2 => { | BinOp _ e1 e2 =>
exp_fav_add fav e1; exp_fav_add fav e1;
exp_fav_add fav e2 exp_fav_add fav e2
}
| Lvar _ => () /* do nothing since we only count non-program variables */ | Lvar _ => () /* do nothing since we only count non-program variables */
| Lfield e _ _ => exp_fav_add fav e | Lfield e _ _ => exp_fav_add fav e
| Lindex e1 e2 => { | Lindex e1 e2 =>
exp_fav_add fav e1; exp_fav_add fav e1;
exp_fav_add fav e2 exp_fav_add fav e2
}
/* TODO: Sizeof length expressions may contain variables, do not ignore them. */ /* TODO: Sizeof length expressions may contain variables, do not ignore them. */
/* | Sizeof _ None _ => () */ /* | Sizeof _ None _ => () */
/* | Sizeof _ (Some l) _ => exp_fav_add fav l; */ /* | Sizeof _ (Some l) _ => exp_fav_add fav l; */
| Sizeof _ _ _ => (); | Sizeof _ _ _ => ()
};
let exp_fav = fav_imperative_to_functional exp_fav_add; let exp_fav = fav_imperative_to_functional exp_fav_add;
@ -2356,7 +2324,7 @@ let array_clean_new_index footprint_part new_idx => {
); );
L.d_ln (); L.d_ln ();
let id = Ident.create_fresh Ident.kfootprint; let id = Ident.create_fresh Ident.kfootprint;
Var id Exp.Var id
} else { } else {
new_idx new_idx
} }
@ -2465,7 +2433,7 @@ let rec sorted_list_check_consecutives f =>
/** substitution */ /** substitution */
type subst = list (Ident.t, exp); type subst = list (Ident.t, Exp.t);
/** Comparison between substitutions. */ /** Comparison between substitutions. */
@ -2651,8 +2619,8 @@ let sub_fpv (sub: subst) => IList.flatten (IList.map (fun (_, e) => exp_fpv e) s
/** Substitutions do not contain binders */ /** Substitutions do not contain binders */
let sub_av_add = sub_fav_add; let sub_av_add = sub_fav_add;
let rec exp_sub_ids (f: Ident.t => exp) exp => let rec exp_sub_ids (f: Ident.t => Exp.t) exp =>
switch exp { switch (exp: Exp.t) {
| Var id => f id | Var id => f id
| Lvar _ => exp | Lvar _ => exp
| Exn e => | Exn e =>
@ -2660,7 +2628,7 @@ let rec exp_sub_ids (f: Ident.t => exp) exp =>
if (e' === e) { if (e' === e) {
exp exp
} else { } else {
Exn e' Exp.Exn e'
} }
| Closure c => | Closure c =>
let captured_vars = let captured_vars =
@ -2679,7 +2647,7 @@ let rec exp_sub_ids (f: Ident.t => exp) exp =>
if (captured_vars === c.captured_vars) { if (captured_vars === c.captured_vars) {
exp exp
} else { } else {
Closure {...c, captured_vars} Exp.Closure {...c, captured_vars}
} }
| Const (Cint _ | Cfun _ | Cstr _ | Cfloat _ | Cclass _ | Cptr_to_fld _) => exp | Const (Cint _ | Cfun _ | Cstr _ | Cfloat _ | Cclass _ | Cptr_to_fld _) => exp
| Cast t e => | Cast t e =>
@ -2687,14 +2655,14 @@ let rec exp_sub_ids (f: Ident.t => exp) exp =>
if (e' === e) { if (e' === e) {
exp exp
} else { } else {
Cast t e' Exp.Cast t e'
} }
| UnOp op e typ_opt => | UnOp op e typ_opt =>
let e' = exp_sub_ids f e; let e' = exp_sub_ids f e;
if (e' === e) { if (e' === e) {
exp exp
} else { } else {
UnOp op e' typ_opt Exp.UnOp op e' typ_opt
} }
| BinOp op e1 e2 => | BinOp op e1 e2 =>
let e1' = exp_sub_ids f e1; let e1' = exp_sub_ids f e1;
@ -2702,14 +2670,14 @@ let rec exp_sub_ids (f: Ident.t => exp) exp =>
if (e1' === e1 && e2' === e2) { if (e1' === e1 && e2' === e2) {
exp exp
} else { } else {
BinOp op e1' e2' Exp.BinOp op e1' e2'
} }
| Lfield e fld typ => | Lfield e fld typ =>
let e' = exp_sub_ids f e; let e' = exp_sub_ids f e;
if (e' === e) { if (e' === e) {
exp exp
} else { } else {
Lfield e' fld typ Exp.Lfield e' fld typ
} }
| Lindex e1 e2 => | Lindex e1 e2 =>
let e1' = exp_sub_ids f e1; let e1' = exp_sub_ids f e1;
@ -2717,7 +2685,7 @@ let rec exp_sub_ids (f: Ident.t => exp) exp =>
if (e1' === e1 && e2' === e2) { if (e1' === e1 && e2' === e2) {
exp exp
} else { } else {
Lindex e1' e2' Exp.Lindex e1' e2'
} }
| Sizeof t l_opt s => | Sizeof t l_opt s =>
switch l_opt { switch l_opt {
@ -2726,7 +2694,7 @@ let rec exp_sub_ids (f: Ident.t => exp) exp =>
if (l' === l) { if (l' === l) {
exp exp
} else { } else {
Sizeof t (Some l') s Exp.Sizeof t (Some l') s
} }
| None => exp | None => exp
} }
@ -2734,7 +2702,7 @@ let rec exp_sub_ids (f: Ident.t => exp) exp =>
let rec apply_sub subst id => let rec apply_sub subst id =>
switch subst { switch subst {
| [] => Var id | [] => Exp.Var id
| [(i, e), ...l] => | [(i, e), ...l] =>
if (Ident.equal i id) { if (Ident.equal i id) {
e e
@ -2747,7 +2715,7 @@ let exp_sub (subst: subst) e => exp_sub_ids (apply_sub subst) e;
/** apply [f] to id's in [instr]. if [sub_id_binders] is false, [f] is only applied to bound id's */ /** apply [f] to id's in [instr]. if [sub_id_binders] is false, [f] is only applied to bound id's */
let instr_sub_ids sub_id_binders::sub_id_binders (f: Ident.t => exp) instr => { let instr_sub_ids sub_id_binders::sub_id_binders (f: Ident.t => Exp.t) instr => {
let sub_id id => let sub_id id =>
switch (exp_sub_ids f (Var id)) { switch (exp_sub_ids f (Var id)) {
| Var id' => id' | Var id' => id'
@ -2979,7 +2947,7 @@ let rec exp_compare_structural e1 e2 exp_map => {
/* assume e1 and e2 equal, enforce by adding to [exp_map] */ /* assume e1 and e2 equal, enforce by adding to [exp_map] */
(0, ExpMap.add e1 e2 exp_map) (0, ExpMap.add e1 e2 exp_map)
}; };
switch (e1, e2) { switch (e1: Exp.t, e2: Exp.t) {
| (Var _, Var _) => compare_exps_with_map e1 e2 exp_map | (Var _, Var _) => compare_exps_with_map e1 e2 exp_map
| (UnOp o1 e1 to1, UnOp o2 e2 to2) => | (UnOp o1 e1 to1, UnOp o2 e2 to2) =>
let n = Unop.compare o1 o2; let n = Unop.compare o1 o2;
@ -3256,7 +3224,7 @@ let hpred_replace_exp epairs =>
/** {2 Compaction} */ /** {2 Compaction} */
let module ExpHash = Hashtbl.Make { let module ExpHash = Hashtbl.Make {
type t = exp; type t = Exp.t;
let equal = exp_equal; let equal = exp_equal;
let hash = Hashtbl.hash; let hash = Hashtbl.hash;
}; };
@ -3267,7 +3235,7 @@ let module HpredHash = Hashtbl.Make {
let hash = Hashtbl.hash; let hash = Hashtbl.hash;
}; };
type sharing_env = {exph: ExpHash.t exp, hpredh: HpredHash.t hpred}; type sharing_env = {exph: ExpHash.t Exp.t, hpredh: HpredHash.t hpred};
/** Create a sharing env to store canonical representations */ /** Create a sharing env to store canonical representations */
@ -3315,7 +3283,7 @@ let hpred_compact sh hpred =>
/** Extract the ids and pvars from an expression */ /** Extract the ids and pvars from an expression */
let exp_get_vars exp => { let exp_get_vars exp => {
let rec exp_get_vars_ exp vars => let rec exp_get_vars_ exp vars =>
switch exp { switch (exp: Exp.t) {
| Lvar pvar => (fst vars, [pvar, ...snd vars]) | Lvar pvar => (fst vars, [pvar, ...snd vars])
| Var id => ([id, ...fst vars], snd vars) | Var id => ([id, ...fst vars], snd vars)
| Cast _ e | Cast _ e
@ -3342,7 +3310,7 @@ let exp_get_vars exp => {
/** Compute the offset list of an expression */ /** Compute the offset list of an expression */
let exp_get_offsets exp => { let exp_get_offsets exp => {
let rec f offlist_past e => let rec f offlist_past e =>
switch e { switch (e: Exp.t) {
| Var _ | Var _
| Const _ | Const _
| UnOp _ | UnOp _
@ -3363,8 +3331,8 @@ let exp_add_offsets exp offsets => {
let rec f acc => let rec f acc =>
fun fun
| [] => acc | [] => acc
| [Off_fld fld typ, ...offs'] => f (Lfield acc fld typ) offs' | [Off_fld fld typ, ...offs'] => f (Exp.Lfield acc fld typ) offs'
| [Off_index e, ...offs'] => f (Lindex acc e) offs'; | [Off_index e, ...offs'] => f (Exp.Lindex acc e) offs';
f exp offsets f exp offsets
}; };
@ -3414,7 +3382,7 @@ let hpara_instantiate para e1 e2 elist => {
IList.map g para.evars IList.map g para.evars
}; };
let subst_for_evars = { let subst_for_evars = {
let g id id' => (id, Var id'); let g id id' => (id, Exp.Var id');
try (IList.map2 g para.evars ids_evars) { try (IList.map2 g para.evars ids_evars) {
| Invalid_argument _ => assert false | Invalid_argument _ => assert false
} }
@ -3443,7 +3411,7 @@ let hpara_dll_instantiate (para: hpara_dll) cell blink flink elist => {
IList.map g para.evars_dll IList.map g para.evars_dll
}; };
let subst_for_evars = { let subst_for_evars = {
let g id id' => (id, Var id'); let g id id' => (id, Exp.Var id');
try (IList.map2 g para.evars_dll ids_evars) { try (IList.map2 g para.evars_dll ids_evars) {
| Invalid_argument _ => assert false | Invalid_argument _ => assert false
} }

@ -102,53 +102,21 @@ type attribute =
/** denotes an object unsubscribed from observers of a notification center */ /** denotes an object unsubscribed from observers of a notification center */
| Aunsubscribed_observer; | Aunsubscribed_observer;
type closure = {name: Procname.t, captured_vars: list (exp, Pvar.t, Typ.t)}
/** dynamically determined length of an array value, if any */
and dynamic_length = option exp
/** Program expressions. */
and exp =
/** Pure variable: it is not an lvalue */
| Var of Ident.t
/** Unary operator with type of the result if known */
| UnOp of Unop.t exp (option Typ.t)
/** Binary operator */
| BinOp of Binop.t exp exp
/** Exception */
| Exn of exp
/** Anonymous function */
| Closure of closure
/** Constants */
| Const of Const.t
/** Type cast */
| Cast of Typ.t exp
/** The address of a program variable */
| Lvar of Pvar.t
/** A field offset, the type is the surrounding struct type */
| Lfield of exp Ident.fieldname Typ.t
/** An array index offset: [exp1\[exp2\]] */
| Lindex of exp exp
/** A sizeof expression. [Sizeof (Tarray elt (Some static_length)) (Some dynamic_length)]
represents the size of an array value consisting of [dynamic_length] elements of type [elt].
The [dynamic_length], tracked by symbolic execution, may differ from the [static_length]
obtained from the type definition, e.g. when an array is over-allocated. For struct types,
the [dynamic_length] is that of the final extensible array, if any. */
| Sizeof of Typ.t dynamic_length Subtype.t;
/** Sets of expressions. */ /** Sets of expressions. */
let module ExpSet: Set.S with type elt = exp; let module ExpSet: Set.S with type elt = Exp.t;
/** Maps with expression keys. */ /** Maps with expression keys. */
let module ExpMap: Map.S with type key = exp; let module ExpMap: Map.S with type key = Exp.t;
/** Hashtable with expressions as keys. */ /** Hashtable with expressions as keys. */
let module ExpHash: Hashtbl.S with type key = exp; let module ExpHash: Hashtbl.S with type key = Exp.t;
/** Convert expression lists to expression sets. */ /** Convert expression lists to expression sets. */
let elist_to_eset: list exp => ExpSet.t; let elist_to_eset: list Exp.t => ExpSet.t;
/** Kind of prune instruction */ /** Kind of prune instruction */
@ -174,15 +142,15 @@ type instr =
/** declaration [let x = *lexp:typ] where [typ] is the root type of [lexp] */ /** declaration [let x = *lexp:typ] where [typ] is the root type of [lexp] */
/* note for frontend writers: [x] must be used in a subsequent instruction, otherwise the entire /* note for frontend writers: [x] must be used in a subsequent instruction, otherwise the entire
`Letderef` instruction may be eliminated by copy-propagation */ `Letderef` instruction may be eliminated by copy-propagation */
| Letderef of Ident.t exp Typ.t Location.t | Letderef of Ident.t Exp.t Typ.t Location.t
/** assignment [*lexp1:typ = exp2] where [typ] is the root type of [lexp1] */ /** assignment [*lexp1:typ = exp2] where [typ] is the root type of [lexp1] */
| Set of exp Typ.t exp Location.t | Set of Exp.t Typ.t Exp.t Location.t
/** prune the state based on [exp=1], the boolean indicates whether true branch */ /** prune the state based on [exp=1], the boolean indicates whether true branch */
| Prune of exp Location.t bool if_kind | Prune of Exp.t Location.t bool if_kind
/** [Call (ret_id1..ret_idn, e_fun, arg_ts, loc, call_flags)] represents an instructions /** [Call (ret_id1..ret_idn, e_fun, arg_ts, loc, call_flags)] represents an instructions
[ret_id1..ret_idn = e_fun(arg_ts);] [ret_id1..ret_idn = e_fun(arg_ts);]
where n = 0 for void return and n > 1 for struct return */ where n = 0 for void return and n > 1 for struct return */
| Call of (list Ident.t) exp (list (exp, Typ.t)) Location.t CallFlags.t | Call of (list Ident.t) Exp.t (list (Exp.t, Typ.t)) Location.t CallFlags.t
/** nullify stack variable */ /** nullify stack variable */
| Nullify of Pvar.t Location.t | Nullify of Pvar.t Location.t
| Abstract of Location.t /** apply abstraction */ | Abstract of Location.t /** apply abstraction */
@ -196,16 +164,16 @@ let instr_is_auxiliary: instr => bool;
/** Offset for an lvalue. */ /** Offset for an lvalue. */
type offset = | Off_fld of Ident.fieldname Typ.t | Off_index of exp; type offset = | Off_fld of Ident.fieldname Typ.t | Off_index of Exp.t;
/** {2 Components of Propositions} */ /** {2 Components of Propositions} */
/** an atom is a pure atomic formula */ /** an atom is a pure atomic formula */
type atom = type atom =
| Aeq of exp exp /** equality */ | Aeq of Exp.t Exp.t /** equality */
| Aneq of exp exp /** disequality */ | Aneq of Exp.t Exp.t /** disequality */
| Apred of attribute (list exp) /** predicate symbol applied to exps */ | Apred of attribute (list Exp.t) /** predicate symbol applied to exps */
| Anpred of attribute (list exp) /** negated predicate symbol applied to exps */; | Anpred of attribute (list Exp.t) /** negated predicate symbol applied to exps */;
/** kind of lseg or dllseg predicates */ /** kind of lseg or dllseg predicates */
@ -289,7 +257,7 @@ let inst_partial_meet: inst => inst => inst;
/** structured expressions represent a value of structured type, such as an array or a struct. */ /** structured expressions represent a value of structured type, such as an array or a struct. */
type strexp = type strexp =
| Eexp of exp inst /** Base case: expression with instrumentation */ | Eexp of Exp.t inst /** Base case: expression with instrumentation */
| Estruct of (list (Ident.fieldname, strexp)) inst /** C structure */ | Estruct of (list (Ident.fieldname, strexp)) inst /** C structure */
/** Array of given length /** Array of given length
There are two conditions imposed / used in the array case. There are two conditions imposed / used in the array case.
@ -298,20 +266,20 @@ type strexp =
For instance, x |->[10 | e1: v1] implies that e1 <= 9. For instance, x |->[10 | e1: v1] implies that e1 <= 9.
Second, if two indices appear in an array, they should be different. Second, if two indices appear in an array, they should be different.
For instance, x |->[10 | e1: v1, e2: v2] implies that e1 != e2. */ For instance, x |->[10 | e1: v1, e2: v2] implies that e1 != e2. */
| Earray of exp (list (exp, strexp)) inst; | Earray of Exp.t (list (Exp.t, strexp)) inst;
/** an atomic heap predicate */ /** an atomic heap predicate */
type hpred = type hpred =
| Hpointsto of exp strexp exp | Hpointsto of Exp.t strexp Exp.t
/** represents [exp|->strexp:typexp] where [typexp] /** represents [exp|->strexp:typexp] where [typexp]
is an expression representing a type, e.g. [sizeof(t)]. */ is an expression representing a type, e.g. [sizeof(t)]. */
| Hlseg of lseg_kind hpara exp exp (list exp) | Hlseg of lseg_kind hpara Exp.t Exp.t (list Exp.t)
/** higher - order predicate for singly - linked lists. /** higher - order predicate for singly - linked lists.
Should ensure that exp1!= exp2 implies that exp1 is allocated. Should ensure that exp1!= exp2 implies that exp1 is allocated.
This assumption is used in the rearrangement. The last [exp list] parameter This assumption is used in the rearrangement. The last [exp list] parameter
is used to denote the shared links by all the nodes in the list.*/ is used to denote the shared links by all the nodes in the list.*/
| Hdllseg of lseg_kind hpara_dll exp exp exp exp (list exp) | Hdllseg of lseg_kind hpara_dll Exp.t Exp.t Exp.t Exp.t (list Exp.t)
/** higher-order predicate for doubly-linked lists. */ /** higher-order predicate for doubly-linked lists. */
/** parameter for the higher-order singly-linked list predicate. /** parameter for the higher-order singly-linked list predicate.
Means "lambda (root,next,svars). Exists evars. body". Means "lambda (root,next,svars). Exists evars. body".
@ -352,7 +320,7 @@ let create_sharing_env: unit => sharing_env;
/** Return a canonical representation of the exp */ /** Return a canonical representation of the exp */
let exp_compact: sharing_env => exp => exp; let exp_compact: sharing_env => Exp.t => Exp.t;
/** Return a compact representation of the exp */ /** Return a compact representation of the exp */
@ -362,23 +330,23 @@ let hpred_compact: sharing_env => hpred => hpred;
/** {2 Comparision And Inspection Functions} */ /** {2 Comparision And Inspection Functions} */
let has_objc_ref_counter: hpred => bool; let has_objc_ref_counter: hpred => bool;
let exp_is_zero: exp => bool; let exp_is_zero: Exp.t => bool;
let exp_is_null_literal: exp => bool; let exp_is_null_literal: Exp.t => bool;
/** return true if [exp] is the special this/self expression */ /** return true if [exp] is the special this/self expression */
let exp_is_this: exp => bool; let exp_is_this: Exp.t => bool;
let path_pos_equal: path_pos => path_pos => bool; let path_pos_equal: path_pos => path_pos => bool;
/** Returns the zero value of a type, for int, float and ptr types, None othwewise */ /** Returns the zero value of a type, for int, float and ptr types, None othwewise */
let zero_value_of_numerical_type_option: Typ.t => option exp; let zero_value_of_numerical_type_option: Typ.t => option Exp.t;
/** Returns the zero value of a type, for int, float and ptr types, fail otherwise */ /** Returns the zero value of a type, for int, float and ptr types, fail otherwise */
let zero_value_of_numerical_type: Typ.t => exp; let zero_value_of_numerical_type: Typ.t => Exp.t;
/** Make a static local name in objc */ /** Make a static local name in objc */
@ -400,7 +368,7 @@ let is_block_pvar: Pvar.t => bool;
with respect to the first argument. It returns an expression [e'] such that with respect to the first argument. It returns an expression [e'] such that
BinOp([binop], [e'], [exp1]) = [exp2]. If the [binop] operation is not invertible, BinOp([binop], [e'], [exp1]) = [exp2]. If the [binop] operation is not invertible,
the function raises an exception by calling "assert false". */ the function raises an exception by calling "assert false". */
let binop_invert: Binop.t => exp => exp => exp; let binop_invert: Binop.t => Exp.t => Exp.t => Exp.t;
let mem_kind_compare: mem_kind => mem_kind => int; let mem_kind_compare: mem_kind => mem_kind => int;
@ -435,15 +403,15 @@ let attribute_to_category: attribute => attribute_category;
let attr_is_undef: attribute => bool; let attr_is_undef: attribute => bool;
let exp_compare: exp => exp => int; let exp_compare: Exp.t => Exp.t => int;
let exp_equal: exp => exp => bool; let exp_equal: Exp.t => Exp.t => bool;
/** exp_is_array_index_of index arr returns true is index is an array index of arr. */ /** exp_is_array_index_of index arr returns true is index is an array index of arr. */
let exp_is_array_index_of: exp => exp => bool; let exp_is_array_index_of: Exp.t => Exp.t => bool;
let exp_typ_compare: (exp, Typ.t) => (exp, Typ.t) => int; let exp_typ_compare: (Exp.t, Typ.t) => (Exp.t, Typ.t) => int;
let instr_compare: instr => instr => int; let instr_compare: instr => instr => int;
@ -451,11 +419,11 @@ let instr_compare: instr => instr => int;
/** compare instructions from different procedures without considering loc's, ident's, and pvar's. /** compare instructions from different procedures without considering loc's, ident's, and pvar's.
the [exp_map] param gives a mapping of names used in the procedure of [instr1] to identifiers the [exp_map] param gives a mapping of names used in the procedure of [instr1] to identifiers
used in the procedure of [instr2] */ used in the procedure of [instr2] */
let instr_compare_structural: instr => instr => ExpMap.t exp => (int, ExpMap.t exp); let instr_compare_structural: instr => instr => ExpMap.t Exp.t => (int, ExpMap.t Exp.t);
let exp_list_compare: list exp => list exp => int; let exp_list_compare: list Exp.t => list Exp.t => int;
let exp_list_equal: list exp => list exp => bool; let exp_list_equal: list Exp.t => list Exp.t => bool;
let atom_compare: atom => atom => int; let atom_compare: atom => atom => int;
@ -486,11 +454,11 @@ let fld_strexp_compare: (Ident.fieldname, strexp) => (Ident.fieldname, strexp) =
let fld_strexp_list_compare: let fld_strexp_list_compare:
list (Ident.fieldname, strexp) => list (Ident.fieldname, strexp) => int; list (Ident.fieldname, strexp) => list (Ident.fieldname, strexp) => int;
let exp_strexp_compare: (exp, strexp) => (exp, strexp) => int; let exp_strexp_compare: (Exp.t, strexp) => (Exp.t, strexp) => int;
/** Return the lhs expression of a hpred */ /** Return the lhs expression of a hpred */
let hpred_get_lhs: hpred => exp; let hpred_get_lhs: hpred => Exp.t;
/** Return the value of the FA_sentinel attribute in [attr_list] if it is found */ /** Return the value of the FA_sentinel attribute in [attr_list] if it is found */
@ -519,39 +487,39 @@ let attribute_to_string: printenv => attribute => string;
/** Pretty print an expression. */ /** Pretty print an expression. */
let pp_exp: printenv => F.formatter => exp => unit; let pp_exp: printenv => F.formatter => Exp.t => unit;
/** Pretty print an expression with type. */ /** Pretty print an expression with type. */
let pp_exp_typ: printenv => F.formatter => (exp, Typ.t) => unit; let pp_exp_typ: printenv => F.formatter => (Exp.t, Typ.t) => unit;
/** Convert an expression to a string */ /** Convert an expression to a string */
let exp_to_string: exp => string; let exp_to_string: Exp.t => string;
/** dump an expression. */ /** dump an expression. */
let d_exp: exp => unit; let d_exp: Exp.t => unit;
/** Pretty print a type. */ /** Pretty print a type. */
let pp_texp: printenv => F.formatter => exp => unit; let pp_texp: printenv => F.formatter => Exp.t => unit;
/** Pretty print a type with all the details. */ /** Pretty print a type with all the details. */
let pp_texp_full: printenv => F.formatter => exp => unit; let pp_texp_full: printenv => F.formatter => Exp.t => unit;
/** Dump a type expression with all the details. */ /** Dump a type expression with all the details. */
let d_texp_full: exp => unit; let d_texp_full: Exp.t => unit;
/** Pretty print a list of expressions. */ /** Pretty print a list of expressions. */
let pp_exp_list: printenv => F.formatter => list exp => unit; let pp_exp_list: printenv => F.formatter => list Exp.t => unit;
/** Dump a list of expressions. */ /** Dump a list of expressions. */
let d_exp_list: list exp => unit; let d_exp_list: list Exp.t => unit;
/** Pretty print an offset */ /** Pretty print an offset */
@ -575,7 +543,7 @@ let instr_get_loc: instr => Location.t;
/** get the expressions occurring in the instruction */ /** get the expressions occurring in the instruction */
let instr_get_exps: instr => list exp; let instr_get_exps: instr => list Exp.t;
/** Pretty print an instruction. */ /** Pretty print an instruction. */
@ -688,17 +656,17 @@ let pp_hpred_env: printenv => option Predicates.env => F.formatter => hpred => u
index. This function "cleans" [exp] according to whether it is the index. This function "cleans" [exp] according to whether it is the
footprint or current part of the prop. footprint or current part of the prop.
The function faults in the re - execution mode, as an internal check of the tool. */ The function faults in the re - execution mode, as an internal check of the tool. */
let array_clean_new_index: bool => exp => exp; let array_clean_new_index: bool => Exp.t => Exp.t;
/** Change exps in strexp using [f]. */ /** Change exps in strexp using [f]. */
/** WARNING: the result might not be normalized. */ /** WARNING: the result might not be normalized. */
let strexp_expmap: ((exp, option inst) => (exp, option inst)) => strexp => strexp; let strexp_expmap: ((Exp.t, option inst) => (Exp.t, option inst)) => strexp => strexp;
/** Change exps in hpred by [f]. */ /** Change exps in hpred by [f]. */
/** WARNING: the result might not be normalized. */ /** WARNING: the result might not be normalized. */
let hpred_expmap: ((exp, option inst) => (exp, option inst)) => hpred => hpred; let hpred_expmap: ((Exp.t, option inst) => (Exp.t, option inst)) => hpred => hpred;
/** Change instrumentations in hpred using [f]. */ /** Change instrumentations in hpred using [f]. */
@ -707,89 +675,89 @@ let hpred_instmap: (inst => inst) => hpred => hpred;
/** Change exps in hpred list by [f]. */ /** Change exps in hpred list by [f]. */
/** WARNING: the result might not be normalized. */ /** WARNING: the result might not be normalized. */
let hpred_list_expmap: ((exp, option inst) => (exp, option inst)) => list hpred => list hpred; let hpred_list_expmap: ((Exp.t, option inst) => (Exp.t, option inst)) => list hpred => list hpred;
/** Change exps in atom by [f]. */ /** Change exps in atom by [f]. */
/** WARNING: the result might not be normalized. */ /** WARNING: the result might not be normalized. */
let atom_expmap: (exp => exp) => atom => atom; let atom_expmap: (Exp.t => Exp.t) => atom => atom;
/** Change exps in atom list by [f]. */ /** Change exps in atom list by [f]. */
/** WARNING: the result might not be normalized. */ /** WARNING: the result might not be normalized. */
let atom_list_expmap: (exp => exp) => list atom => list atom; let atom_list_expmap: (Exp.t => Exp.t) => list atom => list atom;
/** {2 Function for computing lexps in sigma} */ /** {2 Function for computing lexps in sigma} */
let hpred_list_get_lexps: (exp => bool) => list hpred => list exp; let hpred_list_get_lexps: (Exp.t => bool) => list hpred => list Exp.t;
/** {2 Utility Functions for Expressions} */ /** {2 Utility Functions for Expressions} */
/** Turn an expression representing a type into the type it represents /** Turn an expression representing a type into the type it represents
If not a sizeof, return the default type if given, otherwise raise an exception */ If not a sizeof, return the default type if given, otherwise raise an exception */
let texp_to_typ: option Typ.t => exp => Typ.t; let texp_to_typ: option Typ.t => Exp.t => Typ.t;
/** Return the root of [lexp]. */ /** Return the root of [lexp]. */
let root_of_lexp: exp => exp; let root_of_lexp: Exp.t => Exp.t;
/** Get an expression "undefined", the boolean indicates /** Get an expression "undefined", the boolean indicates
whether the undefined value goest into the footprint */ whether the undefined value goest into the footprint */
let exp_get_undefined: bool => exp; let exp_get_undefined: bool => Exp.t;
/** Checks whether an expression denotes a location using pointer arithmetic. /** Checks whether an expression denotes a location using pointer arithmetic.
Currently, catches array - indexing expressions such as a[i] only. */ Currently, catches array - indexing expressions such as a[i] only. */
let exp_pointer_arith: exp => bool; let exp_pointer_arith: Exp.t => bool;
/** Integer constant 0 */ /** Integer constant 0 */
let exp_zero: exp; let exp_zero: Exp.t;
/** Null constant */ /** Null constant */
let exp_null: exp; let exp_null: Exp.t;
/** Integer constant 1 */ /** Integer constant 1 */
let exp_one: exp; let exp_one: Exp.t;
/** Integer constant -1 */ /** Integer constant -1 */
let exp_minus_one: exp; let exp_minus_one: Exp.t;
/** Create integer constant */ /** Create integer constant */
let exp_int: IntLit.t => exp; let exp_int: IntLit.t => Exp.t;
/** Create float constant */ /** Create float constant */
let exp_float: float => exp; let exp_float: float => Exp.t;
/** Create integer constant corresponding to the boolean value */ /** Create integer constant corresponding to the boolean value */
let exp_bool: bool => exp; let exp_bool: bool => Exp.t;
/** Create expresstion [e1 == e2] */ /** Create expresstion [e1 == e2] */
let exp_eq: exp => exp => exp; let exp_eq: Exp.t => Exp.t => Exp.t;
/** Create expresstion [e1 != e2] */ /** Create expresstion [e1 != e2] */
let exp_ne: exp => exp => exp; let exp_ne: Exp.t => Exp.t => Exp.t;
/** Create expresstion [e1 <= e2] */ /** Create expresstion [e1 <= e2] */
let exp_le: exp => exp => exp; let exp_le: Exp.t => Exp.t => Exp.t;
/** Create expression [e1 < e2] */ /** Create expression [e1 < e2] */
let exp_lt: exp => exp => exp; let exp_lt: Exp.t => Exp.t => Exp.t;
/** {2 Functions for computing program variables} */ /** {2 Functions for computing program variables} */
let exp_fpv: exp => list Pvar.t; let exp_fpv: Exp.t => list Pvar.t;
let strexp_fpv: strexp => list Pvar.t; let strexp_fpv: strexp => list Pvar.t;
@ -870,13 +838,13 @@ let ident_list_fav_add: list Ident.t => fav => unit;
/** [exp_fav_add fav exp] extends [fav] with the free variables of [exp] */ /** [exp_fav_add fav exp] extends [fav] with the free variables of [exp] */
let exp_fav_add: fav => exp => unit; let exp_fav_add: fav => Exp.t => unit;
let exp_fav: exp => fav; let exp_fav: Exp.t => fav;
let exp_fav_list: exp => list Ident.t; let exp_fav_list: Exp.t => list Ident.t;
let ident_in_exp: Ident.t => exp => bool; let ident_in_exp: Ident.t => Exp.t => bool;
let strexp_fav_add: fav => strexp => unit; let strexp_fav_add: fav => strexp => unit;
@ -902,7 +870,7 @@ let hpara_dll_shallow_av: hpara_dll => fav;
variables. Thus, the functions essentially compute all the variables. Thus, the functions essentially compute all the
identifiers occuring in a parameter. Some variables can appear more identifiers occuring in a parameter. Some variables can appear more
than once in the result. */ than once in the result. */
let exp_av_add: fav => exp => unit; let exp_av_add: fav => Exp.t => unit;
let strexp_av_add: fav => strexp => unit; let strexp_av_add: fav => strexp => unit;
@ -920,15 +888,15 @@ type subst;
/** Create a substitution from a list of pairs. /** Create a substitution from a list of pairs.
For all (id1, e1), (id2, e2) in the input list, For all (id1, e1), (id2, e2) in the input list,
if id1 = id2, then e1 = e2. */ if id1 = id2, then e1 = e2. */
let sub_of_list: list (Ident.t, exp) => subst; let sub_of_list: list (Ident.t, Exp.t) => subst;
/** like sub_of_list, but allow duplicate ids and only keep the first occurrence */ /** like sub_of_list, but allow duplicate ids and only keep the first occurrence */
let sub_of_list_duplicates: list (Ident.t, exp) => subst; let sub_of_list_duplicates: list (Ident.t, Exp.t) => subst;
/** Convert a subst to a list of pairs. */ /** Convert a subst to a list of pairs. */
let sub_to_list: subst => list (Ident.t, exp); let sub_to_list: subst => list (Ident.t, Exp.t);
/** The empty substitution. */ /** The empty substitution. */
@ -960,7 +928,7 @@ let sub_symmetric_difference: subst => subst => (subst, subst, subst);
/** [sub_find filter sub] returns the expression associated to the first identifier /** [sub_find filter sub] returns the expression associated to the first identifier
that satisfies [filter]. that satisfies [filter].
Raise [Not_found] if there isn't one. */ Raise [Not_found] if there isn't one. */
let sub_find: (Ident.t => bool) => subst => exp; let sub_find: (Ident.t => bool) => subst => Exp.t;
/** [sub_filter filter sub] restricts the domain of [sub] to the /** [sub_filter filter sub] restricts the domain of [sub] to the
@ -970,12 +938,12 @@ let sub_filter: (Ident.t => bool) => subst => subst;
/** [sub_filter_exp filter sub] restricts the domain of [sub] to the /** [sub_filter_exp filter sub] restricts the domain of [sub] to the
identifiers satisfying [filter(id, sub(id))]. */ identifiers satisfying [filter(id, sub(id))]. */
let sub_filter_pair: ((Ident.t, exp) => bool) => subst => subst; let sub_filter_pair: ((Ident.t, Exp.t) => bool) => subst => subst;
/** [sub_range_partition filter sub] partitions [sub] according to /** [sub_range_partition filter sub] partitions [sub] according to
whether range expressions satisfy [filter]. */ whether range expressions satisfy [filter]. */
let sub_range_partition: (exp => bool) => subst => (subst, subst); let sub_range_partition: (Exp.t => bool) => subst => (subst, subst);
/** [sub_domain_partition filter sub] partitions [sub] according to /** [sub_domain_partition filter sub] partitions [sub] according to
@ -988,16 +956,16 @@ let sub_domain: subst => list Ident.t;
/** Return the list of expressions in the range of the substitution. */ /** Return the list of expressions in the range of the substitution. */
let sub_range: subst => list exp; let sub_range: subst => list Exp.t;
/** [sub_range_map f sub] applies [f] to the expressions in the range of [sub]. */ /** [sub_range_map f sub] applies [f] to the expressions in the range of [sub]. */
let sub_range_map: (exp => exp) => subst => subst; let sub_range_map: (Exp.t => Exp.t) => subst => subst;
/** [sub_map f g sub] applies the renaming [f] to identifiers in the domain /** [sub_map f g sub] applies the renaming [f] to identifiers in the domain
of [sub] and the substitution [g] to the expressions in the range of [sub]. */ of [sub] and the substitution [g] to the expressions in the range of [sub]. */
let sub_map: (Ident.t => Ident.t) => (exp => exp) => subst => subst; let sub_map: (Ident.t => Ident.t) => (Exp.t => Exp.t) => subst => subst;
/** Checks whether [id] belongs to the domain of [subst]. */ /** Checks whether [id] belongs to the domain of [subst]. */
@ -1005,7 +973,7 @@ let mem_sub: Ident.t => subst => bool;
/** Extend substitution and return [None] if not possible. */ /** Extend substitution and return [None] if not possible. */
let extend_sub: subst => Ident.t => exp => option subst; let extend_sub: subst => Ident.t => Exp.t => option subst;
/** Free auxilary variables in the domain and range of the /** Free auxilary variables in the domain and range of the
@ -1024,7 +992,7 @@ let sub_fpv: subst => list Pvar.t;
/** substitution functions */ /** substitution functions */
/** WARNING: these functions do not ensure that the results are normalized. */ /** WARNING: these functions do not ensure that the results are normalized. */
let exp_sub: subst => exp => exp; let exp_sub: subst => Exp.t => Exp.t;
let atom_sub: subst => atom => atom; let atom_sub: subst => atom => atom;
@ -1034,36 +1002,36 @@ let instr_sub: subst => instr => instr;
let hpred_sub: subst => hpred => hpred; let hpred_sub: subst => hpred => hpred;
let exp_sub_ids: (Ident.t => exp) => exp => exp; let exp_sub_ids: (Ident.t => Exp.t) => Exp.t => Exp.t;
/** apply [f] to id's in [instr]. if [sub_id_binders] is false, [f] is only applied to bound id's */ /** apply [f] to id's in [instr]. if [sub_id_binders] is false, [f] is only applied to bound id's */
let instr_sub_ids: sub_id_binders::bool => (Ident.t => exp) => instr => instr; let instr_sub_ids: sub_id_binders::bool => (Ident.t => Exp.t) => instr => instr;
/** {2 Functions for replacing occurrences of expressions.} */ /** {2 Functions for replacing occurrences of expressions.} */
/** The first parameter should define a partial function. /** The first parameter should define a partial function.
No parts of hpara are replaced by these functions. */ No parts of hpara are replaced by these functions. */
let exp_replace_exp: list (exp, exp) => exp => exp; let exp_replace_exp: list (Exp.t, Exp.t) => Exp.t => Exp.t;
let strexp_replace_exp: list (exp, exp) => strexp => strexp; let strexp_replace_exp: list (Exp.t, Exp.t) => strexp => strexp;
let atom_replace_exp: list (exp, exp) => atom => atom; let atom_replace_exp: list (Exp.t, Exp.t) => atom => atom;
let hpred_replace_exp: list (exp, exp) => hpred => hpred; let hpred_replace_exp: list (Exp.t, Exp.t) => hpred => hpred;
/** {2 Functions for constructing or destructing entities in this module} */ /** {2 Functions for constructing or destructing entities in this module} */
/** Extract the ids and pvars from an expression */ /** Extract the ids and pvars from an expression */
let exp_get_vars: exp => (list Ident.t, list Pvar.t); let exp_get_vars: Exp.t => (list Ident.t, list Pvar.t);
/** Compute the offset list of an expression */ /** Compute the offset list of an expression */
let exp_get_offsets: exp => list offset; let exp_get_offsets: Exp.t => list offset;
/** Add the offset list to an expression */ /** Add the offset list to an expression */
let exp_add_offsets: exp => list offset => exp; let exp_add_offsets: Exp.t => list offset => Exp.t;
let sigma_to_sigma_ne: list hpred => list (list atom, list hpred); let sigma_to_sigma_ne: list hpred => list (list atom, list hpred);
@ -1072,7 +1040,7 @@ let sigma_to_sigma_ne: list hpred => list (list atom, list hpred);
[e2] and [elist]. If [para = lambda (x, y, xs). exists zs. b], [e2] and [elist]. If [para = lambda (x, y, xs). exists zs. b],
then the result of the instantiation is [b\[e1 / x, e2 / y, elist / xs, _zs'/ zs\]] then the result of the instantiation is [b\[e1 / x, e2 / y, elist / xs, _zs'/ zs\]]
for some fresh [_zs'].*/ for some fresh [_zs'].*/
let hpara_instantiate: hpara => exp => exp => list exp => (list Ident.t, list hpred); let hpara_instantiate: hpara => Exp.t => Exp.t => list Exp.t => (list Ident.t, list hpred);
/** [hpara_dll_instantiate para cell blink flink elist] instantiates [para] with [cell], /** [hpara_dll_instantiate para cell blink flink elist] instantiates [para] with [cell],
@ -1080,6 +1048,7 @@ let hpara_instantiate: hpara => exp => exp => list exp => (list Ident.t, list hp
then the result of the instantiation is then the result of the instantiation is
[b\[cell / x, blink / y, flink / z, elist / xs, _zs'/ zs\]] [b\[cell / x, blink / y, flink / z, elist / xs, _zs'/ zs\]]
for some fresh [_zs'].*/ for some fresh [_zs'].*/
let hpara_dll_instantiate: hpara_dll => exp => exp => exp => list exp => (list Ident.t, list hpred); let hpara_dll_instantiate:
hpara_dll => Exp.t => Exp.t => Exp.t => list Exp.t => (list Ident.t, list hpred);
let custom_error: Pvar.t; let custom_error: Pvar.t;

@ -56,10 +56,10 @@ let create_fresh_primeds_ls para =
let f _ = Ident.create_fresh Ident.kprimed in let f _ = Ident.create_fresh Ident.kprimed in
IList.map f svars in IList.map f svars in
let ids_tuple = (id_base, id_next, id_end, ids_shared) in let ids_tuple = (id_base, id_next, id_end, ids_shared) in
let exp_base = Sil.Var id_base in let exp_base = Exp.Var id_base in
let exp_next = Sil.Var id_next in let exp_next = Exp.Var id_next in
let exp_end = Sil.Var id_end in let exp_end = Exp.Var id_end in
let exps_shared = IList.map (fun id -> Sil.Var id) ids_shared in let exps_shared = IList.map (fun id -> Exp.Var id) ids_shared in
let exps_tuple = (exp_base, exp_next, exp_end, exps_shared) in let exps_tuple = (exp_base, exp_next, exp_end, exps_shared) in
(ids_tuple, exps_tuple) (ids_tuple, exps_tuple)
@ -243,11 +243,11 @@ let mk_rule_ptspts_dll impl_ok1 impl_ok2 para =
let svars = para.Sil.svars_dll in let svars = para.Sil.svars_dll in
let f _ = Ident.create_fresh Ident.kprimed in let f _ = Ident.create_fresh Ident.kprimed in
IList.map f svars in IList.map f svars in
let exp_iF = Sil.Var id_iF in let exp_iF = Exp.Var id_iF in
let exp_iF' = Sil.Var id_iF' in let exp_iF' = Exp.Var id_iF' in
let exp_oB = Sil.Var id_oB in let exp_oB = Exp.Var id_oB in
let exp_oF = Sil.Var id_oF in let exp_oF = Exp.Var id_oF in
let exps_shared = IList.map (fun id -> Sil.Var id) ids_shared in let exps_shared = IList.map (fun id -> Exp.Var id) ids_shared in
let (ids_exist_fst, para_fst) = Sil.hpara_dll_instantiate para exp_iF exp_oB exp_iF' exps_shared in let (ids_exist_fst, para_fst) = Sil.hpara_dll_instantiate para exp_iF exp_oB exp_iF' exps_shared in
let (para_fst_start, para_fst_rest) = let (para_fst_start, para_fst_rest) =
let mark_impl_flag hpred = { Match.hpred = hpred; Match.flag = impl_ok1 } in let mark_impl_flag hpred = { Match.hpred = hpred; Match.flag = impl_ok1 } in
@ -291,12 +291,12 @@ let mk_rule_ptsdll_dll k2 impl_ok1 impl_ok2 para =
let svars = para.Sil.svars_dll in let svars = para.Sil.svars_dll in
let f _ = Ident.create_fresh Ident.kprimed in let f _ = Ident.create_fresh Ident.kprimed in
IList.map f svars in IList.map f svars in
let exp_iF = Sil.Var id_iF in let exp_iF = Exp.Var id_iF in
let exp_iF' = Sil.Var id_iF' in let exp_iF' = Exp.Var id_iF' in
let exp_oB = Sil.Var id_oB in let exp_oB = Exp.Var id_oB in
let exp_oF = Sil.Var id_oF in let exp_oF = Exp.Var id_oF in
let exp_iB = Sil.Var id_iB in let exp_iB = Exp.Var id_iB in
let exps_shared = IList.map (fun id -> Sil.Var id) ids_shared in let exps_shared = IList.map (fun id -> Exp.Var id) ids_shared in
let (ids_exist, para_inst) = Sil.hpara_dll_instantiate para exp_iF exp_oB exp_iF' exps_shared in let (ids_exist, para_inst) = Sil.hpara_dll_instantiate para exp_iF exp_oB exp_iF' exps_shared in
let (para_inst_start, para_inst_rest) = let (para_inst_start, para_inst_rest) =
match para_inst with match para_inst with
@ -327,12 +327,12 @@ let mk_rule_dllpts_dll k1 impl_ok1 impl_ok2 para =
let svars = para.Sil.svars_dll in let svars = para.Sil.svars_dll in
let f _ = Ident.create_fresh Ident.kprimed in let f _ = Ident.create_fresh Ident.kprimed in
IList.map f svars in IList.map f svars in
let exp_iF = Sil.Var id_iF in let exp_iF = Exp.Var id_iF in
let exp_iF' = Sil.Var id_iF' in let exp_iF' = Exp.Var id_iF' in
let exp_oB = Sil.Var id_oB in let exp_oB = Exp.Var id_oB in
let exp_oB' = Sil.Var id_oB' in let exp_oB' = Exp.Var id_oB' in
let exp_oF = Sil.Var id_oF in let exp_oF = Exp.Var id_oF in
let exps_shared = IList.map (fun id -> Sil.Var id) ids_shared in let exps_shared = IList.map (fun id -> Exp.Var id) ids_shared in
let (ids_exist, para_inst) = Sil.hpara_dll_instantiate para exp_iF' exp_oB' exp_oF exps_shared in let (ids_exist, para_inst) = Sil.hpara_dll_instantiate para exp_iF' exp_oB' exp_oF exps_shared in
let para_inst_pat = let para_inst_pat =
let allow_impl hpred = { Match.hpred = hpred; Match.flag = impl_ok2 } in let allow_impl hpred = { Match.hpred = hpred; Match.flag = impl_ok2 } in
@ -361,13 +361,13 @@ let mk_rule_dlldll_dll k1 k2 impl_ok1 impl_ok2 para =
let svars = para.Sil.svars_dll in let svars = para.Sil.svars_dll in
let f _ = Ident.create_fresh Ident.kprimed in let f _ = Ident.create_fresh Ident.kprimed in
IList.map f svars in IList.map f svars in
let exp_iF = Sil.Var id_iF in let exp_iF = Exp.Var id_iF in
let exp_iF' = Sil.Var id_iF' in let exp_iF' = Exp.Var id_iF' in
let exp_oB = Sil.Var id_oB in let exp_oB = Exp.Var id_oB in
let exp_oB' = Sil.Var id_oB' in let exp_oB' = Exp.Var id_oB' in
let exp_oF = Sil.Var id_oF in let exp_oF = Exp.Var id_oF in
let exp_iB = Sil.Var id_iB in let exp_iB = Exp.Var id_iB in
let exps_shared = IList.map (fun id -> Sil.Var id) ids_shared in let exps_shared = IList.map (fun id -> Exp.Var id) ids_shared in
let lseg_fst_pat = { Match.hpred = Prop.mk_dllseg k1 para exp_iF exp_oB exp_iF' exp_oB' exps_shared; Match.flag = impl_ok1 } in let lseg_fst_pat = { Match.hpred = Prop.mk_dllseg k1 para exp_iF exp_oB exp_iF' exp_oB' exps_shared; Match.flag = impl_ok1 } in
let lseg_snd_pat = { Match.hpred = Prop.mk_dllseg k2 para exp_iF' exp_oB' exp_oF exp_iB exps_shared; Match.flag = impl_ok2 } in let lseg_snd_pat = { Match.hpred = Prop.mk_dllseg k2 para exp_iF' exp_oB' exp_oF exp_iB exps_shared; Match.flag = impl_ok2 } in
let k_res = lseg_kind_add k1 k2 in let k_res = lseg_kind_add k1 k2 in
@ -420,15 +420,15 @@ let typ_get_recursive_flds tenv typ_exp =
false false
in in
match typ_exp with match typ_exp with
| Sil.Sizeof (typ, _, _) -> | Exp.Sizeof (typ, _, _) ->
(match Tenv.expand_type tenv typ with (match Tenv.expand_type tenv typ with
| Typ.Tint _ | Typ.Tvoid | Typ.Tfun _ | Typ.Tptr _ | Typ.Tfloat _ -> [] | Typ.Tint _ | Typ.Tvoid | Typ.Tfun _ | Typ.Tptr _ | Typ.Tfloat _ -> []
| Typ.Tstruct { Typ.instance_fields } -> | Typ.Tstruct { Typ.instance_fields } ->
IList.map (fun (x, _, _) -> x) (IList.filter (filter typ) instance_fields) IList.map (fun (x, _, _) -> x) (IList.filter (filter typ) instance_fields)
| Typ.Tarray _ -> [] | Typ.Tarray _ -> []
| Typ.Tvar _ -> assert false) | Typ.Tvar _ -> assert false)
| Sil.Var _ -> [] (* type of |-> not known yet *) | Exp.Var _ -> [] (* type of |-> not known yet *)
| Sil.Const _ -> [] | Exp.Const _ -> []
| _ -> | _ ->
L.err "@.typ_get_recursive: unexpected type expr: %a@." (Sil.pp_exp pe_text) typ_exp; L.err "@.typ_get_recursive: unexpected type expr: %a@." (Sil.pp_exp pe_text) typ_exp;
assert false assert false
@ -597,7 +597,7 @@ let eqs_sub subst eqs =
IList.map (fun (e1, e2) -> (Sil.exp_sub subst e1, Sil.exp_sub subst e2)) eqs IList.map (fun (e1, e2) -> (Sil.exp_sub subst e1, Sil.exp_sub subst e2)) eqs
let eqs_solve ids_in eqs_in = let eqs_solve ids_in eqs_in =
let rec solve (sub: Sil.subst) (eqs: (Sil.exp * Sil.exp) list) : Sil.subst option = let rec solve (sub: Sil.subst) (eqs: (Exp.t * Exp.t) list) : Sil.subst option =
let do_default id e eqs_rest = let do_default id e eqs_rest =
if not (IList.exists (fun id' -> Ident.equal id id') ids_in) then None if not (IList.exists (fun id' -> Ident.equal id id') ids_in) then None
else else
@ -610,11 +610,11 @@ let eqs_solve ids_in eqs_in =
| [] -> Some sub | [] -> Some sub
| (e1, e2) :: eqs_rest when Sil.exp_equal e1 e2 -> | (e1, e2) :: eqs_rest when Sil.exp_equal e1 e2 ->
solve sub eqs_rest solve sub eqs_rest
| (Sil.Var id1, (Sil.Const _ as e2)) :: eqs_rest -> | (Exp.Var id1, (Exp.Const _ as e2)) :: eqs_rest ->
do_default id1 e2 eqs_rest do_default id1 e2 eqs_rest
| ((Sil.Const _ as e1), (Sil.Var _ as e2)) :: eqs_rest -> | ((Exp.Const _ as e1), (Exp.Var _ as e2)) :: eqs_rest ->
solve sub ((e2, e1):: eqs_rest) solve sub ((e2, e1):: eqs_rest)
| ((Sil.Var id1 as e1), (Sil.Var id2 as e2)) :: eqs_rest -> | ((Exp.Var id1 as e1), (Exp.Var id2 as e2)) :: eqs_rest ->
let n = Ident.compare id1 id2 in let n = Ident.compare id1 id2 in
begin begin
if n = 0 then solve sub eqs_rest if n = 0 then solve sub eqs_rest
@ -777,15 +777,15 @@ let abstract_pure_part p ~(from_abstract_footprint: bool) =
(fun pi a -> (fun pi a ->
match a with match a with
(* we only use Lt and Le because Gt and Ge are inserted in terms of Lt and Le. *) (* we only use Lt and Le because Gt and Ge are inserted in terms of Lt and Le. *)
| Sil.Aeq (Sil.Const (Const.Cint i), Sil.BinOp (Binop.Lt, _, _)) | Sil.Aeq (Exp.Const (Const.Cint i), Exp.BinOp (Binop.Lt, _, _))
| Sil.Aeq (Sil.BinOp (Binop.Lt, _, _), Sil.Const (Const.Cint i)) | Sil.Aeq (Exp.BinOp (Binop.Lt, _, _), Exp.Const (Const.Cint i))
| Sil.Aeq (Sil.Const (Const.Cint i), Sil.BinOp (Binop.Le, _, _)) | Sil.Aeq (Exp.Const (Const.Cint i), Exp.BinOp (Binop.Le, _, _))
| Sil.Aeq (Sil.BinOp (Binop.Le, _, _), Sil.Const (Const.Cint i)) when IntLit.isone i -> | Sil.Aeq (Exp.BinOp (Binop.Le, _, _), Exp.Const (Const.Cint i)) when IntLit.isone i ->
a :: pi a :: pi
| Sil.Aeq (Sil.Var name, e) when not (Ident.is_primed name) -> | Sil.Aeq (Exp.Var name, e) when not (Ident.is_primed name) ->
(match e with (match e with
| Sil.Var _ | Exp.Var _
| Sil.Const _ -> a :: pi | Exp.Const _ -> a :: pi
| _ -> pi) | _ -> pi)
| Sil.Aneq (Var _, _) | Sil.Aneq (Var _, _)
| Sil.Apred (_, Var _ :: _) | Anpred (_, Var _ :: _) -> a :: pi | Sil.Apred (_, Var _ :: _) | Anpred (_, Var _ :: _) -> a :: pi
@ -855,7 +855,7 @@ let sigma_reachable root_fav sigma =
IList.iter add_entry (hpred_entries hpred) in IList.iter add_entry (hpred_entries hpred) in
IList.iter do_hpred sigma; IList.iter do_hpred sigma;
let edge_fires (e, _) = match e with let edge_fires (e, _) = match e with
| Sil.Var id -> | Exp.Var id ->
if (Ident.is_primed id || Ident.is_footprint id) then Ident.IdentSet.mem id !reach_set if (Ident.is_primed id || Ident.is_footprint id) then Ident.IdentSet.mem id !reach_set
else true else true
| _ -> true in | _ -> true in
@ -873,7 +873,7 @@ let sigma_reachable root_fav sigma =
if modified then find_fixpoint edges_to_revisit in if modified then find_fixpoint edges_to_revisit in
find_fixpoint !edges; find_fixpoint !edges;
(* L.d_str "reachable: "; (* L.d_str "reachable: ";
Ident.IdentSet.iter (fun id -> Sil.d_exp (Sil.Var id); L.d_str " ") !reach_set; Ident.IdentSet.iter (fun id -> Sil.d_exp (Exp.Var id); L.d_str " ") !reach_set;
L.d_ln (); *) L.d_ln (); *)
!reach_set !reach_set
@ -912,14 +912,14 @@ let get_cycle root prop =
let visited' = (fst et_src):: visited in let visited' = (fst et_src):: visited in
let res = (match get_points_to e with let res = (match get_points_to e with
| None -> path, false | None -> path, false
| Some (Sil.Hpointsto (_, Sil.Estruct (fl, _), Sil.Sizeof (te, _, _))) -> | Some (Sil.Hpointsto (_, Sil.Estruct (fl, _), Exp.Sizeof (te, _, _))) ->
dfs e_root (e, te) ((et_src, f, e):: path) fl visited' dfs e_root (e, te) ((et_src, f, e):: path) fl visited'
| _ -> path, false (* check for lists *)) in | _ -> path, false (* check for lists *)) in
if snd res then res if snd res then res
else dfs e_root et_src path el' visited') in else dfs e_root et_src path el' visited') in
L.d_strln "Looking for cycle with root expression: "; Sil.d_hpred root; L.d_strln ""; L.d_strln "Looking for cycle with root expression: "; Sil.d_hpred root; L.d_strln "";
match root with match root with
| Sil.Hpointsto (e_root, Sil.Estruct (fl, _), Sil.Sizeof (te, _, _)) -> | Sil.Hpointsto (e_root, Sil.Estruct (fl, _), Exp.Sizeof (te, _, _)) ->
let se_root = Sil.Eexp(e_root, Sil.Inone) in let se_root = Sil.Eexp(e_root, Sil.Inone) in
(* start dfs with empty path and expr pointing to root *) (* start dfs with empty path and expr pointing to root *)
let (pot_cycle, res) = dfs se_root (se_root, te) [] fl [] in let (pot_cycle, res) = dfs se_root (se_root, te) [] fl [] in
@ -937,8 +937,8 @@ let get_cycle root prop =
returns the bucket *) returns the bucket *)
let should_raise_objc_leak hpred = let should_raise_objc_leak hpred =
match hpred with match hpred with
| Sil.Hpointsto(_, Sil.Estruct((fn, Sil.Eexp( (Sil.Const (Const.Cint i)), _)):: _, _), | Sil.Hpointsto(_, Sil.Estruct((fn, Sil.Eexp( (Exp.Const (Const.Cint i)), _)):: _, _),
Sil.Sizeof (typ, _, _)) Exp.Sizeof (typ, _, _))
when Ident.fieldname_is_hidden fn && IntLit.gt i IntLit.zero (* counter > 0 *) -> when Ident.fieldname_is_hidden fn && IntLit.gt i IntLit.zero (* counter > 0 *) ->
Mleak_buckets.should_raise_objc_leak typ Mleak_buckets.should_raise_objc_leak typ
| _ -> None | _ -> None
@ -954,11 +954,11 @@ let get_var_retain_cycle _prop =
let sigma = Prop.get_sigma _prop in let sigma = Prop.get_sigma _prop in
let is_pvar v h = let is_pvar v h =
match h with match h with
| Sil.Hpointsto (Sil.Lvar _, v', _) when Sil.strexp_equal v v' -> true | Sil.Hpointsto (Exp.Lvar _, v', _) when Sil.strexp_equal v v' -> true
| _ -> false in | _ -> false in
let is_hpred_block v h = let is_hpred_block v h =
match h, v with match h, v with
| Sil.Hpointsto (e, _, Sil.Sizeof (typ, _, _)), Sil.Eexp (e', _) | Sil.Hpointsto (e, _, Exp.Sizeof (typ, _, _)), Sil.Eexp (e', _)
when Sil.exp_equal e e' && Typ.is_block_type typ -> true when Sil.exp_equal e e' && Typ.is_block_type typ -> true
| _, _ -> false in | _, _ -> false in
let find v = let find v =
@ -968,7 +968,7 @@ let get_var_retain_cycle _prop =
with Not_found -> None in with Not_found -> None in
let find_block v = let find_block v =
if (IList.exists (is_hpred_block v) sigma) then if (IList.exists (is_hpred_block v) sigma) then
Some (Sil.Lvar Sil.block_pvar) Some (Exp.Lvar Sil.block_pvar)
else None in else None in
let sexp e = Sil.Eexp (e, Sil.Inone) in let sexp e = Sil.Eexp (e, Sil.Inone) in
let find_or_block ((e, t), f, e') = let find_or_block ((e, t), f, e') =
@ -976,7 +976,7 @@ let get_var_retain_cycle _prop =
| Some pvar -> [((sexp pvar, t), f, e')] | Some pvar -> [((sexp pvar, t), f, e')]
| _ -> (match find_block e with | _ -> (match find_block e with
| Some blk -> [((sexp blk, t), f, e')] | Some blk -> [((sexp blk, t), f, e')]
| _ -> [((sexp (Sil.Sizeof (t, None, Subtype.exact)), t), f, e')]) in | _ -> [((sexp (Exp.Sizeof (t, None, Subtype.exact)), t), f, e')]) in
(* returns the pvars of the first cycle we find in sigma. (* returns the pvars of the first cycle we find in sigma.
This is an heuristic that works if there is one cycle. This is an heuristic that works if there is one cycle.
In case there are more than one cycle we may return not necessarily In case there are more than one cycle we may return not necessarily
@ -1056,7 +1056,7 @@ let check_junk ?original_prop pname tenv prop =
fun id -> Ident.IdentSet.mem id reach_set in fun id -> Ident.IdentSet.mem id reach_set in
let should_remove_hpred entries = let should_remove_hpred entries =
let predicate = function let predicate = function
| Sil.Var id -> | Exp.Var id ->
(Ident.is_primed id || Ident.is_footprint id) (Ident.is_primed id || Ident.is_footprint id)
&& not (Sil.fav_mem fav_root id) && not (id_considered_reachable id) && not (Sil.fav_mem fav_root id) && not (id_considered_reachable id)
| _ -> false in | _ -> false in
@ -1070,10 +1070,10 @@ let check_junk ?original_prop pname tenv prop =
Ident.IdentSet.mem id set3 in Ident.IdentSet.mem id set3 in
let entries = hpred_entries hpred in let entries = hpred_entries hpred in
let predicate = function let predicate = function
| Sil.Var id -> id_in_cycle id | Exp.Var id -> id_in_cycle id
| _ -> false in | _ -> false in
let hpred_is_loop = match hpred with (* true if hpred has a self loop, ie one field points to id *) let hpred_is_loop = match hpred with (* true if hpred has a self loop, ie one field points to id *)
| Sil.Hpointsto (Sil.Var id, se, _) -> | Sil.Hpointsto (Exp.Var id, se, _) ->
let fav = Sil.fav_new () in let fav = Sil.fav_new () in
Sil.strexp_fav_add fav se; Sil.strexp_fav_add fav se;
Sil.fav_mem fav id Sil.fav_mem fav id
@ -1226,13 +1226,13 @@ let abstract_prop pname tenv ~(rename_primed: bool) ~(from_abstract_footprint: b
let get_local_stack cur_sigma init_sigma = let get_local_stack cur_sigma init_sigma =
let filter_stack = function let filter_stack = function
| Sil.Hpointsto (Sil.Lvar _, _, _) -> true | Sil.Hpointsto (Exp.Lvar _, _, _) -> true
| Sil.Hpointsto _ | Sil.Hlseg _ | Sil.Hdllseg _ -> false in | Sil.Hpointsto _ | Sil.Hlseg _ | Sil.Hdllseg _ -> false in
let get_stack_var = function let get_stack_var = function
| Sil.Hpointsto (Sil.Lvar pvar, _, _) -> pvar | Sil.Hpointsto (Exp.Lvar pvar, _, _) -> pvar
| Sil.Hpointsto _ | Sil.Hlseg _ | Sil.Hdllseg _ -> assert false in | Sil.Hpointsto _ | Sil.Hlseg _ | Sil.Hdllseg _ -> assert false in
let filter_local_stack olds = function let filter_local_stack olds = function
| Sil.Hpointsto (Sil.Lvar pvar, _, _) -> not (IList.exists (Pvar.equal pvar) olds) | Sil.Hpointsto (Exp.Lvar pvar, _, _) -> not (IList.exists (Pvar.equal pvar) olds)
| Sil.Hpointsto _ | Sil.Hlseg _ | Sil.Hdllseg _ -> false in | Sil.Hpointsto _ | Sil.Hlseg _ | Sil.Hdllseg _ -> false in
let init_stack = IList.filter filter_stack init_sigma in let init_stack = IList.filter filter_stack init_sigma in
let init_stack_pvars = IList.map get_stack_var init_stack in let init_stack_pvars = IList.map get_stack_var init_stack in
@ -1252,7 +1252,7 @@ let extract_footprint_for_abs (p : 'a Prop.t) : Prop.exposed Prop.t * Pvar.t lis
let remove_local_stack sigma pvars = let remove_local_stack sigma pvars =
let filter_non_stack = function let filter_non_stack = function
| Sil.Hpointsto (Sil.Lvar pvar, _, _) -> not (IList.exists (Pvar.equal pvar) pvars) | Sil.Hpointsto (Exp.Lvar pvar, _, _) -> not (IList.exists (Pvar.equal pvar) pvars)
| Sil.Hpointsto _ | Sil.Hlseg _ | Sil.Hdllseg _ -> true in | Sil.Hpointsto _ | Sil.Hlseg _ | Sil.Hdllseg _ -> true in
IList.filter filter_non_stack sigma IList.filter filter_non_stack sigma

@ -23,10 +23,10 @@ module StrexpMatch : sig
type path type path
(** convert a path into a list of expressions *) (** convert a path into a list of expressions *)
val path_to_exps : path -> Sil.exp list val path_to_exps : path -> Exp.t list
(** create a path from a root and a list of offsets *) (** create a path from a root and a list of offsets *)
val path_from_exp_offsets : Sil.exp -> Sil.offset list -> path val path_from_exp_offsets : Exp.t -> Sil.offset list -> path
(** path to the root, length, elements and type of a new_array *) (** path to the root, length, elements and type of a new_array *)
type strexp_data = path * Sil.strexp * Typ.t type strexp_data = path * Sil.strexp * Typ.t
@ -47,7 +47,7 @@ module StrexpMatch : sig
val replace_strexp : bool -> t -> Sil.strexp -> sigma val replace_strexp : bool -> t -> Sil.strexp -> sigma
(** Replace the index in the array at a given position with the new index *) (** Replace the index in the array at a given position with the new index *)
val replace_index : bool -> t -> Sil.exp -> Sil.exp -> sigma val replace_index : bool -> t -> Exp.t -> Exp.t -> sigma
(* (*
(** Get the partition of the sigma: the unmatched part of the sigma and the matched hpred *) (** Get the partition of the sigma: the unmatched part of the sigma and the matched hpred *)
val get_sigma_partition : t -> sigma * Sil.hpred val get_sigma_partition : t -> sigma * Sil.hpred
@ -58,10 +58,10 @@ module StrexpMatch : sig
end = struct end = struct
(** syntactic offset *) (** syntactic offset *)
type syn_offset = Field of Ident.fieldname * Typ.t | Index of Sil.exp type syn_offset = Field of Ident.fieldname * Typ.t | Index of Exp.t
(** path through an Estruct *) (** path through an Estruct *)
type path = Sil.exp * (syn_offset list) type path = Exp.t * (syn_offset list)
(** Find a strexp and a type at the given syntactic offset list *) (** Find a strexp and a type at the given syntactic offset list *)
let rec get_strexp_at_syn_offsets se t syn_offs = let rec get_strexp_at_syn_offsets se t syn_offs =
@ -110,10 +110,10 @@ end = struct
let rec convert acc = function let rec convert acc = function
| [] -> acc | [] -> acc
| Field (f, t) :: syn_offs' -> | Field (f, t) :: syn_offs' ->
let acc' = IList.map (fun e -> Sil.Lfield (e, f, t)) acc in let acc' = IList.map (fun e -> Exp.Lfield (e, f, t)) acc in
convert acc' syn_offs' convert acc' syn_offs'
| Index idx :: syn_offs' -> | Index idx :: syn_offs' ->
let acc' = IList.map (fun e -> Sil.Lindex (e, idx)) acc in let acc' = IList.map (fun e -> Exp.Lindex (e, idx)) acc in
convert acc' syn_offs' in convert acc' syn_offs' in
begin begin
convert [root] syn_offs_in convert [root] syn_offs_in
@ -232,7 +232,7 @@ end = struct
replace_hpred (sigma, hpred, syn_offs) hpred' replace_hpred (sigma, hpred, syn_offs) hpred'
(** Replace the index in the array at a given position with the new index *) (** Replace the index in the array at a given position with the new index *)
let replace_index footprint_part ((sigma, hpred, syn_offs) : t) (index: Sil.exp) (index': Sil.exp) = let replace_index footprint_part ((sigma, hpred, syn_offs) : t) (index: Exp.t) (index': Exp.t) =
let update se' = let update se' =
match se' with match se' with
| Sil.Earray (len, esel, inst) -> | Sil.Earray (len, esel, inst) ->
@ -260,14 +260,14 @@ end
let prop_replace_path_index let prop_replace_path_index
(p: Prop.exposed Prop.t) (p: Prop.exposed Prop.t)
(path: StrexpMatch.path) (path: StrexpMatch.path)
(map : (Sil.exp * Sil.exp) list) : Prop.exposed Prop.t (map : (Exp.t * Exp.t) list) : Prop.exposed Prop.t
= =
let elist_path = StrexpMatch.path_to_exps path in let elist_path = StrexpMatch.path_to_exps path in
let expmap_list = let expmap_list =
IList.fold_left (fun acc_outer e_path -> IList.fold_left (fun acc_outer e_path ->
IList.fold_left (fun acc_inner (old_index, new_index) -> IList.fold_left (fun acc_inner (old_index, new_index) ->
let old_e_path_index = Prop.exp_normalize_prop p (Sil.Lindex(e_path, old_index)) in let old_e_path_index = Prop.exp_normalize_prop p (Exp.Lindex(e_path, old_index)) in
let new_e_path_index = Prop.exp_normalize_prop p (Sil.Lindex(e_path, new_index)) in let new_e_path_index = Prop.exp_normalize_prop p (Exp.Lindex(e_path, new_index)) in
(old_e_path_index, new_e_path_index) :: acc_inner (old_e_path_index, new_e_path_index) :: acc_inner
) acc_outer map ) acc_outer map
) [] elist_path in ) [] elist_path in
@ -348,13 +348,13 @@ let generic_strexp_abstract
(** Return [true] if there's a pointer to the index *) (** Return [true] if there's a pointer to the index *)
let index_is_pointed_to (p: Prop.normal Prop.t) (path: StrexpMatch.path) (index: Sil.exp) : bool = let index_is_pointed_to (p: Prop.normal Prop.t) (path: StrexpMatch.path) (index: Exp.t) : bool =
let indices = let indices =
let index_plus_one = Sil.BinOp(Binop.PlusA, index, Sil.exp_one) in let index_plus_one = Exp.BinOp(Binop.PlusA, index, Sil.exp_one) in
[index; index_plus_one] in [index; index_plus_one] in
let add_index_to_paths = let add_index_to_paths =
let elist_path = StrexpMatch.path_to_exps path in let elist_path = StrexpMatch.path_to_exps path in
let add_index i e = Prop.exp_normalize_prop p (Sil.Lindex(e, i)) in let add_index i e = Prop.exp_normalize_prop p (Exp.Lindex(e, i)) in
fun i -> IList.map (add_index i) elist_path in fun i -> IList.map (add_index i) elist_path in
let pointers = IList.flatten (IList.map add_index_to_paths indices) in let pointers = IList.flatten (IList.map add_index_to_paths indices) in
let filter = function let filter = function
@ -367,10 +367,12 @@ let index_is_pointed_to (p: Prop.normal Prop.t) (path: StrexpMatch.path) (index:
let blur_array_index let blur_array_index
(p: Prop.normal Prop.t) (p: Prop.normal Prop.t)
(path: StrexpMatch.path) (path: StrexpMatch.path)
(index: Sil.exp) : Prop.normal Prop.t (index: Exp.t) : Prop.normal Prop.t
= =
try try
let fresh_index = Sil.Var (Ident.create_fresh (if !Config.footprint then Ident.kfootprint else Ident.kprimed)) in let fresh_index =
Exp.Var
(Ident.create_fresh (if !Config.footprint then Ident.kfootprint else Ident.kprimed)) in
let p2 = let p2 =
try try
if !Config.footprint then if !Config.footprint then
@ -387,8 +389,8 @@ let blur_array_index
let sigma' = StrexpMatch.replace_index false matched index fresh_index in let sigma' = StrexpMatch.replace_index false matched index fresh_index in
Prop.replace_sigma sigma' p2 in Prop.replace_sigma sigma' p2 in
let p4 = let p4 =
let index_next = Sil.BinOp(Binop.PlusA, index, Sil.exp_one) in let index_next = Exp.BinOp(Binop.PlusA, index, Sil.exp_one) in
let fresh_index_next = Sil.BinOp (Binop.PlusA, fresh_index, Sil.exp_one) in let fresh_index_next = Exp.BinOp (Binop.PlusA, fresh_index, Sil.exp_one) in
let map = [(index, fresh_index); (index_next, fresh_index_next)] in let map = [(index, fresh_index); (index_next, fresh_index_next)] in
prop_replace_path_index p3 path map in prop_replace_path_index p3 path map in
Prop.normalize p4 Prop.normalize p4
@ -399,7 +401,7 @@ let blur_array_index
let blur_array_indices let blur_array_indices
(p: Prop.normal Prop.t) (p: Prop.normal Prop.t)
(root: StrexpMatch.path) (root: StrexpMatch.path)
(indices: Sil.exp list) : Prop.normal Prop.t * bool (indices: Exp.t list) : Prop.normal Prop.t * bool
= =
let f prop index = blur_array_index prop root index in let f prop index = blur_array_index prop root index in
(IList.fold_left f p indices, IList.length indices > 0) (IList.fold_left f p indices, IList.length indices > 0)
@ -409,7 +411,7 @@ let blur_array_indices
let keep_only_indices let keep_only_indices
(p: Prop.normal Prop.t) (p: Prop.normal Prop.t)
(path: StrexpMatch.path) (path: StrexpMatch.path)
(indices: Sil.exp list) : Prop.normal Prop.t * bool (indices: Exp.t list) : Prop.normal Prop.t * bool
= =
let prune_sigma footprint_part sigma = let prune_sigma footprint_part sigma =
try try
@ -496,8 +498,8 @@ let strexp_do_abstract
(* array case re-execution: remove and blur constant and primed indices *) (* array case re-execution: remove and blur constant and primed indices *)
let is_pointed index = index_is_pointed_to p path index in let is_pointed index = index_is_pointed_to p path index in
let should_keep (index, _) = match index with let should_keep (index, _) = match index with
| Sil.Const _ -> is_pointed index | Exp.Const _ -> is_pointed index
| Sil.Var id -> Ident.is_normal id || is_pointed index | Exp.Var id -> Ident.is_normal id || is_pointed index
| _ -> false in | _ -> false in
let abstract = prune_and_blur_indices path in let abstract = prune_and_blur_indices path in
filter_abstract Sil.d_exp_list should_keep abstract esel [] in filter_abstract Sil.d_exp_list should_keep abstract esel [] in
@ -567,8 +569,8 @@ let remove_redundant_elements prop =
let favl_curr = Sil.fav_to_list fav_curr in let favl_curr = Sil.fav_to_list fav_curr in
let favl_foot = Sil.fav_to_list fav_foot in let favl_foot = Sil.fav_to_list fav_foot in
Sil.fav_duplicates := false; Sil.fav_duplicates := false;
(* L.d_str "favl_curr "; IList.iter (fun id -> Sil.d_exp (Sil.Var id)) favl_curr; L.d_ln(); (* L.d_str "favl_curr "; IList.iter (fun id -> Sil.d_exp (Exp.Var id)) favl_curr; L.d_ln();
L.d_str "favl_foot "; IList.iter (fun id -> Sil.d_exp (Sil.Var id)) favl_foot; L.d_ln(); *) L.d_str "favl_foot "; IList.iter (fun id -> Sil.d_exp (Exp.Var id)) favl_foot; L.d_ln(); *)
let num_occur l id = IList.length (IList.filter (fun id' -> Ident.equal id id') l) in let num_occur l id = IList.length (IList.filter (fun id' -> Ident.equal id id') l) in
let at_most_once v = let at_most_once v =
num_occur favl_curr v <= 1 && num_occur favl_foot v <= 1 in num_occur favl_curr v <= 1 && num_occur favl_foot v <= 1 in
@ -581,10 +583,10 @@ let remove_redundant_elements prop =
modified := true; modified := true;
false in false in
match e, se with match e, se with
| Sil.Const (Const.Cint i), Sil.Eexp (Sil.Var id, _) | Exp.Const (Const.Cint i), Sil.Eexp (Exp.Var id, _)
when (not fp_part || IntLit.iszero i) && not (Ident.is_normal id) && occurs_at_most_once id -> when (not fp_part || IntLit.iszero i) && not (Ident.is_normal id) && occurs_at_most_once id ->
remove () (* unknown value can be removed in re-execution mode or if the index is zero *) remove () (* unknown value can be removed in re-execution mode or if the index is zero *)
| Sil.Var id, Sil.Eexp _ when Ident.is_normal id = false && occurs_at_most_once id -> | Exp.Var id, Sil.Eexp _ when Ident.is_normal id = false && occurs_at_most_once id ->
remove () (* index unknown can be removed *) remove () (* index unknown can be removed *)
| _ -> true in | _ -> true in
let remove_redundant_se fp_part = function let remove_redundant_se fp_part = function

@ -62,7 +62,7 @@ let check_access access_opt de_opt =
IList.exists (Mangled.equal name) formal_names in IList.exists (Mangled.equal name) formal_names in
let formal_ids = ref [] in let formal_ids = ref [] in
let process_formal_letref = function let process_formal_letref = function
| Sil.Letderef (id, Sil.Lvar pvar, _, _) -> | Sil.Letderef (id, Exp.Lvar pvar, _, _) ->
let is_java_this = let is_java_this =
!Config.curr_language = Config.Java && Pvar.is_this pvar in !Config.curr_language = Config.Java && Pvar.is_this pvar in
if not is_java_this && is_formal pvar then formal_ids := id :: !formal_ids if not is_java_this && is_formal pvar then formal_ids := id :: !formal_ids
@ -72,10 +72,10 @@ let check_access access_opt de_opt =
let formal_param_used_in_call = ref false in let formal_param_used_in_call = ref false in
let has_call_or_sets_null node = let has_call_or_sets_null node =
let rec exp_is_null exp = match exp with let rec exp_is_null exp = match exp with
| Sil.Const (Const.Cint n) -> IntLit.iszero n | Exp.Const (Const.Cint n) -> IntLit.iszero n
| Sil.Cast (_, e) -> exp_is_null e | Exp.Cast (_, e) -> exp_is_null e
| Sil.Var _ | Exp.Var _
| Sil.Lvar _ -> | Exp.Lvar _ ->
begin begin
match State.get_const_map () node exp with match State.get_const_map () node exp with
| Some (Const.Cint n) -> | Some (Const.Cint n) ->
@ -87,7 +87,7 @@ let check_access access_opt de_opt =
| Sil.Call (_, _, etl, _, _) -> | Sil.Call (_, _, etl, _, _) ->
let formal_ids = find_formal_ids node in let formal_ids = find_formal_ids node in
let arg_is_formal_param (e, _) = match e with let arg_is_formal_param (e, _) = match e with
| Sil.Var id -> IList.exists (Ident.equal id) formal_ids | Exp.Var id -> IList.exists (Ident.equal id) formal_ids
| _ -> false in | _ -> false in
if IList.exists arg_is_formal_param etl then formal_param_used_in_call := true; if IList.exists arg_is_formal_param etl then formal_param_used_in_call := true;
true true

@ -18,7 +18,7 @@ type args = {
prop_ : Prop.normal Prop.t; prop_ : Prop.normal Prop.t;
path : Paths.Path.t; path : Paths.Path.t;
ret_ids : Ident.t list; ret_ids : Ident.t list;
args : (Sil.exp * Typ.t) list; args : (Exp.t * Typ.t) list;
proc_name : Procname.t; proc_name : Procname.t;
loc : Location.t; loc : Location.t;
} }

@ -18,7 +18,7 @@ type args = {
prop_ : Prop.normal Prop.t; prop_ : Prop.normal Prop.t;
path : Paths.Path.t; path : Paths.Path.t;
ret_ids : Ident.t list; ret_ids : Ident.t list;
args : (Sil.exp * Typ.t) list; args : (Exp.t * Typ.t) list;
proc_name : Procname.t; proc_name : Procname.t;
loc : Location.t; loc : Location.t;
} }

@ -67,7 +67,7 @@ let do_side side f e1 e2 =
module EPset = Set.Make module EPset = Set.Make
(struct (struct
type t = Sil.exp * Sil.exp type t = Exp.t * Exp.t
let compare (e1, e1') (e2, e2') = let compare (e1, e1') (e2, e2') =
match (Sil.exp_compare e1 e2) with match (Sil.exp_compare e1 e2) with
| i when i <> 0 -> i | i when i <> 0 -> i
@ -80,8 +80,8 @@ module NonInj : sig
val init : unit -> unit val init : unit -> unit
val final : unit -> unit val final : unit -> unit
val add : side -> Sil.exp -> Sil.exp -> unit val add : side -> Exp.t -> Exp.t -> unit
val check : side -> Sil.exp list -> bool val check : side -> Exp.t list -> bool
end = struct end = struct
@ -104,7 +104,7 @@ end = struct
let lookup' tbl e default = let lookup' tbl e default =
match e with match e with
| Sil.Var _ -> | Exp.Var _ ->
begin begin
try Hashtbl.find tbl e try Hashtbl.find tbl e
with Not_found -> (Hashtbl.replace tbl e default; default) with Not_found -> (Hashtbl.replace tbl e default; default)
@ -119,7 +119,7 @@ end = struct
let rec find' tbl e = let rec find' tbl e =
let e' = lookup_equiv' tbl e in let e' = lookup_equiv' tbl e in
match e' with match e' with
| Sil.Var _ -> | Exp.Var _ ->
if Sil.exp_equal e e' then e if Sil.exp_equal e e' then e
else else
begin begin
@ -156,7 +156,7 @@ end = struct
| Rhs -> equiv_tbl2, const_tbl2 | Rhs -> equiv_tbl2, const_tbl2
in in
match e, e' with match e, e' with
| Sil.Var id, Sil.Var id' -> | Exp.Var id, Exp.Var id' ->
begin begin
match can_rename id, can_rename id' with match can_rename id, can_rename id' with
| true, true -> union' tbl const_tbl e e' | true, true -> union' tbl const_tbl e e'
@ -164,17 +164,17 @@ end = struct
| false, true -> replace_const' tbl const_tbl e' e | false, true -> replace_const' tbl const_tbl e' e
| _ -> L.d_strln "failure reason 5"; raise IList.Fail | _ -> L.d_strln "failure reason 5"; raise IList.Fail
end end
| Sil.Var id, Sil.Const _ | Sil.Var id, Sil.Lvar _ -> | Exp.Var id, Exp.Const _ | Exp.Var id, Exp.Lvar _ ->
if (can_rename id) then replace_const' tbl const_tbl e e' if (can_rename id) then replace_const' tbl const_tbl e e'
else (L.d_strln "failure reason 6"; raise IList.Fail) else (L.d_strln "failure reason 6"; raise IList.Fail)
| Sil.Const _, Sil.Var id' | Sil.Lvar _, Sil.Var id' -> | Exp.Const _, Exp.Var id' | Exp.Lvar _, Exp.Var id' ->
if (can_rename id') then replace_const' tbl const_tbl e' e if (can_rename id') then replace_const' tbl const_tbl e' e
else (L.d_strln "failure reason 7"; raise IList.Fail) else (L.d_strln "failure reason 7"; raise IList.Fail)
| _ -> | _ ->
if not (Sil.exp_equal e e') then (L.d_strln "failure reason 8"; raise IList.Fail) else () if not (Sil.exp_equal e e') then (L.d_strln "failure reason 8"; raise IList.Fail) else ()
let check side es = let check side es =
let f = function Sil.Var id -> can_rename id | _ -> false in let f = function Exp.Var id -> can_rename id | _ -> false in
let vars, nonvars = IList.partition f es in let vars, nonvars = IList.partition f es in
let tbl, const_tbl = let tbl, const_tbl =
match side with match side with
@ -199,15 +199,15 @@ module type InfoLossCheckerSig =
sig sig
val init : Prop.sigma -> Prop.sigma -> unit val init : Prop.sigma -> Prop.sigma -> unit
val final : unit -> unit val final : unit -> unit
val lost_little : side -> Sil.exp -> Sil.exp list -> bool val lost_little : side -> Exp.t -> Exp.t list -> bool
val add : side -> Sil.exp -> Sil.exp -> unit val add : side -> Exp.t -> Exp.t -> unit
end end
module Dangling : sig module Dangling : sig
val init : Prop.sigma -> Prop.sigma -> unit val init : Prop.sigma -> Prop.sigma -> unit
val final : unit -> unit val final : unit -> unit
val check : side -> Sil.exp -> bool val check : side -> Exp.t -> bool
end = struct end = struct
@ -232,9 +232,9 @@ end = struct
| Rhs -> !lexps2 | Rhs -> !lexps2
in in
match e with match e with
| Sil.Var id -> can_rename id && not (Sil.ExpSet.mem e lexps) | Exp.Var id -> can_rename id && not (Sil.ExpSet.mem e lexps)
| Sil.Const _ -> not (Sil.ExpSet.mem e lexps) | Exp.Const _ -> not (Sil.ExpSet.mem e lexps)
| Sil.BinOp _ -> not (Sil.ExpSet.mem e lexps) | Exp.BinOp _ -> not (Sil.ExpSet.mem e lexps)
| _ -> false | _ -> false
end end
@ -251,9 +251,9 @@ module CheckJoinPre : InfoLossCheckerSig = struct
let fail_case side e es = let fail_case side e es =
let side_op = opposite side in let side_op = opposite side in
match e with match e with
| Sil.Lvar _ -> false | Exp.Lvar _ -> false
| Sil.Var id when Ident.is_normal id -> IList.length es >= 1 | Exp.Var id when Ident.is_normal id -> IList.length es >= 1
| Sil.Var _ -> | Exp.Var _ ->
if Config.join_cond = 0 then if Config.join_cond = 0 then
IList.exists (Sil.exp_equal Sil.exp_zero) es IList.exists (Sil.exp_equal Sil.exp_zero) es
else if Dangling.check side e then else if Dangling.check side e then
@ -280,7 +280,7 @@ module CheckJoinPre : InfoLossCheckerSig = struct
let lost_little side e es = let lost_little side e es =
let side_op = opposite side in let side_op = opposite side in
let es = match e with Sil.Const _ -> [] | _ -> es in let es = match e with Exp.Const _ -> [] | _ -> es in
if (fail_case side e es) then false if (fail_case side e es) then false
else else
match es with match es with
@ -300,14 +300,14 @@ module CheckJoinPost : InfoLossCheckerSig = struct
let fail_case _ e es = let fail_case _ e es =
match e with match e with
| Sil.Lvar _ -> false | Exp.Lvar _ -> false
| Sil.Var id when Ident.is_normal id -> IList.length es >= 1 | Exp.Var id when Ident.is_normal id -> IList.length es >= 1
| Sil.Var _ -> false | Exp.Var _ -> false
| _ -> false | _ -> false
let lost_little side e es = let lost_little side e es =
let side_op = opposite side in let side_op = opposite side in
let es = match e with Sil.Const _ -> [] | _ -> es in let es = match e with Exp.Const _ -> [] | _ -> es in
if (fail_case side e es) then false if (fail_case side e es) then false
else else
match es with match es with
@ -321,8 +321,8 @@ module CheckJoin : sig
val init : JoinState.mode -> Prop.sigma -> Prop.sigma -> unit val init : JoinState.mode -> Prop.sigma -> Prop.sigma -> unit
val final : unit -> unit val final : unit -> unit
val lost_little : side -> Sil.exp -> Sil.exp list -> bool val lost_little : side -> Exp.t -> Exp.t list -> bool
val add : side -> Sil.exp -> Sil.exp -> unit val add : side -> Exp.t -> Exp.t -> unit
end = struct end = struct
@ -373,19 +373,19 @@ module CheckMeet : InfoLossCheckerSig = struct
match es, e with match es, e with
| [], _ -> | [], _ ->
true true
| [Sil.Const _], Sil.Lvar _ -> | [Exp.Const _], Exp.Lvar _ ->
false false
| [Sil.Const _], Sil.Var _ -> | [Exp.Const _], Exp.Var _ ->
not (Sil.ExpSet.mem e lexps) not (Sil.ExpSet.mem e lexps)
| [Sil.Const _], _ -> | [Exp.Const _], _ ->
assert false assert false
| [_], Sil.Lvar _ | [_], Sil.Var _ -> | [_], Exp.Lvar _ | [_], Exp.Var _ ->
true true
| [_], _ -> | [_], _ ->
assert false assert false
| _, Sil.Lvar _ | _, Sil.Var _ -> | _, Exp.Lvar _ | _, Exp.Var _ ->
false false
| _, Sil.Const _ -> | _, Exp.Const _ ->
assert false assert false
| _ -> assert false | _ -> assert false
@ -400,16 +400,16 @@ module Todo : sig
type t type t
val init : unit -> unit val init : unit -> unit
val final : unit -> unit val final : unit -> unit
val reset : (Sil.exp * Sil.exp * Sil.exp) list -> unit val reset : (Exp.t * Exp.t * Exp.t) list -> unit
val push : (Sil.exp * Sil.exp * Sil.exp) -> unit val push : (Exp.t * Exp.t * Exp.t) -> unit
val pop : unit -> (Sil.exp * Sil.exp * Sil.exp) val pop : unit -> (Exp.t * Exp.t * Exp.t)
val set : t -> unit val set : t -> unit
val take : unit -> t val take : unit -> t
end = struct end = struct
exception Empty exception Empty
type t = (Sil.exp * Sil.exp * Sil.exp) list type t = (Exp.t * Exp.t * Exp.t) list
let tbl = ref [] let tbl = ref []
@ -434,12 +434,12 @@ end
module FreshVarExp : sig module FreshVarExp : sig
val init : unit -> unit val init : unit -> unit
val get_fresh_exp : Sil.exp -> Sil.exp -> Sil.exp val get_fresh_exp : Exp.t -> Exp.t -> Exp.t
val get_induced_pi : unit -> Prop.pi val get_induced_pi : unit -> Prop.pi
val final : unit -> unit val final : unit -> unit
(* (*
val lookup : side -> Sil.exp -> (Sil.exp * Sil.exp) option val lookup : side -> Exp.t -> (Exp.t * Exp.t) option
*) *)
end = struct end = struct
@ -462,8 +462,8 @@ end = struct
e e
let get_induced_atom acc strict_lower upper e = let get_induced_atom acc strict_lower upper e =
let ineq_lower = Prop.mk_inequality (Sil.BinOp(Binop.Lt, strict_lower, e)) in let ineq_lower = Prop.mk_inequality (Exp.BinOp(Binop.Lt, strict_lower, e)) in
let ineq_upper = Prop.mk_inequality (Sil.BinOp(Binop.Le, e, upper)) in let ineq_upper = Prop.mk_inequality (Exp.BinOp(Binop.Le, e, upper)) in
ineq_lower:: ineq_upper:: acc ineq_lower:: ineq_upper:: acc
let minus2_to_2 = IList.map IntLit.of_int [-2; -1; 0; 1; 2] let minus2_to_2 = IList.map IntLit.of_int [-2; -1; 0; 1; 2]
@ -473,10 +473,10 @@ end = struct
let add_and_chk_eq e1 e1' n = let add_and_chk_eq e1 e1' n =
match e1, e1' with match e1, e1' with
| Sil.Const (Const.Cint n1), Sil.Const (Const.Cint n1') -> IntLit.eq (n1 ++ n) n1' | Exp.Const (Const.Cint n1), Exp.Const (Const.Cint n1') -> IntLit.eq (n1 ++ n) n1'
| _ -> false in | _ -> false in
let add_and_gen_eq e e' n = let add_and_gen_eq e e' n =
let e_plus_n = Sil.BinOp(Binop.PlusA, e, Sil.exp_int n) in let e_plus_n = Exp.BinOp(Binop.PlusA, e, Sil.exp_int n) in
Prop.mk_eq e_plus_n e' in Prop.mk_eq e_plus_n e' in
let rec f_eqs_entry ((e1, e2, e) as entry) eqs_acc t_seen = function let rec f_eqs_entry ((e1, e2, e) as entry) eqs_acc t_seen = function
| [] -> eqs_acc, t_seen | [] -> eqs_acc, t_seen
@ -499,7 +499,7 @@ end = struct
let f_ineqs acc (e1, e2, e) = let f_ineqs acc (e1, e2, e) =
match e1, e2 with match e1, e2 with
| Sil.Const (Const.Cint n1), Sil.Const (Const.Cint n2) -> | Exp.Const (Const.Cint n1), Exp.Const (Const.Cint n2) ->
let strict_lower1, upper1 = let strict_lower1, upper1 =
if IntLit.leq n1 n2 then (n1 -- IntLit.one, n2) else (n2 -- IntLit.one, n1) in if IntLit.leq n1 n2 then (n1 -- IntLit.one, n2) else (n2 -- IntLit.one, n1) in
let e_strict_lower1 = Sil.exp_int strict_lower1 in let e_strict_lower1 = Sil.exp_int strict_lower1 in
@ -523,31 +523,31 @@ end
module Rename : sig module Rename : sig
type data_opt = ExtFresh | ExtDefault of Sil.exp type data_opt = ExtFresh | ExtDefault of Exp.t
val init : unit -> unit val init : unit -> unit
val final : unit -> unit val final : unit -> unit
val reset : unit -> (Sil.exp * Sil.exp * Sil.exp) list val reset : unit -> (Exp.t * Exp.t * Exp.t) list
val extend : Sil.exp -> Sil.exp -> data_opt -> Sil.exp val extend : Exp.t -> Exp.t -> data_opt -> Exp.t
val check : (side -> Sil.exp -> Sil.exp list -> bool) -> bool val check : (side -> Exp.t -> Exp.t list -> bool) -> bool
val get_others : side -> Sil.exp -> (Sil.exp * Sil.exp) option val get_others : side -> Exp.t -> (Exp.t * Exp.t) option
val get_other_atoms : side -> Sil.atom -> (Sil.atom * Sil.atom) option val get_other_atoms : side -> Sil.atom -> (Sil.atom * Sil.atom) option
val lookup : side -> Sil.exp -> Sil.exp val lookup : side -> Exp.t -> Exp.t
val lookup_list : side -> Sil.exp list -> Sil.exp list val lookup_list : side -> Exp.t list -> Exp.t list
val lookup_list_todo : side -> Sil.exp list -> Sil.exp list val lookup_list_todo : side -> Exp.t list -> Exp.t list
val to_subst_proj : side -> Sil.fav -> Sil.subst val to_subst_proj : side -> Sil.fav -> Sil.subst
val to_subst_emb : side -> Sil.subst val to_subst_emb : side -> Sil.subst
(* (*
val get : Sil.exp -> Sil.exp -> Sil.exp option val get : Exp.t -> Exp.t -> Exp.t option
val pp : printenv -> Format.formatter -> (Sil.exp * Sil.exp * Sil.exp) list -> unit val pp : printenv -> Format.formatter -> (Exp.t * Exp.t * Exp.t) list -> unit
*) *)
end = struct end = struct
type t = (Sil.exp * Sil.exp * Sil.exp) list type t = (Exp.t * Exp.t * Exp.t) list
let tbl : t ref = ref [] let tbl : t ref = ref []
@ -555,7 +555,7 @@ end = struct
let final () = tbl := [] let final () = tbl := []
let reset () = let reset () =
let f = function let f = function
| Sil.Var id, e, _ | e, Sil.Var id, _ -> | Exp.Var id, e, _ | e, Exp.Var id, _ ->
(Ident.is_footprint id) && (Ident.is_footprint id) &&
(Sil.fav_for_all (Sil.exp_fav e) (fun id -> not (Ident.is_primed id))) (Sil.fav_for_all (Sil.exp_fav e) (fun id -> not (Ident.is_primed id)))
| _ -> false in | _ -> false in
@ -570,9 +570,9 @@ end = struct
let side_op = opposite side in let side_op = opposite side in
let assoc_es = let assoc_es =
match e with match e with
| Sil.Const _ -> [] | Exp.Const _ -> []
| Sil.Lvar _ | Sil.Var _ | Exp.Lvar _ | Exp.Var _
| Sil.BinOp (Binop.PlusA, Sil.Var _, _) -> | Exp.BinOp (Binop.PlusA, Exp.Var _, _) ->
let is_same_e (e1, e2, _) = Sil.exp_equal e (select side e1 e2) in let is_same_e (e1, e2, _) = Sil.exp_equal e (select side e1 e2) in
let assoc = IList.filter is_same_e !tbl in let assoc = IList.filter is_same_e !tbl in
IList.map (fun (e1, e2, _) -> select side_op e1 e2) assoc IList.map (fun (e1, e2, _) -> select side_op e1 e2) assoc
@ -591,15 +591,15 @@ end = struct
let lookup_side_induced' side e = let lookup_side_induced' side e =
let res = ref [] in let res = ref [] in
let f v = match v, side with let f v = match v, side with
| (Sil.BinOp (Binop.PlusA, e1', Sil.Const (Const.Cint i)), e2, e'), Lhs | (Exp.BinOp (Binop.PlusA, e1', Exp.Const (Const.Cint i)), e2, e'), Lhs
when Sil.exp_equal e e1' -> when Sil.exp_equal e e1' ->
let c' = Sil.exp_int (IntLit.neg i) in let c' = Sil.exp_int (IntLit.neg i) in
let v' = (e1', Sil.BinOp(Binop.PlusA, e2, c'), Sil.BinOp (Binop.PlusA, e', c')) in let v' = (e1', Exp.BinOp(Binop.PlusA, e2, c'), Exp.BinOp (Binop.PlusA, e', c')) in
res := v'::!res res := v'::!res
| (e1, Sil.BinOp (Binop.PlusA, e2', Sil.Const (Const.Cint i)), e'), Rhs | (e1, Exp.BinOp (Binop.PlusA, e2', Exp.Const (Const.Cint i)), e'), Rhs
when Sil.exp_equal e e2' -> when Sil.exp_equal e e2' ->
let c' = Sil.exp_int (IntLit.neg i) in let c' = Sil.exp_int (IntLit.neg i) in
let v' = (Sil.BinOp(Binop.PlusA, e1, c'), e2', Sil.BinOp (Binop.PlusA, e', c')) in let v' = (Exp.BinOp(Binop.PlusA, e1, c'), e2', Exp.BinOp (Binop.PlusA, e', c')) in
res := v'::!res res := v'::!res
| _ -> () in | _ -> () in
begin begin
@ -608,16 +608,16 @@ end = struct
end end
(* Return the triple whose side is [e], if it exists unique *) (* Return the triple whose side is [e], if it exists unique *)
let lookup' todo side e : Sil.exp = let lookup' todo side e : Exp.t =
match e with match e with
| Sil.Var id when can_rename id -> | Exp.Var id when can_rename id ->
begin begin
let r = lookup_side' side e in let r = lookup_side' side e in
match r with match r with
| [(_, _, id) as t] -> if todo then Todo.push t; id | [(_, _, id) as t] -> if todo then Todo.push t; id
| _ -> L.d_strln "failure reason 9"; raise IList.Fail | _ -> L.d_strln "failure reason 9"; raise IList.Fail
end end
| Sil.Var _ | Sil.Const _ | Sil.Lvar _ -> if todo then Todo.push (e, e, e); e | Exp.Var _ | Exp.Const _ | Exp.Lvar _ -> if todo then Todo.push (e, e, e); e
| _ -> L.d_strln "failure reason 10"; raise IList.Fail | _ -> L.d_strln "failure reason 10"; raise IList.Fail
let lookup side e = lookup' false side e let lookup side e = lookup' false side e
@ -627,10 +627,10 @@ end = struct
let to_subst_proj (side: side) vars = let to_subst_proj (side: side) vars =
let renaming_restricted = let renaming_restricted =
IList.filter (function (_, _, Sil.Var i) -> Sil.fav_mem vars i | _ -> assert false) !tbl in IList.filter (function (_, _, Exp.Var i) -> Sil.fav_mem vars i | _ -> assert false) !tbl in
let sub_list_side = let sub_list_side =
IList.map IList.map
(function (e1, e2, Sil.Var i) -> (i, select side e1 e2) | _ -> assert false) (function (e1, e2, Exp.Var i) -> (i, select side e1 e2) | _ -> assert false)
renaming_restricted in renaming_restricted in
let sub_list_side_sorted = let sub_list_side_sorted =
IList.sort (fun (_, e) (_, e') -> Sil.exp_compare e e') sub_list_side in IList.sort (fun (_, e) (_, e') -> Sil.exp_compare e e') sub_list_side in
@ -645,13 +645,13 @@ end = struct
let renaming_restricted = let renaming_restricted =
let pick_id_case (e1, e2, _) = let pick_id_case (e1, e2, _) =
match select side e1 e2 with match select side e1 e2 with
| Sil.Var i -> can_rename i | Exp.Var i -> can_rename i
| _ -> false in | _ -> false in
IList.filter pick_id_case !tbl in IList.filter pick_id_case !tbl in
let sub_list = let sub_list =
let project (e1, e2, e) = let project (e1, e2, e) =
match select side e1 e2 with match select side e1 e2 with
| Sil.Var i -> (i, e) | Exp.Var i -> (i, e)
| _ -> assert false in | _ -> assert false in
IList.map project renaming_restricted in IList.map project renaming_restricted in
let sub_list_sorted = let sub_list_sorted =
@ -677,14 +677,14 @@ end = struct
| None -> get_others' lookup_side_induced' side e | None -> get_others' lookup_side_induced' side e
| Some _ -> others | Some _ -> others
let get_others_deep side = function let get_others_deep side = function
| Sil.BinOp(op, e, e') -> | Exp.BinOp(op, e, e') ->
let others = get_others_direct_or_induced side e in let others = get_others_direct_or_induced side e in
let others' = get_others_direct_or_induced side e' in let others' = get_others_direct_or_induced side e' in
(match others, others' with (match others, others' with
| None, _ | _, None -> None | None, _ | _, None -> None
| Some (e_res, e_op), Some(e_res', e_op') -> | Some (e_res, e_op), Some(e_res', e_op') ->
let e_res'' = Sil.BinOp(op, e_res, e_res') in let e_res'' = Exp.BinOp(op, e_res, e_res') in
let e_op'' = Sil.BinOp(op, e_op, e_op') in let e_op'' = Exp.BinOp(op, e_op, e_op') in
Some (e_res'', e_op'')) Some (e_res'', e_op''))
| _ -> None | _ -> None
@ -714,7 +714,7 @@ end = struct
else else
begin begin
match atom_in with match atom_in with
| Sil.Aneq((Sil.Var id as e), e') | Sil.Aneq(e', (Sil.Var id as e)) | Sil.Aneq((Exp.Var id as e), e') | Sil.Aneq(e', (Exp.Var id as e))
when (exp_contains_only_normal_ids e' && not (Ident.is_normal id)) -> when (exp_contains_only_normal_ids e' && not (Ident.is_normal id)) ->
build_other_atoms (fun e0 -> Prop.mk_neq e0 e') side e build_other_atoms (fun e0 -> Prop.mk_neq e0 e') side e
@ -726,26 +726,26 @@ end = struct
when not (Ident.is_normal id) && IList.for_all exp_contains_only_normal_ids es -> when not (Ident.is_normal id) && IList.for_all exp_contains_only_normal_ids es ->
build_other_atoms (fun e0 -> Prop.mk_npred a (e0 :: es)) side e build_other_atoms (fun e0 -> Prop.mk_npred a (e0 :: es)) side e
| Sil.Aeq((Sil.Var id as e), e') | Sil.Aeq(e', (Sil.Var id as e)) | Sil.Aeq((Exp.Var id as e), e') | Sil.Aeq(e', (Exp.Var id as e))
when (exp_contains_only_normal_ids e' && not (Ident.is_normal id)) -> when (exp_contains_only_normal_ids e' && not (Ident.is_normal id)) ->
build_other_atoms (fun e0 -> Prop.mk_eq e0 e') side e build_other_atoms (fun e0 -> Prop.mk_eq e0 e') side e
| Sil.Aeq(Sil.BinOp(Binop.Le, e, e'), Sil.Const (Const.Cint i)) | Sil.Aeq(Exp.BinOp(Binop.Le, e, e'), Exp.Const (Const.Cint i))
| Sil.Aeq(Sil.Const (Const.Cint i), Sil.BinOp(Binop.Le, e, e')) | Sil.Aeq(Exp.Const (Const.Cint i), Exp.BinOp(Binop.Le, e, e'))
when IntLit.isone i && (exp_contains_only_normal_ids e') -> when IntLit.isone i && (exp_contains_only_normal_ids e') ->
let construct e0 = Prop.mk_inequality (Sil.BinOp(Binop.Le, e0, e')) in let construct e0 = Prop.mk_inequality (Exp.BinOp(Binop.Le, e0, e')) in
build_other_atoms construct side e build_other_atoms construct side e
| Sil.Aeq(Sil.BinOp(Binop.Lt, e', e), Sil.Const (Const.Cint i)) | Sil.Aeq(Exp.BinOp(Binop.Lt, e', e), Exp.Const (Const.Cint i))
| Sil.Aeq(Sil.Const (Const.Cint i), Sil.BinOp(Binop.Lt, e', e)) | Sil.Aeq(Exp.Const (Const.Cint i), Exp.BinOp(Binop.Lt, e', e))
when IntLit.isone i && (exp_contains_only_normal_ids e') -> when IntLit.isone i && (exp_contains_only_normal_ids e') ->
let construct e0 = Prop.mk_inequality (Sil.BinOp(Binop.Lt, e', e0)) in let construct e0 = Prop.mk_inequality (Exp.BinOp(Binop.Lt, e', e0)) in
build_other_atoms construct side e build_other_atoms construct side e
| Sil.Aeq _ | Aneq _ | Apred _ | Anpred _ -> None | Sil.Aeq _ | Aneq _ | Apred _ | Anpred _ -> None
end end
type data_opt = ExtFresh | ExtDefault of Sil.exp type data_opt = ExtFresh | ExtDefault of Exp.t
(* Extend the renaming relation. At least one of e1 and e2 (* Extend the renaming relation. At least one of e1 and e2
* should be a primed or footprint variable *) * should be a primed or footprint variable *)
@ -768,7 +768,7 @@ end = struct
| ExtDefault e -> e | ExtDefault e -> e
| ExtFresh -> | ExtFresh ->
let kind = if JoinState.get_footprint () && not (some_primed ()) then Ident.kfootprint else Ident.kprimed in let kind = if JoinState.get_footprint () && not (some_primed ()) then Ident.kfootprint else Ident.kprimed in
Sil.Var (Ident.create_fresh kind) in Exp.Var (Ident.create_fresh kind) in
let entry = e1, e2, e in let entry = e1, e2, e in
push entry; push entry;
Todo.push entry; Todo.push entry;
@ -792,8 +792,8 @@ end
let extend_side' kind side e = let extend_side' kind side e =
match Rename.get_others side e with match Rename.get_others side e with
| None -> | None ->
let e_op = Sil.Var (Ident.create_fresh kind) in let e_op = Exp.Var (Ident.create_fresh kind) in
let e_new = Sil.Var (Ident.create_fresh kind) in let e_new = Exp.Var (Ident.create_fresh kind) in
let e1, e2 = let e1, e2 =
match side with match side with
| Lhs -> e, e_op | Lhs -> e, e_op
@ -803,39 +803,39 @@ let extend_side' kind side e =
let rec exp_construct_fresh side e = let rec exp_construct_fresh side e =
match e with match e with
| Sil.Var id -> | Exp.Var id ->
if Ident.is_normal id then if Ident.is_normal id then
(Todo.push (e, e, e); e) (Todo.push (e, e, e); e)
else if Ident.is_footprint id then else if Ident.is_footprint id then
extend_side' Ident.kfootprint side e extend_side' Ident.kfootprint side e
else else
extend_side' Ident.kprimed side e extend_side' Ident.kprimed side e
| Sil.Const _ -> e | Exp.Const _ -> e
| Sil.Cast (t, e1) -> | Exp.Cast (t, e1) ->
let e1' = exp_construct_fresh side e1 in let e1' = exp_construct_fresh side e1 in
Sil.Cast (t, e1') Exp.Cast (t, e1')
| Sil.UnOp(unop, e1, topt) -> | Exp.UnOp(unop, e1, topt) ->
let e1' = exp_construct_fresh side e1 in let e1' = exp_construct_fresh side e1 in
Sil.UnOp(unop, e1', topt) Exp.UnOp(unop, e1', topt)
| Sil.BinOp(binop, e1, e2) -> | Exp.BinOp(binop, e1, e2) ->
let e1' = exp_construct_fresh side e1 in let e1' = exp_construct_fresh side e1 in
let e2' = exp_construct_fresh side e2 in let e2' = exp_construct_fresh side e2 in
Sil.BinOp(binop, e1', e2') Exp.BinOp(binop, e1', e2')
| Sil.Exn _ -> e | Exp.Exn _ -> e
| Sil.Closure _ -> e | Exp.Closure _ -> e
| Sil.Lvar _ -> | Exp.Lvar _ ->
e e
| Sil.Lfield(e1, fld, typ) -> | Exp.Lfield(e1, fld, typ) ->
let e1' = exp_construct_fresh side e1 in let e1' = exp_construct_fresh side e1 in
Sil.Lfield(e1', fld, typ) Exp.Lfield(e1', fld, typ)
| Sil.Lindex(e1, e2) -> | Exp.Lindex(e1, e2) ->
let e1' = exp_construct_fresh side e1 in let e1' = exp_construct_fresh side e1 in
let e2' = exp_construct_fresh side e2 in let e2' = exp_construct_fresh side e2 in
Sil.Lindex(e1', e2') Exp.Lindex(e1', e2')
| Sil.Sizeof (_, None, _) -> | Exp.Sizeof (_, None, _) ->
e e
| Sil.Sizeof (typ, Some len, st) -> | Exp.Sizeof (typ, Some len, st) ->
Sil.Sizeof (typ, Some (exp_construct_fresh side len), st) Exp.Sizeof (typ, Some (exp_construct_fresh side len), st)
let strexp_construct_fresh side = let strexp_construct_fresh side =
let f (e, inst_opt) = (exp_construct_fresh side e, inst_opt) in let f (e, inst_opt) = (exp_construct_fresh side e, inst_opt) in
@ -854,35 +854,35 @@ let ident_same_kind_primed_footprint id1 id2 =
let ident_partial_join (id1: Ident.t) (id2: Ident.t) = let ident_partial_join (id1: Ident.t) (id2: Ident.t) =
match Ident.is_normal id1, Ident.is_normal id2 with match Ident.is_normal id1, Ident.is_normal id2 with
| true, true -> | true, true ->
if Ident.equal id1 id2 then Sil.Var id1 else (L.d_strln "failure reason 14"; raise IList.Fail) if Ident.equal id1 id2 then Exp.Var id1 else (L.d_strln "failure reason 14"; raise IList.Fail)
| true, _ | _, true -> | true, _ | _, true ->
Rename.extend (Sil.Var id1) (Sil.Var id2) Rename.ExtFresh Rename.extend (Exp.Var id1) (Exp.Var id2) Rename.ExtFresh
| _ -> | _ ->
begin begin
if not (ident_same_kind_primed_footprint id1 id2) then if not (ident_same_kind_primed_footprint id1 id2) then
(L.d_strln "failure reason 15"; raise IList.Fail) (L.d_strln "failure reason 15"; raise IList.Fail)
else else
let e1 = Sil.Var id1 in let e1 = Exp.Var id1 in
let e2 = Sil.Var id2 in let e2 = Exp.Var id2 in
Rename.extend e1 e2 Rename.ExtFresh Rename.extend e1 e2 Rename.ExtFresh
end end
let ident_partial_meet (id1: Ident.t) (id2: Ident.t) = let ident_partial_meet (id1: Ident.t) (id2: Ident.t) =
match Ident.is_normal id1, Ident.is_normal id2 with match Ident.is_normal id1, Ident.is_normal id2 with
| true, true -> | true, true ->
if Ident.equal id1 id2 then Sil.Var id1 if Ident.equal id1 id2 then Exp.Var id1
else (L.d_strln "failure reason 16"; raise IList.Fail) else (L.d_strln "failure reason 16"; raise IList.Fail)
| true, _ -> | true, _ ->
let e1, e2 = Sil.Var id1, Sil.Var id2 in let e1, e2 = Exp.Var id1, Exp.Var id2 in
Rename.extend e1 e2 (Rename.ExtDefault(e1)) Rename.extend e1 e2 (Rename.ExtDefault(e1))
| _, true -> | _, true ->
let e1, e2 = Sil.Var id1, Sil.Var id2 in let e1, e2 = Exp.Var id1, Exp.Var id2 in
Rename.extend e1 e2 (Rename.ExtDefault(e2)) Rename.extend e1 e2 (Rename.ExtDefault(e2))
| _ -> | _ ->
if Ident.is_primed id1 && Ident.is_primed id2 then if Ident.is_primed id1 && Ident.is_primed id2 then
Rename.extend (Sil.Var id1) (Sil.Var id2) Rename.ExtFresh Rename.extend (Exp.Var id1) (Exp.Var id2) Rename.ExtFresh
else if Ident.is_footprint id1 && Ident.equal id1 id2 then else if Ident.is_footprint id1 && Ident.equal id1 id2 then
let e = Sil.Var id1 in Rename.extend e e (Rename.ExtDefault(e)) let e = Exp.Var id1 in Rename.extend e e (Rename.ExtDefault(e))
else else
(L.d_strln "failure reason 17"; raise IList.Fail) (L.d_strln "failure reason 17"; raise IList.Fail)
@ -896,92 +896,92 @@ let option_partial_join partial_join o1 o2 =
let const_partial_join c1 c2 = let const_partial_join c1 c2 =
let is_int = function Const.Cint _ -> true | _ -> false in let is_int = function Const.Cint _ -> true | _ -> false in
if Const.equal c1 c2 then Sil.Const c1 if Const.equal c1 c2 then Exp.Const c1
else if Const.kind_equal c1 c2 && not (is_int c1) then else if Const.kind_equal c1 c2 && not (is_int c1) then
(L.d_strln "failure reason 18"; raise IList.Fail) (L.d_strln "failure reason 18"; raise IList.Fail)
else if !Config.abs_val >= 2 then else if !Config.abs_val >= 2 then
FreshVarExp.get_fresh_exp (Sil.Const c1) (Sil.Const c2) FreshVarExp.get_fresh_exp (Exp.Const c1) (Exp.Const c2)
else (L.d_strln "failure reason 19"; raise IList.Fail) else (L.d_strln "failure reason 19"; raise IList.Fail)
let rec exp_partial_join (e1: Sil.exp) (e2: Sil.exp) : Sil.exp = let rec exp_partial_join (e1: Exp.t) (e2: Exp.t) : Exp.t =
(* L.d_str "exp_partial_join "; Sil.d_exp e1; L.d_str " "; Sil.d_exp e2; L.d_ln (); *) (* L.d_str "exp_partial_join "; Sil.d_exp e1; L.d_str " "; Sil.d_exp e2; L.d_ln (); *)
match e1, e2 with match e1, e2 with
| Sil.Var id1, Sil.Var id2 -> | Exp.Var id1, Exp.Var id2 ->
ident_partial_join id1 id2 ident_partial_join id1 id2
| Sil.Var id, Sil.Const _ | Exp.Var id, Exp.Const _
| Sil.Const _, Sil.Var id -> | Exp.Const _, Exp.Var id ->
if Ident.is_normal id then if Ident.is_normal id then
(L.d_strln "failure reason 20"; raise IList.Fail) (L.d_strln "failure reason 20"; raise IList.Fail)
else else
Rename.extend e1 e2 Rename.ExtFresh Rename.extend e1 e2 Rename.ExtFresh
| Sil.Const c1, Sil.Const c2 -> | Exp.Const c1, Exp.Const c2 ->
const_partial_join c1 c2 const_partial_join c1 c2
| Sil.Var id, Sil.Lvar _ | Exp.Var id, Exp.Lvar _
| Sil.Lvar _, Sil.Var id -> | Exp.Lvar _, Exp.Var id ->
if Ident.is_normal id then (L.d_strln "failure reason 21"; raise IList.Fail) if Ident.is_normal id then (L.d_strln "failure reason 21"; raise IList.Fail)
else Rename.extend e1 e2 Rename.ExtFresh else Rename.extend e1 e2 Rename.ExtFresh
| Sil.BinOp(Binop.PlusA, Sil.Var id1, Sil.Const _), Sil.Var id2 | Exp.BinOp(Binop.PlusA, Exp.Var id1, Exp.Const _), Exp.Var id2
| Sil.Var id1, Sil.BinOp(Binop.PlusA, Sil.Var id2, Sil.Const _) | Exp.Var id1, Exp.BinOp(Binop.PlusA, Exp.Var id2, Exp.Const _)
when ident_same_kind_primed_footprint id1 id2 -> when ident_same_kind_primed_footprint id1 id2 ->
Rename.extend e1 e2 Rename.ExtFresh Rename.extend e1 e2 Rename.ExtFresh
| Sil.BinOp(Binop.PlusA, Sil.Var id1, Sil.Const (Const.Cint c1)), Sil.Const (Const.Cint c2) | Exp.BinOp(Binop.PlusA, Exp.Var id1, Exp.Const (Const.Cint c1)), Exp.Const (Const.Cint c2)
when can_rename id1 -> when can_rename id1 ->
let c2' = c2 -- c1 in let c2' = c2 -- c1 in
let e_res = Rename.extend (Sil.Var id1) (Sil.exp_int c2') Rename.ExtFresh in let e_res = Rename.extend (Exp.Var id1) (Sil.exp_int c2') Rename.ExtFresh in
Sil.BinOp(Binop.PlusA, e_res, Sil.exp_int c1) Exp.BinOp(Binop.PlusA, e_res, Sil.exp_int c1)
| Sil.Const (Const.Cint c1), Sil.BinOp(Binop.PlusA, Sil.Var id2, Sil.Const (Const.Cint c2)) | Exp.Const (Const.Cint c1), Exp.BinOp(Binop.PlusA, Exp.Var id2, Exp.Const (Const.Cint c2))
when can_rename id2 -> when can_rename id2 ->
let c1' = c1 -- c2 in let c1' = c1 -- c2 in
let e_res = Rename.extend (Sil.exp_int c1') (Sil.Var id2) Rename.ExtFresh in let e_res = Rename.extend (Sil.exp_int c1') (Exp.Var id2) Rename.ExtFresh in
Sil.BinOp(Binop.PlusA, e_res, Sil.exp_int c2) Exp.BinOp(Binop.PlusA, e_res, Sil.exp_int c2)
| Sil.Cast(t1, e1), Sil.Cast(t2, e2) -> | Exp.Cast(t1, e1), Exp.Cast(t2, e2) ->
if not (Typ.equal t1 t2) then (L.d_strln "failure reason 22"; raise IList.Fail) if not (Typ.equal t1 t2) then (L.d_strln "failure reason 22"; raise IList.Fail)
else else
let e1'' = exp_partial_join e1 e2 in let e1'' = exp_partial_join e1 e2 in
Sil.Cast (t1, e1'') Exp.Cast (t1, e1'')
| Sil.UnOp(unop1, e1, topt1), Sil.UnOp(unop2, e2, _) -> | Exp.UnOp(unop1, e1, topt1), Exp.UnOp(unop2, e2, _) ->
if not (Unop.equal unop1 unop2) then (L.d_strln "failure reason 23"; raise IList.Fail) if not (Unop.equal unop1 unop2) then (L.d_strln "failure reason 23"; raise IList.Fail)
else Sil.UnOp (unop1, exp_partial_join e1 e2, topt1) (* should be topt1 = topt2 *) else Exp.UnOp (unop1, exp_partial_join e1 e2, topt1) (* should be topt1 = topt2 *)
| Sil.BinOp(Binop.PlusPI, e1, e1'), Sil.BinOp(Binop.PlusPI, e2, e2') -> | Exp.BinOp(Binop.PlusPI, e1, e1'), Exp.BinOp(Binop.PlusPI, e2, e2') ->
let e1'' = exp_partial_join e1 e2 in let e1'' = exp_partial_join e1 e2 in
let e2'' = match e1', e2' with let e2'' = match e1', e2' with
| Sil.Const _, Sil.Const _ -> exp_partial_join e1' e2' | Exp.Const _, Exp.Const _ -> exp_partial_join e1' e2'
| _ -> FreshVarExp.get_fresh_exp e1 e2 in | _ -> FreshVarExp.get_fresh_exp e1 e2 in
Sil.BinOp(Binop.PlusPI, e1'', e2'') Exp.BinOp(Binop.PlusPI, e1'', e2'')
| Sil.BinOp(binop1, e1, e1'), Sil.BinOp(binop2, e2, e2') -> | Exp.BinOp(binop1, e1, e1'), Exp.BinOp(binop2, e2, e2') ->
if not (Binop.equal binop1 binop2) then (L.d_strln "failure reason 24"; raise IList.Fail) if not (Binop.equal binop1 binop2) then (L.d_strln "failure reason 24"; raise IList.Fail)
else else
let e1'' = exp_partial_join e1 e2 in let e1'' = exp_partial_join e1 e2 in
let e2'' = exp_partial_join e1' e2' in let e2'' = exp_partial_join e1' e2' in
Sil.BinOp(binop1, e1'', e2'') Exp.BinOp(binop1, e1'', e2'')
| Sil.Lvar(pvar1), Sil.Lvar(pvar2) -> | Exp.Lvar(pvar1), Exp.Lvar(pvar2) ->
if not (Pvar.equal pvar1 pvar2) then (L.d_strln "failure reason 25"; raise IList.Fail) if not (Pvar.equal pvar1 pvar2) then (L.d_strln "failure reason 25"; raise IList.Fail)
else e1 else e1
| Sil.Lfield(e1, f1, t1), Sil.Lfield(e2, f2, _) -> | Exp.Lfield(e1, f1, t1), Exp.Lfield(e2, f2, _) ->
if not (Ident.fieldname_equal f1 f2) then (L.d_strln "failure reason 26"; raise IList.Fail) if not (Ident.fieldname_equal f1 f2) then (L.d_strln "failure reason 26"; raise IList.Fail)
else Sil.Lfield(exp_partial_join e1 e2, f1, t1) (* should be t1 = t2 *) else Exp.Lfield(exp_partial_join e1 e2, f1, t1) (* should be t1 = t2 *)
| Sil.Lindex(e1, e1'), Sil.Lindex(e2, e2') -> | Exp.Lindex(e1, e1'), Exp.Lindex(e2, e2') ->
let e1'' = exp_partial_join e1 e2 in let e1'' = exp_partial_join e1 e2 in
let e2'' = exp_partial_join e1' e2' in let e2'' = exp_partial_join e1' e2' in
Sil.Lindex(e1'', e2'') Exp.Lindex(e1'', e2'')
| Sil.Sizeof (t1, len1, st1), Sil.Sizeof (t2, len2, st2) -> | Exp.Sizeof (t1, len1, st1), Exp.Sizeof (t2, len2, st2) ->
Sil.Sizeof Exp.Sizeof
(typ_partial_join t1 t2, dynamic_length_partial_join len1 len2, Subtype.join st1 st2) (typ_partial_join t1 t2, dynamic_length_partial_join len1 len2, Subtype.join st1 st2)
| _ -> | _ ->
L.d_str "exp_partial_join no match "; Sil.d_exp e1; L.d_str " "; Sil.d_exp e2; L.d_ln (); L.d_str "exp_partial_join no match "; Sil.d_exp e1; L.d_str " "; Sil.d_exp e2; L.d_ln ();
raise IList.Fail raise IList.Fail
and length_partial_join len1 len2 = match len1, len2 with and length_partial_join len1 len2 = match len1, len2 with
| Sil.BinOp(Binop.PlusA, e1, Sil.Const c1), Sil.BinOp(Binop.PlusA, e2, Sil.Const c2) -> | Exp.BinOp(Binop.PlusA, e1, Exp.Const c1), Exp.BinOp(Binop.PlusA, e2, Exp.Const c2) ->
let e' = exp_partial_join e1 e2 in let e' = exp_partial_join e1 e2 in
let c' = exp_partial_join (Sil.Const c1) (Sil.Const c2) in let c' = exp_partial_join (Exp.Const c1) (Exp.Const c2) in
Sil.BinOp (Binop.PlusA, e', c') Exp.BinOp (Binop.PlusA, e', c')
| Sil.BinOp(Binop.PlusA, _, _), Sil.BinOp(Binop.PlusA, _, _) -> | Exp.BinOp(Binop.PlusA, _, _), Exp.BinOp(Binop.PlusA, _, _) ->
Rename.extend len1 len2 Rename.ExtFresh Rename.extend len1 len2 Rename.ExtFresh
| Sil.Var id1, Sil.Var id2 when Ident.equal id1 id2 -> | Exp.Var id1, Exp.Var id2 when Ident.equal id1 id2 ->
len1 len1
| _ -> exp_partial_join len1 len2 | _ -> exp_partial_join len1 len2
@ -1004,52 +1004,52 @@ and typ_partial_join t1 t2 = match t1, t2 with
Typ.d_full t1; L.d_str " "; Typ.d_full t2; L.d_ln (); Typ.d_full t1; L.d_str " "; Typ.d_full t2; L.d_ln ();
raise IList.Fail raise IList.Fail
let rec exp_partial_meet (e1: Sil.exp) (e2: Sil.exp) : Sil.exp = let rec exp_partial_meet (e1: Exp.t) (e2: Exp.t) : Exp.t =
match e1, e2 with match e1, e2 with
| Sil.Var id1, Sil.Var id2 -> | Exp.Var id1, Exp.Var id2 ->
ident_partial_meet id1 id2 ident_partial_meet id1 id2
| Sil.Var id, Sil.Const _ -> | Exp.Var id, Exp.Const _ ->
if not (Ident.is_normal id) then if not (Ident.is_normal id) then
Rename.extend e1 e2 (Rename.ExtDefault(e2)) Rename.extend e1 e2 (Rename.ExtDefault(e2))
else (L.d_strln "failure reason 27"; raise IList.Fail) else (L.d_strln "failure reason 27"; raise IList.Fail)
| Sil.Const _, Sil.Var id -> | Exp.Const _, Exp.Var id ->
if not (Ident.is_normal id) then if not (Ident.is_normal id) then
Rename.extend e1 e2 (Rename.ExtDefault(e1)) Rename.extend e1 e2 (Rename.ExtDefault(e1))
else (L.d_strln "failure reason 28"; raise IList.Fail) else (L.d_strln "failure reason 28"; raise IList.Fail)
| Sil.Const c1, Sil.Const c2 -> | Exp.Const c1, Exp.Const c2 ->
if (Const.equal c1 c2) then e1 else (L.d_strln "failure reason 29"; raise IList.Fail) if (Const.equal c1 c2) then e1 else (L.d_strln "failure reason 29"; raise IList.Fail)
| Sil.Cast(t1, e1), Sil.Cast(t2, e2) -> | Exp.Cast(t1, e1), Exp.Cast(t2, e2) ->
if not (Typ.equal t1 t2) then (L.d_strln "failure reason 30"; raise IList.Fail) if not (Typ.equal t1 t2) then (L.d_strln "failure reason 30"; raise IList.Fail)
else else
let e1'' = exp_partial_meet e1 e2 in let e1'' = exp_partial_meet e1 e2 in
Sil.Cast (t1, e1'') Exp.Cast (t1, e1'')
| Sil.UnOp(unop1, e1, topt1), Sil.UnOp(unop2, e2, _) -> | Exp.UnOp(unop1, e1, topt1), Exp.UnOp(unop2, e2, _) ->
if not (Unop.equal unop1 unop2) then (L.d_strln "failure reason 31"; raise IList.Fail) if not (Unop.equal unop1 unop2) then (L.d_strln "failure reason 31"; raise IList.Fail)
else Sil.UnOp (unop1, exp_partial_meet e1 e2, topt1) (* should be topt1 = topt2 *) else Exp.UnOp (unop1, exp_partial_meet e1 e2, topt1) (* should be topt1 = topt2 *)
| Sil.BinOp(binop1, e1, e1'), Sil.BinOp(binop2, e2, e2') -> | Exp.BinOp(binop1, e1, e1'), Exp.BinOp(binop2, e2, e2') ->
if not (Binop.equal binop1 binop2) then (L.d_strln "failure reason 32"; raise IList.Fail) if not (Binop.equal binop1 binop2) then (L.d_strln "failure reason 32"; raise IList.Fail)
else else
let e1'' = exp_partial_meet e1 e2 in let e1'' = exp_partial_meet e1 e2 in
let e2'' = exp_partial_meet e1' e2' in let e2'' = exp_partial_meet e1' e2' in
Sil.BinOp(binop1, e1'', e2'') Exp.BinOp(binop1, e1'', e2'')
| Sil.Var id, Sil.Lvar _ -> | Exp.Var id, Exp.Lvar _ ->
if not (Ident.is_normal id) then if not (Ident.is_normal id) then
Rename.extend e1 e2 (Rename.ExtDefault(e2)) Rename.extend e1 e2 (Rename.ExtDefault(e2))
else (L.d_strln "failure reason 33"; raise IList.Fail) else (L.d_strln "failure reason 33"; raise IList.Fail)
| Sil.Lvar _, Sil.Var id -> | Exp.Lvar _, Exp.Var id ->
if not (Ident.is_normal id) then if not (Ident.is_normal id) then
Rename.extend e1 e2 (Rename.ExtDefault(e1)) Rename.extend e1 e2 (Rename.ExtDefault(e1))
else (L.d_strln "failure reason 34"; raise IList.Fail) else (L.d_strln "failure reason 34"; raise IList.Fail)
| Sil.Lvar(pvar1), Sil.Lvar(pvar2) -> | Exp.Lvar(pvar1), Exp.Lvar(pvar2) ->
if not (Pvar.equal pvar1 pvar2) then (L.d_strln "failure reason 35"; raise IList.Fail) if not (Pvar.equal pvar1 pvar2) then (L.d_strln "failure reason 35"; raise IList.Fail)
else e1 else e1
| Sil.Lfield(e1, f1, t1), Sil.Lfield(e2, f2, _) -> | Exp.Lfield(e1, f1, t1), Exp.Lfield(e2, f2, _) ->
if not (Ident.fieldname_equal f1 f2) then (L.d_strln "failure reason 36"; raise IList.Fail) if not (Ident.fieldname_equal f1 f2) then (L.d_strln "failure reason 36"; raise IList.Fail)
else Sil.Lfield(exp_partial_meet e1 e2, f1, t1) (* should be t1 = t2 *) else Exp.Lfield(exp_partial_meet e1 e2, f1, t1) (* should be t1 = t2 *)
| Sil.Lindex(e1, e1'), Sil.Lindex(e2, e2') -> | Exp.Lindex(e1, e1'), Exp.Lindex(e2, e2') ->
let e1'' = exp_partial_meet e1 e2 in let e1'' = exp_partial_meet e1 e2 in
let e2'' = exp_partial_meet e1' e2' in let e2'' = exp_partial_meet e1' e2' in
Sil.Lindex(e1'', e2'') Exp.Lindex(e1'', e2'')
| _ -> (L.d_strln "failure reason 37"; raise IList.Fail) | _ -> (L.d_strln "failure reason 37"; raise IList.Fail)
let exp_list_partial_join = IList.map2 exp_partial_join let exp_list_partial_join = IList.map2 exp_partial_join
@ -1221,7 +1221,8 @@ let hpara_dll_partial_meet (hpara1: Sil.hpara_dll) (hpara2: Sil.hpara_dll) : Sil
(** {2 Join and Meet for hpred} *) (** {2 Join and Meet for hpred} *)
let hpred_partial_join mode (todo: Sil.exp * Sil.exp * Sil.exp) (hpred1: Sil.hpred) (hpred2: Sil.hpred) : Sil.hpred = let hpred_partial_join mode (todo: Exp.t * Exp.t * Exp.t) (hpred1: Sil.hpred) (hpred2: Sil.hpred)
: Sil.hpred =
let e1, e2, e = todo in let e1, e2, e = todo in
match hpred1, hpred2 with match hpred1, hpred2 with
| Sil.Hpointsto (_, se1, te1), Sil.Hpointsto (_, se2, te2) -> | Sil.Hpointsto (_, se1, te1), Sil.Hpointsto (_, se2, te2) ->
@ -1248,7 +1249,8 @@ let hpred_partial_join mode (todo: Sil.exp * Sil.exp * Sil.exp) (hpred1: Sil.hpr
| _ -> | _ ->
assert false assert false
let hpred_partial_meet (todo: Sil.exp * Sil.exp * Sil.exp) (hpred1: Sil.hpred) (hpred2: Sil.hpred) : Sil.hpred = let hpred_partial_meet (todo: Exp.t * Exp.t * Exp.t) (hpred1: Sil.hpred) (hpred2: Sil.hpred)
: Sil.hpred =
let e1, e2, e = todo in let e1, e2, e = todo in
match hpred1, hpred2 with match hpred1, hpred2 with
| Sil.Hpointsto (_, se1, te1), Sil.Hpointsto (_, se2, te2) when Sil.exp_equal te1 te2 -> | Sil.Hpointsto (_, se1, te1), Sil.Hpointsto (_, se2, te2) when Sil.exp_equal te1 te2 ->
@ -1278,7 +1280,7 @@ let hpred_partial_meet (todo: Sil.exp * Sil.exp * Sil.exp) (hpred1: Sil.hpred) (
(** {2 Join and Meet for Sigma} *) (** {2 Join and Meet for Sigma} *)
let find_hpred_by_address (e: Sil.exp) (sigma: Prop.sigma) : Sil.hpred option * Prop.sigma = let find_hpred_by_address (e: Exp.t) (sigma: Prop.sigma) : Sil.hpred option * Prop.sigma =
let is_root_for_e e' = let is_root_for_e e' =
match (Prover.is_root Prop.prop_emp e' e) with match (Prover.is_root Prop.prop_emp e' e) with
| None -> false | None -> false
@ -1573,15 +1575,15 @@ let pi_partial_join mode
(pi1: Prop.pi) (pi2: Prop.pi) : Prop.pi (pi1: Prop.pi) (pi2: Prop.pi) : Prop.pi
= =
let exp_is_const = function let exp_is_const = function
(* | Sil.Var id -> is_normal id *) (* | Exp.Var id -> is_normal id *)
| Sil.Const _ -> true | Exp.Const _ -> true
(* | Sil.Lvar _ -> true *) (* | Exp.Lvar _ -> true *)
| _ -> false in | _ -> false in
let get_array_len prop = let get_array_len prop =
(* find some array length in the prop, to be used as heuritic for upper bound in widening *) (* find some array length in the prop, to be used as heuritic for upper bound in widening *)
let len_list = ref [] in let len_list = ref [] in
let do_hpred = function let do_hpred = function
| Sil.Hpointsto (_, Sil.Earray (Sil.Const (Const.Cint n), _, _), _) -> | Sil.Hpointsto (_, Sil.Earray (Exp.Const (Const.Cint n), _, _), _) ->
(if IntLit.geq n IntLit.one then len_list := n :: !len_list) (if IntLit.geq n IntLit.one then len_list := n :: !len_list)
| _ -> () in | _ -> () in
IList.iter do_hpred (Prop.get_sigma prop); IList.iter do_hpred (Prop.get_sigma prop);
@ -1601,11 +1603,11 @@ let pi_partial_join mode
if IntLit.leq n first_try then if IntLit.leq n first_try then
if IntLit.leq n second_try then second_try else first_try if IntLit.leq n second_try then second_try else first_try
else widening_top in else widening_top in
let a' = Prop.mk_inequality (Sil.BinOp(Binop.Le, e, Sil.exp_int bound)) in let a' = Prop.mk_inequality (Exp.BinOp(Binop.Le, e, Sil.exp_int bound)) in
Some a' Some a'
| Some (e, _), [] -> | Some (e, _), [] ->
let bound = widening_top in let bound = widening_top in
let a' = Prop.mk_inequality (Sil.BinOp(Binop.Le, e, Sil.exp_int bound)) in let a' = Prop.mk_inequality (Exp.BinOp(Binop.Le, e, Sil.exp_int bound)) in
Some a' Some a'
| _ -> | _ ->
begin begin
@ -1614,7 +1616,7 @@ let pi_partial_join mode
| Some (n, e) -> | Some (n, e) ->
let bound = let bound =
if IntLit.leq IntLit.minus_one n then IntLit.minus_one else widening_bottom in if IntLit.leq IntLit.minus_one n then IntLit.minus_one else widening_bottom in
let a' = Prop.mk_inequality (Sil.BinOp(Binop.Lt, Sil.exp_int bound, e)) in let a' = Prop.mk_inequality (Exp.BinOp(Binop.Lt, Sil.exp_int bound, e)) in
Some a' Some a'
end in end in
let is_stronger_le e n a = let is_stronger_le e n a =
@ -1668,8 +1670,8 @@ let pi_partial_join mode
| Sil.Aneq(e, e') | Sil.Aeq(e, e') | Sil.Aneq(e, e') | Sil.Aeq(e, e')
when (exp_is_const e && exp_is_const e') -> when (exp_is_const e && exp_is_const e') ->
true true
| Sil.Aneq(Sil.Var _, e') | Sil.Aneq(e', Sil.Var _) | Sil.Aneq(Exp.Var _, e') | Sil.Aneq(e', Exp.Var _)
| Sil.Aeq(Sil.Var _, e') | Sil.Aeq(e', Sil.Var _) | Sil.Aeq(Exp.Var _, e') | Sil.Aeq(e', Exp.Var _)
when (exp_is_const e') -> when (exp_is_const e') ->
true true
| Sil.Aneq _ -> false | Sil.Aneq _ -> false
@ -1792,7 +1794,8 @@ let eprop_partial_join' mode (ep1: Prop.exposed Prop.t) (ep2: Prop.exposed Prop.
let f e = Sil.fav_for_all (Sil.exp_fav e) Ident.is_normal in let f e = Sil.fav_for_all (Sil.exp_fav e) Ident.is_normal in
Sil.sub_range_partition f sub_common in Sil.sub_range_partition f sub_common in
let eqs1, eqs2 = let eqs1, eqs2 =
let sub_to_eqs sub = IList.map (fun (id, e) -> Sil.Aeq(Sil.Var id, e)) (Sil.sub_to_list sub) in let sub_to_eqs sub =
IList.map (fun (id, e) -> Sil.Aeq (Exp.Var id, e)) (Sil.sub_to_list sub) in
let eqs1 = sub_to_eqs sub1_only @ sub_to_eqs sub_common_other in let eqs1 = sub_to_eqs sub1_only @ sub_to_eqs sub_common_other in
let eqs2 = sub_to_eqs sub2_only in let eqs2 = sub_to_eqs sub2_only in
(eqs1, eqs2) in (eqs1, eqs2) in

@ -59,18 +59,19 @@ type link = {
type dotty_node = type dotty_node =
| Dotnil of coordinate (* nil box *) | Dotnil of coordinate (* nil box *)
(* Dotdangling(coo,e,c): dangling box for expression e at coordinate coo and color c *) (* Dotdangling(coo,e,c): dangling box for expression e at coordinate coo and color c *)
| Dotdangling of coordinate * Sil.exp * string | Dotdangling of coordinate * Exp.t * string
(* Dotpointsto(coo,e,c): basic memory cell box for expression e at coordinate coo and color c *) (* Dotpointsto(coo,e,c): basic memory cell box for expression e at coordinate coo and color c *)
| Dotpointsto of coordinate * Sil.exp * string | Dotpointsto of coordinate * Exp.t * string
(* Dotstruct(coo,e,l,c): struct box for expression e with field list l at coordinate coo and color c *) (* Dotstruct(coo,e,l,c): struct box for expression e with field list l at coordinate coo and color c *)
| Dotstruct of coordinate * Sil.exp * (Ident.fieldname * Sil.strexp) list * string * Sil.exp | Dotstruct of coordinate * Exp.t * (Ident.fieldname * Sil.strexp) list * string * Exp.t
(* Dotarray(coo,e1,e2,l,t,c): array box for expression e1 with field list l at coordinate coo and color c*) (* Dotarray(coo,e1,e2,l,t,c): array box for expression e1 with field list l at coordinate coo and color c*)
(* e2 is the len and t is the type *) (* e2 is the len and t is the type *)
| Dotarray of coordinate * Sil.exp * Sil.exp * (Sil.exp * Sil.strexp) list * Typ.t * string | Dotarray of coordinate * Exp.t * Exp.t * (Exp.t * Sil.strexp) list * Typ.t * string
(* Dotlseg(coo,e1,e2,k,h,c): list box from e1 to e2 at coordinate coo and color c*) (* Dotlseg(coo,e1,e2,k,h,c): list box from e1 to e2 at coordinate coo and color c*)
| Dotlseg of coordinate * Sil.exp * Sil.exp * Sil.lseg_kind * Sil.hpred list * string | Dotlseg of coordinate * Exp.t * Exp.t * Sil.lseg_kind * Sil.hpred list * string
(* Dotlseg(coo,e1,e2,e3,e4,k,h,c): doubly linked-list box from with parameters (e1,e2,e3,e4) at coordinate coo and color c*) (* Dotlseg(coo,e1,e2,e3,e4,k,h,c): doubly linked-list box from with parameters (e1,e2,e3,e4) at coordinate coo and color c*)
| Dotdllseg of coordinate * Sil.exp * Sil.exp * Sil.exp * Sil.exp * Sil.lseg_kind * Sil.hpred list * string | Dotdllseg of
coordinate * Exp.t * Exp.t * Exp.t * Exp.t * Sil.lseg_kind * Sil.hpred list * string
let mk_coordinate i l = { id = i; lambda = l } let mk_coordinate i l = { id = i; lambda = l }
@ -127,8 +128,8 @@ let strip_special_chars s =
let rec strexp_to_string pe coo f se = let rec strexp_to_string pe coo f se =
match se with match se with
| Sil.Eexp (Sil.Lvar pvar, _) -> F.fprintf f "%a" (Pvar.pp pe) pvar | Sil.Eexp (Exp.Lvar pvar, _) -> F.fprintf f "%a" (Pvar.pp pe) pvar
| Sil.Eexp (Sil.Var id, _) -> | Sil.Eexp (Exp.Var id, _) ->
if !print_full_prop then if !print_full_prop then
F.fprintf f "%a" (Ident.pp pe) id F.fprintf f "%a" (Ident.pp pe) id
else () else ()
@ -235,7 +236,7 @@ let color_to_str c =
| Red -> "red" | Red -> "red"
let make_dangling_boxes pe allocated_nodes (sigma_lambda: (Sil.hpred * int) list) = let make_dangling_boxes pe allocated_nodes (sigma_lambda: (Sil.hpred * int) list) =
let exp_color hpred (exp : Sil.exp) = let exp_color hpred (exp : Exp.t) =
if pe.pe_cmap_norm (Obj.repr hpred) == Red then Red if pe.pe_cmap_norm (Obj.repr hpred) == Red then Red
else pe.pe_cmap_norm (Obj.repr exp) in else pe.pe_cmap_norm (Obj.repr exp) in
let get_rhs_predicate (hpred, lambda) = let get_rhs_predicate (hpred, lambda) =
@ -294,7 +295,7 @@ let rec dotty_mk_node pe sigma =
let n = !dotty_state_count in let n = !dotty_state_count in
incr dotty_state_count; incr dotty_state_count;
let do_hpred_lambda exp_color = function let do_hpred_lambda exp_color = function
| (Sil.Hpointsto (e, Sil.Earray (e', l, _), Sil.Sizeof (Typ.Tarray (t, _), _, _)), lambda) -> | (Sil.Hpointsto (e, Sil.Earray (e', l, _), Exp.Sizeof (Typ.Tarray (t, _), _, _)), lambda) ->
incr dotty_state_count; (* increment once more n+1 is the box for the array *) incr dotty_state_count; (* increment once more n+1 is the box for the array *)
let e_color_str = color_to_str (exp_color e) in let e_color_str = color_to_str (exp_color e) in
let e_color_str'= color_to_str (exp_color e') in let e_color_str'= color_to_str (exp_color e') in
@ -320,14 +321,14 @@ let rec dotty_mk_node pe sigma =
match sigma with match sigma with
| [] -> [] | [] -> []
| (hpred, lambda) :: sigma' -> | (hpred, lambda) :: sigma' ->
let exp_color (exp : Sil.exp) = let exp_color (exp : Exp.t) =
if pe.pe_cmap_norm (Obj.repr hpred) == Red then Red if pe.pe_cmap_norm (Obj.repr hpred) == Red then Red
else pe.pe_cmap_norm (Obj.repr exp) in else pe.pe_cmap_norm (Obj.repr exp) in
do_hpred_lambda exp_color (hpred, lambda) @ dotty_mk_node pe sigma' do_hpred_lambda exp_color (hpred, lambda) @ dotty_mk_node pe sigma'
let set_exps_neq_zero pi = let set_exps_neq_zero pi =
let f = function let f = function
| Sil.Aneq (e, Sil.Const (Const.Cint i)) when IntLit.iszero i -> | Sil.Aneq (e, Exp.Const (Const.Cint i)) when IntLit.iszero i ->
exps_neq_zero := e :: !exps_neq_zero exps_neq_zero := e :: !exps_neq_zero
| _ -> () in | _ -> () in
exps_neq_zero := []; exps_neq_zero := [];
@ -650,7 +651,7 @@ let filter_useless_spec_dollar_box (nodes: dotty_node list) (links: link list) =
l:: boxes_pointing_at n ln' ) l:: boxes_pointing_at n ln' )
else boxes_pointing_at n ln' in else boxes_pointing_at n ln' in
let is_spec_variable = function let is_spec_variable = function
| Sil.Var id -> | Exp.Var id ->
Ident.is_normal id && Ident.name_equal (Ident.get_name id) Ident.name_spec Ident.is_normal id && Ident.name_equal (Ident.get_name id) Ident.name_spec
| _ -> false in | _ -> false in
let handle_one_node node = let handle_one_node node =
@ -674,7 +675,7 @@ let filter_useless_spec_dollar_box (nodes: dotty_node list) (links: link list) =
(* print a struct node *) (* print a struct node *)
let rec print_struct f pe e te l coo c = let rec print_struct f pe e te l coo c =
let print_type = match te with let print_type = match te with
| Sil.Sizeof (t, _, _) -> | Exp.Sizeof (t, _, _) ->
let str_t = Typ.to_string t in let str_t = Typ.to_string t in
(match Str.split_delim (Str.regexp_string Config.anonymous_block_prefix) str_t with (match Str.split_delim (Str.regexp_string Config.anonymous_block_prefix) str_t with
| [_; _] -> "BLOCK object" | [_; _] -> "BLOCK object"
@ -1076,11 +1077,11 @@ let pp_speclist_dotty_file (filename : DB.filename) spec_list =
(* each node has an unique integer identifier *) (* each node has an unique integer identifier *)
type visual_heap_node = type visual_heap_node =
| VH_dangling of int * Sil.exp | VH_dangling of int * Exp.t
| VH_pointsto of int * Sil.exp * Sil.strexp * Sil.exp (* VH_pointsto(id,address,content,type) *) | VH_pointsto of int * Exp.t * Sil.strexp * Exp.t (* VH_pointsto(id,address,content,type) *)
| VH_lseg of int * Sil.exp * Sil.exp * Sil.lseg_kind (*VH_lseg(id,address,content last cell, kind) *) | VH_lseg of int * Exp.t * Exp.t * Sil.lseg_kind (*VH_lseg(id,address,content last cell, kind) *)
(*VH_dllseg(id, address, content first cell, content last cell, address last cell, kind) *) (*VH_dllseg(id, address, content first cell, content last cell, address last cell, kind) *)
| VH_dllseg of int * Sil.exp * Sil.exp * Sil.exp * Sil.exp * Sil.lseg_kind | VH_dllseg of int * Exp.t * Exp.t * Exp.t * Exp.t * Sil.lseg_kind
(* an edge is a pair of node identifiers*) (* an edge is a pair of node identifiers*)
type visual_heap_edge = { type visual_heap_edge = {
@ -1321,7 +1322,7 @@ let xml_pure_info prop =
(** Return a string describing the kind of a pointsto address *) (** Return a string describing the kind of a pointsto address *)
let pointsto_addr_kind = function let pointsto_addr_kind = function
| Sil.Lvar pv -> | Exp.Lvar pv ->
if Pvar.is_global pv if Pvar.is_global pv
then "global" then "global"
else if Pvar.is_local pv && Mangled.equal (Pvar.get_name pv) Ident.name_return else if Pvar.is_local pv && Mangled.equal (Pvar.get_name pv) Ident.name_return

@ -74,7 +74,7 @@ let explain_deallocate_stack_var pvar ra =
let explain_deallocate_constant_string s ra = let explain_deallocate_constant_string s ra =
let const_str = let const_str =
let pp fmt () = let pp fmt () =
Sil.pp_exp pe_text fmt (Sil.Const (Const.Cstr s)) in Sil.pp_exp pe_text fmt (Exp.Const (Const.Cstr s)) in
pp_to_string pp () in pp_to_string pp () in
Localise.desc_deallocate_static_memory const_str ra.Sil.ra_pname ra.Sil.ra_loc Localise.desc_deallocate_static_memory const_str ra.Sil.ra_pname ra.Sil.ra_loc
@ -97,7 +97,7 @@ let find_in_node_or_preds start_node f_node_instr =
(** Find the Set instruction used to assign [id] to a program variable, if any *) (** Find the Set instruction used to assign [id] to a program variable, if any *)
let find_variable_assigment node id : Sil.instr option = let find_variable_assigment node id : Sil.instr option =
let find_set _ instr = match instr with let find_set _ instr = match instr with
| Sil.Set (Sil.Lvar _, _, e, _) when Sil.exp_equal (Sil.Var id) e -> Some instr | Sil.Set (Exp.Lvar _, _, e, _) when Sil.exp_equal (Exp.Var id) e -> Some instr
| _ -> None in | _ -> None in
find_in_node_or_preds node find_set find_in_node_or_preds node find_set
@ -126,7 +126,7 @@ let find_other_prune_node node =
(** Return true if [id] is assigned to a program variable which is then nullified *) (** Return true if [id] is assigned to a program variable which is then nullified *)
let id_is_assigned_then_dead node id = let id_is_assigned_then_dead node id =
match find_variable_assigment node id with match find_variable_assigment node id with
| Some (Sil.Set (Sil.Lvar pvar, _, _, _) as instr) | Some (Sil.Set (Exp.Lvar pvar, _, _, _) as instr)
when Pvar.is_local pvar || Pvar.is_callee pvar -> when Pvar.is_local pvar || Pvar.is_callee pvar ->
let is_prune = match Cfg.Node.get_kind node with let is_prune = match Cfg.Node.get_kind node with
| Cfg.Node.Prune_node _ -> true | Cfg.Node.Prune_node _ -> true
@ -146,7 +146,7 @@ let id_is_assigned_then_dead node id =
and return the function name and arguments *) and return the function name and arguments *)
let find_normal_variable_funcall let find_normal_variable_funcall
(node: Cfg.Node.t) (node: Cfg.Node.t)
(id: Ident.t): (Sil.exp * (Sil.exp list) * Location.t * CallFlags.t) option = (id: Ident.t): (Exp.t * (Exp.t list) * Location.t * CallFlags.t) option =
let find_declaration _ = function let find_declaration _ = function
| Sil.Call ([id0], fun_exp, args, loc, call_flags) when Ident.equal id id0 -> | Sil.Call ([id0], fun_exp, args, loc, call_flags) when Ident.equal id id0 ->
Some (fun_exp, IList.map fst args, loc, call_flags) Some (fun_exp, IList.map fst args, loc, call_flags)
@ -165,7 +165,7 @@ let find_normal_variable_funcall
(** Find a program variable assignment in the current node or predecessors. *) (** Find a program variable assignment in the current node or predecessors. *)
let find_program_variable_assignment node pvar : (Cfg.Node.t * Ident.t) option = let find_program_variable_assignment node pvar : (Cfg.Node.t * Ident.t) option =
let find_instr node = function let find_instr node = function
| Sil.Set (Sil.Lvar _pvar, _, Sil.Var id, _) when Pvar.equal pvar _pvar && Ident.is_normal id -> | Sil.Set (Exp.Lvar _pvar, _, Exp.Var id, _) when Pvar.equal pvar _pvar && Ident.is_normal id ->
Some (node, id) Some (node, id)
| _ -> | _ ->
None in None in
@ -182,7 +182,7 @@ let find_struct_by_value_assignment node pvar =
| Sil.Call (_, Const (Cfun pname), args, loc, cf) -> | Sil.Call (_, Const (Cfun pname), args, loc, cf) ->
begin begin
match IList.last args with match IList.last args with
| Some (Sil.Lvar last_arg, _) when Pvar.equal pvar last_arg -> | Some (Exp.Lvar last_arg, _) when Pvar.equal pvar last_arg ->
Some (node, pname, loc, cf) Some (node, pname, loc, cf)
| _ -> | _ ->
None None
@ -193,7 +193,7 @@ let find_struct_by_value_assignment node pvar =
else None else None
(** Find a program variable assignment to id in the current node or predecessors. *) (** Find a program variable assignment to id in the current node or predecessors. *)
let find_ident_assignment node id : (Cfg.Node.t * Sil.exp) option = let find_ident_assignment node id : (Cfg.Node.t * Exp.t) option =
let find_instr node = function let find_instr node = function
| Sil.Letderef(_id, e, _, _) when Ident.equal _id id -> Some (node, e) | Sil.Letderef(_id, e, _, _) when Ident.equal _id id -> Some (node, e)
| _ -> None in | _ -> None in
@ -204,7 +204,7 @@ let find_ident_assignment node id : (Cfg.Node.t * Sil.exp) option =
let rec find_boolean_assignment node pvar true_branch : Cfg.Node.t option = let rec find_boolean_assignment node pvar true_branch : Cfg.Node.t option =
let find_instr n = let find_instr n =
let filter = function let filter = function
| Sil.Set (Sil.Lvar _pvar, _, Sil.Const (Const.Cint i), _) when Pvar.equal pvar _pvar -> | Sil.Set (Exp.Lvar _pvar, _, Exp.Const (Const.Cint i), _) when Pvar.equal pvar _pvar ->
IntLit.iszero i <> true_branch IntLit.iszero i <> true_branch
| _ -> false in | _ -> false in
IList.exists filter (Cfg.Node.get_instrs n) in IList.exists filter (Cfg.Node.get_instrs n) in
@ -227,14 +227,14 @@ let rec _find_normal_variable_letderef (seen : Sil.ExpSet.t) node id : DExp.t op
(L.d_str "find_normal_variable_letderef defining "; (L.d_str "find_normal_variable_letderef defining ";
Sil.d_exp e; L.d_ln ()); Sil.d_exp e; L.d_ln ());
_exp_lv_dexp seen node e _exp_lv_dexp seen node e
| Sil.Call ([id0], Sil.Const (Const.Cfun pn), (e, _):: _, _, _) | Sil.Call ([id0], Exp.Const (Const.Cfun pn), (e, _):: _, _, _)
when Ident.equal id id0 && Procname.equal pn (Procname.from_string_c_fun "__cast") -> when Ident.equal id id0 && Procname.equal pn (Procname.from_string_c_fun "__cast") ->
if verbose if verbose
then then
(L.d_str "find_normal_variable_letderef cast on "; (L.d_str "find_normal_variable_letderef cast on ";
Sil.d_exp e; L.d_ln ()); Sil.d_exp e; L.d_ln ());
_exp_rv_dexp seen node e _exp_rv_dexp seen node e
| Sil.Call ([id0], (Sil.Const (Const.Cfun pname) as fun_exp), args, loc, call_flags) | Sil.Call ([id0], (Exp.Const (Const.Cfun pname) as fun_exp), args, loc, call_flags)
when Ident.equal id id0 -> when Ident.equal id id0 ->
if verbose if verbose
then then
@ -250,7 +250,7 @@ let rec _find_normal_variable_letderef (seen : Sil.ExpSet.t) node id : DExp.t op
let unNone = function Some x -> x | None -> assert false in let unNone = function Some x -> x | None -> assert false in
IList.map unNone args_dexpo in IList.map unNone args_dexpo in
Some (DExp.Dretcall (fun_dexp, args_dexp, loc, call_flags)) Some (DExp.Dretcall (fun_dexp, args_dexp, loc, call_flags))
| Sil.Set (Sil.Lvar pvar, _, Sil.Var id0, _) | Sil.Set (Exp.Lvar pvar, _, Exp.Var id0, _)
when is_infer && Ident.equal id id0 && not (Pvar.is_frontend_tmp pvar) -> when is_infer && Ident.equal id id0 && not (Pvar.is_frontend_tmp pvar) ->
(* this case is a hack to make bucketing continue to work in the presence of copy (* this case is a hack to make bucketing continue to work in the presence of copy
propagation. previously, we would have code like: propagation. previously, we would have code like:
@ -277,20 +277,20 @@ and _exp_lv_dexp (_seen : Sil.ExpSet.t) node e : DExp.t option =
else else
let seen = Sil.ExpSet.add e _seen in let seen = Sil.ExpSet.add e _seen in
match Prop.exp_normalize_noabs Sil.sub_empty e with match Prop.exp_normalize_noabs Sil.sub_empty e with
| Sil.Const c -> | Exp.Const c ->
if verbose then (L.d_str "exp_lv_dexp: constant "; Sil.d_exp e; L.d_ln ()); if verbose then (L.d_str "exp_lv_dexp: constant "; Sil.d_exp e; L.d_ln ());
Some (DExp.Dderef (DExp.Dconst c)) Some (DExp.Dderef (DExp.Dconst c))
| Sil.BinOp(Binop.PlusPI, e1, e2) -> | Exp.BinOp(Binop.PlusPI, e1, e2) ->
if verbose then (L.d_str "exp_lv_dexp: (e1 +PI e2) "; Sil.d_exp e; L.d_ln ()); if verbose then (L.d_str "exp_lv_dexp: (e1 +PI e2) "; Sil.d_exp e; L.d_ln ());
(match _exp_lv_dexp seen node e1, _exp_rv_dexp seen node e2 with (match _exp_lv_dexp seen node e1, _exp_rv_dexp seen node e2 with
| Some de1, Some de2 -> Some (DExp.Dbinop(Binop.PlusPI, de1, de2)) | Some de1, Some de2 -> Some (DExp.Dbinop(Binop.PlusPI, de1, de2))
| _ -> None) | _ -> None)
| Sil.Var id when Ident.is_normal id -> | Exp.Var id when Ident.is_normal id ->
if verbose then (L.d_str "exp_lv_dexp: normal var "; Sil.d_exp e; L.d_ln ()); if verbose then (L.d_str "exp_lv_dexp: normal var "; Sil.d_exp e; L.d_ln ());
(match _find_normal_variable_letderef seen node id with (match _find_normal_variable_letderef seen node id with
| None -> None | None -> None
| Some de -> Some (DExp.Dderef de)) | Some de -> Some (DExp.Dderef de))
| Sil.Lvar pvar -> | Exp.Lvar pvar ->
if verbose then (L.d_str "exp_lv_dexp: program var "; Sil.d_exp e; L.d_ln ()); if verbose then (L.d_str "exp_lv_dexp: program var "; Sil.d_exp e; L.d_ln ());
if Pvar.is_frontend_tmp pvar then if Pvar.is_frontend_tmp pvar then
begin begin
@ -315,22 +315,22 @@ and _exp_lv_dexp (_seen : Sil.ExpSet.t) node e : DExp.t option =
let args = IList.map unNone blame_args in let args = IList.map unNone blame_args in
Some (DExp.Dfcall (unNone fun_dexpo, args, loc, call_flags)) Some (DExp.Dfcall (unNone fun_dexpo, args, loc, call_flags))
| None -> | None ->
_exp_rv_dexp seen node' (Sil.Var id) _exp_rv_dexp seen node' (Exp.Var id)
end end
end end
else Some (DExp.Dpvar pvar) else Some (DExp.Dpvar pvar)
| Sil.Lfield (Sil.Var id, f, _) when Ident.is_normal id -> | Exp.Lfield (Exp.Var id, f, _) when Ident.is_normal id ->
if verbose then if verbose then
begin begin
L.d_str "exp_lv_dexp: Lfield with var "; L.d_str "exp_lv_dexp: Lfield with var ";
Sil.d_exp (Sil.Var id); Sil.d_exp (Exp.Var id);
L.d_str (" " ^ Ident.fieldname_to_string f); L.d_str (" " ^ Ident.fieldname_to_string f);
L.d_ln () L.d_ln ()
end; end;
(match _find_normal_variable_letderef seen node id with (match _find_normal_variable_letderef seen node id with
| None -> None | None -> None
| Some de -> Some (DExp.Darrow (de, f))) | Some de -> Some (DExp.Darrow (de, f)))
| Sil.Lfield (e1, f, _) -> | Exp.Lfield (e1, f, _) ->
if verbose then if verbose then
begin begin
L.d_str "exp_lv_dexp: Lfield "; L.d_str "exp_lv_dexp: Lfield ";
@ -341,7 +341,7 @@ and _exp_lv_dexp (_seen : Sil.ExpSet.t) node e : DExp.t option =
(match _exp_lv_dexp seen node e1 with (match _exp_lv_dexp seen node e1 with
| None -> None | None -> None
| Some de -> Some (DExp.Ddot (de, f))) | Some de -> Some (DExp.Ddot (de, f)))
| Sil.Lindex (e1, e2) -> | Exp.Lindex (e1, e2) ->
if verbose then if verbose then
begin begin
L.d_str "exp_lv_dexp: Lindex "; L.d_str "exp_lv_dexp: Lindex ";
@ -367,18 +367,18 @@ and _exp_rv_dexp (_seen : Sil.ExpSet.t) node e : DExp.t option =
else else
let seen = Sil.ExpSet.add e _seen in let seen = Sil.ExpSet.add e _seen in
match e with match e with
| Sil.Const c -> | Exp.Const c ->
if verbose then (L.d_str "exp_rv_dexp: constant "; Sil.d_exp e; L.d_ln ()); if verbose then (L.d_str "exp_rv_dexp: constant "; Sil.d_exp e; L.d_ln ());
Some (DExp.Dconst c) Some (DExp.Dconst c)
| Sil.Lvar pv -> | Exp.Lvar pv ->
if verbose then (L.d_str "exp_rv_dexp: program var "; Sil.d_exp e; L.d_ln ()); if verbose then (L.d_str "exp_rv_dexp: program var "; Sil.d_exp e; L.d_ln ());
if Pvar.is_frontend_tmp pv if Pvar.is_frontend_tmp pv
then _exp_lv_dexp _seen (* avoid spurious cycle detection *) node e then _exp_lv_dexp _seen (* avoid spurious cycle detection *) node e
else Some (DExp.Dpvaraddr pv) else Some (DExp.Dpvaraddr pv)
| Sil.Var id when Ident.is_normal id -> | Exp.Var id when Ident.is_normal id ->
if verbose then (L.d_str "exp_rv_dexp: normal var "; Sil.d_exp e; L.d_ln ()); if verbose then (L.d_str "exp_rv_dexp: normal var "; Sil.d_exp e; L.d_ln ());
_find_normal_variable_letderef seen node id _find_normal_variable_letderef seen node id
| Sil.Lfield (e1, f, _) -> | Exp.Lfield (e1, f, _) ->
if verbose then if verbose then
begin begin
L.d_str "exp_rv_dexp: Lfield "; L.d_str "exp_rv_dexp: Lfield ";
@ -389,7 +389,7 @@ and _exp_rv_dexp (_seen : Sil.ExpSet.t) node e : DExp.t option =
(match _exp_rv_dexp seen node e1 with (match _exp_rv_dexp seen node e1 with
| None -> None | None -> None
| Some de -> Some (DExp.Ddot(de, f))) | Some de -> Some (DExp.Ddot(de, f)))
| Sil.Lindex (e1, e2) -> | Exp.Lindex (e1, e2) ->
if verbose then if verbose then
begin begin
L.d_str "exp_rv_dexp: Lindex "; L.d_str "exp_rv_dexp: Lindex ";
@ -401,20 +401,20 @@ and _exp_rv_dexp (_seen : Sil.ExpSet.t) node e : DExp.t option =
(match _exp_rv_dexp seen node e1, _exp_rv_dexp seen node e2 with (match _exp_rv_dexp seen node e1, _exp_rv_dexp seen node e2 with
| None, _ | _, None -> None | None, _ | _, None -> None
| Some de1, Some de2 -> Some (DExp.Darray(de1, de2))) | Some de1, Some de2 -> Some (DExp.Darray(de1, de2)))
| Sil.BinOp (op, e1, e2) -> | Exp.BinOp (op, e1, e2) ->
if verbose then (L.d_str "exp_rv_dexp: BinOp "; Sil.d_exp e; L.d_ln ()); if verbose then (L.d_str "exp_rv_dexp: BinOp "; Sil.d_exp e; L.d_ln ());
(match _exp_rv_dexp seen node e1, _exp_rv_dexp seen node e2 with (match _exp_rv_dexp seen node e1, _exp_rv_dexp seen node e2 with
| None, _ | _, None -> None | None, _ | _, None -> None
| Some de1, Some de2 -> Some (DExp.Dbinop (op, de1, de2))) | Some de1, Some de2 -> Some (DExp.Dbinop (op, de1, de2)))
| Sil.UnOp (op, e1, _) -> | Exp.UnOp (op, e1, _) ->
if verbose then (L.d_str "exp_rv_dexp: UnOp "; Sil.d_exp e; L.d_ln ()); if verbose then (L.d_str "exp_rv_dexp: UnOp "; Sil.d_exp e; L.d_ln ());
(match _exp_rv_dexp seen node e1 with (match _exp_rv_dexp seen node e1 with
| None -> None | None -> None
| Some de1 -> Some (DExp.Dunop (op, de1))) | Some de1 -> Some (DExp.Dunop (op, de1)))
| Sil.Cast (_, e1) -> | Exp.Cast (_, e1) ->
if verbose then (L.d_str "exp_rv_dexp: Cast "; Sil.d_exp e; L.d_ln ()); if verbose then (L.d_str "exp_rv_dexp: Cast "; Sil.d_exp e; L.d_ln ());
_exp_rv_dexp seen node e1 _exp_rv_dexp seen node e1
| Sil.Sizeof (typ, len, sub) -> | Exp.Sizeof (typ, len, sub) ->
if verbose then (L.d_str "exp_rv_dexp: type "; Sil.d_exp e; L.d_ln ()); if verbose then (L.d_str "exp_rv_dexp: type "; Sil.d_exp e; L.d_ln ());
Some (DExp.Dsizeof (typ, Option.map_default (_exp_rv_dexp seen node) None len, sub)) Some (DExp.Dsizeof (typ, Option.map_default (_exp_rv_dexp seen node) None len, sub))
| _ -> | _ ->
@ -479,7 +479,7 @@ let find_hpred_typ hpred = match hpred with
let find_typ_without_ptr prop pvar = let find_typ_without_ptr prop pvar =
let res = ref None in let res = ref None in
let do_hpred = function let do_hpred = function
| Sil.Hpointsto (e, _, te) when Sil.exp_equal e (Sil.Lvar pvar) -> | Sil.Hpointsto (e, _, te) when Sil.exp_equal e (Exp.Lvar pvar) ->
res := Some te res := Some te
| _ -> () in | _ -> () in
IList.iter do_hpred (Prop.get_sigma prop); IList.iter do_hpred (Prop.get_sigma prop);
@ -518,12 +518,12 @@ let explain_leak tenv hpred prop alloc_att_opt bucket =
(Pvar.is_local pvar || Pvar.is_global pvar) && (Pvar.is_local pvar || Pvar.is_global pvar) &&
not (Pvar.is_frontend_tmp pvar) && not (Pvar.is_frontend_tmp pvar) &&
match hpred_typ_opt, find_typ_without_ptr prop pvar with match hpred_typ_opt, find_typ_without_ptr prop pvar with
| Some (Sil.Sizeof (t1, _, _)), Some (Sil.Sizeof (Typ.Tptr (t2_, _), _, _)) -> | Some (Exp.Sizeof (t1, _, _)), Some (Exp.Sizeof (Typ.Tptr (t2_, _), _, _)) ->
(try (try
let t2 = Tenv.expand_type tenv t2_ in let t2 = Tenv.expand_type tenv t2_ in
Typ.equal t1 t2 Typ.equal t1 t2
with exn when SymOp.exn_not_failure exn -> false) with exn when SymOp.exn_not_failure exn -> false)
| Some (Sil.Sizeof (Typ.Tint _, _, _)), Some (Sil.Sizeof (Typ.Tint _, _, _)) | Some (Exp.Sizeof (Typ.Tint _, _, _)), Some (Exp.Sizeof (Typ.Tint _, _, _))
when is_file -> (* must be a file opened with "open" *) when is_file -> (* must be a file opened with "open" *)
true true
| _ -> false in | _ -> false in
@ -536,7 +536,7 @@ let explain_leak tenv hpred prop alloc_att_opt bucket =
then then
(L.d_str "explain_leak: current instruction is Nullify for pvar "; (L.d_str "explain_leak: current instruction is Nullify for pvar ";
Pvar.d pvar; L.d_ln ()); Pvar.d pvar; L.d_ln ());
(match exp_lv_dexp (State.get_node ()) (Sil.Lvar pvar) with (match exp_lv_dexp (State.get_node ()) (Exp.Lvar pvar) with
| Some de when not (DExp.has_tmp_var de)-> Some (DExp.to_string de) | Some de when not (DExp.has_tmp_var de)-> Some (DExp.to_string de)
| _ -> None) | _ -> None)
| Some (Sil.Abstract _) -> | Some (Sil.Abstract _) ->
@ -589,9 +589,9 @@ let vpath_find prop _exp : DExp.t option * Typ.t option =
| Sil.Eexp (e, _) when Sil.exp_equal exp e -> | Sil.Eexp (e, _) when Sil.exp_equal exp e ->
let sigma' = (IList.rev_append sigma_acc' sigma_todo') in let sigma' = (IList.rev_append sigma_acc' sigma_todo') in
(match lexp with (match lexp with
| Sil.Lvar pv -> | Exp.Lvar pv ->
let typo = match texp with let typo = match texp with
| Sil.Sizeof (Typ.Tstruct struct_typ, _, _) -> | Exp.Sizeof (Typ.Tstruct struct_typ, _, _) ->
(try (try
let _, t, _ = let _, t, _ =
IList.find (fun (f', _, _) -> IList.find (fun (f', _, _) ->
@ -601,8 +601,8 @@ let vpath_find prop _exp : DExp.t option * Typ.t option =
with Not_found -> None) with Not_found -> None)
| _ -> None in | _ -> None in
res := Some (DExp.Ddot (DExp.Dpvar pv, f)), typo res := Some (DExp.Ddot (DExp.Dpvar pv, f)), typo
| Sil.Var id -> | Exp.Var id ->
(match find [] sigma' (Sil.Var id) with (match find [] sigma' (Exp.Var id) with
| None, _ -> () | None, _ -> ()
| Some de, typo -> res := Some (DExp.Darrow (de, f)), typo) | Some de, typo -> res := Some (DExp.Darrow (de, f)), typo)
| lexp -> | lexp ->
@ -615,13 +615,13 @@ let vpath_find prop _exp : DExp.t option * Typ.t option =
| Sil.Eexp (e, _) when Sil.exp_equal exp e -> | Sil.Eexp (e, _) when Sil.exp_equal exp e ->
let sigma' = (IList.rev_append sigma_acc' sigma_todo') in let sigma' = (IList.rev_append sigma_acc' sigma_todo') in
(match lexp with (match lexp with
| Sil.Lvar pv when not (Pvar.is_frontend_tmp pv) -> | Exp.Lvar pv when not (Pvar.is_frontend_tmp pv) ->
let typo = match texp with let typo = match texp with
| Sil.Sizeof (typ, _, _) -> Some typ | Exp.Sizeof (typ, _, _) -> Some typ
| _ -> None in | _ -> None in
Some (DExp.Dpvar pv), typo Some (DExp.Dpvar pv), typo
| Sil.Var id -> | Exp.Var id ->
(match find [] sigma' (Sil.Var id) with (match find [] sigma' (Exp.Var id) with
| None, typo -> None, typo | None, typo -> None, typo
| Some de, typo -> Some (DExp.Dderef de), typo) | Some de, typo -> Some (DExp.Dderef de), typo)
| lexp -> | lexp ->
@ -639,16 +639,16 @@ let vpath_find prop _exp : DExp.t option * Typ.t option =
let do_hpred sigma_acc' sigma_todo' = let do_hpred sigma_acc' sigma_todo' =
let substituted_from_normal id = let substituted_from_normal id =
let filter = function let filter = function
| (ni, Sil.Var id') -> Ident.is_normal ni && Ident.equal id' id | (ni, Exp.Var id') -> Ident.is_normal ni && Ident.equal id' id
| _ -> false in | _ -> false in
IList.exists filter (Sil.sub_to_list (Prop.get_sub prop)) in IList.exists filter (Sil.sub_to_list (Prop.get_sub prop)) in
function function
| Sil.Hpointsto (Sil.Lvar pv, sexp, texp) | Sil.Hpointsto (Exp.Lvar pv, sexp, texp)
when (Pvar.is_local pv || Pvar.is_global pv || Pvar.is_seed pv) -> when (Pvar.is_local pv || Pvar.is_global pv || Pvar.is_seed pv) ->
do_sexp sigma_acc' sigma_todo' (Sil.Lvar pv) sexp texp do_sexp sigma_acc' sigma_todo' (Exp.Lvar pv) sexp texp
| Sil.Hpointsto (Sil.Var id, sexp, texp) | Sil.Hpointsto (Exp.Var id, sexp, texp)
when Ident.is_normal id || (Ident.is_footprint id && substituted_from_normal id) -> when Ident.is_normal id || (Ident.is_footprint id && substituted_from_normal id) ->
do_sexp sigma_acc' sigma_todo' (Sil.Var id) sexp texp do_sexp sigma_acc' sigma_todo' (Exp.Var id) sexp texp
| _ -> | _ ->
None, None in None, None in
match sigma_todo with match sigma_todo with
@ -679,7 +679,7 @@ let explain_dexp_access prop dexp is_nullable =
| Some se -> | Some se ->
if verbose then (L.d_str "sexpo_to_inst: can't find inst "; Sil.d_sexp se; L.d_ln()); if verbose then (L.d_str "sexpo_to_inst: can't find inst "; Sil.d_sexp se; L.d_ln());
None in None in
let find_ptsto (e : Sil.exp) : Sil.strexp option = let find_ptsto (e : Exp.t) : Sil.strexp option =
let res = ref None in let res = ref None in
let do_hpred = function let do_hpred = function
| Sil.Hpointsto (e', se, _) when Sil.exp_equal e e' -> | Sil.Hpointsto (e', se, _) when Sil.exp_equal e e' ->
@ -705,7 +705,7 @@ let explain_dexp_access prop dexp is_nullable =
else lookup_esel esel' e in else lookup_esel esel' e in
let rec lookup : DExp.t -> Sil.strexp option = function let rec lookup : DExp.t -> Sil.strexp option = function
| DExp.Dconst c -> | DExp.Dconst c ->
Some (Sil.Eexp (Sil.Const c, Sil.inst_none)) Some (Sil.Eexp (Exp.Const c, Sil.inst_none))
| DExp.Darray (de1, de2) -> | DExp.Darray (de1, de2) ->
(match lookup de1, lookup de2 with (match lookup de1, lookup de2 with
| None, _ | _, None -> None | None, _ | _, None -> None
@ -745,7 +745,7 @@ let explain_dexp_access prop dexp is_nullable =
None) None)
| DExp.Dpvar pvar -> | DExp.Dpvar pvar ->
if verbose then (L.d_str "lookup: found Dpvar "; L.d_ln ()); if verbose then (L.d_str "lookup: found Dpvar "; L.d_ln ());
(find_ptsto (Sil.Lvar pvar)) (find_ptsto (Exp.Lvar pvar))
| DExp.Dderef de -> | DExp.Dderef de ->
(match lookup de with (match lookup de with
| None -> None | None -> None
@ -758,15 +758,15 @@ let explain_dexp_access prop dexp is_nullable =
if verbose then (L.d_strln "lookup: found Dfcall "); if verbose then (L.d_strln "lookup: found Dfcall ");
(match c with (match c with
| Const.Cfun _ -> (* Treat function as an update *) | Const.Cfun _ -> (* Treat function as an update *)
Some (Sil.Eexp (Sil.Const c, Sil.Ireturn_from_call loc.Location.line)) Some (Sil.Eexp (Exp.Const c, Sil.Ireturn_from_call loc.Location.line))
| _ -> None) | _ -> None)
| DExp.Dretcall (DExp.Dconst (Const.Cfun pname as c ) , _, loc, _ ) | DExp.Dretcall (DExp.Dconst (Const.Cfun pname as c ) , _, loc, _ )
when method_of_pointer_wrapper pname -> when method_of_pointer_wrapper pname ->
if verbose then (L.d_strln "lookup: found Dretcall "); if verbose then (L.d_strln "lookup: found Dretcall ");
Some (Sil.Eexp (Sil.Const c, Sil.Ireturn_from_pointer_wrapper_call loc.Location.line)) Some (Sil.Eexp (Exp.Const c, Sil.Ireturn_from_pointer_wrapper_call loc.Location.line))
| DExp.Dpvaraddr pvar -> | DExp.Dpvaraddr pvar ->
(L.d_strln ("lookup: found Dvaraddr " ^ DExp.to_string (DExp.Dpvaraddr pvar))); (L.d_strln ("lookup: found Dvaraddr " ^ DExp.to_string (DExp.Dpvaraddr pvar)));
find_ptsto (Sil.Lvar pvar) find_ptsto (Exp.Lvar pvar)
| de -> | de ->
if verbose then (L.d_strln ("lookup: unknown case not matched " ^ DExp.to_string de)); if verbose then (L.d_strln ("lookup: unknown case not matched " ^ DExp.to_string de));
None in None in
@ -847,7 +847,7 @@ let create_dereference_desc
match de_opt with match de_opt with
| Some (DExp.Dpvar pvar) | Some (DExp.Dpvar pvar)
| Some (DExp.Dpvaraddr pvar) -> | Some (DExp.Dpvaraddr pvar) ->
(match Prop.get_objc_null_attribute prop (Sil.Lvar pvar) with (match Prop.get_objc_null_attribute prop (Exp.Lvar pvar) with
| Some (Apred (Aobjc_null, [_; vfs])) -> | Some (Apred (Aobjc_null, [_; vfs])) ->
Localise.parameter_field_not_null_checked_desc desc vfs Localise.parameter_field_not_null_checked_desc desc vfs
| _ -> | _ ->
@ -875,34 +875,34 @@ let _explain_access
?(is_premature_nil = false) ?(is_premature_nil = false)
deref_str prop loc = deref_str prop loc =
let rec find_outermost_dereference node e = match e with let rec find_outermost_dereference node e = match e with
| Sil.Const _ -> | Exp.Const _ ->
if verbose then (L.d_str "find_outermost_dereference: constant "; Sil.d_exp e; L.d_ln ()); if verbose then (L.d_str "find_outermost_dereference: constant "; Sil.d_exp e; L.d_ln ());
exp_lv_dexp node e exp_lv_dexp node e
| Sil.Var id when Ident.is_normal id -> (* look up the normal variable declaration *) | Exp.Var id when Ident.is_normal id -> (* look up the normal variable declaration *)
if verbose if verbose
then then
(L.d_str "find_outermost_dereference: normal var "; (L.d_str "find_outermost_dereference: normal var ";
Sil.d_exp e; L.d_ln ()); Sil.d_exp e; L.d_ln ());
find_normal_variable_letderef node id find_normal_variable_letderef node id
| Sil.Lfield (e', _, _) -> | Exp.Lfield (e', _, _) ->
if verbose then (L.d_str "find_outermost_dereference: Lfield "; Sil.d_exp e; L.d_ln ()); if verbose then (L.d_str "find_outermost_dereference: Lfield "; Sil.d_exp e; L.d_ln ());
find_outermost_dereference node e' find_outermost_dereference node e'
| Sil.Lindex(e', _) -> | Exp.Lindex(e', _) ->
if verbose then (L.d_str "find_outermost_dereference: Lindex "; Sil.d_exp e; L.d_ln ()); if verbose then (L.d_str "find_outermost_dereference: Lindex "; Sil.d_exp e; L.d_ln ());
find_outermost_dereference node e' find_outermost_dereference node e'
| Sil.Lvar _ -> | Exp.Lvar _ ->
if verbose then (L.d_str "find_outermost_dereference: Lvar "; Sil.d_exp e; L.d_ln ()); if verbose then (L.d_str "find_outermost_dereference: Lvar "; Sil.d_exp e; L.d_ln ());
exp_lv_dexp node e exp_lv_dexp node e
| Sil.BinOp(Binop.PlusPI, Sil.Lvar _, _) -> | Exp.BinOp(Binop.PlusPI, Exp.Lvar _, _) ->
if verbose if verbose
then then
(L.d_str "find_outermost_dereference: Lvar+index "; (L.d_str "find_outermost_dereference: Lvar+index ";
Sil.d_exp e; L.d_ln ()); Sil.d_exp e; L.d_ln ());
exp_lv_dexp node e exp_lv_dexp node e
| Sil.Cast (_, e') -> | Exp.Cast (_, e') ->
if verbose then (L.d_str "find_outermost_dereference: cast "; Sil.d_exp e; L.d_ln ()); if verbose then (L.d_str "find_outermost_dereference: cast "; Sil.d_exp e; L.d_ln ());
find_outermost_dereference node e' find_outermost_dereference node e'
| Sil.BinOp(Binop.PtrFld, _, e') -> | Exp.BinOp(Binop.PtrFld, _, e') ->
if verbose then (L.d_str "find_outermost_dereference: PtrFld "; Sil.d_exp e; L.d_ln ()); if verbose then (L.d_str "find_outermost_dereference: PtrFld "; Sil.d_exp e; L.d_ln ());
find_outermost_dereference node e' find_outermost_dereference node e'
| _ -> | _ ->
@ -918,11 +918,11 @@ let _explain_access
| Some Sil.Letderef (_, e, _, _) -> | Some Sil.Letderef (_, e, _, _) ->
if verbose then (L.d_str "explain_dereference Binop.Leteref "; Sil.d_exp e; L.d_ln ()); if verbose then (L.d_str "explain_dereference Binop.Leteref "; Sil.d_exp e; L.d_ln ());
Some e Some e
| Some Sil.Call (_, Sil.Const (Const.Cfun fn), [(e, _)], _, _) | Some Sil.Call (_, Exp.Const (Const.Cfun fn), [(e, _)], _, _)
when Procname.to_string fn = "free" -> when Procname.to_string fn = "free" ->
if verbose then (L.d_str "explain_dereference Sil.Call "; Sil.d_exp e; L.d_ln ()); if verbose then (L.d_str "explain_dereference Sil.Call "; Sil.d_exp e; L.d_ln ());
Some e Some e
| Some Sil.Call (_, (Sil.Var _ as e), _, _, _) -> | Some Sil.Call (_, (Exp.Var _ as e), _, _, _) ->
if verbose then (L.d_str "explain_dereference Sil.Call "; Sil.d_exp e; L.d_ln ()); if verbose then (L.d_str "explain_dereference Sil.Call "; Sil.d_exp e; L.d_ln ());
Some e Some e
| _ -> None in | _ -> None in
@ -1015,7 +1015,7 @@ let find_with_exp prop exp =
if Sil.exp_equal e e1 then search_struct pv [] se if Sil.exp_equal e e1 then search_struct pv [] se
| _ -> () in | _ -> () in
let do_hpred = function let do_hpred = function
| Sil.Hpointsto(Sil.Lvar pv, Sil.Eexp (e, _), _) -> | Sil.Hpointsto(Exp.Lvar pv, Sil.Eexp (e, _), _) ->
if Sil.exp_equal e exp then found_in_pvar pv if Sil.exp_equal e exp then found_in_pvar pv
else IList.iter (do_hpred_pointed_by_pvar pv e) (Prop.get_sigma prop) else IList.iter (do_hpred_pointed_by_pvar pv e) (Prop.get_sigma prop)
| _ -> () in | _ -> () in
@ -1040,7 +1040,7 @@ let explain_dereference_as_caller_expression
let pv_name = Pvar.get_name pv in let pv_name = Pvar.get_name pv in
if Pvar.is_global pv if Pvar.is_global pv
then then
let dexp = exp_lv_dexp node (Sil.Lvar pv) in let dexp = exp_lv_dexp node (Exp.Lvar pv) in
create_dereference_desc ~use_buckets dexp deref_str actual_pre loc create_dereference_desc ~use_buckets dexp deref_str actual_pre loc
else if Pvar.is_callee pv then else if Pvar.is_callee pv then
let position = find_formal_param_number pv_name in let position = find_formal_param_number pv_name in
@ -1092,7 +1092,7 @@ let explain_tainted_value_reaching_sensitive_function
prop e { Sil.taint_source; taint_kind } sensitive_fun loc = prop e { Sil.taint_source; taint_kind } sensitive_fun loc =
let var_desc = let var_desc =
match e with match e with
| Sil.Lvar pv -> Pvar.to_string pv | Exp.Lvar pv -> Pvar.to_string pv
| _ -> | _ ->
begin begin
match find_with_exp prop e with match find_with_exp prop e with

@ -14,7 +14,7 @@ open! Utils
(** find the dexp, if any, where the given value is stored (** find the dexp, if any, where the given value is stored
also return the type of the value if found *) also return the type of the value if found *)
val vpath_find : 'a Prop.t -> Sil.exp -> DecompiledExp.vpath * Typ.t option val vpath_find : 'a Prop.t -> Exp.t -> DecompiledExp.vpath * Typ.t option
(** Return true if [id] is assigned to a program variable which is then nullified *) (** Return true if [id] is assigned to a program variable which is then nullified *)
val id_is_assigned_then_dead : Cfg.Node.t -> Ident.t -> bool val id_is_assigned_then_dead : Cfg.Node.t -> Ident.t -> bool
@ -25,20 +25,20 @@ val hpred_is_open_resource : 'a Prop.t -> Sil.hpred -> Sil.resource option
(** Find the function call instruction used to initialize normal variable [id], (** Find the function call instruction used to initialize normal variable [id],
and return the function name and arguments *) and return the function name and arguments *)
val find_normal_variable_funcall : val find_normal_variable_funcall :
Cfg.Node.t -> Ident.t -> (Sil.exp * (Sil.exp list) * Location.t * CallFlags.t) option Cfg.Node.t -> Ident.t -> (Exp.t * (Exp.t list) * Location.t * CallFlags.t) option
(** Find a program variable assignment in the current node or straightline predecessor. *) (** Find a program variable assignment in the current node or straightline predecessor. *)
val find_program_variable_assignment : Cfg.Node.t -> Pvar.t -> (Cfg.Node.t * Ident.t) option val find_program_variable_assignment : Cfg.Node.t -> Pvar.t -> (Cfg.Node.t * Ident.t) option
(** Find a program variable assignment to id in the current node or predecessors. *) (** Find a program variable assignment to id in the current node or predecessors. *)
val find_ident_assignment : Cfg.Node.t -> Ident.t -> (Cfg.Node.t * Sil.exp) option val find_ident_assignment : Cfg.Node.t -> Ident.t -> (Cfg.Node.t * Exp.t) option
(** Find a boolean assignment to a temporary variable holding a boolean condition. (** Find a boolean assignment to a temporary variable holding a boolean condition.
The boolean parameter indicates whether the true or false branch is required. *) The boolean parameter indicates whether the true or false branch is required. *)
val find_boolean_assignment : Cfg.Node.t -> Pvar.t -> bool -> Cfg.Node.t option val find_boolean_assignment : Cfg.Node.t -> Pvar.t -> bool -> Cfg.Node.t option
(** describe rvalue [e] as a dexp *) (** describe rvalue [e] as a dexp *)
val exp_rv_dexp : Cfg.Node.t -> Sil.exp -> DecompiledExp.t option val exp_rv_dexp : Cfg.Node.t -> Exp.t -> DecompiledExp.t option
(** Produce a description of a persistent reference to an Android Context *) (** Produce a description of a persistent reference to an Android Context *)
val explain_context_leak : Procname.t -> Typ.t -> Ident.fieldname -> val explain_context_leak : Procname.t -> Typ.t -> Ident.fieldname ->
@ -52,7 +52,7 @@ val explain_array_access : Localise.deref_str -> 'a Prop.t -> Location.t -> Loca
(** explain a class cast exception *) (** explain a class cast exception *)
val explain_class_cast_exception : val explain_class_cast_exception :
Procname.t option -> Sil.exp -> Sil.exp -> Sil.exp -> Procname.t option -> Exp.t -> Exp.t -> Exp.t ->
Cfg.Node.t -> Location.t -> Localise.error_desc Cfg.Node.t -> Location.t -> Localise.error_desc
(** Explain a deallocate stack variable error *) (** Explain a deallocate stack variable error *)
@ -70,11 +70,11 @@ val explain_dereference :
using the formal parameters of the call *) using the formal parameters of the call *)
val explain_dereference_as_caller_expression : val explain_dereference_as_caller_expression :
?use_buckets:bool -> ?use_buckets:bool ->
Localise.deref_str -> 'a Prop.t -> 'b Prop.t -> Sil.exp -> Localise.deref_str -> 'a Prop.t -> 'b Prop.t -> Exp.t ->
Cfg.Node.t -> Location.t -> Pvar.t list -> Localise.error_desc Cfg.Node.t -> Location.t -> Pvar.t list -> Localise.error_desc
(** explain a division by zero *) (** explain a division by zero *)
val explain_divide_by_zero : Sil.exp -> Cfg.Node.t -> Location.t -> Localise.error_desc val explain_divide_by_zero : Exp.t -> Cfg.Node.t -> Location.t -> Localise.error_desc
(** explain a return expression required *) (** explain a return expression required *)
val explain_return_expression_required : Location.t -> Typ.t -> Localise.error_desc val explain_return_expression_required : Location.t -> Typ.t -> Localise.error_desc
@ -87,7 +87,7 @@ val explain_condition_is_assignment : Location.t -> Localise.error_desc
(** explain a condition which is always true or false *) (** explain a condition which is always true or false *)
val explain_condition_always_true_false : val explain_condition_always_true_false :
IntLit.t -> Sil.exp -> Cfg.Node.t -> Location.t -> Localise.error_desc IntLit.t -> Exp.t -> Cfg.Node.t -> Location.t -> Localise.error_desc
(** explain the escape of a stack variable address from its scope *) (** explain the escape of a stack variable address from its scope *)
val explain_stack_variable_address_escape : val explain_stack_variable_address_escape :
@ -106,11 +106,11 @@ val explain_retain_cycle :
(** explain unary minus applied to unsigned expression *) (** explain unary minus applied to unsigned expression *)
val explain_unary_minus_applied_to_unsigned_expression : val explain_unary_minus_applied_to_unsigned_expression :
Sil.exp -> Typ.t -> Cfg.Node.t -> Location.t -> Localise.error_desc Exp.t -> Typ.t -> Cfg.Node.t -> Location.t -> Localise.error_desc
(** Explain a tainted value error *) (** Explain a tainted value error *)
val explain_tainted_value_reaching_sensitive_function : val explain_tainted_value_reaching_sensitive_function :
Prop.normal Prop.t -> Sil.exp -> Sil.taint_info -> Procname.t -> Location.t -> Localise.error_desc Prop.normal Prop.t -> Exp.t -> Sil.taint_info -> Procname.t -> Location.t -> Localise.error_desc
(** Produce a description of a leak by looking at the current state. (** Produce a description of a leak by looking at the current state.
If the current instruction is a variable nullify, blame the variable. If the current instruction is a variable nullify, blame the variable.
@ -125,7 +125,7 @@ val explain_memory_access : Localise.deref_str -> 'a Prop.t -> Location.t -> Loc
(** explain a test for NULL of a dereferenced pointer *) (** explain a test for NULL of a dereferenced pointer *)
val explain_null_test_after_dereference : val explain_null_test_after_dereference :
Sil.exp -> Cfg.Node.t -> int -> Location.t -> Localise.error_desc Exp.t -> Cfg.Node.t -> int -> Location.t -> Localise.error_desc
(** Print a warning to the err stream at the given location (note: only prints in developer mode) *) (** Print a warning to the err stream at the given location (note: only prints in developer mode) *)
val warning_err : Location.t -> ('a, Format.formatter, unit) format -> 'a val warning_err : Location.t -> ('a, Format.formatter, unit) format -> 'a
@ -136,4 +136,4 @@ type pvar_off =
| Fstruct of Ident.fieldname list (* value obtained by dereferencing the pvar and following a sequence of fields *) | Fstruct of Ident.fieldname list (* value obtained by dereferencing the pvar and following a sequence of fields *)
(** Find a program variable whose value is [exp] or pointing to a struct containing [exp] *) (** Find a program variable whose value is [exp] or pointing to a struct containing [exp] *)
val find_with_exp : 'a Prop.t -> Sil.exp -> (Pvar.t * pvar_off) option val find_with_exp : 'a Prop.t -> Exp.t -> (Pvar.t * pvar_off) option

@ -386,7 +386,7 @@ let check_assignement_guard node =
| _ -> false in | _ -> false in
let is_frontend_tmp e = let is_frontend_tmp e =
match e with match e with
| Sil.Lvar pv -> | Exp.Lvar pv ->
Pvar.is_frontend_tmp pv Pvar.is_frontend_tmp pv
| _ -> false in | _ -> false in
let succs = Cfg.Node.get_succs node in let succs = Cfg.Node.get_succs node in
@ -399,8 +399,8 @@ let check_assignement_guard node =
let pi = IList.filter is_prune_instr ins in let pi = IList.filter is_prune_instr ins in
let leti = IList.filter is_letderef_instr ins in let leti = IList.filter is_letderef_instr ins in
match pi, leti with match pi, leti with
| [Sil.Prune (Sil.Var(e1), _, _, _)], [Sil.Letderef(e2, e', _, _)] | [Sil.Prune (Exp.Var(e1), _, _, _)], [Sil.Letderef(e2, e', _, _)]
| [Sil.Prune (Sil.UnOp(Unop.LNot, Sil.Var(e1), _), _, _, _)], | [Sil.Prune (Exp.UnOp(Unop.LNot, Exp.Var(e1), _), _, _, _)],
[Sil.Letderef(e2, e', _, _)] [Sil.Letderef(e2, e', _, _)]
when (Ident.equal e1 e2) -> when (Ident.equal e1 e2) ->
if verbose if verbose
@ -429,8 +429,8 @@ let check_assignement_guard node =
(* check that the guards of the succs are a var or its negation *) (* check that the guards of the succs are a var or its negation *)
let succs_have_simple_guards () = let succs_have_simple_guards () =
let check_instr = function let check_instr = function
| Sil.Prune (Sil.Var _, _, _, _) -> true | Sil.Prune (Exp.Var _, _, _, _) -> true
| Sil.Prune (Sil.UnOp(Unop.LNot, Sil.Var _, _), _, _, _) -> true | Sil.Prune (Exp.UnOp(Unop.LNot, Exp.Var _, _), _, _, _) -> true
| Sil.Prune _ -> false | Sil.Prune _ -> false
| _ -> true in | _ -> true in
let check_guard n = let check_guard n =
@ -649,7 +649,7 @@ let report_context_leaks pname sigma tenv =
sigma in sigma in
IList.iter IList.iter
(function (function
| Sil.Hpointsto (Sil.Lvar pv, Sil.Estruct (static_flds, _), _) | Sil.Hpointsto (Exp.Lvar pv, Sil.Estruct (static_flds, _), _)
when Pvar.is_global pv -> when Pvar.is_global pv ->
IList.iter IList.iter
(fun (f_name, f_strexp) -> (fun (f_name, f_strexp) ->
@ -665,7 +665,7 @@ let remove_locals_formals_and_check pdesc p =
let pvars, p' = Cfg.remove_locals_formals pdesc p in let pvars, p' = Cfg.remove_locals_formals pdesc p in
let check_pvar pvar = let check_pvar pvar =
let loc = Cfg.Node.get_loc (Cfg.Procdesc.get_exit_node pdesc) in let loc = Cfg.Node.get_loc (Cfg.Procdesc.get_exit_node pdesc) in
let dexp_opt, _ = Errdesc.vpath_find p (Sil.Lvar pvar) in let dexp_opt, _ = Errdesc.vpath_find p (Exp.Lvar pvar) in
let desc = Errdesc.explain_stack_variable_address_escape loc pvar dexp_opt in let desc = Errdesc.explain_stack_variable_address_escape loc pvar dexp_opt in
let exn = Exceptions.Stack_variable_address_escape (desc, __POS__) in let exn = Exceptions.Stack_variable_address_escape (desc, __POS__) in
Reporting.log_warning pname exn in Reporting.log_warning pname exn in
@ -716,7 +716,7 @@ let extract_specs tenv pdesc pathset : Prop.normal Specs.spec list =
pathset; pathset;
let sub_list = let sub_list =
IList.map IList.map
(fun id -> (id, Sil.Var (Ident.create_fresh (Ident.knormal)))) (fun id -> (id, Exp.Var (Ident.create_fresh (Ident.knormal))))
(Sil.fav_to_list fav) in (Sil.fav_to_list fav) in
Sil.sub_of_list sub_list in Sil.sub_of_list sub_list in
let pre_post_visited_list = let pre_post_visited_list =
@ -807,8 +807,8 @@ let collect_postconditions wl tenv pdesc : Paths.PathSet.t * Specs.Visitedset.t
let create_seed_vars sigma = let create_seed_vars sigma =
let hpred_add_seed sigma = function let hpred_add_seed sigma = function
| Sil.Hpointsto (Sil.Lvar pv, se, typ) when not (Pvar.is_abducted pv) -> | Sil.Hpointsto (Exp.Lvar pv, se, typ) when not (Pvar.is_abducted pv) ->
Sil.Hpointsto(Sil.Lvar (Pvar.to_seed pv), se, typ) :: sigma Sil.Hpointsto(Exp.Lvar (Pvar.to_seed pv), se, typ) :: sigma
| _ -> sigma in | _ -> sigma in
IList.fold_left hpred_add_seed [] sigma IList.fold_left hpred_add_seed [] sigma
@ -820,8 +820,8 @@ let prop_init_formals_seed tenv new_formals (prop : 'a Prop.t) : Prop.exposed Pr
let sigma_new_formals = let sigma_new_formals =
let do_formal (pv, typ) = let do_formal (pv, typ) =
let texp = match !Config.curr_language with let texp = match !Config.curr_language with
| Config.Clang -> Sil.Sizeof (typ, None, Subtype.exact) | Config.Clang -> Exp.Sizeof (typ, None, Subtype.exact)
| Config.Java -> Sil.Sizeof (typ, None, Subtype.subtypes) in | Config.Java -> Exp.Sizeof (typ, None, Subtype.subtypes) in
Prop.mk_ptsto_lvar (Some tenv) Prop.Fld_init Sil.inst_formal (pv, texp, None) in Prop.mk_ptsto_lvar (Some tenv) Prop.Fld_init Sil.inst_formal (pv, texp, None) in
IList.map do_formal new_formals in IList.map do_formal new_formals in
let sigma_seed = let sigma_seed =
@ -866,7 +866,7 @@ let initial_prop_from_pre tenv curr_f pre =
let vars = Sil.fav_to_list (Prop.prop_fav pre) in let vars = Sil.fav_to_list (Prop.prop_fav pre) in
let sub_list = let sub_list =
IList.map IList.map
(fun id -> (id, Sil.Var (Ident.create_fresh (Ident.kfootprint)))) (fun id -> (id, Exp.Var (Ident.create_fresh (Ident.kfootprint))))
vars in vars in
let sub = Sil.sub_of_list sub_list in let sub = Sil.sub_of_list sub_list in
let pre2 = Prop.prop_sub sub pre in let pre2 = Prop.prop_sub sub pre in
@ -1114,12 +1114,12 @@ let custom_error_preconditions summary =
(* Remove the constrain of the form this != null which is true for all Java virtual calls *) (* Remove the constrain of the form this != null which is true for all Java virtual calls *)
let remove_this_not_null prop = let remove_this_not_null prop =
let collect_hpred (var_option, hpreds) = function let collect_hpred (var_option, hpreds) = function
| Sil.Hpointsto (Sil.Lvar pvar, Sil.Eexp (Sil.Var var, _), _) | Sil.Hpointsto (Exp.Lvar pvar, Sil.Eexp (Exp.Var var, _), _)
when !Config.curr_language = Config.Java && Pvar.is_this pvar -> when !Config.curr_language = Config.Java && Pvar.is_this pvar ->
(Some var, hpreds) (Some var, hpreds)
| hpred -> (var_option, hpred:: hpreds) in | hpred -> (var_option, hpred:: hpreds) in
let collect_atom var atoms = function let collect_atom var atoms = function
| Sil.Aneq (Sil.Var v, e) | Sil.Aneq (Exp.Var v, e)
when Ident.equal v var && Sil.exp_equal e Sil.exp_null -> atoms when Ident.equal v var && Sil.exp_equal e Sil.exp_null -> atoms
| a -> a:: atoms in | a -> a:: atoms in
match IList.fold_left collect_hpred (None, []) (Prop.get_sigma prop) with match IList.fold_left collect_hpred (None, []) (Prop.get_sigma prop) with

@ -536,8 +536,8 @@ let parameter_field_not_null_checked_desc (desc : error_desc) exp =
let field_not_nullable_desc exp = let field_not_nullable_desc exp =
let rec exp_to_string exp = let rec exp_to_string exp =
match exp with match exp with
| Sil.Lfield (exp', field, _) -> (exp_to_string exp')^" -> "^(Ident.fieldname_to_string field) | Exp.Lfield (exp', field, _) -> (exp_to_string exp')^" -> "^(Ident.fieldname_to_string field)
| Sil.Lvar pvar -> Mangled.to_string (Pvar.get_name pvar) | Exp.Lvar pvar -> Mangled.to_string (Pvar.get_name pvar)
| _ -> "" in | _ -> "" in
let var_s = exp_to_string exp in let var_s = exp_to_string exp in
let field_not_null_desc = let field_not_null_desc =
@ -545,8 +545,8 @@ let parameter_field_not_null_checked_desc (desc : error_desc) exp =
{ desc with descriptions = field_not_null_desc :: desc.descriptions; { desc with descriptions = field_not_null_desc :: desc.descriptions;
tags = (Tags.field_not_null_checked, var_s) :: desc.tags; } in tags = (Tags.field_not_null_checked, var_s) :: desc.tags; } in
match exp with match exp with
| Sil.Lvar var -> parameter_not_nullable_desc var | Exp.Lvar var -> parameter_not_nullable_desc var
| Sil.Lfield _ -> field_not_nullable_desc exp | Exp.Lfield _ -> field_not_nullable_desc exp
| _ -> desc | _ -> desc
let has_tag (desc : error_desc) tag = let has_tag (desc : error_desc) tag =
@ -688,7 +688,7 @@ let desc_leak hpred_type_opt value_str_opt resource_opt resource_action_opt loc
s, " to ", " on " in s, " to ", " on " in
let typ_str = let typ_str =
match hpred_type_opt with match hpred_type_opt with
| Some (Sil.Sizeof (Typ.Tstruct | Some (Exp.Sizeof (Typ.Tstruct
{ Typ.csu = Csu.Class _; { Typ.csu = Csu.Class _;
Typ.struct_name = Some classname; Typ.struct_name = Some classname;
}, _, _)) -> }, _, _)) ->
@ -766,17 +766,17 @@ let desc_retain_cycle prop cycle loc cycle_dotty =
| _ -> s in | _ -> s in
let do_edge ((se, _), f, _) = let do_edge ((se, _), f, _) =
match se with match se with
| Sil.Eexp(Sil.Lvar pvar, _) when Pvar.equal pvar Sil.block_pvar -> | Sil.Eexp(Exp.Lvar pvar, _) when Pvar.equal pvar Sil.block_pvar ->
str_cycle:=!str_cycle^" ("^(string_of_int !ct)^") a block capturing "^(Ident.fieldname_to_string f)^"; "; str_cycle:=!str_cycle^" ("^(string_of_int !ct)^") a block capturing "^(Ident.fieldname_to_string f)^"; ";
ct:=!ct +1; ct:=!ct +1;
| Sil.Eexp(Sil.Lvar pvar as e, _) -> | Sil.Eexp(Exp.Lvar pvar as e, _) ->
let e_str = Sil.exp_to_string e in let e_str = Sil.exp_to_string e in
let e_str = if Pvar.is_seed pvar then let e_str = if Pvar.is_seed pvar then
remove_old e_str remove_old e_str
else e_str in else e_str in
str_cycle:=!str_cycle^" ("^(string_of_int !ct)^") object "^e_str^" retaining "^e_str^"."^(Ident.fieldname_to_string f)^", "; str_cycle:=!str_cycle^" ("^(string_of_int !ct)^") object "^e_str^" retaining "^e_str^"."^(Ident.fieldname_to_string f)^", ";
ct:=!ct +1 ct:=!ct +1
| Sil.Eexp (Sil.Sizeof (typ, _, _), _) -> | Sil.Eexp (Exp.Sizeof (typ, _, _), _) ->
let step = let step =
" (" ^ (string_of_int !ct) ^ ") an object of " " (" ^ (string_of_int !ct) ^ ") an object of "
^ (Typ.to_string typ) ^ " retaining another object via instance variable " ^ (Typ.to_string typ) ^ " retaining another object via instance variable "

@ -180,7 +180,7 @@ type access =
val dereference_string : deref_str -> string -> access option -> Location.t -> error_desc val dereference_string : deref_str -> string -> access option -> Location.t -> error_desc
val parameter_field_not_null_checked_desc : error_desc -> Sil.exp -> error_desc val parameter_field_not_null_checked_desc : error_desc -> Exp.t -> error_desc
val is_parameter_not_null_checked_desc : error_desc -> bool val is_parameter_not_null_checked_desc : error_desc -> bool
@ -213,7 +213,7 @@ val is_empty_vector_access_desc : error_desc -> bool
val desc_frontend_warning : string -> string option -> Location.t -> error_desc val desc_frontend_warning : string -> string option -> Location.t -> error_desc
val desc_leak : val desc_leak :
Sil.exp option -> string option -> Sil.resource option -> Sil.res_action option -> Exp.t option -> string option -> Sil.resource option -> Sil.res_action option ->
Location.t -> string option -> error_desc Location.t -> string option -> error_desc
val desc_null_test_after_dereference : string -> int -> Location.t -> error_desc val desc_null_test_after_dereference : string -> int -> Location.t -> error_desc

@ -40,45 +40,45 @@ let rec exp_match e1 sub vars e2 : (Sil.subst * Ident.t list) option =
let e2_inst = Sil.exp_sub sub e2 let e2_inst = Sil.exp_sub sub e2
in if (Sil.exp_equal e1 e2_inst) then Some(sub, vars) else None in in if (Sil.exp_equal e1 e2_inst) then Some(sub, vars) else None in
match e1, e2 with match e1, e2 with
| _, Sil.Var id2 when (Ident.is_primed id2 && mem_idlist id2 vars) -> | _, Exp.Var id2 when (Ident.is_primed id2 && mem_idlist id2 vars) ->
let vars_new = IList.filter (fun id -> not (Ident.equal id id2)) vars in let vars_new = IList.filter (fun id -> not (Ident.equal id id2)) vars in
let sub_new = match (Sil.extend_sub sub id2 e1) with let sub_new = match (Sil.extend_sub sub id2 e1) with
| None -> assert false (* happens when vars contains the same variable twice. *) | None -> assert false (* happens when vars contains the same variable twice. *)
| Some sub_new -> sub_new | Some sub_new -> sub_new
in Some (sub_new, vars_new) in Some (sub_new, vars_new)
| _, Sil.Var _ -> | _, Exp.Var _ ->
check_equal sub vars e1 e2 check_equal sub vars e1 e2
| Sil.Var _, _ -> | Exp.Var _, _ ->
None None
| Sil.Const _, _ | _, Sil.Const _ -> | Exp.Const _, _ | _, Exp.Const _ ->
check_equal sub vars e1 e2 check_equal sub vars e1 e2
| Sil.Sizeof _, _ | _, Sil.Sizeof _ -> | Exp.Sizeof _, _ | _, Exp.Sizeof _ ->
check_equal sub vars e1 e2 check_equal sub vars e1 e2
| Sil.Cast (_, e1'), Sil.Cast (_, e2') -> (* we are currently ignoring cast *) | Exp.Cast (_, e1'), Exp.Cast (_, e2') -> (* we are currently ignoring cast *)
exp_match e1' sub vars e2' exp_match e1' sub vars e2'
| Sil.Cast _, _ | _, Sil.Cast _ -> | Exp.Cast _, _ | _, Exp.Cast _ ->
None None
| Sil.UnOp(o1, e1', _), Sil.UnOp(o2, e2', _) when Unop.equal o1 o2 -> | Exp.UnOp(o1, e1', _), Exp.UnOp(o2, e2', _) when Unop.equal o1 o2 ->
exp_match e1' sub vars e2' exp_match e1' sub vars e2'
| Sil.UnOp _, _ | _, Sil.UnOp _ -> | Exp.UnOp _, _ | _, Exp.UnOp _ ->
None (* Naive *) None (* Naive *)
| Sil.BinOp(b1, e1', e1''), Sil.BinOp(b2, e2', e2'') when Binop.equal b1 b2 -> | Exp.BinOp(b1, e1', e1''), Exp.BinOp(b2, e2', e2'') when Binop.equal b1 b2 ->
(match exp_match e1' sub vars e2' with (match exp_match e1' sub vars e2' with
| None -> None | None -> None
| Some (sub', vars') -> exp_match e1'' sub' vars' e2'') | Some (sub', vars') -> exp_match e1'' sub' vars' e2'')
| Sil.BinOp _, _ | _, Sil.BinOp _ -> | Exp.BinOp _, _ | _, Exp.BinOp _ ->
None (* Naive *) None (* Naive *)
| Sil.Exn _, _ | _, Sil.Exn _ -> | Exp.Exn _, _ | _, Exp.Exn _ ->
check_equal sub vars e1 e2 check_equal sub vars e1 e2
| Sil.Closure _, _ | _, Sil.Closure _ -> | Exp.Closure _, _ | _, Exp.Closure _ ->
check_equal sub vars e1 e2 check_equal sub vars e1 e2
| Sil.Lvar _, _ | _, Sil.Lvar _ -> | Exp.Lvar _, _ | _, Exp.Lvar _ ->
check_equal sub vars e1 e2 check_equal sub vars e1 e2
| Sil.Lfield(e1', fld1, _), Sil.Lfield(e2', fld2, _) when (Ident.fieldname_equal fld1 fld2) -> | Exp.Lfield(e1', fld1, _), Exp.Lfield(e2', fld2, _) when (Ident.fieldname_equal fld1 fld2) ->
exp_match e1' sub vars e2' exp_match e1' sub vars e2'
| Sil.Lfield _, _ | _, Sil.Lfield _ -> | Exp.Lfield _, _ | _, Exp.Lfield _ ->
None None
| Sil.Lindex(base1, idx1), Sil.Lindex(base2, idx2) -> | Exp.Lindex(base1, idx1), Exp.Lindex(base2, idx2) ->
(match exp_match base1 sub vars base2 with (match exp_match base1 sub vars base2 with
| None -> None | None -> None
| Some (sub', vars') -> exp_match idx1 sub' vars' idx2) | Some (sub', vars') -> exp_match idx1 sub' vars' idx2)
@ -165,7 +165,7 @@ let sub_extend_with_ren (sub: Sil.subst) vars =
if overlap then assert false in if overlap then assert false in
check_precondition (); check_precondition ();
*) *)
let f id = (id, Sil.Var (Ident.create_fresh Ident.kprimed)) in let f id = (id, Exp.Var (Ident.create_fresh Ident.kprimed)) in
let renaming_for_vars = Sil.sub_of_list (IList.map f vars) in let renaming_for_vars = Sil.sub_of_list (IList.map f vars) in
Sil.sub_join sub renaming_for_vars Sil.sub_join sub renaming_for_vars
@ -414,13 +414,13 @@ and hpara_common_match_with_impl impl_ok ids1 sigma1 eids2 ids2 sigma2 =
try try
let sub_ids = let sub_ids =
let ren_ids = IList.combine ids2 ids1 in let ren_ids = IList.combine ids2 ids1 in
let f (id2, id1) = (id2, Sil.Var id1) in let f (id2, id1) = (id2, Exp.Var id1) in
IList.map f ren_ids in IList.map f ren_ids in
let (sub_eids, eids_fresh) = let (sub_eids, eids_fresh) =
let f id = (id, Ident.create_fresh Ident.kprimed) in let f id = (id, Ident.create_fresh Ident.kprimed) in
let ren_eids = IList.map f eids2 in let ren_eids = IList.map f eids2 in
let eids_fresh = IList.map snd ren_eids in let eids_fresh = IList.map snd ren_eids in
let sub_eids = IList.map (fun (id2, id1) -> (id2, Sil.Var id1)) ren_eids in let sub_eids = IList.map (fun (id2, id1) -> (id2, Exp.Var id1)) ren_eids in
(sub_eids, eids_fresh) in (sub_eids, eids_fresh) in
let sub = Sil.sub_of_list (sub_ids @ sub_eids) in let sub = Sil.sub_of_list (sub_ids @ sub_eids) in
match sigma2 with match sigma2 with
@ -717,7 +717,7 @@ let sigma_lift_to_pe sigma =
let generic_para_create corres sigma1 elist1 = let generic_para_create corres sigma1 elist1 =
let corres_ids = let corres_ids =
let not_same_consts = function let not_same_consts = function
| Sil.Const c1, Sil.Const c2 -> not (Const.equal c1 c2) | Exp.Const c1, Exp.Const c2 -> not (Const.equal c1 c2)
| _ -> true in | _ -> true in
let new_corres' = IList.filter not_same_consts corres in let new_corres' = IList.filter not_same_consts corres in
let add_fresh_id pair = (pair, Ident.create_fresh Ident.kprimed) in let add_fresh_id pair = (pair, Ident.create_fresh Ident.kprimed) in
@ -732,7 +732,7 @@ let generic_para_create corres sigma1 elist1 =
let renaming = IList.map (fun ((e1, _), id) -> (e1, id)) corres_ids in let renaming = IList.map (fun ((e1, _), id) -> (e1, id)) corres_ids in
let body = let body =
let sigma1' = sigma_lift_to_pe sigma1 in let sigma1' = sigma_lift_to_pe sigma1 in
let renaming_exp = IList.map (fun (e1, id) -> (e1, Sil.Var id)) renaming in let renaming_exp = IList.map (fun (e1, id) -> (e1, Exp.Var id)) renaming in
Prop.sigma_replace_exp renaming_exp sigma1' in Prop.sigma_replace_exp renaming_exp sigma1' in
(renaming, body, ids_exists, ids_shared, es_shared) (renaming, body, ids_exists, ids_shared, es_shared)

@ -46,11 +46,11 @@ val prop_match_with_impl : Prop.normal Prop.t -> sidecondition -> Ident.t list -
and it uses expressions in the range of the isomorphism. The third is the unused and it uses expressions in the range of the isomorphism. The third is the unused
part of the input sigma. *) part of the input sigma. *)
val find_partial_iso : val find_partial_iso :
(Sil.exp -> Sil.exp -> bool) -> (Exp.t -> Exp.t -> bool) ->
(Sil.exp * Sil.exp) list -> (Exp.t * Exp.t) list ->
(Sil.exp * Sil.exp) list -> (Exp.t * Exp.t) list ->
Sil.hpred list -> Sil.hpred list ->
((Sil.exp * Sil.exp) list * Sil.hpred list * Sil.hpred list * Sil.hpred list) option ((Exp.t * Exp.t) list * Sil.hpred list * Sil.hpred list * Sil.hpred list) option
(** This mode expresses the flexibility allowed during the isomorphism check *) (** This mode expresses the flexibility allowed during the isomorphism check *)
type iso_mode = Exact | LFieldForget | RFieldForget type iso_mode = Exact | LFieldForget | RFieldForget
@ -64,12 +64,13 @@ type iso_mode = Exact | LFieldForget | RFieldForget
are the unused parts of the two input sigmas. *) are the unused parts of the two input sigmas. *)
val find_partial_iso_from_two_sigmas : val find_partial_iso_from_two_sigmas :
iso_mode -> iso_mode ->
(Sil.exp -> Sil.exp -> bool) -> (Exp.t -> Exp.t -> bool) ->
(Sil.exp * Sil.exp) list -> (Exp.t * Exp.t) list ->
(Sil.exp * Sil.exp) list -> (Exp.t * Exp.t) list ->
Sil.hpred list -> Sil.hpred list ->
Sil.hpred list -> Sil.hpred list ->
((Sil.exp * Sil.exp) list * Sil.hpred list * Sil.hpred list * (Sil.hpred list * Sil.hpred list)) option ((Exp.t * Exp.t) list * Sil.hpred list * Sil.hpred list * (Sil.hpred list * Sil.hpred list))
option
(** [hpara_iso] soundly checks whether two hparas are isomorphic. *) (** [hpara_iso] soundly checks whether two hparas are isomorphic. *)
val hpara_iso : Sil.hpara -> Sil.hpara -> bool val hpara_iso : Sil.hpara -> Sil.hpara -> bool
@ -83,20 +84,20 @@ val hpara_dll_iso : Sil.hpara_dll -> Sil.hpara_dll -> bool
hpara and discovers a list of shared expressions that are hpara and discovers a list of shared expressions that are
passed as arguments to hpara. Both of them are returned as a result. *) passed as arguments to hpara. Both of them are returned as a result. *)
val hpara_create : val hpara_create :
(Sil.exp * Sil.exp) list -> (Exp.t * Exp.t) list ->
Sil.hpred list -> Sil.hpred list ->
Sil.exp -> Exp.t ->
Sil.exp -> Exp.t ->
Sil.hpara * Sil.exp list Sil.hpara * Exp.t list
(** [hpara_dll_create] takes a correspondence, and a sigma, a root, (** [hpara_dll_create] takes a correspondence, and a sigma, a root,
a blink and a flink for the first part of this correspondence. Then, a blink and a flink for the first part of this correspondence. Then,
it creates a hpara_dll and discovers a list of shared expressions that are it creates a hpara_dll and discovers a list of shared expressions that are
passed as arguments to hpara. Both of them are returned as a result. *) passed as arguments to hpara. Both of them are returned as a result. *)
val hpara_dll_create : val hpara_dll_create :
(Sil.exp * Sil.exp) list -> (Exp.t * Exp.t) list ->
Sil.hpred list -> Sil.hpred list ->
Sil.exp -> Exp.t ->
Sil.exp -> Exp.t ->
Sil.exp -> Exp.t ->
Sil.hpara_dll * Sil.exp list Sil.hpara_dll * Exp.t list

@ -51,7 +51,7 @@ let extract_array_type typ =
(** Return a result from a procedure call. *) (** Return a result from a procedure call. *)
let return_result e prop ret_ids = let return_result e prop ret_ids =
match ret_ids with match ret_ids with
| [ret_id] -> Prop.conjoin_eq e (Sil.Var ret_id) prop | [ret_id] -> Prop.conjoin_eq e (Exp.Var ret_id) prop
| _ -> prop | _ -> prop
(* Add an array of typ pointed to by lexp to prop_ if it doesn't already exist *) (* Add an array of typ pointed to by lexp to prop_ if it doesn't already exist *)
@ -72,9 +72,9 @@ let add_array_to_prop pdesc prop_ lexp typ =
with Not_found -> (* e is not allocated, so we can add the array *) with Not_found -> (* e is not allocated, so we can add the array *)
match extract_array_type typ with match extract_array_type typ with
| Some arr_typ -> | Some arr_typ ->
let len = Sil.Var (Ident.create_fresh Ident.kfootprint) in let len = Exp.Var (Ident.create_fresh Ident.kfootprint) in
let s = mk_empty_array_rearranged len in let s = mk_empty_array_rearranged len in
let hpred = Prop.mk_ptsto n_lexp s (Sil.Sizeof (arr_typ, Some len, Subtype.exact)) in let hpred = Prop.mk_ptsto n_lexp s (Exp.Sizeof (arr_typ, Some len, Subtype.exact)) in
let sigma = Prop.get_sigma prop in let sigma = Prop.get_sigma prop in
let sigma_fp = Prop.get_sigma_footprint prop in let sigma_fp = Prop.get_sigma_footprint prop in
let prop'= Prop.replace_sigma (hpred:: sigma) prop in let prop'= Prop.replace_sigma (hpred:: sigma) prop in
@ -155,13 +155,13 @@ let create_type tenv n_lexp typ prop =
| Typ.Tptr (typ', _) -> | Typ.Tptr (typ', _) ->
let sexp = Sil.Estruct ([], Sil.inst_none) in let sexp = Sil.Estruct ([], Sil.inst_none) in
let typ'' = Tenv.expand_type tenv typ' in let typ'' = Tenv.expand_type tenv typ' in
let texp = Sil.Sizeof (typ'', None, Subtype.subtypes) in let texp = Exp.Sizeof (typ'', None, Subtype.subtypes) in
let hpred = Prop.mk_ptsto n_lexp sexp texp in let hpred = Prop.mk_ptsto n_lexp sexp texp in
Some hpred Some hpred
| Typ.Tarray _ -> | Typ.Tarray _ ->
let len = Sil.Var (Ident.create_fresh Ident.kfootprint) in let len = Exp.Var (Ident.create_fresh Ident.kfootprint) in
let sexp = mk_empty_array len in let sexp = mk_empty_array len in
let texp = Sil.Sizeof (typ, None, Subtype.subtypes) in let texp = Exp.Sizeof (typ, None, Subtype.subtypes) in
let hpred = Prop.mk_ptsto n_lexp sexp texp in let hpred = Prop.mk_ptsto n_lexp sexp texp in
Some hpred Some hpred
| _ -> None in | _ -> None in
@ -179,8 +179,8 @@ let create_type tenv n_lexp typ prop =
let prop''= Prop.normalize prop'' in let prop''= Prop.normalize prop'' in
prop'' prop''
| None -> prop in | None -> prop in
let sil_is_null = Sil.BinOp (Binop.Eq, n_lexp, Sil.exp_zero) in let sil_is_null = Exp.BinOp (Binop.Eq, n_lexp, Sil.exp_zero) in
let sil_is_nonnull = Sil.UnOp (Unop.LNot, sil_is_null, None) in let sil_is_nonnull = Exp.UnOp (Unop.LNot, sil_is_null, None) in
let null_case = Propset.to_proplist (prune ~positive:true sil_is_null prop) in let null_case = Propset.to_proplist (prune ~positive:true sil_is_null prop) in
let non_null_case = Propset.to_proplist (prune ~positive:true sil_is_nonnull prop_type) in let non_null_case = Propset.to_proplist (prune ~positive:true sil_is_nonnull prop_type) in
if ((IList.length non_null_case) > 0) && (!Config.footprint) then if ((IList.length non_null_case) > 0) && (!Config.footprint) then
@ -390,7 +390,7 @@ let execute___get_hidden_field { Builtin.pdesc; prop_; path; ret_ids; args; }
let return_val p = match !ret_val with let return_val p = match !ret_val with
| Some e -> return_result e p ret_ids | Some e -> return_result e p ret_ids
| None -> p in | None -> p in
let foot_var = lazy (Sil.Var (Ident.create_fresh Ident.kfootprint)) in let foot_var = lazy (Exp.Var (Ident.create_fresh Ident.kfootprint)) in
let filter_fld_hidden (f, _ ) = Ident.fieldname_is_hidden f in let filter_fld_hidden (f, _ ) = Ident.fieldname_is_hidden f in
let has_fld_hidden fsel = IList.exists filter_fld_hidden fsel in let has_fld_hidden fsel = IList.exists filter_fld_hidden fsel in
let do_hpred in_foot hpred = match hpred with let do_hpred in_foot hpred = match hpred with
@ -426,7 +426,7 @@ let execute___set_hidden_field { Builtin.pdesc; prop_; path; args; }
let pname = Cfg.Procdesc.get_proc_name pdesc in let pname = Cfg.Procdesc.get_proc_name pdesc in
let n_lexp1, prop__ = check_arith_norm_exp pname lexp1 prop_ in let n_lexp1, prop__ = check_arith_norm_exp pname lexp1 prop_ in
let n_lexp2, prop = check_arith_norm_exp pname lexp2 prop__ in let n_lexp2, prop = check_arith_norm_exp pname lexp2 prop__ in
let foot_var = lazy (Sil.Var (Ident.create_fresh Ident.kfootprint)) in let foot_var = lazy (Exp.Var (Ident.create_fresh Ident.kfootprint)) in
let filter_fld_hidden (f, _ ) = Ident.fieldname_is_hidden f in let filter_fld_hidden (f, _ ) = Ident.fieldname_is_hidden f in
let has_fld_hidden fsel = IList.exists filter_fld_hidden fsel in let has_fld_hidden fsel = IList.exists filter_fld_hidden fsel in
let do_hpred in_foot hpred = match hpred with let do_hpred in_foot hpred = match hpred with
@ -471,14 +471,14 @@ let execute___objc_counter_update
(* This is the case as a call f(o) it's translates as n$1=*&o; f(n$1) *) (* This is the case as a call f(o) it's translates as n$1=*&o; f(n$1) *)
(* n$2 = *n$1.hidden *) (* n$2 = *n$1.hidden *)
let tmp = Ident.create_fresh Ident.knormal in let tmp = Ident.create_fresh Ident.knormal in
let hidden_field = Sil.Lfield(lexp, Ident.fieldname_hidden, typ') in let hidden_field = Exp.Lfield(lexp, Ident.fieldname_hidden, typ') in
let counter_to_tmp = Sil.Letderef(tmp, hidden_field, typ', loc) in let counter_to_tmp = Sil.Letderef(tmp, hidden_field, typ', loc) in
(* *n$1.hidden = (n$2 +/- delta) *) (* *n$1.hidden = (n$2 +/- delta) *)
let update_counter = let update_counter =
Sil.Set Sil.Set
(hidden_field, (hidden_field,
typ', typ',
Sil.BinOp(op, Sil.Var tmp, Sil.Const (Const.Cint delta)), Exp.BinOp(op, Exp.Var tmp, Exp.Const (Const.Cint delta)),
loc) in loc) in
let update_counter_instrs = let update_counter_instrs =
[ counter_to_tmp; update_counter; Sil.Remove_temps([tmp], loc) ] in [ counter_to_tmp; update_counter; Sil.Remove_temps([tmp], loc) ] in
@ -490,7 +490,7 @@ let execute___objc_counter_update
removed from the list of args. *) removed from the list of args. *)
let get_suppress_npe_flag args = let get_suppress_npe_flag args =
match args with match args with
| (Sil.Const (Const.Cint i), Typ.Tint Typ.IBool):: args' when IntLit.isone i -> | (Exp.Const (Const.Cint i), Typ.Tint Typ.IBool):: args' when IntLit.isone i ->
false, args' (* this is a CFRelease/CFRetain *) false, args' (* this is a CFRelease/CFRetain *)
| _ -> true, args | _ -> true, args
@ -565,7 +565,7 @@ let execute___release_autorelease_pool
| Sil.Hpointsto(e1, _, _) -> Sil.exp_equal e1 exp | Sil.Hpointsto(e1, _, _) -> Sil.exp_equal e1 exp
| _ -> false) (Prop.get_sigma prop_) in | _ -> false) (Prop.get_sigma prop_) in
match hpred with match hpred with
| Sil.Hpointsto (_, _, Sil.Sizeof (typ, _, _)) -> | Sil.Hpointsto (_, _, Exp.Sizeof (typ, _, _)) ->
let res1 = let res1 =
execute___objc_release execute___objc_release
{ builtin_args with { builtin_args with
@ -629,7 +629,7 @@ let execute___set_taint_attribute
({ Builtin.pdesc; args; prop_; path; }) ({ Builtin.pdesc; args; prop_; path; })
: Builtin.ret_typ = : Builtin.ret_typ =
match args with match args with
| (exp, _) :: [(Sil.Const (Const.Cstr taint_kind_str), _)] -> | (exp, _) :: [(Exp.Const (Const.Cstr taint_kind_str), _)] ->
let taint_source = Cfg.Procdesc.get_proc_name pdesc in let taint_source = Cfg.Procdesc.get_proc_name pdesc in
let taint_kind = match taint_kind_str with let taint_kind = match taint_kind_str with
| "UnverifiedSSLSocket" -> Sil.Tk_unverified_SSL_socket | "UnverifiedSSLSocket" -> Sil.Tk_unverified_SSL_socket
@ -664,7 +664,7 @@ let execute___objc_cast { Builtin.pdesc; prop_; path; ret_ids; args; }
| Sil.Hpointsto(e1, _, _) -> Sil.exp_equal e1 val1 | Sil.Hpointsto(e1, _, _) -> Sil.exp_equal e1 val1
| _ -> false) (Prop.get_sigma prop) in | _ -> false) (Prop.get_sigma prop) in
match hpred, texp2 with match hpred, texp2 with
| Sil.Hpointsto (val1, _, _), Sil.Sizeof _ -> | Sil.Hpointsto (val1, _, _), Exp.Sizeof _ ->
let prop' = replace_ptsto_texp prop val1 texp2 in let prop' = replace_ptsto_texp prop val1 texp2 in
[(return_result val1 prop' ret_ids, path)] [(return_result val1 prop' ret_ids, path)]
| _ -> [(return_result val1 prop ret_ids, path)] | _ -> [(return_result val1 prop ret_ids, path)]
@ -747,30 +747,30 @@ let execute_alloc mk can_return_null
: Builtin.ret_typ = : Builtin.ret_typ =
let pname = Cfg.Procdesc.get_proc_name pdesc in let pname = Cfg.Procdesc.get_proc_name pdesc in
let rec evaluate_char_sizeof e = match e with let rec evaluate_char_sizeof e = match e with
| Sil.Var _ -> e | Exp.Var _ -> e
| Sil.UnOp (uop, e', typ) -> | Exp.UnOp (uop, e', typ) ->
Sil.UnOp (uop, evaluate_char_sizeof e', typ) Exp.UnOp (uop, evaluate_char_sizeof e', typ)
| Sil.BinOp (bop, e1', e2') -> | Exp.BinOp (bop, e1', e2') ->
Sil.BinOp (bop, evaluate_char_sizeof e1', evaluate_char_sizeof e2') Exp.BinOp (bop, evaluate_char_sizeof e1', evaluate_char_sizeof e2')
| Sil.Exn _ | Sil.Closure _ | Sil.Const _ | Sil.Cast _ | Sil.Lvar _ | Sil.Lfield _ | Exp.Exn _ | Exp.Closure _ | Exp.Const _ | Exp.Cast _ | Exp.Lvar _ | Exp.Lfield _
| Sil.Lindex _ -> e | Exp.Lindex _ -> e
| Sil.Sizeof (Typ.Tarray (Typ.Tint ik, _), Some len, _) when Typ.ikind_is_char ik -> | Exp.Sizeof (Typ.Tarray (Typ.Tint ik, _), Some len, _) when Typ.ikind_is_char ik ->
evaluate_char_sizeof len evaluate_char_sizeof len
| Sil.Sizeof (Typ.Tarray (Typ.Tint ik, Some len), None, _) when Typ.ikind_is_char ik -> | Exp.Sizeof (Typ.Tarray (Typ.Tint ik, Some len), None, _) when Typ.ikind_is_char ik ->
evaluate_char_sizeof (Sil.Const (Const.Cint len)) evaluate_char_sizeof (Exp.Const (Const.Cint len))
| Sil.Sizeof _ -> e in | Exp.Sizeof _ -> e in
let size_exp, procname = match args with let size_exp, procname = match args with
| [(Sil.Sizeof | [(Exp.Sizeof
(Typ.Tstruct (Typ.Tstruct
{ Typ.csu = Csu.Class Csu.Objc; struct_name = Some c } as s, len, subt), _)] -> { Typ.csu = Csu.Class Csu.Objc; struct_name = Some c } as s, len, subt), _)] ->
let struct_type = let struct_type =
match AttributesTable.get_correct_type_from_objc_class_name c with match AttributesTable.get_correct_type_from_objc_class_name c with
| Some struct_type -> struct_type | Some struct_type -> struct_type
| None -> s in | None -> s in
Sil.Sizeof (struct_type, len, subt), pname Exp.Sizeof (struct_type, len, subt), pname
| [(size_exp, _)] -> (* for malloc and __new *) | [(size_exp, _)] -> (* for malloc and __new *)
size_exp, Sil.mem_alloc_pname mk size_exp, Sil.mem_alloc_pname mk
| [(size_exp, _); (Sil.Const (Const.Cfun pname), _)] -> | [(size_exp, _); (Exp.Const (Const.Cfun pname), _)] ->
size_exp, pname size_exp, pname
| _ -> | _ ->
raise (Exceptions.Wrong_argument_number __POS__) in raise (Exceptions.Wrong_argument_number __POS__) in
@ -782,9 +782,9 @@ let execute_alloc mk can_return_null
let n_size_exp' = evaluate_char_sizeof n_size_exp in let n_size_exp' = evaluate_char_sizeof n_size_exp in
Prop.exp_normalize_prop prop n_size_exp', prop in Prop.exp_normalize_prop prop n_size_exp', prop in
let cnt_te = let cnt_te =
Sil.Sizeof (Typ.Tarray (Typ.Tint Typ.IChar, None), Some size_exp', Subtype.exact) in Exp.Sizeof (Typ.Tarray (Typ.Tint Typ.IChar, None), Some size_exp', Subtype.exact) in
let id_new = Ident.create_fresh Ident.kprimed in let id_new = Ident.create_fresh Ident.kprimed in
let exp_new = Sil.Var id_new in let exp_new = Exp.Var id_new in
let ptsto_new = let ptsto_new =
Prop.mk_ptsto_exp (Some tenv) Prop.Fld_init (exp_new, cnt_te, None) Sil.Ialloc in Prop.mk_ptsto_exp (Some tenv) Prop.Fld_init (exp_new, cnt_te, None) Sil.Ialloc in
let prop_plus_ptsto = let prop_plus_ptsto =
@ -797,9 +797,9 @@ let execute_alloc mk can_return_null
Sil.ra_vpath = None } in Sil.ra_vpath = None } in
(* mark value as allocated *) (* mark value as allocated *)
Prop.add_or_replace_attribute prop' (Apred (Aresource ra, [exp_new])) in Prop.add_or_replace_attribute prop' (Apred (Aresource ra, [exp_new])) in
let prop_alloc = Prop.conjoin_eq (Sil.Var ret_id) exp_new prop_plus_ptsto in let prop_alloc = Prop.conjoin_eq (Exp.Var ret_id) exp_new prop_plus_ptsto in
if can_return_null then if can_return_null then
let prop_null = Prop.conjoin_eq (Sil.Var ret_id) Sil.exp_zero prop in let prop_null = Prop.conjoin_eq (Exp.Var ret_id) Sil.exp_zero prop in
[(prop_alloc, path); (prop_null, path)] [(prop_alloc, path); (prop_null, path)]
else [(prop_alloc, path)] else [(prop_alloc, path)]
@ -818,11 +818,11 @@ let execute___cxx_typeid ({ Builtin.pdesc; tenv; prop_; args; loc} as r)
| Sil.Hpointsto (e, _, _) -> Sil.exp_equal e n_lexp | Sil.Hpointsto (e, _, _) -> Sil.exp_equal e n_lexp
| _ -> false) (Prop.get_sigma prop) in | _ -> false) (Prop.get_sigma prop) in
match hpred with match hpred with
| Sil.Hpointsto (_, _, Sil.Sizeof (dynamic_type, _, _)) -> dynamic_type | Sil.Hpointsto (_, _, Exp.Sizeof (dynamic_type, _, _)) -> dynamic_type
| _ -> typ | _ -> typ
with Not_found -> typ in with Not_found -> typ in
let typ_string = Typ.to_string typ in let typ_string = Typ.to_string typ in
let set_instr = Sil.Set (field_exp, Typ.Tvoid, Sil.Const (Const.Cstr typ_string), loc) in let set_instr = Sil.Set (field_exp, Typ.Tvoid, Exp.Const (Const.Cstr typ_string), loc) in
SymExec.instrs ~mask_errors:true tenv pdesc [set_instr] res SymExec.instrs ~mask_errors:true tenv pdesc [set_instr] res
| _ -> res) | _ -> res)
| _ -> raise (Exceptions.Wrong_argument_number __POS__) | _ -> raise (Exceptions.Wrong_argument_number __POS__)
@ -834,7 +834,7 @@ let execute_pthread_create ({ Builtin.prop_; path; args; } as builtin_args)
let routine_name = Prop.exp_normalize_prop prop_ (fst start_routine) in let routine_name = Prop.exp_normalize_prop prop_ (fst start_routine) in
let routine_arg = Prop.exp_normalize_prop prop_ (fst arg) in let routine_arg = Prop.exp_normalize_prop prop_ (fst arg) in
(match routine_name, (snd start_routine) with (match routine_name, (snd start_routine) with
| Sil.Lvar pvar, _ -> | Exp.Lvar pvar, _ ->
let fun_name = Pvar.get_name pvar in let fun_name = Pvar.get_name pvar in
let fun_string = Mangled.to_string fun_name in let fun_string = Mangled.to_string fun_name in
L.d_strln ("pthread_create: calling function " ^ fun_string); L.d_strln ("pthread_create: calling function " ^ fun_string);
@ -875,7 +875,7 @@ let execute__unwrap_exception { Builtin.pdesc; prop_; path; ret_ids; args; }
let pname = Cfg.Procdesc.get_proc_name pdesc in let pname = Cfg.Procdesc.get_proc_name pdesc in
let n_ret_exn, prop = check_arith_norm_exp pname ret_exn prop_ in let n_ret_exn, prop = check_arith_norm_exp pname ret_exn prop_ in
match n_ret_exn with match n_ret_exn with
| Sil.Exn exp -> | Exp.Exn exp ->
let prop_with_exn = return_result exp prop ret_ids in let prop_with_exn = return_result exp prop ret_ids in
[(prop_with_exn, path)] [(prop_with_exn, path)]
| _ -> assert false | _ -> assert false
@ -901,12 +901,12 @@ let execute___split_get_nth { Builtin.pdesc; prop_; path; ret_ids; args; }
let n_lexp2, prop___ = check_arith_norm_exp pname lexp2 prop__ in let n_lexp2, prop___ = check_arith_norm_exp pname lexp2 prop__ in
let n_lexp3, prop = check_arith_norm_exp pname lexp3 prop___ in let n_lexp3, prop = check_arith_norm_exp pname lexp3 prop___ in
(match n_lexp1, n_lexp2, n_lexp3 with (match n_lexp1, n_lexp2, n_lexp3 with
| Sil.Const (Const.Cstr str1), Sil.Const (Const.Cstr str2), Sil.Const (Const.Cint n_sil) -> | Exp.Const (Const.Cstr str1), Exp.Const (Const.Cstr str2), Exp.Const (Const.Cint n_sil) ->
(let n = IntLit.to_int n_sil in (let n = IntLit.to_int n_sil in
try try
let parts = Str.split (Str.regexp_string str2) str1 in let parts = Str.split (Str.regexp_string str2) str1 in
let n_part = IList.nth parts n in let n_part = IList.nth parts n in
let res = Sil.Const (Const.Cstr n_part) in let res = Exp.Const (Const.Cstr n_part) in
[(return_result res prop ret_ids, path)] [(return_result res prop ret_ids, path)]
with Not_found -> assert false) with Not_found -> assert false)
| _ -> [(prop, path)]) | _ -> [(prop, path)])
@ -932,13 +932,13 @@ let execute___infer_fail { Builtin.pdesc; tenv; prop_; path; args; loc; }
| [(lexp_msg, _)] -> | [(lexp_msg, _)] ->
begin begin
match Prop.exp_normalize_prop prop_ lexp_msg with match Prop.exp_normalize_prop prop_ lexp_msg with
| Sil.Const (Const.Cstr str) -> str | Exp.Const (Const.Cstr str) -> str
| _ -> assert false | _ -> assert false
end end
| _ -> | _ ->
raise (Exceptions.Wrong_argument_number __POS__) in raise (Exceptions.Wrong_argument_number __POS__) in
let set_instr = let set_instr =
Sil.Set (Sil.Lvar Sil.custom_error, Typ.Tvoid, Sil.Const (Const.Cstr error_str), loc) in Sil.Set (Exp.Lvar Sil.custom_error, Typ.Tvoid, Exp.Const (Const.Cstr error_str), loc) in
SymExec.instrs ~mask_errors:true tenv pdesc [set_instr] [(prop_, path)] SymExec.instrs ~mask_errors:true tenv pdesc [set_instr] [(prop_, path)]
(* translate builtin assertion failure *) (* translate builtin assertion failure *)
@ -951,7 +951,7 @@ let execute___assert_fail { Builtin.pdesc; tenv; prop_; path; args; loc; }
| _ -> | _ ->
raise (Exceptions.Wrong_argument_number __POS__) in raise (Exceptions.Wrong_argument_number __POS__) in
let set_instr = let set_instr =
Sil.Set (Sil.Lvar Sil.custom_error, Typ.Tvoid, Sil.Const (Const.Cstr error_str), loc) in Sil.Set (Exp.Lvar Sil.custom_error, Typ.Tvoid, Exp.Const (Const.Cstr error_str), loc) in
SymExec.instrs ~mask_errors:true tenv pdesc [set_instr] [(prop_, path)] SymExec.instrs ~mask_errors:true tenv pdesc [set_instr] [(prop_, path)]
let __assert_fail = Builtin.register let __assert_fail = Builtin.register
@ -1154,12 +1154,12 @@ let _ = Builtin.register
let execute_objc_alloc_no_fail let execute_objc_alloc_no_fail
symb_state typ alloc_fun_opt symb_state typ alloc_fun_opt
{ Builtin.pdesc; tenv; ret_ids; loc; } = { Builtin.pdesc; tenv; ret_ids; loc; } =
let alloc_fun = Sil.Const (Const.Cfun __objc_alloc_no_fail) in let alloc_fun = Exp.Const (Const.Cfun __objc_alloc_no_fail) in
let ptr_typ = Typ.Tptr (typ, Typ.Pk_pointer) in let ptr_typ = Typ.Tptr (typ, Typ.Pk_pointer) in
let sizeof_typ = Sil.Sizeof (typ, None, Subtype.exact) in let sizeof_typ = Exp.Sizeof (typ, None, Subtype.exact) in
let alloc_fun_exp = let alloc_fun_exp =
match alloc_fun_opt with match alloc_fun_opt with
| Some pname -> [Sil.Const (Const.Cfun pname), Typ.Tvoid] | Some pname -> [Exp.Const (Const.Cfun pname), Typ.Tvoid]
| None -> [] in | None -> [] in
let alloc_instr = let alloc_instr =
Sil.Call Sil.Call

@ -24,7 +24,7 @@ let add_dispatch_calls pdesc cg tenv =
let has_dispatch_call instrs = let has_dispatch_call instrs =
IList.exists instr_is_dispatch_call instrs in IList.exists instr_is_dispatch_call instrs in
let replace_dispatch_calls = function let replace_dispatch_calls = function
| Sil.Call (ret_ids, (Sil.Const (Const.Cfun callee_pname) as call_exp), | Sil.Call (ret_ids, (Exp.Const (Const.Cfun callee_pname) as call_exp),
(((_, receiver_typ) :: _) as args), loc, call_flags) as instr (((_, receiver_typ) :: _) as args), loc, call_flags) as instr
when call_flags_is_dispatch call_flags -> when call_flags_is_dispatch call_flags ->
(* the frontend should not populate the list of targets *) (* the frontend should not populate the list of targets *)
@ -143,7 +143,7 @@ module NullifyTransferFunctions = struct
active_defs active_defs
lhs_ids in lhs_ids in
active_defs', to_nullify active_defs', to_nullify
| Sil.Set (Sil.Lvar lhs_pvar, _, _, _) -> | Sil.Set (Exp.Lvar lhs_pvar, _, _, _) ->
VarDomain.add (Var.of_pvar lhs_pvar) active_defs, to_nullify VarDomain.add (Var.of_pvar lhs_pvar) active_defs, to_nullify
| Sil.Set _ | Prune _ | Declare_locals _ | Stackop _ | Remove_temps _ | Sil.Set _ | Prune _ | Declare_locals _ | Stackop _ | Remove_temps _
| Abstract _ -> | Abstract _ ->
@ -218,9 +218,9 @@ let add_nullify_instrs pdesc tenv liveness_inv_map =
Var.Set.fold Var.Set.fold
(fun var (pvars_acc, ids_acc) -> match Var.to_exp var with (fun var (pvars_acc, ids_acc) -> match Var.to_exp var with
(* we nullify all address taken variables at the end of the procedure *) (* we nullify all address taken variables at the end of the procedure *)
| Sil.Lvar pvar when not (AddressTaken.Domain.mem pvar address_taken_vars) -> | Exp.Lvar pvar when not (AddressTaken.Domain.mem pvar address_taken_vars) ->
pvar :: pvars_acc, ids_acc pvar :: pvars_acc, ids_acc
| Sil.Var id -> | Exp.Var id ->
pvars_acc, id :: ids_acc pvars_acc, id :: ids_acc
| _ -> pvars_acc, ids_acc) | _ -> pvars_acc, ids_acc)
to_nullify to_nullify
@ -259,7 +259,7 @@ let do_copy_propagation pdesc tenv =
| _ -> last_id in | _ -> last_id in
id_sub_inner var_map var' last_id' id_sub_inner var_map var' last_id'
with Not_found -> with Not_found ->
Sil.Var last_id in Exp.Var last_id in
id_sub_inner var_map (Var.of_id id) id in id_sub_inner var_map (Var.of_id id) id in
(* perform copy-propagation on each instruction in [node] *) (* perform copy-propagation on each instruction in [node] *)

@ -179,10 +179,10 @@ let force_delayed_print fmt =
let (n: int) = Obj.obj n in let (n: int) = Obj.obj n in
for _ = 1 to n do F.fprintf fmt "@]" done for _ = 1 to n do F.fprintf fmt "@]" done
| (L.PTexp, e) -> | (L.PTexp, e) ->
let (e: Sil.exp) = Obj.obj e in let (e: Exp.t) = Obj.obj e in
Sil.pp_exp pe_default fmt e Sil.pp_exp pe_default fmt e
| (L.PTexp_list, el) -> | (L.PTexp_list, el) ->
let (el: Sil.exp list) = Obj.obj el in let (el: Exp.t list) = Obj.obj el in
Sil.pp_exp_list pe_default fmt el Sil.pp_exp_list pe_default fmt el
| (L.PThpred, hpred) -> | (L.PThpred, hpred) ->
let (hpred: Sil.hpred) = Obj.obj hpred in let (hpred: Sil.hpred) = Obj.obj hpred in
@ -306,7 +306,7 @@ let force_delayed_print fmt =
let (sub: Sil.subst) = Obj.obj sub in let (sub: Sil.subst) = Obj.obj sub in
Prop.pp_sub pe_default fmt sub Prop.pp_sub pe_default fmt sub
| (L.PTtexp_full, te) -> | (L.PTtexp_full, te) ->
let (te: Sil.exp) = Obj.obj te in let (te: Exp.t) = Obj.obj te in
Sil.pp_texp_full pe_default fmt te Sil.pp_texp_full pe_default fmt te
| (L.PTtyp_full, t) -> | (L.PTtyp_full, t) ->
let (t: Typ.t) = Obj.obj t in let (t: Typ.t) = Obj.obj t in

File diff suppressed because it is too large Load Diff

@ -134,28 +134,28 @@ val sigma_sub : subst -> hpred list -> hpred list
val prop_sub : subst -> 'a t -> exposed t val prop_sub : subst -> 'a t -> exposed t
(** Apply the substitution to all the expressions in the prop. *) (** Apply the substitution to all the expressions in the prop. *)
val prop_expmap : (Sil.exp -> Sil.exp) -> 'a t -> exposed t val prop_expmap : (Exp.t -> Exp.t) -> 'a t -> exposed t
(** Relaces all expressions in the [hpred list] using the first argument. (** Relaces all expressions in the [hpred list] using the first argument.
Assume that the first parameter defines a partial function. Assume that the first parameter defines a partial function.
No expressions inside hpara are replaced. *) No expressions inside hpara are replaced. *)
val sigma_replace_exp : (exp * exp) list -> hpred list -> hpred list val sigma_replace_exp : (Exp.t * Exp.t) list -> hpred list -> hpred list
val sigma_map : 'a t -> (hpred -> hpred) -> 'a t val sigma_map : 'a t -> (hpred -> hpred) -> 'a t
(** {2 Normalization} *) (** {2 Normalization} *)
(** Turn an inequality expression into an atom *) (** Turn an inequality expression into an atom *)
val mk_inequality : Sil.exp -> Sil.atom val mk_inequality : Exp.t -> Sil.atom
(** Return [true] if the atom is an inequality *) (** Return [true] if the atom is an inequality *)
val atom_is_inequality : Sil.atom -> bool val atom_is_inequality : Sil.atom -> bool
(** If the atom is [e<=n] return [e,n] *) (** If the atom is [e<=n] return [e,n] *)
val atom_exp_le_const : Sil.atom -> (Sil.exp * IntLit.t) option val atom_exp_le_const : Sil.atom -> (Exp.t * IntLit.t) option
(** If the atom is [n<e] return [n,e] *) (** If the atom is [n<e] return [n,e] *)
val atom_const_lt_exp : Sil.atom -> (IntLit.t * Sil.exp) option val atom_const_lt_exp : Sil.atom -> (IntLit.t * Exp.t) option
(** Negate an atom *) (** Negate an atom *)
val atom_negate : Sil.atom -> Sil.atom val atom_negate : Sil.atom -> Sil.atom
@ -163,30 +163,30 @@ val atom_negate : Sil.atom -> Sil.atom
(** type for arithmetic problems *) (** type for arithmetic problems *)
type arith_problem = type arith_problem =
(* division by zero *) (* division by zero *)
| Div0 of Sil.exp | Div0 of Exp.t
(* unary minus of unsigned type applied to the given expression *) (* unary minus of unsigned type applied to the given expression *)
| UminusUnsigned of Sil.exp * Typ.t | UminusUnsigned of Exp.t * Typ.t
(** Look for an arithmetic problem in [exp] *) (** Look for an arithmetic problem in [exp] *)
val find_arithmetic_problem : path_pos -> normal t -> Sil.exp -> arith_problem option * normal t val find_arithmetic_problem : path_pos -> normal t -> Exp.t -> arith_problem option * normal t
(** Normalize [exp] using the pure part of [prop]. Later, we should (** Normalize [exp] using the pure part of [prop]. Later, we should
change this such that the normalization exposes offsets of [exp] change this such that the normalization exposes offsets of [exp]
as much as possible. *) as much as possible. *)
val exp_normalize_prop : 'a t -> Sil.exp -> Sil.exp val exp_normalize_prop : 'a t -> Exp.t -> Exp.t
(** Normalize the expression without abstracting complex subexpressions *) (** Normalize the expression without abstracting complex subexpressions *)
val exp_normalize_noabs : Sil.subst -> Sil.exp -> Sil.exp val exp_normalize_noabs : Sil.subst -> Exp.t -> Exp.t
(** Collapse consecutive indices that should be added. For instance, (** Collapse consecutive indices that should be added. For instance,
this function reduces x[1][1] to x[2]. The [typ] argument is used this function reduces x[1][1] to x[2]. The [typ] argument is used
to ensure the soundness of this collapsing. *) to ensure the soundness of this collapsing. *)
val exp_collapse_consecutive_indices_prop : Typ.t -> Sil.exp -> Sil.exp val exp_collapse_consecutive_indices_prop : Typ.t -> Exp.t -> Exp.t
(** Normalize [exp] used for the address of a heap cell. (** Normalize [exp] used for the address of a heap cell.
This normalization does not combine two offsets inside [exp]. *) This normalization does not combine two offsets inside [exp]. *)
val lexp_normalize_prop : 'a t -> exp -> exp val lexp_normalize_prop : 'a t -> Exp.t -> Exp.t
val atom_normalize_prop : 'a t -> atom -> atom val atom_normalize_prop : 'a t -> atom -> atom
@ -217,38 +217,39 @@ val prop_is_emp : 'a t -> bool
(** {2 Functions for changing and generating propositions} *) (** {2 Functions for changing and generating propositions} *)
(** Construct a disequality. *) (** Construct a disequality. *)
val mk_neq : exp -> exp -> atom val mk_neq : Exp.t -> Exp.t -> atom
(** Construct an equality. *) (** Construct an equality. *)
val mk_eq : exp -> exp -> atom val mk_eq : Exp.t -> Exp.t -> atom
(** Construct a positive pred. *) (** Construct a positive pred. *)
val mk_pred : attribute -> exp list -> atom val mk_pred : attribute -> Exp.t list -> atom
(** Construct a negative pred. *) (** Construct a negative pred. *)
val mk_npred : attribute -> exp list -> atom val mk_npred : attribute -> Exp.t list -> atom
(** create a strexp of the given type, populating the structures if [expand_structs] is true *) (** create a strexp of the given type, populating the structures if [expand_structs] is true *)
val create_strexp_of_type : val create_strexp_of_type :
Tenv.t option -> struct_init_mode -> Typ.t -> Sil.exp option -> Sil.inst -> Sil.strexp Tenv.t option -> struct_init_mode -> Typ.t -> Exp.t option -> Sil.inst -> Sil.strexp
(** Construct a pointsto. *) (** Construct a pointsto. *)
val mk_ptsto : exp -> strexp -> exp -> hpred val mk_ptsto : Exp.t -> strexp -> Exp.t -> hpred
(** Construct a points-to predicate for an expression using either the provided expression [name] as (** Construct a points-to predicate for an expression using either the provided expression [name] as
base for fresh identifiers. *) base for fresh identifiers. *)
val mk_ptsto_exp : Tenv.t option -> struct_init_mode -> exp * exp * exp option -> Sil.inst -> hpred val mk_ptsto_exp :
Tenv.t option -> struct_init_mode -> Exp.t * Exp.t * Exp.t option -> Sil.inst -> hpred
(** Construct a points-to predicate for a single program variable. (** Construct a points-to predicate for a single program variable.
If [expand_structs] is true, initialize the fields of structs with fresh variables. *) If [expand_structs] is true, initialize the fields of structs with fresh variables. *)
val mk_ptsto_lvar : val mk_ptsto_lvar :
Tenv.t option -> struct_init_mode -> Sil.inst -> Pvar.t * exp * exp option -> hpred Tenv.t option -> struct_init_mode -> Sil.inst -> Pvar.t * Exp.t * Exp.t option -> hpred
(** Construct a lseg predicate *) (** Construct a lseg predicate *)
val mk_lseg : lseg_kind -> hpara -> exp -> exp -> exp list -> hpred val mk_lseg : lseg_kind -> hpara -> Exp.t -> Exp.t -> Exp.t list -> hpred
(** Construct a dllseg predicate *) (** Construct a dllseg predicate *)
val mk_dllseg : lseg_kind -> hpara_dll -> exp -> exp -> exp -> exp -> exp list -> hpred val mk_dllseg : lseg_kind -> hpara_dll -> Exp.t -> Exp.t -> Exp.t -> Exp.t -> Exp.t list -> hpred
(** Construct a hpara *) (** Construct a hpara *)
val mk_hpara : Ident.t -> Ident.t -> Ident.t list -> Ident.t list -> hpred list -> hpara val mk_hpara : Ident.t -> Ident.t -> Ident.t list -> Ident.t list -> hpred list -> hpara
@ -273,55 +274,55 @@ val prop_sigma_star : 'a t -> hpred list -> exposed t
val prop_atom_and : ?footprint: bool -> normal t -> atom -> normal t val prop_atom_and : ?footprint: bool -> normal t -> atom -> normal t
(** Conjoin [exp1]=[exp2] with a symbolic heap [prop]. *) (** Conjoin [exp1]=[exp2] with a symbolic heap [prop]. *)
val conjoin_eq : ?footprint: bool -> exp -> exp -> normal t -> normal t val conjoin_eq : ?footprint: bool -> Exp.t -> Exp.t -> normal t -> normal t
(** Conjoin [exp1]!=[exp2] with a symbolic heap [prop]. *) (** Conjoin [exp1]!=[exp2] with a symbolic heap [prop]. *)
val conjoin_neq : ?footprint: bool -> exp -> exp -> normal t -> normal t val conjoin_neq : ?footprint: bool -> Exp.t -> Exp.t -> normal t -> normal t
(** Check whether an atom is used to mark an attribute *) (** Check whether an atom is used to mark an attribute *)
val atom_is_attribute : atom -> bool val atom_is_attribute : atom -> bool
(** Apply f to every resource attribute in the prop *) (** Apply f to every resource attribute in the prop *)
val attribute_map_resource : normal t -> (Sil.exp -> Sil.res_action -> Sil.res_action) -> normal t val attribute_map_resource : normal t -> (Exp.t -> Sil.res_action -> Sil.res_action) -> normal t
(** Return the exp and attribute marked in the atom if any, and return None otherwise *) (** Return the exp and attribute marked in the atom if any, and return None otherwise *)
val atom_get_attribute : atom -> atom option val atom_get_attribute : atom -> atom option
(** Get the attributes associated to the expression, if any *) (** Get the attributes associated to the expression, if any *)
val get_attributes : 'a t -> exp -> atom list val get_attributes : 'a t -> Exp.t -> atom list
(** Get the undef attribute associated to the expression, if any *) (** Get the undef attribute associated to the expression, if any *)
val get_undef_attribute : 'a t -> exp -> atom option val get_undef_attribute : 'a t -> Exp.t -> atom option
(** Get the resource attribute associated to the expression, if any *) (** Get the resource attribute associated to the expression, if any *)
val get_resource_attribute : 'a t -> exp -> atom option val get_resource_attribute : 'a t -> Exp.t -> atom option
(** Get the taint attribute associated to the expression, if any *) (** Get the taint attribute associated to the expression, if any *)
val get_taint_attribute : 'a t -> exp -> atom option val get_taint_attribute : 'a t -> Exp.t -> atom option
(** Get the autorelease attribute associated to the expression, if any *) (** Get the autorelease attribute associated to the expression, if any *)
val get_autorelease_attribute : 'a t -> exp -> atom option val get_autorelease_attribute : 'a t -> Exp.t -> atom option
(** Get the div0 attribute associated to the expression, if any *) (** Get the div0 attribute associated to the expression, if any *)
val get_div0_attribute : 'a t -> exp -> atom option val get_div0_attribute : 'a t -> Exp.t -> atom option
(** Get the observer attribute associated to the expression, if any *) (** Get the observer attribute associated to the expression, if any *)
val get_observer_attribute : 'a t -> exp -> atom option val get_observer_attribute : 'a t -> Exp.t -> atom option
(** Get the objc null attribute associated to the expression, if any *) (** Get the objc null attribute associated to the expression, if any *)
val get_objc_null_attribute : 'a t -> exp -> atom option val get_objc_null_attribute : 'a t -> Exp.t -> atom option
(** Get the retval null attribute associated to the expression, if any *) (** Get the retval null attribute associated to the expression, if any *)
val get_retval_attribute : 'a t -> exp -> atom option val get_retval_attribute : 'a t -> Exp.t -> atom option
(** Get all the attributes of the prop *) (** Get all the attributes of the prop *)
val get_all_attributes : 'a t -> atom list val get_all_attributes : 'a t -> atom list
val has_dangling_uninit_attribute : 'a t -> exp -> bool val has_dangling_uninit_attribute : 'a t -> Exp.t -> bool
(** Set an attribute associated to the argument expressions *) (** Set an attribute associated to the argument expressions *)
val set_attribute : ?footprint: bool -> ?polarity: bool -> val set_attribute : ?footprint: bool -> ?polarity: bool ->
normal t -> attribute -> exp list -> normal t normal t -> attribute -> Exp.t list -> normal t
val add_or_replace_attribute_check_changed : val add_or_replace_attribute_check_changed :
(Sil.attribute -> Sil.attribute -> unit) -> normal t -> atom -> normal t (Sil.attribute -> Sil.attribute -> unit) -> normal t -> atom -> normal t
@ -329,8 +330,8 @@ val add_or_replace_attribute_check_changed :
(** Replace an attribute associated to the expression *) (** Replace an attribute associated to the expression *)
val add_or_replace_attribute : normal t -> atom -> normal t val add_or_replace_attribute : normal t -> atom -> normal t
(** mark Sil.Var's or Sil.Lvar's as undefined *) (** mark Exp.Var's or Exp.Lvar's as undefined *)
val mark_vars_as_undefined : normal t -> Sil.exp list -> Procname.t -> Typ.item_annotation -> val mark_vars_as_undefined : normal t -> Exp.t list -> Procname.t -> Typ.item_annotation ->
Location.t -> Sil.path_pos -> normal t Location.t -> Sil.path_pos -> normal t
(** Remove an attribute from all the atoms in the heap *) (** Remove an attribute from all the atoms in the heap *)
@ -340,9 +341,9 @@ val remove_resource_attribute : Sil.res_act_kind -> Sil.resource -> 'a t -> norm
(** [replace_objc_null lhs rhs]. (** [replace_objc_null lhs rhs].
If rhs has the objc_null attribute, replace the attribute and set the lhs = 0 *) If rhs has the objc_null attribute, replace the attribute and set the lhs = 0 *)
val replace_objc_null : normal t -> exp -> exp -> normal t val replace_objc_null : normal t -> Exp.t -> Exp.t -> normal t
val nullify_exp_with_objc_null : normal t -> exp -> normal t val nullify_exp_with_objc_null : normal t -> Exp.t -> normal t
(** Remove an attribute from an exp in the heap *) (** Remove an attribute from an exp in the heap *)
val remove_attribute_from_exp : 'a t -> atom -> normal t val remove_attribute_from_exp : 'a t -> atom -> normal t
@ -390,15 +391,15 @@ val prop_expand : normal t -> normal t list
(** translate a logical and/or operation (** translate a logical and/or operation
taking care of the non-strict semantics for side effects *) taking care of the non-strict semantics for side effects *)
val trans_land_lor : val trans_land_lor :
Binop.t -> (Ident.t list * Sil.instr list) * Sil.exp -> Binop.t -> (Ident.t list * Sil.instr list) * Exp.t ->
(Ident.t list * Sil.instr list) * Sil.exp -> Location.t -> (Ident.t list * Sil.instr list) * Exp.t -> Location.t ->
(Ident.t list * Sil.instr list) * Sil.exp (Ident.t list * Sil.instr list) * Exp.t
(** translate an if-then-else expression *) (** translate an if-then-else expression *)
val trans_if_then_else : val trans_if_then_else :
(Ident.t list * Sil.instr list) * Sil.exp -> (Ident.t list * Sil.instr list) * Sil.exp -> (Ident.t list * Sil.instr list) * Exp.t -> (Ident.t list * Sil.instr list) * Exp.t ->
(Ident.t list * Sil.instr list) * Sil.exp -> Location.t -> (Ident.t list * Sil.instr list) * Exp.t -> Location.t ->
(Ident.t list * Sil.instr list) * Sil.exp (Ident.t list * Sil.instr list) * Exp.t
(** {2 Functions for existentially quantifying and unquantifying variables} *) (** {2 Functions for existentially quantifying and unquantifying variables} *)
@ -497,7 +498,7 @@ val prop_iter_make_id_primed : Ident.t -> 'a prop_iter -> 'a prop_iter
(** Collect garbage fields. *) (** Collect garbage fields. *)
val prop_iter_gc_fields : unit prop_iter -> unit prop_iter val prop_iter_gc_fields : unit prop_iter -> unit prop_iter
val find_equal_formal_path : exp -> 'a t -> exp option val find_equal_formal_path : Exp.t -> 'a t -> Exp.t option
(** return the set of subexpressions of [strexp] *) (** return the set of subexpressions of [strexp] *)
val strexp_get_exps : Sil.strexp -> Sil.ExpSet.t val strexp_get_exps : Sil.strexp -> Sil.ExpSet.t
@ -512,7 +513,7 @@ val compute_reachable_hpreds : hpred list -> Sil.ExpSet.t -> Sil.HpredSet.t * Si
(** if possible, produce a (fieldname, typ) path from one of the [src_exps] to [snk_exp] using (** if possible, produce a (fieldname, typ) path from one of the [src_exps] to [snk_exp] using
[reachable_hpreds]. *) [reachable_hpreds]. *)
val get_fld_typ_path_opt : Sil.ExpSet.t -> Sil.exp -> Sil.HpredSet.t -> val get_fld_typ_path_opt : Sil.ExpSet.t -> Exp.t -> Sil.HpredSet.t ->
(Ident.fieldname option * Typ.t) list option (Ident.fieldname option * Typ.t) list option
(** filter [pi] by removing the pure atoms that do not contain an expression in [exps] *) (** filter [pi] by removing the pure atoms that do not contain an expression in [exps] *)

@ -17,9 +17,9 @@ module L = Logging
type t = Prop.normal Prop.t type t = Prop.normal Prop.t
type node = Sil.exp type node = Exp.t
type sub_entry = Ident.t * Sil.exp type sub_entry = Ident.t * Exp.t
type edge = Ehpred of Sil.hpred | Eatom of Sil.atom | Esub_entry of sub_entry type edge = Ehpred of Sil.hpred | Eatom of Sil.atom | Esub_entry of sub_entry
@ -27,10 +27,10 @@ let from_prop p = p
(** Return [true] if root node *) (** Return [true] if root node *)
let rec is_root = function let rec is_root = function
| Sil.Var id -> Ident.is_normal id | Exp.Var id -> Ident.is_normal id
| Sil.Exn _ | Sil.Closure _ | Sil.Const _ | Sil.Lvar _ -> true | Exp.Exn _ | Exp.Closure _ | Exp.Const _ | Exp.Lvar _ -> true
| Sil.Cast (_, e) -> is_root e | Exp.Cast (_, e) -> is_root e
| Sil.UnOp _ | Sil.BinOp _ | Sil.Lfield _ | Sil.Lindex _ | Sil.Sizeof _ -> false | Exp.UnOp _ | Exp.BinOp _ | Exp.Lfield _ | Exp.Lindex _ | Exp.Sizeof _ -> false
(** Return [true] if the nodes are connected. Used to compute reachability. *) (** Return [true] if the nodes are connected. Used to compute reachability. *)
let nodes_connected n1 n2 = let nodes_connected n1 n2 =
@ -51,7 +51,7 @@ let edge_get_source = function
| Eatom (Sil.Aneq (e1, _)) -> Some e1 | Eatom (Sil.Aneq (e1, _)) -> Some e1
| Eatom (Sil.Apred (_, e :: _) | Anpred (_, e :: _)) -> Some e | Eatom (Sil.Apred (_, e :: _) | Anpred (_, e :: _)) -> Some e
| Eatom (Sil.Apred (_, []) | Anpred (_, [])) -> None | Eatom (Sil.Apred (_, []) | Anpred (_, [])) -> None
| Esub_entry (x, _) -> Some (Sil.Var x) | Esub_entry (x, _) -> Some (Exp.Var x)
(** Return the successor nodes of the edge *) (** Return the successor nodes of the edge *)
let edge_get_succs = function let edge_get_succs = function
@ -123,7 +123,7 @@ type diff =
diff_cmap_foot : colormap (** colormap for the footprint part *) } diff_cmap_foot : colormap (** colormap for the footprint part *) }
(** Compute the subobjects in [e2] which are different from those in [e1] *) (** Compute the subobjects in [e2] which are different from those in [e1] *)
let compute_exp_diff (e1: Sil.exp) (e2: Sil.exp) : Obj.t list = let compute_exp_diff (e1: Exp.t) (e2: Exp.t) : Obj.t list =
if Sil.exp_equal e1 e2 then [] else [Obj.repr e2] if Sil.exp_equal e1 e2 then [] else [Obj.repr e2]

@ -55,16 +55,16 @@ let (--) = IntLit.sub
module DiffConstr : sig module DiffConstr : sig
type t type t
val to_leq : t -> Sil.exp * Sil.exp val to_leq : t -> Exp.t * Exp.t
val to_lt : t -> Sil.exp * Sil.exp val to_lt : t -> Exp.t * Exp.t
val to_triple : t -> Sil.exp * Sil.exp * IntLit.t val to_triple : t -> Exp.t * Exp.t * IntLit.t
val from_leq : t list -> Sil.exp * Sil.exp -> t list val from_leq : t list -> Exp.t * Exp.t -> t list
val from_lt : t list -> Sil.exp * Sil.exp -> t list val from_lt : t list -> Exp.t * Exp.t -> t list
val saturate : t list -> bool * t list val saturate : t list -> bool * t list
end = struct end = struct
type t = Sil.exp * Sil.exp * IntLit.t type t = Exp.t * Exp.t * IntLit.t
let compare (e1, e2, n) (f1, f2, m) = let compare (e1, e2, n) (f1, f2, m) =
let c1 = exp_pair_compare (e1, e2) (f1, f2) in let c1 = exp_pair_compare (e1, e2) (f1, f2) in
@ -72,15 +72,15 @@ end = struct
let equal entry1 entry2 = compare entry1 entry2 = 0 let equal entry1 entry2 = compare entry1 entry2 = 0
let to_leq (e1, e2, n) = let to_leq (e1, e2, n) =
Sil.BinOp(Binop.MinusA, e1, e2), Sil.exp_int n Exp.BinOp(Binop.MinusA, e1, e2), Sil.exp_int n
let to_lt (e1, e2, n) = let to_lt (e1, e2, n) =
Sil.exp_int (IntLit.zero -- n -- IntLit.one), Sil.BinOp(Binop.MinusA, e2, e1) Sil.exp_int (IntLit.zero -- n -- IntLit.one), Exp.BinOp(Binop.MinusA, e2, e1)
let to_triple entry = entry let to_triple entry = entry
let from_leq acc (e1, e2) = let from_leq acc (e1, e2) =
match e1, e2 with match e1, e2 with
| Sil.BinOp (Binop.MinusA, (Sil.Var id11 as e11), (Sil.Var id12 as e12)), | Exp.BinOp (Binop.MinusA, (Exp.Var id11 as e11), (Exp.Var id12 as e12)),
Sil.Const (Const.Cint n) Exp.Const (Const.Cint n)
when not (Ident.equal id11 id12) -> when not (Ident.equal id11 id12) ->
(match IntLit.to_signed n with (match IntLit.to_signed n with
| None -> acc (* ignore: constraint algorithm only terminates on signed integers *) | None -> acc (* ignore: constraint algorithm only terminates on signed integers *)
@ -89,8 +89,8 @@ end = struct
| _ -> acc | _ -> acc
let from_lt acc (e1, e2) = let from_lt acc (e1, e2) =
match e1, e2 with match e1, e2 with
| Sil.Const (Const.Cint n), | Exp.Const (Const.Cint n),
Sil.BinOp (Binop.MinusA, (Sil.Var id21 as e21), (Sil.Var id22 as e22)) Exp.BinOp (Binop.MinusA, (Exp.Var id21 as e21), (Exp.Var id22 as e22))
when not (Ident.equal id21 id22) -> when not (Ident.equal id21 id22) ->
(match IntLit.to_signed n with (match IntLit.to_signed n with
| None -> acc (* ignore: constraint algorithm only terminates on signed integers *) | None -> acc (* ignore: constraint algorithm only terminates on signed integers *)
@ -206,19 +206,19 @@ module Inequalities : sig
val from_prop : Prop.normal Prop.t -> t val from_prop : Prop.normal Prop.t -> t
(** Check [t |- e1!=e2]. Result [false] means "don't know". *) (** Check [t |- e1!=e2]. Result [false] means "don't know". *)
val check_ne : t -> Sil.exp -> Sil.exp -> bool val check_ne : t -> Exp.t -> Exp.t -> bool
(** Check [t |- e1<=e2]. Result [false] means "don't know". *) (** Check [t |- e1<=e2]. Result [false] means "don't know". *)
val check_le : t -> Sil.exp -> Sil.exp -> bool val check_le : t -> Exp.t -> Exp.t -> bool
(** Check [t |- e1<e2]. Result [false] means "don't know". *) (** Check [t |- e1<e2]. Result [false] means "don't know". *)
val check_lt : t -> Sil.exp -> Sil.exp -> bool val check_lt : t -> Exp.t -> Exp.t -> bool
(** Find a IntLit.t n such that [t |- e<=n] if possible. *) (** Find a IntLit.t n such that [t |- e<=n] if possible. *)
val compute_upper_bound : t -> Sil.exp -> IntLit.t option val compute_upper_bound : t -> Exp.t -> IntLit.t option
(** Find a IntLit.t n such that [t |- n<e] if possible. *) (** Find a IntLit.t n such that [t |- n<e] if possible. *)
val compute_lower_bound : t -> Sil.exp -> IntLit.t option val compute_lower_bound : t -> Exp.t -> IntLit.t option
(** Return [true] if a simple inconsistency is detected *) (** Return [true] if a simple inconsistency is detected *)
val inconsistent : t -> bool val inconsistent : t -> bool
@ -248,9 +248,9 @@ module Inequalities : sig
end = struct end = struct
type t = { type t = {
mutable leqs: (Sil.exp * Sil.exp) list; (** le fasts [e1 <= e2] *) mutable leqs: (Exp.t * Exp.t) list; (** le fasts [e1 <= e2] *)
mutable lts: (Sil.exp * Sil.exp) list; (** lt facts [e1 < e2] *) mutable lts: (Exp.t * Exp.t) list; (** lt facts [e1 < e2] *)
mutable neqs: (Sil.exp * Sil.exp) list; (** ne facts [e1 != e2] *) mutable neqs: (Exp.t * Exp.t) list; (** ne facts [e1 != e2] *)
} }
let inconsistent_ineq = { leqs = [(Sil.exp_one, Sil.exp_zero)]; lts = []; neqs = [] } let inconsistent_ineq = { leqs = [(Sil.exp_one, Sil.exp_zero)]; lts = []; neqs = [] }
@ -266,7 +266,7 @@ end = struct
let leqs_sorted = IList.sort leq_compare leqs in let leqs_sorted = IList.sort leq_compare leqs in
let have_same_key leq1 leq2 = let have_same_key leq1 leq2 =
match leq1, leq2 with match leq1, leq2 with
| (e1, Sil.Const (Const.Cint n1)), (e2, Sil.Const (Const.Cint n2)) -> | (e1, Exp.Const (Const.Cint n1)), (e2, Exp.Const (Const.Cint n2)) ->
Sil.exp_equal e1 e2 && IntLit.leq n1 n2 Sil.exp_equal e1 e2 && IntLit.leq n1 n2
| _, _ -> false in | _, _ -> false in
remove_redundancy have_same_key [] leqs_sorted remove_redundancy have_same_key [] leqs_sorted
@ -274,7 +274,7 @@ end = struct
let lts_sorted = IList.sort lt_compare lts in let lts_sorted = IList.sort lt_compare lts in
let have_same_key lt1 lt2 = let have_same_key lt1 lt2 =
match lt1, lt2 with match lt1, lt2 with
| (Sil.Const (Const.Cint n1), e1), (Sil.Const (Const.Cint n2), e2) -> | (Exp.Const (Const.Cint n1), e1), (Exp.Const (Const.Cint n2), e2) ->
Sil.exp_equal e1 e2 && IntLit.geq n1 n2 Sil.exp_equal e1 e2 && IntLit.geq n1 n2
| _, _ -> false in | _, _ -> false in
remove_redundancy have_same_key [] lts_sorted remove_redundancy have_same_key [] lts_sorted
@ -300,13 +300,13 @@ end = struct
with Not_found -> Sil.ExpMap.add e new_lower lmap in with Not_found -> Sil.ExpMap.add e new_lower lmap in
let rec umap_create_from_leqs umap = function let rec umap_create_from_leqs umap = function
| [] -> umap | [] -> umap
| (e1, Sil.Const (Const.Cint upper1)):: leqs_rest -> | (e1, Exp.Const (Const.Cint upper1)):: leqs_rest ->
let umap' = umap_add umap e1 upper1 in let umap' = umap_add umap e1 upper1 in
umap_create_from_leqs umap' leqs_rest umap_create_from_leqs umap' leqs_rest
| _:: leqs_rest -> umap_create_from_leqs umap leqs_rest in | _:: leqs_rest -> umap_create_from_leqs umap leqs_rest in
let rec lmap_create_from_lts lmap = function let rec lmap_create_from_lts lmap = function
| [] -> lmap | [] -> lmap
| (Sil.Const (Const.Cint lower1), e1):: lts_rest -> | (Exp.Const (Const.Cint lower1), e1):: lts_rest ->
let lmap' = lmap_add lmap e1 lower1 in let lmap' = lmap_add lmap e1 lower1 in
lmap_create_from_lts lmap' lts_rest lmap_create_from_lts lmap' lts_rest
| _:: lts_rest -> lmap_create_from_lts lmap lts_rest in | _:: lts_rest -> lmap_create_from_lts lmap lts_rest in
@ -359,9 +359,9 @@ end = struct
let process_atom = function let process_atom = function
| Sil.Aneq (e1, e2) -> (* != *) | Sil.Aneq (e1, e2) -> (* != *)
neqs := (e1, e2) :: !neqs neqs := (e1, e2) :: !neqs
| Sil.Aeq (Sil.BinOp (Binop.Le, e1, e2), Sil.Const (Const.Cint i)) when IntLit.isone i -> | Sil.Aeq (Exp.BinOp (Binop.Le, e1, e2), Exp.Const (Const.Cint i)) when IntLit.isone i ->
leqs := (e1, e2) :: !leqs (* <= *) leqs := (e1, e2) :: !leqs (* <= *)
| Sil.Aeq (Sil.BinOp (Binop.Lt, e1, e2), Sil.Const (Const.Cint i)) when IntLit.isone i -> | Sil.Aeq (Exp.BinOp (Binop.Lt, e1, e2), Exp.Const (Const.Cint i)) when IntLit.isone i ->
lts := (e1, e2) :: !lts (* < *) lts := (e1, e2) :: !lts (* < *)
| Sil.Aeq _ | Sil.Aeq _
| Sil.Apred _ | Anpred _ -> () in | Sil.Apred _ | Anpred _ -> () in
@ -374,7 +374,7 @@ end = struct
let add_lt_minus1_e e = let add_lt_minus1_e e =
lts := (Sil.exp_minus_one, e)::!lts in lts := (Sil.exp_minus_one, e)::!lts in
let texp_is_unsigned = function let texp_is_unsigned = function
| Sil.Sizeof (Typ.Tint ik, _, _) -> Typ.ikind_is_unsigned ik | Exp.Sizeof (Typ.Tint ik, _, _) -> Typ.ikind_is_unsigned ik
| _ -> false in | _ -> false in
let strexp_lt_minus1 = function let strexp_lt_minus1 = function
| Sil.Eexp (e, _) -> add_lt_minus1_e e | Sil.Eexp (e, _) -> add_lt_minus1_e e
@ -417,19 +417,19 @@ end = struct
let check_le { leqs = leqs; lts = lts; neqs = _ } e1 e2 = let check_le { leqs = leqs; lts = lts; neqs = _ } e1 e2 =
(* L.d_str "check_le "; Sil.d_exp e1; L.d_str " "; Sil.d_exp e2; L.d_ln (); *) (* L.d_str "check_le "; Sil.d_exp e1; L.d_str " "; Sil.d_exp e2; L.d_ln (); *)
match e1, e2 with match e1, e2 with
| Sil.Const (Const.Cint n1), Sil.Const (Const.Cint n2) -> IntLit.leq n1 n2 | Exp.Const (Const.Cint n1), Exp.Const (Const.Cint n2) -> IntLit.leq n1 n2
| Sil.BinOp (Binop.MinusA, Sil.Sizeof (t1, None, _), Sil.Sizeof (t2, None, _)), | Exp.BinOp (Binop.MinusA, Exp.Sizeof (t1, None, _), Exp.Sizeof (t2, None, _)),
Sil.Const(Const.Cint n2) Exp.Const(Const.Cint n2)
when IntLit.isminusone n2 && type_size_comparable t1 t2 -> when IntLit.isminusone n2 && type_size_comparable t1 t2 ->
(* [ sizeof(t1) - sizeof(t2) <= -1 ] *) (* [ sizeof(t1) - sizeof(t2) <= -1 ] *)
check_type_size_lt t1 t2 check_type_size_lt t1 t2
| e, Sil.Const (Const.Cint n) -> (* [e <= n' <= n |- e <= n] *) | e, Exp.Const (Const.Cint n) -> (* [e <= n' <= n |- e <= n] *)
IList.exists (function IList.exists (function
| e', Sil.Const (Const.Cint n') -> Sil.exp_equal e e' && IntLit.leq n' n | e', Exp.Const (Const.Cint n') -> Sil.exp_equal e e' && IntLit.leq n' n
| _, _ -> false) leqs | _, _ -> false) leqs
| Sil.Const (Const.Cint n), e -> (* [ n-1 <= n' < e |- n <= e] *) | Exp.Const (Const.Cint n), e -> (* [ n-1 <= n' < e |- n <= e] *)
IList.exists (function IList.exists (function
| Sil.Const (Const.Cint n'), e' -> Sil.exp_equal e e' && IntLit.leq (n -- IntLit.one) n' | Exp.Const (Const.Cint n'), e' -> Sil.exp_equal e e' && IntLit.leq (n -- IntLit.one) n'
| _, _ -> false) lts | _, _ -> false) lts
| _ -> Sil.exp_equal e1 e2 | _ -> Sil.exp_equal e1 e2
@ -437,14 +437,14 @@ end = struct
let check_lt { leqs = leqs; lts = lts; neqs = _ } e1 e2 = let check_lt { leqs = leqs; lts = lts; neqs = _ } e1 e2 =
(* L.d_str "check_lt "; Sil.d_exp e1; L.d_str " "; Sil.d_exp e2; L.d_ln (); *) (* L.d_str "check_lt "; Sil.d_exp e1; L.d_str " "; Sil.d_exp e2; L.d_ln (); *)
match e1, e2 with match e1, e2 with
| Sil.Const (Const.Cint n1), Sil.Const (Const.Cint n2) -> IntLit.lt n1 n2 | Exp.Const (Const.Cint n1), Exp.Const (Const.Cint n2) -> IntLit.lt n1 n2
| Sil.Const (Const.Cint n), e -> (* [n <= n' < e |- n < e] *) | Exp.Const (Const.Cint n), e -> (* [n <= n' < e |- n < e] *)
IList.exists (function IList.exists (function
| Sil.Const (Const.Cint n'), e' -> Sil.exp_equal e e' && IntLit.leq n n' | Exp.Const (Const.Cint n'), e' -> Sil.exp_equal e e' && IntLit.leq n n'
| _, _ -> false) lts | _, _ -> false) lts
| e, Sil.Const (Const.Cint n) -> (* [e <= n' <= n-1 |- e < n] *) | e, Exp.Const (Const.Cint n) -> (* [e <= n' <= n-1 |- e < n] *)
IList.exists (function IList.exists (function
| e', Sil.Const (Const.Cint n') -> Sil.exp_equal e e' && IntLit.leq n' (n -- IntLit.one) | e', Exp.Const (Const.Cint n') -> Sil.exp_equal e e' && IntLit.leq n' (n -- IntLit.one)
| _, _ -> false) leqs | _, _ -> false) leqs
| _ -> false | _ -> false
@ -456,15 +456,15 @@ end = struct
(** Find a IntLit.t n such that [t |- e<=n] if possible. *) (** Find a IntLit.t n such that [t |- e<=n] if possible. *)
let compute_upper_bound { leqs = leqs; lts = _; neqs = _ } e1 = let compute_upper_bound { leqs = leqs; lts = _; neqs = _ } e1 =
match e1 with match e1 with
| Sil.Const (Const.Cint n1) -> Some n1 | Exp.Const (Const.Cint n1) -> Some n1
| _ -> | _ ->
let e_upper_list = let e_upper_list =
IList.filter (function IList.filter (function
| e', Sil.Const (Const.Cint _) -> Sil.exp_equal e1 e' | e', Exp.Const (Const.Cint _) -> Sil.exp_equal e1 e'
| _, _ -> false) leqs in | _, _ -> false) leqs in
let upper_list = let upper_list =
IList.map (function IList.map (function
| _, Sil.Const (Const.Cint n) -> n | _, Exp.Const (Const.Cint n) -> n
| _ -> assert false) e_upper_list in | _ -> assert false) e_upper_list in
if upper_list == [] then None if upper_list == [] then None
else Some (compute_min_from_nonempty_int_list upper_list) else Some (compute_min_from_nonempty_int_list upper_list)
@ -472,16 +472,16 @@ end = struct
(** Find a IntLit.t n such that [t |- n < e] if possible. *) (** Find a IntLit.t n such that [t |- n < e] if possible. *)
let compute_lower_bound { leqs = _; lts = lts; neqs = _ } e1 = let compute_lower_bound { leqs = _; lts = lts; neqs = _ } e1 =
match e1 with match e1 with
| Sil.Const (Const.Cint n1) -> Some (n1 -- IntLit.one) | Exp.Const (Const.Cint n1) -> Some (n1 -- IntLit.one)
| Sil.Sizeof _ -> Some IntLit.zero | Exp.Sizeof _ -> Some IntLit.zero
| _ -> | _ ->
let e_lower_list = let e_lower_list =
IList.filter (function IList.filter (function
| Sil.Const (Const.Cint _), e' -> Sil.exp_equal e1 e' | Exp.Const (Const.Cint _), e' -> Sil.exp_equal e1 e'
| _, _ -> false) lts in | _, _ -> false) lts in
let lower_list = let lower_list =
IList.map (function IList.map (function
| Sil.Const (Const.Cint n), _ -> n | Exp.Const (Const.Cint n), _ -> n
| _ -> assert false) e_lower_list in | _ -> assert false) e_lower_list in
if lower_list == [] then None if lower_list == [] then None
else Some (compute_max_from_nonempty_int_list lower_list) else Some (compute_max_from_nonempty_int_list lower_list)
@ -505,15 +505,15 @@ end = struct
Format.fprintf fmt "%a %a %a" (pp_seq pp_leq) leqs (pp_seq pp_lt) lts (pp_seq pp_neq) neqs Format.fprintf fmt "%a %a %a" (pp_seq pp_leq) leqs (pp_seq pp_lt) lts (pp_seq pp_neq) neqs
let d_leqs { leqs = leqs; lts = lts; neqs = neqs } = let d_leqs { leqs = leqs; lts = lts; neqs = neqs } =
let elist = IList.map (fun (e1, e2) -> Sil.BinOp(Binop.Le, e1, e2)) leqs in let elist = IList.map (fun (e1, e2) -> Exp.BinOp(Binop.Le, e1, e2)) leqs in
Sil.d_exp_list elist Sil.d_exp_list elist
let d_lts { leqs = leqs; lts = lts; neqs = neqs } = let d_lts { leqs = leqs; lts = lts; neqs = neqs } =
let elist = IList.map (fun (e1, e2) -> Sil.BinOp(Binop.Lt, e1, e2)) lts in let elist = IList.map (fun (e1, e2) -> Exp.BinOp(Binop.Lt, e1, e2)) lts in
Sil.d_exp_list elist Sil.d_exp_list elist
let d_neqs { leqs = leqs; lts = lts; neqs = neqs } = let d_neqs { leqs = leqs; lts = lts; neqs = neqs } =
let elist = IList.map (fun (e1, e2) -> Sil.BinOp(Binop.Ne, e1, e2)) lts in let elist = IList.map (fun (e1, e2) -> Exp.BinOp(Binop.Ne, e1, e2)) lts in
Sil.d_exp_list elist Sil.d_exp_list elist
*) *)
end end
@ -527,13 +527,13 @@ let check_equal prop e1 e2 =
Sil.exp_equal n_e1 n_e2 in Sil.exp_equal n_e1 n_e2 in
let check_equal_const () = let check_equal_const () =
match n_e1, n_e2 with match n_e1, n_e2 with
| Sil.BinOp (Binop.PlusA, e1, Sil.Const (Const.Cint d)), e2 | Exp.BinOp (Binop.PlusA, e1, Exp.Const (Const.Cint d)), e2
| e2, Sil.BinOp (Binop.PlusA, e1, Sil.Const (Const.Cint d)) -> | e2, Exp.BinOp (Binop.PlusA, e1, Exp.Const (Const.Cint d)) ->
if Sil.exp_equal e1 e2 then IntLit.iszero d if Sil.exp_equal e1 e2 then IntLit.iszero d
else false else false
| Sil.Const c1, Sil.Lindex(Sil.Const c2, Sil.Const (Const.Cint i)) when IntLit.iszero i -> | Exp.Const c1, Exp.Lindex(Exp.Const c2, Exp.Const (Const.Cint i)) when IntLit.iszero i ->
Const.equal c1 c2 Const.equal c1 c2
| Sil.Lindex(Sil.Const c1, Sil.Const (Const.Cint i)), Sil.Const c2 when IntLit.iszero i -> | Exp.Lindex(Exp.Const c1, Exp.Const (Const.Cint i)), Exp.Const c2 when IntLit.iszero i ->
Const.equal c1 c2 Const.equal c1 c2
| _, _ -> false in | _, _ -> false in
let check_equal_pi () = let check_equal_pi () =
@ -554,23 +554,23 @@ let check_zero e =
*) *)
let is_root prop base_exp exp = let is_root prop base_exp exp =
let rec f offlist_past e = match e with let rec f offlist_past e = match e with
| Sil.Var _ | Sil.Const _ | Sil.UnOp _ | Sil.BinOp _ | Sil.Exn _ | Sil.Closure _ | Sil.Lvar _ | Exp.Var _ | Exp.Const _ | Exp.UnOp _ | Exp.BinOp _ | Exp.Exn _ | Exp.Closure _ | Exp.Lvar _
| Sil.Sizeof _ -> | Exp.Sizeof _ ->
if check_equal prop base_exp e if check_equal prop base_exp e
then Some offlist_past then Some offlist_past
else None else None
| Sil.Cast(_, sub_exp) -> f offlist_past sub_exp | Exp.Cast(_, sub_exp) -> f offlist_past sub_exp
| Sil.Lfield(sub_exp, fldname, typ) -> f (Sil.Off_fld (fldname, typ) :: offlist_past) sub_exp | Exp.Lfield(sub_exp, fldname, typ) -> f (Sil.Off_fld (fldname, typ) :: offlist_past) sub_exp
| Sil.Lindex(sub_exp, e) -> f (Sil.Off_index e :: offlist_past) sub_exp | Exp.Lindex(sub_exp, e) -> f (Sil.Off_index e :: offlist_past) sub_exp
in f [] exp in f [] exp
(** Get upper and lower bounds of an expression, if any *) (** Get upper and lower bounds of an expression, if any *)
let get_bounds prop _e = let get_bounds prop _e =
let e_norm = Prop.exp_normalize_prop prop _e in let e_norm = Prop.exp_normalize_prop prop _e in
let e_root, off = match e_norm with let e_root, off = match e_norm with
| Sil.BinOp (Binop.PlusA, e, Sil.Const (Const.Cint n1)) -> | Exp.BinOp (Binop.PlusA, e, Exp.Const (Const.Cint n1)) ->
e, IntLit.neg n1 e, IntLit.neg n1
| Sil.BinOp (Binop.MinusA, e, Sil.Const (Const.Cint n1)) -> | Exp.BinOp (Binop.MinusA, e, Exp.Const (Const.Cint n1)) ->
e, n1 e, n1
| _ -> | _ ->
e_norm, IntLit.zero in e_norm, IntLit.zero in
@ -589,23 +589,23 @@ let check_disequal prop e1 e2 =
let n_e2 = Prop.exp_normalize_prop prop e2 in let n_e2 = Prop.exp_normalize_prop prop e2 in
let check_disequal_const () = let check_disequal_const () =
match n_e1, n_e2 with match n_e1, n_e2 with
| Sil.Const c1, Sil.Const c2 -> | Exp.Const c1, Exp.Const c2 ->
(Const.kind_equal c1 c2) && not (Const.equal c1 c2) (Const.kind_equal c1 c2) && not (Const.equal c1 c2)
| Sil.Const c1, Sil.Lindex(Sil.Const c2, Sil.Const (Const.Cint d)) -> | Exp.Const c1, Exp.Lindex(Exp.Const c2, Exp.Const (Const.Cint d)) ->
if IntLit.iszero d if IntLit.iszero d
then not (Const.equal c1 c2) (* offset=0 is no offset *) then not (Const.equal c1 c2) (* offset=0 is no offset *)
else Const.equal c1 c2 (* same base, different offsets *) else Const.equal c1 c2 (* same base, different offsets *)
| Sil.BinOp (Binop.PlusA, e1, Sil.Const (Const.Cint d1)), | Exp.BinOp (Binop.PlusA, e1, Exp.Const (Const.Cint d1)),
Sil.BinOp (Binop.PlusA, e2, Sil.Const (Const.Cint d2)) -> Exp.BinOp (Binop.PlusA, e2, Exp.Const (Const.Cint d2)) ->
if Sil.exp_equal e1 e2 then IntLit.neq d1 d2 if Sil.exp_equal e1 e2 then IntLit.neq d1 d2
else false else false
| Sil.BinOp (Binop.PlusA, e1, Sil.Const (Const.Cint d)), e2 | Exp.BinOp (Binop.PlusA, e1, Exp.Const (Const.Cint d)), e2
| e2, Sil.BinOp (Binop.PlusA, e1, Sil.Const (Const.Cint d)) -> | e2, Exp.BinOp (Binop.PlusA, e1, Exp.Const (Const.Cint d)) ->
if Sil.exp_equal e1 e2 then not (IntLit.iszero d) if Sil.exp_equal e1 e2 then not (IntLit.iszero d)
else false else false
| Sil.Lindex(Sil.Const c1, Sil.Const (Const.Cint d)), Sil.Const c2 -> | Exp.Lindex(Exp.Const c1, Exp.Const (Const.Cint d)), Exp.Const c2 ->
if IntLit.iszero d then not (Const.equal c1 c2) else Const.equal c1 c2 if IntLit.iszero d then not (Const.equal c1 c2) else Const.equal c1 c2
| Sil.Lindex(Sil.Const c1, Sil.Const d1), Sil.Lindex (Sil.Const c2, Sil.Const d2) -> | Exp.Lindex(Exp.Const c1, Exp.Const d1), Exp.Lindex (Exp.Const c2, Exp.Const d2) ->
Const.equal c1 c2 && not (Const.equal d1 d2) Const.equal c1 c2 && not (Const.equal d1 d2)
| _, _ -> false in | _, _ -> false in
let ineq = lazy (Inequalities.from_prop prop) in let ineq = lazy (Inequalities.from_prop prop) in
@ -678,7 +678,7 @@ let check_disequal prop e1 e2 =
let check_le_normalized prop e1 e2 = let check_le_normalized prop e1 e2 =
(* L.d_str "check_le_normalized "; Sil.d_exp e1; L.d_str " "; Sil.d_exp e2; L.d_ln (); *) (* L.d_str "check_le_normalized "; Sil.d_exp e1; L.d_str " "; Sil.d_exp e2; L.d_ln (); *)
let eL, eR, off = match e1, e2 with let eL, eR, off = match e1, e2 with
| Sil.BinOp(Binop.MinusA, f1, f2), Sil.Const (Const.Cint n) -> | Exp.BinOp(Binop.MinusA, f1, f2), Exp.Const (Const.Cint n) ->
if Sil.exp_equal f1 f2 if Sil.exp_equal f1 f2
then Sil.exp_zero, Sil.exp_zero, n then Sil.exp_zero, Sil.exp_zero, n
else f1, f2, n else f1, f2, n
@ -735,9 +735,9 @@ let check_atom prop a0 =
close_out outc; close_out outc;
end; end;
match a with match a with
| Sil.Aeq (Sil.BinOp (Binop.Le, e1, e2), Sil.Const (Const.Cint i)) | Sil.Aeq (Exp.BinOp (Binop.Le, e1, e2), Exp.Const (Const.Cint i))
when IntLit.isone i -> check_le_normalized prop e1 e2 when IntLit.isone i -> check_le_normalized prop e1 e2
| Sil.Aeq (Sil.BinOp (Binop.Lt, e1, e2), Sil.Const (Const.Cint i)) | Sil.Aeq (Exp.BinOp (Binop.Lt, e1, e2), Exp.Const (Const.Cint i))
when IntLit.isone i -> check_lt_normalized prop e1 e2 when IntLit.isone i -> check_lt_normalized prop e1 e2
| Sil.Aeq (e1, e2) -> check_equal prop e1 e2 | Sil.Aeq (e1, e2) -> check_equal prop e1 e2
| Sil.Aneq (e1, e2) -> check_disequal prop e1 e2 | Sil.Aneq (e1, e2) -> check_disequal prop e1 e2
@ -745,7 +745,7 @@ let check_atom prop a0 =
(** Check [prop |- e1<=e2]. Result [false] means "don't know". *) (** Check [prop |- e1<=e2]. Result [false] means "don't know". *)
let check_le prop e1 e2 = let check_le prop e1 e2 =
let e1_le_e2 = Sil.BinOp (Binop.Le, e1, e2) in let e1_le_e2 = Exp.BinOp (Binop.Le, e1, e2) in
check_atom prop (Prop.mk_inequality e1_le_e2) check_atom prop (Prop.mk_inequality e1_le_e2)
(** Check whether [prop |- allocated(e)]. *) (** Check whether [prop |- allocated(e)]. *)
@ -782,7 +782,7 @@ let check_inconsistency_two_hpreds prop =
| (Sil.Hdllseg (Sil.Lseg_NE, _, iF, _, _, iB, _) as hpred) :: sigma_rest -> | (Sil.Hdllseg (Sil.Lseg_NE, _, iF, _, _, iB, _) as hpred) :: sigma_rest ->
if Sil.exp_equal iF e || Sil.exp_equal iB e then true if Sil.exp_equal iF e || Sil.exp_equal iB e then true
else f e (hpred:: sigma_seen) sigma_rest else f e (hpred:: sigma_seen) sigma_rest
| Sil.Hlseg (Sil.Lseg_PE, _, e1, Sil.Const (Const.Cint i), _) as hpred :: sigma_rest | Sil.Hlseg (Sil.Lseg_PE, _, e1, Exp.Const (Const.Cint i), _) as hpred :: sigma_rest
when IntLit.iszero i -> when IntLit.iszero i ->
if Sil.exp_equal e1 e then true if Sil.exp_equal e1 e then true
else f e (hpred:: sigma_seen) sigma_rest else f e (hpred:: sigma_seen) sigma_rest
@ -795,7 +795,7 @@ let check_inconsistency_two_hpreds prop =
let e_new = Prop.exp_normalize_prop prop_new e let e_new = Prop.exp_normalize_prop prop_new e
in f e_new [] sigma_new in f e_new [] sigma_new
else f e (hpred:: sigma_seen) sigma_rest else f e (hpred:: sigma_seen) sigma_rest
| Sil.Hdllseg (Sil.Lseg_PE, _, e1, _, Sil.Const (Const.Cint i), _, _) as hpred :: sigma_rest | Sil.Hdllseg (Sil.Lseg_PE, _, e1, _, Exp.Const (Const.Cint i), _, _) as hpred :: sigma_rest
when IntLit.iszero i -> when IntLit.iszero i ->
if Sil.exp_equal e1 e then true if Sil.exp_equal e1 e then true
else f e (hpred:: sigma_seen) sigma_rest else f e (hpred:: sigma_seen) sigma_rest
@ -844,7 +844,7 @@ let check_inconsistency_base prop =
Pvar.is_this pvar && Pvar.is_this pvar &&
procedure_attr.ProcAttributes.is_cpp_instance_method in procedure_attr.ProcAttributes.is_cpp_instance_method in
let do_hpred = function let do_hpred = function
| Sil.Hpointsto (Sil.Lvar pv, Sil.Eexp (e, _), _) -> | Sil.Hpointsto (Exp.Lvar pv, Sil.Eexp (e, _), _) ->
Sil.exp_equal e Sil.exp_zero && Sil.exp_equal e Sil.exp_zero &&
Pvar.is_seed pv && Pvar.is_seed pv &&
(is_java_this pv || is_cpp_this pv || is_objc_instance_self pv) (is_java_this pv || is_cpp_this pv || is_objc_instance_self pv)
@ -853,11 +853,11 @@ let check_inconsistency_base prop =
let inconsistent_atom = function let inconsistent_atom = function
| Sil.Aeq (e1, e2) -> | Sil.Aeq (e1, e2) ->
(match e1, e2 with (match e1, e2 with
| Sil.Const c1, Sil.Const c2 -> not (Const.equal c1 c2) | Exp.Const c1, Exp.Const c2 -> not (Const.equal c1 c2)
| _ -> check_disequal prop e1 e2) | _ -> check_disequal prop e1 e2)
| Sil.Aneq (e1, e2) -> | Sil.Aneq (e1, e2) ->
(match e1, e2 with (match e1, e2 with
| Sil.Const c1, Sil.Const c2 -> Const.equal c1 c2 | Exp.Const c1, Exp.Const c2 -> Const.equal c1 c2
| _ -> (Sil.exp_compare e1 e2 = 0)) | _ -> (Sil.exp_compare e1 e2 = 0))
| Sil.Apred _ | Anpred _ -> false in | Sil.Apred _ | Anpred _ -> false in
let inconsistent_inequalities () = let inconsistent_inequalities () =
@ -893,7 +893,7 @@ type subst2 = Sil.subst * Sil.subst
type exc_body = type exc_body =
| EXC_FALSE | EXC_FALSE
| EXC_FALSE_HPRED of Sil.hpred | EXC_FALSE_HPRED of Sil.hpred
| EXC_FALSE_EXPS of Sil.exp * Sil.exp | EXC_FALSE_EXPS of Exp.t * Exp.t
| EXC_FALSE_SEXPS of Sil.strexp * Sil.strexp | EXC_FALSE_SEXPS of Sil.strexp * Sil.strexp
| EXC_FALSE_ATOM of Sil.atom | EXC_FALSE_ATOM of Sil.atom
| EXC_FALSE_SIGMA of Sil.hpred list | EXC_FALSE_SIGMA of Sil.hpred list
@ -904,7 +904,7 @@ exception MISSING_EXC of string
type check = type check =
| Bounds_check | Bounds_check
| Class_cast_check of Sil.exp * Sil.exp * Sil.exp | Class_cast_check of Exp.t * Exp.t * Exp.t
let d_typings typings = let d_typings typings =
let d_elem (exp, texp) = let d_elem (exp, texp) =
@ -918,32 +918,32 @@ module ProverState : sig
(** type for array bounds checks *) (** type for array bounds checks *)
type bounds_check = type bounds_check =
| BClen_imply of Sil.exp * Sil.exp * Sil.exp list (** coming from array_len_imply *) | BClen_imply of Exp.t * Exp.t * Exp.t list (** coming from array_len_imply *)
| BCfrom_pre of Sil.atom (** coming implicitly from preconditions *) | BCfrom_pre of Sil.atom (** coming implicitly from preconditions *)
val add_bounds_check : bounds_check -> unit val add_bounds_check : bounds_check -> unit
val add_frame_fld : Sil.hpred -> unit val add_frame_fld : Sil.hpred -> unit
val add_frame_typ : Sil.exp * Sil.exp -> unit val add_frame_typ : Exp.t * Exp.t -> unit
val add_missing_fld : Sil.hpred -> unit val add_missing_fld : Sil.hpred -> unit
val add_missing_pi : Sil.atom -> unit val add_missing_pi : Sil.atom -> unit
val add_missing_sigma : Sil.hpred list -> unit val add_missing_sigma : Sil.hpred list -> unit
val add_missing_typ : Sil.exp * Sil.exp -> unit val add_missing_typ : Exp.t * Exp.t -> unit
val atom_is_array_bounds_check : Sil.atom -> bool (** check if atom in pre is a bounds check *) val atom_is_array_bounds_check : Sil.atom -> bool (** check if atom in pre is a bounds check *)
val get_bounds_checks : unit -> bounds_check list val get_bounds_checks : unit -> bounds_check list
val get_frame_fld : unit -> Sil.hpred list val get_frame_fld : unit -> Sil.hpred list
val get_frame_typ : unit -> (Sil.exp * Sil.exp) list val get_frame_typ : unit -> (Exp.t * Exp.t) list
val get_missing_fld : unit -> Sil.hpred list val get_missing_fld : unit -> Sil.hpred list
val get_missing_pi : unit -> Sil.atom list val get_missing_pi : unit -> Sil.atom list
val get_missing_sigma : unit -> Sil.hpred list val get_missing_sigma : unit -> Sil.hpred list
val get_missing_typ : unit -> (Sil.exp * Sil.exp) list val get_missing_typ : unit -> (Exp.t * Exp.t) list
val d_implication : Sil.subst * Sil.subst -> 'a Prop.t * 'b Prop.t -> unit val d_implication : Sil.subst * Sil.subst -> 'a Prop.t * 'b Prop.t -> unit
val d_implication_error : string * (Sil.subst * Sil.subst) * exc_body -> unit val d_implication_error : string * (Sil.subst * Sil.subst) * exc_body -> unit
end = struct end = struct
type bounds_check = type bounds_check =
| BClen_imply of Sil.exp * Sil.exp * Sil.exp list | BClen_imply of Exp.t * Exp.t * Exp.t list
| BCfrom_pre of Sil.atom | BCfrom_pre of Sil.atom
let implication_lhs = ref Prop.prop_emp let implication_lhs = ref Prop.prop_emp
@ -962,7 +962,7 @@ end = struct
let prop_fav_len prop = let prop_fav_len prop =
let fav = Sil.fav_new () in let fav = Sil.fav_new () in
let do_hpred = function let do_hpred = function
| Sil.Hpointsto (_, Sil.Earray (Sil.Var _ as len, _, _), _) -> | Sil.Hpointsto (_, Sil.Earray (Exp.Var _ as len, _, _), _) ->
Sil.exp_fav_add fav len Sil.exp_fav_add fav len
| _ -> () in | _ -> () in
IList.iter do_hpred (Prop.get_sigma prop); IList.iter do_hpred (Prop.get_sigma prop);
@ -1127,19 +1127,19 @@ let exp_imply calc_missing subs e1_in e2_in : subst2 =
else raise (IMPL_EXC ("exps", subs, (EXC_FALSE_EXPS (e1, e2)))) else raise (IMPL_EXC ("exps", subs, (EXC_FALSE_EXPS (e1, e2))))
| true, false -> raise (IMPL_EXC ("exps", subs, (EXC_FALSE_EXPS (e1, e2)))) | true, false -> raise (IMPL_EXC ("exps", subs, (EXC_FALSE_EXPS (e1, e2))))
| false, true -> | false, true ->
let sub2' = extend_sub (snd subs) v2 (Sil.exp_sub (fst subs) (Sil.Var v1)) in let sub2' = extend_sub (snd subs) v2 (Sil.exp_sub (fst subs) (Exp.Var v1)) in
(fst subs, sub2') (fst subs, sub2')
| true, true -> | true, true ->
let v1' = Ident.create_fresh Ident.knormal in let v1' = Ident.create_fresh Ident.knormal in
let sub1' = extend_sub (fst subs) v1 (Sil.Var v1') in let sub1' = extend_sub (fst subs) v1 (Exp.Var v1') in
let sub2' = extend_sub (snd subs) v2 (Sil.Var v1') in let sub2' = extend_sub (snd subs) v2 (Exp.Var v1') in
(sub1', sub2') in (sub1', sub2') in
let rec do_imply subs e1 e2 : subst2 = let rec do_imply subs e1 e2 : subst2 =
L.d_str "do_imply "; Sil.d_exp e1; L.d_str " "; Sil.d_exp e2; L.d_ln (); L.d_str "do_imply "; Sil.d_exp e1; L.d_str " "; Sil.d_exp e2; L.d_ln ();
match e1, e2 with match e1, e2 with
| Sil.Var v1, Sil.Var v2 -> | Exp.Var v1, Exp.Var v2 ->
var_imply subs v1 v2 var_imply subs v1 v2
| e1, Sil.Var v2 -> | e1, Exp.Var v2 ->
let occurs_check v e = (* check whether [v] occurs in normalized [e] *) let occurs_check v e = (* check whether [v] occurs in normalized [e] *)
if Sil.fav_mem (Sil.exp_fav e) v if Sil.fav_mem (Sil.exp_fav e) v
&& Sil.fav_mem (Sil.exp_fav (Prop.exp_normalize_prop Prop.prop_emp e)) v && Sil.fav_mem (Sil.exp_fav (Prop.exp_normalize_prop Prop.prop_emp e)) v
@ -1150,42 +1150,42 @@ let exp_imply calc_missing subs e1_in e2_in : subst2 =
(fst subs, sub2') (fst subs, sub2')
else else
raise (IMPL_EXC ("expressions not equal", subs, (EXC_FALSE_EXPS (e1, e2)))) raise (IMPL_EXC ("expressions not equal", subs, (EXC_FALSE_EXPS (e1, e2))))
| e1, Sil.BinOp (Binop.PlusA, Sil.Var v2, e2) | e1, Exp.BinOp (Binop.PlusA, Exp.Var v2, e2)
| e1, Sil.BinOp (Binop.PlusA, e2, Sil.Var v2) | e1, Exp.BinOp (Binop.PlusA, e2, Exp.Var v2)
when Ident.is_primed v2 || Ident.is_footprint v2 -> when Ident.is_primed v2 || Ident.is_footprint v2 ->
let e' = Sil.BinOp (Binop.MinusA, e1, e2) in let e' = Exp.BinOp (Binop.MinusA, e1, e2) in
do_imply subs (Prop.exp_normalize_noabs Sil.sub_empty e') (Sil.Var v2) do_imply subs (Prop.exp_normalize_noabs Sil.sub_empty e') (Exp.Var v2)
| Sil.Var _, e2 -> | Exp.Var _, e2 ->
if calc_missing then if calc_missing then
let () = ProverState.add_missing_pi (Sil.Aeq (e1_in, e2_in)) in let () = ProverState.add_missing_pi (Sil.Aeq (e1_in, e2_in)) in
subs subs
else raise (IMPL_EXC ("expressions not equal", subs, (EXC_FALSE_EXPS (e1, e2)))) else raise (IMPL_EXC ("expressions not equal", subs, (EXC_FALSE_EXPS (e1, e2))))
| Sil.Lvar pv1, Sil.Const _ when Pvar.is_global pv1 -> | Exp.Lvar pv1, Exp.Const _ when Pvar.is_global pv1 ->
if calc_missing then if calc_missing then
let () = ProverState.add_missing_pi (Sil.Aeq (e1_in, e2_in)) in let () = ProverState.add_missing_pi (Sil.Aeq (e1_in, e2_in)) in
subs subs
else raise (IMPL_EXC ("expressions not equal", subs, (EXC_FALSE_EXPS (e1, e2)))) else raise (IMPL_EXC ("expressions not equal", subs, (EXC_FALSE_EXPS (e1, e2))))
| Sil.Lvar v1, Sil.Lvar v2 -> | Exp.Lvar v1, Exp.Lvar v2 ->
if Pvar.equal v1 v2 then subs if Pvar.equal v1 v2 then subs
else raise (IMPL_EXC ("expressions not equal", subs, (EXC_FALSE_EXPS (e1, e2)))) else raise (IMPL_EXC ("expressions not equal", subs, (EXC_FALSE_EXPS (e1, e2))))
| Sil.Const c1, Sil.Const c2 -> | Exp.Const c1, Exp.Const c2 ->
if (Const.equal c1 c2) then subs if (Const.equal c1 c2) then subs
else raise (IMPL_EXC ("constants not equal", subs, (EXC_FALSE_EXPS (e1, e2)))) else raise (IMPL_EXC ("constants not equal", subs, (EXC_FALSE_EXPS (e1, e2))))
| Sil.Const (Const.Cint _), Sil.BinOp (Binop.PlusPI, _, _) -> | Exp.Const (Const.Cint _), Exp.BinOp (Binop.PlusPI, _, _) ->
raise (IMPL_EXC ("pointer+index cannot evaluate to a constant", subs, (EXC_FALSE_EXPS (e1, e2)))) raise (IMPL_EXC ("pointer+index cannot evaluate to a constant", subs, (EXC_FALSE_EXPS (e1, e2))))
| Sil.Const (Const.Cint n1), Sil.BinOp (Binop.PlusA, f1, Sil.Const (Const.Cint n2)) -> | Exp.Const (Const.Cint n1), Exp.BinOp (Binop.PlusA, f1, Exp.Const (Const.Cint n2)) ->
do_imply subs (Sil.exp_int (n1 -- n2)) f1 do_imply subs (Sil.exp_int (n1 -- n2)) f1
| Sil.BinOp(op1, e1, f1), Sil.BinOp(op2, e2, f2) when op1 == op2 -> | Exp.BinOp(op1, e1, f1), Exp.BinOp(op2, e2, f2) when op1 == op2 ->
do_imply (do_imply subs e1 e2) f1 f2 do_imply (do_imply subs e1 e2) f1 f2
| Sil.BinOp (Binop.PlusA, Sil.Var v1, e1), e2 -> | Exp.BinOp (Binop.PlusA, Exp.Var v1, e1), e2 ->
do_imply subs (Sil.Var v1) (Sil.BinOp (Binop.MinusA, e2, e1)) do_imply subs (Exp.Var v1) (Exp.BinOp (Binop.MinusA, e2, e1))
| Sil.BinOp (Binop.PlusPI, Sil.Lvar pv1, e1), e2 -> | Exp.BinOp (Binop.PlusPI, Exp.Lvar pv1, e1), e2 ->
do_imply subs (Sil.Lvar pv1) (Sil.BinOp (Binop.MinusA, e2, e1)) do_imply subs (Exp.Lvar pv1) (Exp.BinOp (Binop.MinusA, e2, e1))
| e1, Sil.Const _ -> | e1, Exp.Const _ ->
raise (IMPL_EXC ("lhs not constant", subs, (EXC_FALSE_EXPS (e1, e2)))) raise (IMPL_EXC ("lhs not constant", subs, (EXC_FALSE_EXPS (e1, e2))))
| Sil.Lfield(e1, fd1, _), Sil.Lfield(e2, fd2, _) when fd1 == fd2 -> | Exp.Lfield(e1, fd1, _), Exp.Lfield(e2, fd2, _) when fd1 == fd2 ->
do_imply subs e1 e2 do_imply subs e1 e2
| Sil.Lindex(e1, f1), Sil.Lindex(e2, f2) -> | Exp.Lindex(e1, f1), Exp.Lindex(e2, f2) ->
do_imply (do_imply subs e1 e2) f1 f2 do_imply (do_imply subs e1 e2) f1 f2
| _ -> | _ ->
d_impl_err ("exp_imply not implemented", subs, (EXC_FALSE_EXPS (e1, e2))); d_impl_err ("exp_imply not implemented", subs, (EXC_FALSE_EXPS (e1, e2)));
@ -1198,24 +1198,24 @@ let exp_imply calc_missing subs e1_in e2_in : subst2 =
and stamp - 1 *) and stamp - 1 *)
let path_to_id path = let path_to_id path =
let rec f = function let rec f = function
| Sil.Var id -> | Exp.Var id ->
if Ident.is_footprint id then None if Ident.is_footprint id then None
else Some (Ident.name_to_string (Ident.get_name id) ^ (string_of_int (Ident.get_stamp id))) else Some (Ident.name_to_string (Ident.get_name id) ^ (string_of_int (Ident.get_stamp id)))
| Sil.Lfield (e, fld, _) -> | Exp.Lfield (e, fld, _) ->
(match f e with (match f e with
| None -> None | None -> None
| Some s -> Some (s ^ "_" ^ (Ident.fieldname_to_string fld))) | Some s -> Some (s ^ "_" ^ (Ident.fieldname_to_string fld)))
| Sil.Lindex (e, ind) -> | Exp.Lindex (e, ind) ->
(match f e with (match f e with
| None -> None | None -> None
| Some s -> Some (s ^ "_" ^ (Sil.exp_to_string ind))) | Some s -> Some (s ^ "_" ^ (Sil.exp_to_string ind)))
| Sil.Lvar _ -> | Exp.Lvar _ ->
Some (Sil.exp_to_string path) Some (Sil.exp_to_string path)
| Sil.Const (Const.Cstr s) -> | Exp.Const (Const.Cstr s) ->
Some ("_const_str_" ^ s) Some ("_const_str_" ^ s)
| Sil.Const (Const.Cclass c) -> | Exp.Const (Const.Cclass c) ->
Some ("_const_class_" ^ Ident.name_to_string c) Some ("_const_class_" ^ Ident.name_to_string c)
| Sil.Const _ -> None | Exp.Const _ -> None
| _ -> | _ ->
L.d_str "path_to_id undefined on "; Sil.d_exp path; L.d_ln (); L.d_str "path_to_id undefined on "; Sil.d_exp path; L.d_ln ();
assert false (* None *) in assert false (* None *) in
@ -1227,10 +1227,10 @@ let path_to_id path =
(** Implication for the length of arrays *) (** Implication for the length of arrays *)
let array_len_imply calc_missing subs len1 len2 indices2 = let array_len_imply calc_missing subs len1 len2 indices2 =
match len1, len2 with match len1, len2 with
| _, Sil.Var _ | _, Exp.Var _
| _, Sil.BinOp (Binop.PlusA, Sil.Var _, _) | _, Exp.BinOp (Binop.PlusA, Exp.Var _, _)
| _, Sil.BinOp (Binop.PlusA, _, Sil.Var _) | _, Exp.BinOp (Binop.PlusA, _, Exp.Var _)
| Sil.BinOp (Binop.Mult, _, _), _ -> | Exp.BinOp (Binop.Mult, _, _), _ ->
(try exp_imply calc_missing subs len1 len2 with (try exp_imply calc_missing subs len1 len2 with
| IMPL_EXC (s, subs', x) -> | IMPL_EXC (s, subs', x) ->
raise (IMPL_EXC ("array len:" ^ s, subs', x))) raise (IMPL_EXC ("array len:" ^ s, subs', x)))
@ -1256,9 +1256,9 @@ let rec sexp_imply source calc_index_frame calc_missing subs se1 se2 typ2 : subs
begin begin
let e2' = Sil.exp_sub (snd subs) e2 in let e2' = Sil.exp_sub (snd subs) e2 in
match e2' with match e2' with
| Sil.Var id2 when Ident.is_primed id2 -> | Exp.Var id2 when Ident.is_primed id2 ->
let id2' = Ident.create_fresh Ident.knormal in let id2' = Ident.create_fresh Ident.knormal in
let sub2' = extend_sub (snd subs) id2 (Sil.Var id2') in let sub2' = extend_sub (snd subs) id2 (Exp.Var id2') in
(fst subs, sub2'), None, None (fst subs, sub2'), None, None
| _ -> | _ ->
d_impl_err ("sexp_imply not implemented", subs, (EXC_FALSE_SEXPS (se1, se2))); d_impl_err ("sexp_imply not implemented", subs, (EXC_FALSE_SEXPS (se1, se2)));
@ -1281,7 +1281,7 @@ let rec sexp_imply source calc_index_frame calc_missing subs se1 se2 typ2 : subs
| Sil.Eexp (_, inst), Sil.Estruct (fsel, inst') -> | Sil.Eexp (_, inst), Sil.Estruct (fsel, inst') ->
d_impl_err ("WARNING: function call with parameters of struct type, treating as unknown", subs, (EXC_FALSE_SEXPS (se1, se2))); d_impl_err ("WARNING: function call with parameters of struct type, treating as unknown", subs, (EXC_FALSE_SEXPS (se1, se2)));
let fsel' = let fsel' =
let g (f, _) = (f, Sil.Eexp (Sil.Var (Ident.create_fresh Ident.knormal), inst)) in let g (f, _) = (f, Sil.Eexp (Exp.Var (Ident.create_fresh Ident.knormal), inst)) in
IList.map g fsel in IList.map g fsel in
sexp_imply source calc_index_frame calc_missing subs (Sil.Estruct (fsel', inst')) se2 typ2 sexp_imply source calc_index_frame calc_missing subs (Sil.Estruct (fsel', inst')) se2 typ2
| Sil.Eexp _, Sil.Earray (len, _, inst) | Sil.Eexp _, Sil.Earray (len, _, inst)
@ -1292,7 +1292,7 @@ let rec sexp_imply source calc_index_frame calc_missing subs se1 se2 typ2 : subs
let se2' = Sil.Earray (len, [(Sil.exp_zero, se2)], inst) in let se2' = Sil.Earray (len, [(Sil.exp_zero, se2)], inst) in
let typ2' = Typ.Tarray (typ2, None) in let typ2' = Typ.Tarray (typ2, None) in
(* In the sexp_imply, struct_imply, array_imply, and sexp_imply_nolhs functions, the typ2 (* In the sexp_imply, struct_imply, array_imply, and sexp_imply_nolhs functions, the typ2
argument is only used by eventually passing its value to Typ.struct_typ_fld, Sil.Lfield, argument is only used by eventually passing its value to Typ.struct_typ_fld, Exp.Lfield,
Typ.struct_typ_fld, or Typ.array_elem. None of these are sensitive to the length field Typ.struct_typ_fld, or Typ.array_elem. None of these are sensitive to the length field
of Tarray, so forgetting the length of typ2' here is not a problem. *) of Tarray, so forgetting the length of typ2' here is not a problem. *)
sexp_imply source true calc_missing subs se1 se2' typ2' (* calculate index_frame because the rhs is a singleton array *) sexp_imply source true calc_missing subs se1 se2' typ2' (* calculate index_frame because the rhs is a singleton array *)
@ -1308,7 +1308,8 @@ and struct_imply source calc_missing subs fsel1 fsel2 typ2 : subst2 * ((Ident.fi
match Ident.fieldname_compare f1 f2 with match Ident.fieldname_compare f1 f2 with
| 0 -> | 0 ->
let typ' = Typ.struct_typ_fld (Some Typ.Tvoid) f2 typ2 in let typ' = Typ.struct_typ_fld (Some Typ.Tvoid) f2 typ2 in
let subs', se_frame, se_missing = sexp_imply (Sil.Lfield (source, f2, typ2)) false calc_missing subs se1 se2 typ' in let subs', se_frame, se_missing =
sexp_imply (Exp.Lfield (source, f2, typ2)) false calc_missing subs se1 se2 typ' in
let subs'', fld_frame, fld_missing = struct_imply source calc_missing subs' fsel1' fsel2' typ2 in let subs'', fld_frame, fld_missing = struct_imply source calc_missing subs' fsel1' fsel2' typ2 in
let fld_frame' = match se_frame with let fld_frame' = match se_frame with
| None -> fld_frame | None -> fld_frame
@ -1322,19 +1323,20 @@ and struct_imply source calc_missing subs fsel1 fsel2 typ2 : subst2 * ((Ident.fi
subs', ((f1, se1) :: fld_frame), fld_missing subs', ((f1, se1) :: fld_frame), fld_missing
| _ -> | _ ->
let typ' = Typ.struct_typ_fld (Some Typ.Tvoid) f2 typ2 in let typ' = Typ.struct_typ_fld (Some Typ.Tvoid) f2 typ2 in
let subs' = sexp_imply_nolhs (Sil.Lfield (source, f2, typ2)) calc_missing subs se2 typ' in let subs' =
sexp_imply_nolhs (Exp.Lfield (source, f2, typ2)) calc_missing subs se2 typ' in
let subs', fld_frame, fld_missing = struct_imply source calc_missing subs' fsel1 fsel2' typ2 in let subs', fld_frame, fld_missing = struct_imply source calc_missing subs' fsel1 fsel2' typ2 in
let fld_missing' = (f2, se2) :: fld_missing in let fld_missing' = (f2, se2) :: fld_missing in
subs', fld_frame, fld_missing' subs', fld_frame, fld_missing'
end end
| [], (f2, se2) :: fsel2' -> | [], (f2, se2) :: fsel2' ->
let typ' = Typ.struct_typ_fld (Some Typ.Tvoid) f2 typ2 in let typ' = Typ.struct_typ_fld (Some Typ.Tvoid) f2 typ2 in
let subs' = sexp_imply_nolhs (Sil.Lfield (source, f2, typ2)) calc_missing subs se2 typ' in let subs' = sexp_imply_nolhs (Exp.Lfield (source, f2, typ2)) calc_missing subs se2 typ' in
let subs'', fld_frame, fld_missing = struct_imply source calc_missing subs' [] fsel2' typ2 in let subs'', fld_frame, fld_missing = struct_imply source calc_missing subs' [] fsel2' typ2 in
subs'', fld_frame, (f2, se2):: fld_missing subs'', fld_frame, (f2, se2):: fld_missing
and array_imply source calc_index_frame calc_missing subs esel1 esel2 typ2 and array_imply source calc_index_frame calc_missing subs esel1 esel2 typ2
: subst2 * ((Sil.exp * Sil.strexp) list) * ((Sil.exp * Sil.strexp) list) : subst2 * ((Exp.t * Sil.strexp) list) * ((Exp.t * Sil.strexp) list)
= =
let typ_elem = Typ.array_elem (Some Typ.Tvoid) typ2 in let typ_elem = Typ.array_elem (Some Typ.Tvoid) typ2 in
match esel1, esel2 with match esel1, esel2 with
@ -1346,10 +1348,11 @@ and array_imply source calc_index_frame calc_missing subs esel1 esel2 typ2
if n < 0 then array_imply source calc_index_frame calc_missing subs esel1' esel2 typ2 if n < 0 then array_imply source calc_index_frame calc_missing subs esel1' esel2 typ2
else if n > 0 then array_imply source calc_index_frame calc_missing subs esel1 esel2' typ2 else if n > 0 then array_imply source calc_index_frame calc_missing subs esel1 esel2' typ2
else (* n=0 *) else (* n=0 *)
let subs', _, _ = sexp_imply (Sil.Lindex (source, e1)) false calc_missing subs se1 se2 typ_elem in let subs', _, _ =
sexp_imply (Exp.Lindex (source, e1)) false calc_missing subs se1 se2 typ_elem in
array_imply source calc_index_frame calc_missing subs' esel1' esel2' typ2 array_imply source calc_index_frame calc_missing subs' esel1' esel2' typ2
| [], (e2, se2) :: esel2' -> | [], (e2, se2) :: esel2' ->
let subs' = sexp_imply_nolhs (Sil.Lindex (source, e2)) calc_missing subs se2 typ_elem in let subs' = sexp_imply_nolhs (Exp.Lindex (source, e2)) calc_missing subs se2 typ_elem in
let subs'', index_frame, index_missing = array_imply source calc_index_frame calc_missing subs' [] esel2' typ2 in let subs'', index_frame, index_missing = array_imply source calc_index_frame calc_missing subs' [] esel2' typ2 in
let index_missing' = (e2, se2) :: index_missing in let index_missing' = (e2, se2) :: index_missing in
subs'', index_frame, index_missing' subs'', index_frame, index_missing'
@ -1360,17 +1363,18 @@ and sexp_imply_nolhs source calc_missing subs se2 typ2 =
let e2 = Sil.exp_sub (snd subs) _e2 in let e2 = Sil.exp_sub (snd subs) _e2 in
begin begin
match e2 with match e2 with
| Sil.Var v2 when Ident.is_primed v2 -> | Exp.Var v2 when Ident.is_primed v2 ->
let v2' = path_to_id source in let v2' = path_to_id source in
(* L.d_str "called path_to_id on "; Sil.d_exp e2; L.d_str " returns "; Sil.d_exp (Sil.Var v2'); L.d_ln (); *) (* L.d_str "called path_to_id on "; Sil.d_exp e2; *)
let sub2' = extend_sub (snd subs) v2 (Sil.Var v2') in (* L.d_str " returns "; Sil.d_exp (Exp.Var v2'); L.d_ln (); *)
let sub2' = extend_sub (snd subs) v2 (Exp.Var v2') in
(fst subs, sub2') (fst subs, sub2')
| Sil.Var _ -> | Exp.Var _ ->
if calc_missing then subs if calc_missing then subs
else raise (IMPL_EXC ("exp only in rhs is not a primed var", subs, EXC_FALSE)) else raise (IMPL_EXC ("exp only in rhs is not a primed var", subs, EXC_FALSE))
| Sil.Const _ when calc_missing -> | Exp.Const _ when calc_missing ->
let id = path_to_id source in let id = path_to_id source in
ProverState.add_missing_pi (Sil.Aeq (Sil.Var id, _e2)); ProverState.add_missing_pi (Sil.Aeq (Exp.Var id, _e2));
subs subs
| _ -> | _ ->
raise (IMPL_EXC ("exp only in rhs is not a primed var", subs, EXC_FALSE)) raise (IMPL_EXC ("exp only in rhs is not a primed var", subs, EXC_FALSE))
@ -1406,11 +1410,11 @@ let filter_hpred sub hpred2 hpred1 = match (Sil.hpred_sub sub hpred1), hpred2 wi
let hpred_has_primed_lhs sub hpred = let hpred_has_primed_lhs sub hpred =
let rec find_primed e = match e with let rec find_primed e = match e with
| Sil.Lfield (e, _, _) -> | Exp.Lfield (e, _, _) ->
find_primed e find_primed e
| Sil.Lindex (e, _) -> | Exp.Lindex (e, _) ->
find_primed e find_primed e
| Sil.BinOp (Binop.PlusPI, e1, _) -> | Exp.BinOp (Binop.PlusPI, e1, _) ->
find_primed e1 find_primed e1
| _ -> | _ ->
Sil.fav_exists (Sil.exp_fav e) Ident.is_primed in Sil.fav_exists (Sil.exp_fav e) Ident.is_primed in
@ -1437,13 +1441,13 @@ let move_primed_lhs_from_front subs sigma = match sigma with
Return [(changed, calc_index_frame', hpred')] where [changed] indicates whether the predicate has changed. *) Return [(changed, calc_index_frame', hpred')] where [changed] indicates whether the predicate has changed. *)
let expand_hpred_pointer calc_index_frame hpred : bool * bool * Sil.hpred = let expand_hpred_pointer calc_index_frame hpred : bool * bool * Sil.hpred =
let rec expand changed calc_index_frame hpred = match hpred with let rec expand changed calc_index_frame hpred = match hpred with
| Sil.Hpointsto (Sil.Lfield (e, fld, typ_fld), se, t) -> | Sil.Hpointsto (Exp.Lfield (e, fld, typ_fld), se, t) ->
let t' = match t, typ_fld with let t' = match t, typ_fld with
| _, Typ.Tstruct _ -> (* the struct type of fld is known *) | _, Typ.Tstruct _ -> (* the struct type of fld is known *)
Sil.Sizeof (typ_fld, None, Subtype.exact) Exp.Sizeof (typ_fld, None, Subtype.exact)
| Sil.Sizeof (t1, len, st), _ -> | Exp.Sizeof (t1, len, st), _ ->
(* the struct type of fld is not known -- typically Tvoid *) (* the struct type of fld is not known -- typically Tvoid *)
Sil.Sizeof Exp.Sizeof
(Typ.Tstruct (Typ.Tstruct
{ Typ.instance_fields = [(fld, t1, Typ.item_annotation_empty)]; { Typ.instance_fields = [(fld, t1, Typ.item_annotation_empty)];
static_fields = []; static_fields = [];
@ -1457,17 +1461,17 @@ let expand_hpred_pointer calc_index_frame hpred : bool * bool * Sil.hpred =
| _ -> raise (Failure "expand_hpred_pointer: Unexpected non-sizeof type in Lfield") in | _ -> raise (Failure "expand_hpred_pointer: Unexpected non-sizeof type in Lfield") in
let hpred' = Sil.Hpointsto (e, Sil.Estruct ([(fld, se)], Sil.inst_none), t') in let hpred' = Sil.Hpointsto (e, Sil.Estruct ([(fld, se)], Sil.inst_none), t') in
expand true true hpred' expand true true hpred'
| Sil.Hpointsto (Sil.Lindex (e, ind), se, t) -> | Sil.Hpointsto (Exp.Lindex (e, ind), se, t) ->
let t' = match t with let t' = match t with
| Sil.Sizeof (t_, len, st) -> Sil.Sizeof (Typ.Tarray (t_, None), len, st) | Exp.Sizeof (t_, len, st) -> Exp.Sizeof (Typ.Tarray (t_, None), len, st)
| _ -> raise (Failure "expand_hpred_pointer: Unexpected non-sizeof type in Lindex") in | _ -> raise (Failure "expand_hpred_pointer: Unexpected non-sizeof type in Lindex") in
let len = match t' with let len = match t' with
| Sil.Sizeof (_, Some len, _) -> len | Exp.Sizeof (_, Some len, _) -> len
| _ -> Sil.exp_get_undefined false in | _ -> Sil.exp_get_undefined false in
let hpred' = Sil.Hpointsto (e, Sil.Earray (len, [(ind, se)], Sil.inst_none), t') in let hpred' = Sil.Hpointsto (e, Sil.Earray (len, [(ind, se)], Sil.inst_none), t') in
expand true true hpred' expand true true hpred'
| Sil.Hpointsto (Sil.BinOp (Binop.PlusPI, e1, e2), Sil.Earray (len, esel, inst), t) -> | Sil.Hpointsto (Exp.BinOp (Binop.PlusPI, e1, e2), Sil.Earray (len, esel, inst), t) ->
let shift_exp e = Sil.BinOp (Binop.PlusA, e, e2) in let shift_exp e = Exp.BinOp (Binop.PlusA, e, e2) in
let len' = shift_exp len in let len' = shift_exp len in
let esel' = IList.map (fun (e, se) -> (shift_exp e, se)) esel in let esel' = IList.map (fun (e, se) -> (shift_exp e, se)) esel in
let hpred' = Sil.Hpointsto (e1, Sil.Earray (len', esel', inst), t) in let hpred' = Sil.Hpointsto (e1, Sil.Earray (len', esel', inst), t) in
@ -1606,17 +1610,17 @@ struct
case, if they are possible *) case, if they are possible *)
let subtype_case_analysis tenv texp1 texp2 = let subtype_case_analysis tenv texp1 texp2 =
match texp1, texp2 with match texp1, texp2 with
| Sil.Sizeof (t1, len1, st1), Sil.Sizeof (t2, len2, st2) -> | Exp.Sizeof (t1, len1, st1), Exp.Sizeof (t2, len2, st2) ->
begin begin
let pos_opt, neg_opt = case_analysis_type tenv (t1, st1) (t2, st2) in let pos_opt, neg_opt = case_analysis_type tenv (t1, st1) (t2, st2) in
let pos_type_opt = match pos_opt with let pos_type_opt = match pos_opt with
| None -> None | None -> None
| Some st1' -> | Some st1' ->
let t1', len1' = if check_subtype tenv t1 t2 then t1, len1 else t2, len2 in let t1', len1' = if check_subtype tenv t1 t2 then t1, len1 else t2, len2 in
Some (Sil.Sizeof (t1', len1', st1')) in Some (Exp.Sizeof (t1', len1', st1')) in
let neg_type_opt = match neg_opt with let neg_type_opt = match neg_opt with
| None -> None | None -> None
| Some st1' -> Some (Sil.Sizeof (t1, len1, st1')) in | Some st1' -> Some (Exp.Sizeof (t1, len1, st1')) in
pos_type_opt, neg_type_opt pos_type_opt, neg_type_opt
end end
| _ -> (* don't know, consider both possibilities *) | _ -> (* don't know, consider both possibilities *)
@ -1625,7 +1629,7 @@ end
let cast_exception tenv texp1 texp2 e1 subs = let cast_exception tenv texp1 texp2 e1 subs =
let _ = match texp1, texp2 with let _ = match texp1, texp2 with
| Sil.Sizeof (t1, _, _), Sil.Sizeof (t2, _, st2) -> | Exp.Sizeof (t1, _, _), Exp.Sizeof (t2, _, st2) ->
if Config.developer_mode || if Config.developer_mode ||
(Subtype.is_cast st2 && (Subtype.is_cast st2 &&
not (Subtyping_check.check_subtype tenv t1 t2)) then not (Subtyping_check.check_subtype tenv t1 t2)) then
@ -1655,7 +1659,7 @@ let get_overrides_of tenv supertype pname =
(** Check the equality of two types ignoring flags in the subtyping components *) (** Check the equality of two types ignoring flags in the subtyping components *)
let texp_equal_modulo_subtype_flag texp1 texp2 = match texp1, texp2 with let texp_equal_modulo_subtype_flag texp1 texp2 = match texp1, texp2 with
| Sil.Sizeof (t1, len1, st1), Sil.Sizeof (t2, len2, st2) -> | Exp.Sizeof (t1, len1, st1), Exp.Sizeof (t2, len2, st2) ->
Typ.equal t1 t2 Typ.equal t1 t2
&& (opt_equal Sil.exp_equal len1 len2) && (opt_equal Sil.exp_equal len1 len2)
&& Subtype.equal_modulo_flag st1 st2 && Subtype.equal_modulo_flag st1 st2
@ -1667,13 +1671,13 @@ let texp_imply tenv subs texp1 texp2 e1 calc_missing =
(* classes and arrays in Java, and just classes in C++ and ObjC *) (* classes and arrays in Java, and just classes in C++ and ObjC *)
let types_subject_to_dynamic_cast = let types_subject_to_dynamic_cast =
match texp1, texp2 with match texp1, texp2 with
| Sil.Sizeof ((Typ.Tstruct _) as typ1, _, _), Sil.Sizeof (Typ.Tstruct _, _, _) | Exp.Sizeof ((Typ.Tstruct _) as typ1, _, _), Exp.Sizeof (Typ.Tstruct _, _, _)
| Sil.Sizeof ((Typ.Tarray _) as typ1, _, _), Sil.Sizeof (Typ.Tarray _, _, _) | Exp.Sizeof ((Typ.Tarray _) as typ1, _, _), Exp.Sizeof (Typ.Tarray _, _, _)
| Sil.Sizeof ((Typ.Tarray _) as typ1, _, _), Sil.Sizeof (Typ.Tstruct _, _, _) | Exp.Sizeof ((Typ.Tarray _) as typ1, _, _), Exp.Sizeof (Typ.Tstruct _, _, _)
| Sil.Sizeof ((Typ.Tstruct _) as typ1, _, _), Sil.Sizeof (Typ.Tarray _, _, _) | Exp.Sizeof ((Typ.Tstruct _) as typ1, _, _), Exp.Sizeof (Typ.Tarray _, _, _)
when is_java_class typ1 -> true when is_java_class typ1 -> true
| Sil.Sizeof (typ1, _, _), Sil.Sizeof (typ2, _, _) -> | Exp.Sizeof (typ1, _, _), Exp.Sizeof (typ2, _, _) ->
(Typ.is_cpp_class typ1 && Typ.is_cpp_class typ2) || (Typ.is_cpp_class typ1 && Typ.is_cpp_class typ2) ||
(Typ.is_objc_class typ1 && Typ.is_objc_class typ2) (Typ.is_objc_class typ1 && Typ.is_objc_class typ2)
| _ -> false in | _ -> false in
@ -1707,7 +1711,7 @@ let texp_imply tenv subs texp1 texp2 e1 calc_missing =
(** pre-process implication between a non-array and an array: the non-array is turned into an array (** pre-process implication between a non-array and an array: the non-array is turned into an array
of length given by its type only active in type_size mode *) of length given by its type only active in type_size mode *)
let sexp_imply_preprocess se1 texp1 se2 = match se1, texp1, se2 with let sexp_imply_preprocess se1 texp1 se2 = match se1, texp1, se2 with
| Sil.Eexp (_, inst), Sil.Sizeof _, Sil.Earray _ when Config.type_size -> | Sil.Eexp (_, inst), Exp.Sizeof _, Sil.Earray _ when Config.type_size ->
let se1' = Sil.Earray (texp1, [(Sil.exp_zero, se1)], inst) in let se1' = Sil.Earray (texp1, [(Sil.exp_zero, se1)], inst) in
L.d_strln_color Orange "sexp_imply_preprocess"; L.d_str " se1: "; Sil.d_sexp se1; L.d_ln (); L.d_str " se1': "; Sil.d_sexp se1'; L.d_ln (); L.d_strln_color Orange "sexp_imply_preprocess"; L.d_str " se1: "; Sil.d_sexp se1; L.d_ln (); L.d_str " se1': "; Sil.d_sexp se1'; L.d_ln ();
se1' se1'
@ -1717,7 +1721,7 @@ let sexp_imply_preprocess se1 texp1 se2 = match se1, texp1, se2 with
of the one in the callee, add a type frame and type missing *) of the one in the callee, add a type frame and type missing *)
let handle_parameter_subtype tenv prop1 sigma2 subs (e1, se1, texp1) (se2, texp2) = let handle_parameter_subtype tenv prop1 sigma2 subs (e1, se1, texp1) (se2, texp2) =
let is_callee = match e1 with let is_callee = match e1 with
| Sil.Lvar pv -> Pvar.is_callee pv | Exp.Lvar pv -> Pvar.is_callee pv
| _ -> false in | _ -> false in
let is_allocated_lhs e = let is_allocated_lhs e =
let filter = function let filter = function
@ -1727,13 +1731,13 @@ let handle_parameter_subtype tenv prop1 sigma2 subs (e1, se1, texp1) (se2, texp2
let type_rhs e = let type_rhs e =
let sub_opt = ref None in let sub_opt = ref None in
let filter = function let filter = function
| Sil.Hpointsto(e', _, Sil.Sizeof(t, len, sub)) when Sil.exp_equal e' e -> | Sil.Hpointsto(e', _, Exp.Sizeof(t, len, sub)) when Sil.exp_equal e' e ->
sub_opt := Some (t, len, sub); sub_opt := Some (t, len, sub);
true true
| _ -> false in | _ -> false in
if IList.exists filter sigma2 then !sub_opt else None in if IList.exists filter sigma2 then !sub_opt else None in
let add_subtype () = match texp1, texp2, se1, se2 with let add_subtype () = match texp1, texp2, se1, se2 with
| Sil.Sizeof (Typ.Tptr (t1_, _), None, _), Sil.Sizeof (Typ.Tptr (t2_, _), None, _), | Exp.Sizeof (Typ.Tptr (t1_, _), None, _), Exp.Sizeof (Typ.Tptr (t2_, _), None, _),
Sil.Eexp (e1', _), Sil.Eexp (e2', _) Sil.Eexp (e1', _), Sil.Eexp (e2', _)
when not (is_allocated_lhs e1') -> when not (is_allocated_lhs e1') ->
begin begin
@ -1744,8 +1748,8 @@ let handle_parameter_subtype tenv prop1 sigma2 subs (e1, se1, texp1) (se2, texp2
then begin then begin
let pos_type_opt, _ = let pos_type_opt, _ =
Subtyping_check.subtype_case_analysis tenv Subtyping_check.subtype_case_analysis tenv
(Sil.Sizeof (t1, None, Subtype.subtypes)) (Exp.Sizeof (t1, None, Subtype.subtypes))
(Sil.Sizeof (t2_ptsto, len2, sub2)) in (Exp.Sizeof (t2_ptsto, len2, sub2)) in
match pos_type_opt with match pos_type_opt with
| Some t1_noptr -> | Some t1_noptr ->
ProverState.add_frame_typ (e1', t1_noptr); ProverState.add_frame_typ (e1', t1_noptr);
@ -1761,8 +1765,8 @@ let rec hpred_imply tenv calc_index_frame calc_missing subs prop1 sigma2 hpred2
| Sil.Hpointsto (_e2, se2, texp2) -> | Sil.Hpointsto (_e2, se2, texp2) ->
let e2 = Sil.exp_sub (snd subs) _e2 in let e2 = Sil.exp_sub (snd subs) _e2 in
let _ = match e2 with let _ = match e2 with
| Sil.Lvar _ -> () | Exp.Lvar _ -> ()
| Sil.Var v -> if Ident.is_primed v then | Exp.Var v -> if Ident.is_primed v then
(d_impl_err ("rhs |-> not implemented", subs, (EXC_FALSE_HPRED hpred2)); (d_impl_err ("rhs |-> not implemented", subs, (EXC_FALSE_HPRED hpred2));
raise (Exceptions.Abduction_case_not_implemented __POS__)) raise (Exceptions.Abduction_case_not_implemented __POS__))
| _ -> () in | _ -> () in
@ -1805,7 +1809,7 @@ let rec hpred_imply tenv calc_index_frame calc_missing subs prop1 sigma2 hpred2
| IMPL_EXC (s, _, _) when calc_missing -> | IMPL_EXC (s, _, _) when calc_missing ->
raise (MISSING_EXC s)) raise (MISSING_EXC s))
| Sil.Hlseg (Sil.Lseg_NE, para1, e1, f1, elist1), _ -> (* Unroll lseg *) | Sil.Hlseg (Sil.Lseg_NE, para1, e1, f1, elist1), _ -> (* Unroll lseg *)
let n' = Sil.Var (Ident.create_fresh Ident.kprimed) in let n' = Exp.Var (Ident.create_fresh Ident.kprimed) in
let (_, para_inst1) = Sil.hpara_instantiate para1 e1 n' elist1 in let (_, para_inst1) = Sil.hpara_instantiate para1 e1 n' elist1 in
let hpred_list1 = para_inst1@[Prop.mk_lseg Sil.Lseg_PE para1 n' f1 elist1] in let hpred_list1 = para_inst1@[Prop.mk_lseg Sil.Lseg_PE para1 n' f1 elist1] in
let iter1'' = Prop.prop_iter_update_current_by_list iter1' hpred_list1 in let iter1'' = Prop.prop_iter_update_current_by_list iter1' hpred_list1 in
@ -1817,7 +1821,7 @@ let rec hpred_imply tenv calc_index_frame calc_missing subs prop1 sigma2 hpred2
res res
| Sil.Hdllseg (Sil.Lseg_NE, para1, iF1, oB1, oF1, iB1, elist1), _ | Sil.Hdllseg (Sil.Lseg_NE, para1, iF1, oB1, oF1, iB1, elist1), _
when Sil.exp_equal (Sil.exp_sub (fst subs) iF1) e2 -> (* Unroll dllseg forward *) when Sil.exp_equal (Sil.exp_sub (fst subs) iF1) e2 -> (* Unroll dllseg forward *)
let n' = Sil.Var (Ident.create_fresh Ident.kprimed) in let n' = Exp.Var (Ident.create_fresh Ident.kprimed) in
let (_, para_inst1) = Sil.hpara_dll_instantiate para1 iF1 oB1 n' elist1 in let (_, para_inst1) = Sil.hpara_dll_instantiate para1 iF1 oB1 n' elist1 in
let hpred_list1 = para_inst1@[Prop.mk_dllseg Sil.Lseg_PE para1 n' iF1 oF1 iB1 elist1] in let hpred_list1 = para_inst1@[Prop.mk_dllseg Sil.Lseg_PE para1 n' iF1 oF1 iB1 elist1] in
let iter1'' = Prop.prop_iter_update_current_by_list iter1' hpred_list1 in let iter1'' = Prop.prop_iter_update_current_by_list iter1' hpred_list1 in
@ -1830,7 +1834,7 @@ let rec hpred_imply tenv calc_index_frame calc_missing subs prop1 sigma2 hpred2
| Sil.Hdllseg (Sil.Lseg_NE, para1, iF1, oB1, oF1, iB1, elist1), _ | Sil.Hdllseg (Sil.Lseg_NE, para1, iF1, oB1, oF1, iB1, elist1), _
when Sil.exp_equal (Sil.exp_sub (fst subs) iB1) e2 -> when Sil.exp_equal (Sil.exp_sub (fst subs) iB1) e2 ->
(* Unroll dllseg backward *) (* Unroll dllseg backward *)
let n' = Sil.Var (Ident.create_fresh Ident.kprimed) in let n' = Exp.Var (Ident.create_fresh Ident.kprimed) in
let (_, para_inst1) = Sil.hpara_dll_instantiate para1 iB1 n' oF1 elist1 in let (_, para_inst1) = Sil.hpara_dll_instantiate para1 iB1 n' oF1 elist1 in
let hpred_list1 = para_inst1@[Prop.mk_dllseg Sil.Lseg_PE para1 iF1 oB1 iB1 n' elist1] in let hpred_list1 = para_inst1@[Prop.mk_dllseg Sil.Lseg_PE para1 iF1 oB1 iB1 n' elist1] in
let iter1'' = Prop.prop_iter_update_current_by_list iter1' hpred_list1 in let iter1'' = Prop.prop_iter_update_current_by_list iter1' hpred_list1 in
@ -1847,8 +1851,8 @@ let rec hpred_imply tenv calc_index_frame calc_missing subs prop1 sigma2 hpred2
| Sil.Hlseg (k, para2, _e2, _f2, _elist2) -> (* for now ignore implications between PE and NE *) | Sil.Hlseg (k, para2, _e2, _f2, _elist2) -> (* for now ignore implications between PE and NE *)
let e2, f2 = Sil.exp_sub (snd subs) _e2, Sil.exp_sub (snd subs) _f2 in let e2, f2 = Sil.exp_sub (snd subs) _e2, Sil.exp_sub (snd subs) _f2 in
let _ = match e2 with let _ = match e2 with
| Sil.Lvar _ -> () | Exp.Lvar _ -> ()
| Sil.Var v -> if Ident.is_primed v then | Exp.Var v -> if Ident.is_primed v then
(d_impl_err ("rhs |-> not implemented", subs, (EXC_FALSE_HPRED hpred2)); (d_impl_err ("rhs |-> not implemented", subs, (EXC_FALSE_HPRED hpred2));
raise (Exceptions.Abduction_case_not_implemented __POS__)) raise (Exceptions.Abduction_case_not_implemented __POS__))
| _ -> () | _ -> ()
@ -1881,7 +1885,7 @@ let rec hpred_imply tenv calc_index_frame calc_missing subs prop1 sigma2 hpred2
in match hpred1 with in match hpred1 with
| Sil.Hlseg _ -> (subs', prop1') | Sil.Hlseg _ -> (subs', prop1')
| Sil.Hpointsto _ -> (* unroll rhs list and try again *) | Sil.Hpointsto _ -> (* unroll rhs list and try again *)
let n' = Sil.Var (Ident.create_fresh Ident.kprimed) in let n' = Exp.Var (Ident.create_fresh Ident.kprimed) in
let (_, para_inst2) = Sil.hpara_instantiate para2 _e2 n' elist2 in let (_, para_inst2) = Sil.hpara_instantiate para2 _e2 n' elist2 in
let hpred_list2 = para_inst2@[Prop.mk_lseg Sil.Lseg_PE para2 n' _f2 _elist2] in let hpred_list2 = para_inst2@[Prop.mk_lseg Sil.Lseg_PE para2 n' _f2 _elist2] in
L.d_increase_indent 1; L.d_increase_indent 1;
@ -1908,15 +1912,15 @@ let rec hpred_imply tenv calc_index_frame calc_missing subs prop1 sigma2 hpred2
let iF2, oF2 = Sil.exp_sub (snd subs) iF2, Sil.exp_sub (snd subs) oF2 in let iF2, oF2 = Sil.exp_sub (snd subs) iF2, Sil.exp_sub (snd subs) oF2 in
let iB2, oB2 = Sil.exp_sub (snd subs) iB2, Sil.exp_sub (snd subs) oB2 in let iB2, oB2 = Sil.exp_sub (snd subs) iB2, Sil.exp_sub (snd subs) oB2 in
let _ = match oF2 with let _ = match oF2 with
| Sil.Lvar _ -> () | Exp.Lvar _ -> ()
| Sil.Var v -> if Ident.is_primed v then | Exp.Var v -> if Ident.is_primed v then
(d_impl_err ("rhs dllseg not implemented", subs, (EXC_FALSE_HPRED hpred2)); (d_impl_err ("rhs dllseg not implemented", subs, (EXC_FALSE_HPRED hpred2));
raise (Exceptions.Abduction_case_not_implemented __POS__)) raise (Exceptions.Abduction_case_not_implemented __POS__))
| _ -> () | _ -> ()
in in
let _ = match oB2 with let _ = match oB2 with
| Sil.Lvar _ -> () | Exp.Lvar _ -> ()
| Sil.Var v -> if Ident.is_primed v then | Exp.Var v -> if Ident.is_primed v then
(d_impl_err ("rhs dllseg not implemented", subs, (EXC_FALSE_HPRED hpred2)); (d_impl_err ("rhs dllseg not implemented", subs, (EXC_FALSE_HPRED hpred2));
raise (Exceptions.Abduction_case_not_implemented __POS__)) raise (Exceptions.Abduction_case_not_implemented __POS__))
| _ -> () | _ -> ()
@ -1958,13 +1962,13 @@ and sigma_imply tenv calc_index_frame calc_missing subs prop1 sigma2 : (subst2 *
| Sil.Hpointsto (_e2, _, _) -> | Sil.Hpointsto (_e2, _, _) ->
let e2 = Sil.exp_sub (snd subs) _e2 in let e2 = Sil.exp_sub (snd subs) _e2 in
(match e2 with (match e2 with
| Sil.Const (Const.Cstr s) -> Some (s, true) | Exp.Const (Const.Cstr s) -> Some (s, true)
| Sil.Const (Const.Cclass c) -> Some (Ident.name_to_string c, false) | Exp.Const (Const.Cclass c) -> Some (Ident.name_to_string c, false)
| _ -> None) | _ -> None)
| _ -> None in | _ -> None in
let mk_constant_string_hpred s = (* create an hpred from a constant string *) let mk_constant_string_hpred s = (* create an hpred from a constant string *)
let len = IntLit.of_int (1 + String.length s) in let len = IntLit.of_int (1 + String.length s) in
let root = Sil.Const (Const.Cstr s) in let root = Exp.Const (Const.Cstr s) in
let sexp = let sexp =
let index = Sil.exp_int (IntLit.of_int (String.length s)) in let index = Sil.exp_int (IntLit.of_int (String.length s)) in
match !Config.curr_language with match !Config.curr_language with
@ -1974,35 +1978,35 @@ and sigma_imply tenv calc_index_frame calc_missing subs prop1 sigma2 : (subst2 *
| Config.Java -> | Config.Java ->
let mk_fld_sexp s = let mk_fld_sexp s =
let fld = Ident.create_fieldname (Mangled.from_string s) 0 in let fld = Ident.create_fieldname (Mangled.from_string s) 0 in
let se = Sil.Eexp (Sil.Var (Ident.create_fresh Ident.kprimed), Sil.Inone) in let se = Sil.Eexp (Exp.Var (Ident.create_fresh Ident.kprimed), Sil.Inone) in
(fld, se) in (fld, se) in
let fields = ["java.lang.String.count"; "java.lang.String.hash"; "java.lang.String.offset"; "java.lang.String.value"] in let fields = ["java.lang.String.count"; "java.lang.String.hash"; "java.lang.String.offset"; "java.lang.String.value"] in
Sil.Estruct (IList.map mk_fld_sexp fields, Sil.inst_none) in Sil.Estruct (IList.map mk_fld_sexp fields, Sil.inst_none) in
let const_string_texp = let const_string_texp =
match !Config.curr_language with match !Config.curr_language with
| Config.Clang -> | Config.Clang ->
Sil.Sizeof (Typ.Tarray (Typ.Tint Typ.IChar, Some len), None, Subtype.exact) Exp.Sizeof (Typ.Tarray (Typ.Tint Typ.IChar, Some len), None, Subtype.exact)
| Config.Java -> | Config.Java ->
let object_type = let object_type =
Typename.TN_csu (Csu.Class Csu.Java, Mangled.from_string "java.lang.String") in Typename.TN_csu (Csu.Class Csu.Java, Mangled.from_string "java.lang.String") in
let typ = match Tenv.lookup tenv object_type with let typ = match Tenv.lookup tenv object_type with
| Some typ -> typ | Some typ -> typ
| None -> assert false in | None -> assert false in
Sil.Sizeof (Typ.Tstruct typ, None, Subtype.exact) in Exp.Sizeof (Typ.Tstruct typ, None, Subtype.exact) in
Sil.Hpointsto (root, sexp, const_string_texp) in Sil.Hpointsto (root, sexp, const_string_texp) in
let mk_constant_class_hpred s = (* creat an hpred from a constant class *) let mk_constant_class_hpred s = (* creat an hpred from a constant class *)
let root = Sil.Const (Const.Cclass (Ident.string_to_name s)) in let root = Exp.Const (Const.Cclass (Ident.string_to_name s)) in
let sexp = (* TODO: add appropriate fields *) let sexp = (* TODO: add appropriate fields *)
Sil.Estruct Sil.Estruct
([(Ident.create_fieldname (Mangled.from_string "java.lang.Class.name") 0, ([(Ident.create_fieldname (Mangled.from_string "java.lang.Class.name") 0,
Sil.Eexp ((Sil.Const (Const.Cstr s), Sil.Inone)))], Sil.inst_none) in Sil.Eexp ((Exp.Const (Const.Cstr s), Sil.Inone)))], Sil.inst_none) in
let class_texp = let class_texp =
let class_type = let class_type =
Typename.TN_csu (Csu.Class Csu.Java, Mangled.from_string "java.lang.Class") in Typename.TN_csu (Csu.Class Csu.Java, Mangled.from_string "java.lang.Class") in
let typ = match Tenv.lookup tenv class_type with let typ = match Tenv.lookup tenv class_type with
| Some typ -> typ | Some typ -> typ
| None -> assert false in | None -> assert false in
Sil.Sizeof (Typ.Tstruct typ, None, Subtype.exact) in Exp.Sizeof (Typ.Tstruct typ, None, Subtype.exact) in
Sil.Hpointsto (root, sexp, class_texp) in Sil.Hpointsto (root, sexp, class_texp) in
try try
(match move_primed_lhs_from_front subs sigma2 with (match move_primed_lhs_from_front subs sigma2 with
@ -2093,12 +2097,12 @@ let rec pre_check_pure_implication calc_missing subs pi1 pi2 =
if Sil.exp_equal e2 f2 then pre_check_pure_implication calc_missing subs pi1 pi2' if Sil.exp_equal e2 f2 then pre_check_pure_implication calc_missing subs pi1 pi2'
else else
(match e2, f2 with (match e2, f2 with
| Sil.Var v2, f2 | Exp.Var v2, f2
when Ident.is_primed v2 (* && not (Sil.mem_sub v2 (snd subs)) *) -> when Ident.is_primed v2 (* && not (Sil.mem_sub v2 (snd subs)) *) ->
(* The commented-out condition should always hold. *) (* The commented-out condition should always hold. *)
let sub2' = extend_sub (snd subs) v2 f2 in let sub2' = extend_sub (snd subs) v2 f2 in
pre_check_pure_implication calc_missing (fst subs, sub2') pi1 pi2' pre_check_pure_implication calc_missing (fst subs, sub2') pi1 pi2'
| e2, Sil.Var v2 | e2, Exp.Var v2
when Ident.is_primed v2 (* && not (Sil.mem_sub v2 (snd subs)) *) -> when Ident.is_primed v2 (* && not (Sil.mem_sub v2 (snd subs)) *) ->
(* The commented-out condition should always hold. *) (* The commented-out condition should always hold. *)
let sub2' = extend_sub (snd subs) v2 e2 in let sub2' = extend_sub (snd subs) v2 e2 in
@ -2126,7 +2130,7 @@ let check_array_bounds (sub1, sub2) prop =
if (not Config.bound_error_allowed_in_procedure_call) then if (not Config.bound_error_allowed_in_procedure_call) then
raise (IMPL_EXC ("bounds check", (sub1, sub2), EXC_FALSE)) in raise (IMPL_EXC ("bounds check", (sub1, sub2), EXC_FALSE)) in
let fail_if_le e' e'' = let fail_if_le e' e'' =
let lt_ineq = Prop.mk_inequality (Sil.BinOp(Binop.Le, e', e'')) in let lt_ineq = Prop.mk_inequality (Exp.BinOp(Binop.Le, e', e'')) in
if check_atom prop lt_ineq then check_failed lt_ineq in if check_atom prop lt_ineq then check_failed lt_ineq in
let check_bound = function let check_bound = function
| ProverState.BClen_imply (len1_, len2_, _indices2) -> | ProverState.BClen_imply (len1_, len2_, _indices2) ->
@ -2135,7 +2139,7 @@ let check_array_bounds (sub1, sub2) prop =
(* L.d_strln_color Orange "check_bound "; (* L.d_strln_color Orange "check_bound ";
Sil.d_exp len1; L.d_str " "; Sil.d_exp len2; L.d_ln(); *) Sil.d_exp len1; L.d_str " "; Sil.d_exp len2; L.d_ln(); *)
let indices_to_check = match len2 with let indices_to_check = match len2 with
| _ -> [Sil.BinOp(Binop.PlusA, len2, Sil.exp_minus_one)] (* only check len *) in | _ -> [Exp.BinOp(Binop.PlusA, len2, Sil.exp_minus_one)] (* only check len *) in
IList.iter (fail_if_le len1) indices_to_check IList.iter (fail_if_le len1) indices_to_check
| ProverState.BCfrom_pre _atom -> | ProverState.BCfrom_pre _atom ->
let atom_neg = Prop.atom_negate (Sil.atom_sub sub2 _atom) in let atom_neg = Prop.atom_negate (Sil.atom_sub sub2 _atom) in
@ -2197,7 +2201,9 @@ let check_implication_base pname tenv check_frame_empty calc_missing prop1 prop2
None None
type implication_result = type implication_result =
| ImplOK of (check list * Sil.subst * Sil.subst * Sil.hpred list * (Sil.atom list) * (Sil.hpred list) * (Sil.hpred list) * (Sil.hpred list) * ((Sil.exp * Sil.exp) list) * ((Sil.exp * Sil.exp) list)) | ImplOK of
(check list * Sil.subst * Sil.subst * Sil.hpred list * (Sil.atom list) * (Sil.hpred list) *
(Sil.hpred list) * (Sil.hpred list) * ((Exp.t * Exp.t) list) * ((Exp.t * Exp.t) list))
| ImplFail of check list | ImplFail of check list
(** [check_implication_for_footprint p1 p2] returns (** [check_implication_for_footprint p1 p2] returns
@ -2265,7 +2271,7 @@ let find_minimum_pure_cover cases =
(* (*
(** Check [prop |- e1<e2]. Result [false] means "don't know". *) (** Check [prop |- e1<e2]. Result [false] means "don't know". *)
let check_lt prop e1 e2 = let check_lt prop e1 e2 =
let e1_lt_e2 = Sil.BinOp (Binop.Lt, e1, e2) in let e1_lt_e2 = Exp.BinOp (Binop.Lt, e1, e2) in
check_atom prop (Prop.mk_inequality e1_lt_e2) check_atom prop (Prop.mk_inequality e1_lt_e2)
let filter_ptsto_lhs sub e0 = function let filter_ptsto_lhs sub e0 = function

@ -17,15 +17,15 @@ open Sil
(** {2 Ordinary Theorem Proving} *) (** {2 Ordinary Theorem Proving} *)
(** Check [ |- e=0]. Result [false] means "don't know". *) (** Check [ |- e=0]. Result [false] means "don't know". *)
val check_zero : exp -> bool val check_zero : Exp.t -> bool
(** Check [prop |- exp1=exp2]. Result [false] means "don't know". *) (** Check [prop |- exp1=exp2]. Result [false] means "don't know". *)
val check_equal : Prop.normal Prop.t -> exp -> exp -> bool val check_equal : Prop.normal Prop.t -> Exp.t -> Exp.t -> bool
(** Check whether [prop |- exp1!=exp2]. Result [false] means "don't know". *) (** Check whether [prop |- exp1!=exp2]. Result [false] means "don't know". *)
val check_disequal : Prop.normal Prop.t -> exp -> exp -> bool val check_disequal : Prop.normal Prop.t -> Exp.t -> Exp.t -> bool
val check_le : Prop.normal Prop.t -> exp -> exp -> bool val check_le : Prop.normal Prop.t -> Exp.t -> Exp.t -> bool
(** Return true if the two types have sizes which can be compared *) (** Return true if the two types have sizes which can be compared *)
val type_size_comparable : Typ.t -> Typ.t -> bool val type_size_comparable : Typ.t -> Typ.t -> bool
@ -46,20 +46,20 @@ val check_inconsistency_base : Prop.normal Prop.t -> bool
val check_inconsistency : Prop.normal Prop.t -> bool val check_inconsistency : Prop.normal Prop.t -> bool
(** Check whether [prop |- allocated(exp)]. *) (** Check whether [prop |- allocated(exp)]. *)
val check_allocatedness : Prop.normal Prop.t -> exp -> bool val check_allocatedness : Prop.normal Prop.t -> Exp.t -> bool
(** [is_root prop base_exp exp] checks whether [base_exp = (** [is_root prop base_exp exp] checks whether [base_exp =
exp.offlist] for some list of offsets [offlist]. If so, it returns exp.offlist] for some list of offsets [offlist]. If so, it returns
[Some(offlist)]. Otherwise, it returns [None]. Assumes that [Some(offlist)]. Otherwise, it returns [None]. Assumes that
[base_exp] points to the beginning of a structure, not the middle. *) [base_exp] points to the beginning of a structure, not the middle. *)
val is_root : Prop.normal Prop.t -> exp -> exp -> offset list option val is_root : Prop.normal Prop.t -> Exp.t -> Exp.t -> offset list option
(** [expand_hpred_pointer calc_index_frame hpred] expands [hpred] if it is a |-> whose lhs is a Lfield or Lindex or ptr+off. (** [expand_hpred_pointer calc_index_frame hpred] expands [hpred] if it is a |-> whose lhs is a Lfield or Lindex or ptr+off.
Return [(changed, calc_index_frame', hpred')] where [changed] indicates whether the predicate has changed. *) Return [(changed, calc_index_frame', hpred')] where [changed] indicates whether the predicate has changed. *)
val expand_hpred_pointer : bool -> Sil.hpred -> bool * bool * Sil.hpred val expand_hpred_pointer : bool -> Sil.hpred -> bool * bool * Sil.hpred
(** Get upper and lower bounds of an expression, if any *) (** Get upper and lower bounds of an expression, if any *)
val get_bounds : Prop.normal Prop.t -> Sil.exp -> IntLit.t option * IntLit.t option val get_bounds : Prop.normal Prop.t -> Exp.t -> IntLit.t option * IntLit.t option
(** {2 Abduction prover} *) (** {2 Abduction prover} *)
@ -68,12 +68,14 @@ val check_implication : Procname.t -> Tenv.t -> Prop.normal Prop.t -> Prop.expos
type check = type check =
| Bounds_check | Bounds_check
| Class_cast_check of Sil.exp * Sil.exp * Sil.exp | Class_cast_check of Exp.t * Exp.t * Exp.t
val d_typings : (Sil.exp * Sil.exp) list -> unit val d_typings : (Exp.t * Exp.t) list -> unit
type implication_result = type implication_result =
| ImplOK of (check list * Sil.subst * Sil.subst * Sil.hpred list * (Sil.atom list) * (Sil.hpred list) * (Sil.hpred list) * (Sil.hpred list) * ((Sil.exp * Sil.exp) list) * ((Sil.exp * Sil.exp) list)) | ImplOK of
(check list * Sil.subst * Sil.subst * Sil.hpred list * (Sil.atom list) * (Sil.hpred list) *
(Sil.hpred list) * (Sil.hpred list) * ((Exp.t * Exp.t) list) * ((Exp.t * Exp.t) list))
| ImplFail of check list | ImplFail of check list
(** [check_implication_for_footprint p1 p2] returns (** [check_implication_for_footprint p1 p2] returns
@ -91,7 +93,7 @@ val find_minimum_pure_cover : (Sil.atom list * 'a) list -> (Sil.atom list * 'a)
(** {2 Compute various lower or upper bounds} *) (** {2 Compute various lower or upper bounds} *)
(** Computer an upper bound of an expression *) (** Computer an upper bound of an expression *)
val compute_upper_bound_of_exp : Prop.normal Prop.t -> Sil.exp -> IntLit.t option val compute_upper_bound_of_exp : Prop.normal Prop.t -> Exp.t -> IntLit.t option
(** {2 Subtype checking} *) (** {2 Subtype checking} *)
@ -103,7 +105,7 @@ sig
(** subtype_case_analysis tenv tecp1 texp2 performs case analysis on [texp1 <: texp2], (** subtype_case_analysis tenv tecp1 texp2 performs case analysis on [texp1 <: texp2],
and returns the updated types in the true and false case, if they are possible *) and returns the updated types in the true and false case, if they are possible *)
val subtype_case_analysis : Tenv.t -> Sil.exp -> Sil.exp -> Sil.exp option * Sil.exp option val subtype_case_analysis : Tenv.t -> Exp.t -> Exp.t -> Exp.t option * Exp.t option
end end

@ -34,16 +34,16 @@ let rec list_rev_and_concat l1 l2 =
*) *)
let check_bad_index pname p len index loc = let check_bad_index pname p len index loc =
let len_is_constant = match len with let len_is_constant = match len with
| Sil.Const _ -> true | Exp.Const _ -> true
| _ -> false in | _ -> false in
let index_provably_out_of_bound () = let index_provably_out_of_bound () =
let index_too_large = Prop.mk_inequality (Sil.BinOp (Binop.Le, len, index)) in let index_too_large = Prop.mk_inequality (Exp.BinOp (Binop.Le, len, index)) in
let index_negative = Prop.mk_inequality (Sil.BinOp (Binop.Le, index, Sil.exp_minus_one)) in let index_negative = Prop.mk_inequality (Exp.BinOp (Binop.Le, index, Sil.exp_minus_one)) in
(Prover.check_atom p index_too_large) || (Prover.check_atom p index_negative) in (Prover.check_atom p index_too_large) || (Prover.check_atom p index_negative) in
let index_provably_in_bound () = let index_provably_in_bound () =
let len_minus_one = Sil.BinOp(Binop.PlusA, len, Sil.exp_minus_one) in let len_minus_one = Exp.BinOp(Binop.PlusA, len, Sil.exp_minus_one) in
let index_not_too_large = Prop.mk_inequality (Sil.BinOp(Binop.Le, index, len_minus_one)) in let index_not_too_large = Prop.mk_inequality (Exp.BinOp(Binop.Le, index, len_minus_one)) in
let index_nonnegative = Prop.mk_inequality (Sil.BinOp(Binop.Le, Sil.exp_zero, index)) in let index_nonnegative = Prop.mk_inequality (Exp.BinOp(Binop.Le, Sil.exp_zero, index)) in
Prover.check_zero index || (* index 0 always in bound, even when we know nothing about len *) Prover.check_zero index || (* index 0 always in bound, even when we know nothing about len *)
((Prover.check_atom p index_not_too_large) && (Prover.check_atom p index_nonnegative)) in ((Prover.check_atom p index_not_too_large) && (Prover.check_atom p index_nonnegative)) in
let index_has_bounds () = let index_has_bounds () =
@ -51,7 +51,7 @@ let check_bad_index pname p len index loc =
| Some _, Some _ -> true | Some _, Some _ -> true
| _ -> false in | _ -> false in
let get_const_opt = function let get_const_opt = function
| Sil.Const (Const.Cint n) -> Some n | Exp.Const (Const.Cint n) -> Some n
| _ -> None in | _ -> None in
if not (index_provably_in_bound ()) then if not (index_provably_in_bound ()) then
begin begin
@ -122,14 +122,14 @@ let rec create_struct_values pname tenv orig_prop footprint_part kind max_stamp
create_struct_values create_struct_values
pname tenv orig_prop footprint_part kind max_stamp t off' inst in pname tenv orig_prop footprint_part kind max_stamp t off' inst in
let e' = Sil.array_clean_new_index footprint_part e in let e' = Sil.array_clean_new_index footprint_part e in
let len = Sil.Var (new_id ()) in let len = Exp.Var (new_id ()) in
let se = Sil.Earray (len, [(e', se')], inst) in let se = Sil.Earray (len, [(e', se')], inst) in
let res_t = Typ.Tarray (res_t', None) in let res_t = Typ.Tarray (res_t', None) in
(Sil.Aeq(e, e') :: atoms', se, res_t) (Sil.Aeq(e, e') :: atoms', se, res_t)
| Typ.Tarray (t', len_), off -> | Typ.Tarray (t', len_), off ->
let len = match len_ with let len = match len_ with
| None -> Sil.Var (new_id ()) | None -> Exp.Var (new_id ())
| Some len -> Sil.Const (Const.Cint len) in | Some len -> Exp.Const (Const.Cint len) in
(match off with (match off with
| [] -> | [] ->
([], Sil.Earray (len, [], inst), t) ([], Sil.Earray (len, [], inst), t)
@ -147,7 +147,7 @@ let rec create_struct_values pname tenv orig_prop footprint_part kind max_stamp
) )
| Typ.Tint _, [] | Typ.Tfloat _, [] | Typ.Tvoid, [] | Typ.Tfun _, [] | Typ.Tptr _, [] -> | Typ.Tint _, [] | Typ.Tfloat _, [] | Typ.Tvoid, [] | Typ.Tfun _, [] | Typ.Tptr _, [] ->
let id = new_id () in let id = new_id () in
([], Sil.Eexp (Sil.Var id, inst), t) ([], Sil.Eexp (Exp.Var id, inst), t)
| Typ.Tint _, [Sil.Off_index e] | Typ.Tfloat _, [Sil.Off_index e] | Typ.Tint _, [Sil.Off_index e] | Typ.Tfloat _, [Sil.Off_index e]
| Typ.Tvoid, [Sil.Off_index e] | Typ.Tvoid, [Sil.Off_index e]
| Typ.Tfun _, [Sil.Off_index e] | Typ.Tptr _, [Sil.Off_index e] -> | Typ.Tfun _, [Sil.Off_index e] | Typ.Tptr _, [Sil.Off_index e] ->
@ -155,7 +155,7 @@ let rec create_struct_values pname tenv orig_prop footprint_part kind max_stamp
let t' = match t with let t' = match t with
| Typ.Tptr(t', _) -> t' | Typ.Tptr(t', _) -> t'
| _ -> t in | _ -> t in
let len = Sil.Var (new_id ()) in let len = Exp.Var (new_id ()) in
let atoms', se', res_t' = let atoms', se', res_t' =
create_struct_values create_struct_values
pname tenv orig_prop footprint_part kind max_stamp t' [] inst in pname tenv orig_prop footprint_part kind max_stamp t' [] inst in
@ -255,8 +255,8 @@ let rec _strexp_extend_values
let len = match se with let len = match se with
| Sil.Eexp (_, Sil.Ialloc) -> Sil.exp_one (* if allocated explicitly, we know len is 1 *) | Sil.Eexp (_, Sil.Ialloc) -> Sil.exp_one (* if allocated explicitly, we know len is 1 *)
| _ -> | _ ->
if Config.type_size then Sil.exp_one (* Sil.Sizeof (typ, Subtype.exact) *) if Config.type_size then Sil.exp_one (* Exp.Sizeof (typ, Subtype.exact) *)
else Sil.Var (new_id ()) in else Exp.Var (new_id ()) in
let se_new = Sil.Earray (len, [(Sil.exp_zero, se)], inst) in let se_new = Sil.Earray (len, [(Sil.exp_zero, se)], inst) in
let typ_new = Typ.Tarray (typ, None) in let typ_new = Typ.Tarray (typ, None) in
_strexp_extend_values _strexp_extend_values
@ -303,7 +303,7 @@ and array_case_analysis_index pname tenv orig_prop
IList.exists (fun (i, _) -> Prover.check_equal Prop.prop_emp index i) array_cont in IList.exists (fun (i, _) -> Prover.check_equal Prop.prop_emp index i) array_cont in
let array_is_full = let array_is_full =
match array_len with match array_len with
| Sil.Const (Const.Cint n') -> IntLit.geq (IntLit.of_int (IList.length array_cont)) n' | Exp.Const (Const.Cint n') -> IntLit.geq (IntLit.of_int (IList.length array_cont)) n'
| _ -> false in | _ -> false in
if index_in_array then if index_in_array then
@ -374,7 +374,7 @@ let laundry_offset_for_footprint max_stamp offs_in =
else else
let () = incr max_stamp in let () = incr max_stamp in
let fid_new = Ident.create Ident.kfootprint !max_stamp in let fid_new = Ident.create Ident.kfootprint !max_stamp in
let exp_new = Sil.Var fid_new in let exp_new = Exp.Var fid_new in
let off_new = Sil.Off_index exp_new in let off_new = Sil.Off_index exp_new in
let offs_seen' = off_new:: offs_seen in let offs_seen' = off_new:: offs_seen in
let eqs' = (fid_new, idx):: eqs in let eqs' = (fid_new, idx):: eqs in
@ -389,7 +389,7 @@ let strexp_extend_values
let off', eqs = laundry_offset_for_footprint max_stamp off in let off', eqs = laundry_offset_for_footprint max_stamp off in
(* do laundry_offset whether footprint_part is true or not, so max_stamp is modified anyway *) (* do laundry_offset whether footprint_part is true or not, so max_stamp is modified anyway *)
if footprint_part then if footprint_part then
off', IList.map (fun (id, e) -> Prop.mk_eq (Sil.Var id) e) eqs off', IList.map (fun (id, e) -> Prop.mk_eq (Exp.Var id) e) eqs
else off, [] in else off, [] in
if Config.trace_rearrange then if Config.trace_rearrange then
(L.d_str "entering strexp_extend_values se: "; Sil.d_sexp se; L.d_str " typ: "; (L.d_str "entering strexp_extend_values se: "; Sil.d_sexp se; L.d_str " typ: ";
@ -404,9 +404,9 @@ let strexp_extend_values
IList.filter check_not_inconsistent atoms_se_typ_list in IList.filter check_not_inconsistent atoms_se_typ_list in
if Config.trace_rearrange then L.d_strln "exiting strexp_extend_values"; if Config.trace_rearrange then L.d_strln "exiting strexp_extend_values";
let len, st = match te with let len, st = match te with
| Sil.Sizeof(_, len, st) -> (len, st) | Exp.Sizeof(_, len, st) -> (len, st)
| _ -> None, Subtype.exact in | _ -> None, Subtype.exact in
IList.map (fun (atoms', se', typ') -> (laundry_atoms @ atoms', se', Sil.Sizeof (typ', len, st))) IList.map (fun (atoms', se', typ') -> (laundry_atoms @ atoms', se', Exp.Sizeof (typ', len, st)))
atoms_se_typ_list_filtered atoms_se_typ_list_filtered
let collect_root_offset exp = let collect_root_offset exp =
@ -414,7 +414,7 @@ let collect_root_offset exp =
let offsets = Sil.exp_get_offsets exp in let offsets = Sil.exp_get_offsets exp in
(root, offsets) (root, offsets)
(** Sil.Construct a points-to predicate for an expression, to add to a footprint. *) (** Exp.Construct a points-to predicate for an expression, to add to a footprint. *)
let mk_ptsto_exp_footprint let mk_ptsto_exp_footprint
pname tenv orig_prop (lexp, typ) max_stamp inst : Sil.hpred * Sil.hpred * Sil.atom list = pname tenv orig_prop (lexp, typ) max_stamp inst : Sil.hpred * Sil.hpred * Sil.atom list =
let root, off = collect_root_offset lexp in let root, off = collect_root_offset lexp in
@ -439,24 +439,24 @@ let mk_ptsto_exp_footprint
| Config.Clang -> Subtype.exact | Config.Clang -> Subtype.exact
| Config.Java -> Subtype.subtypes in | Config.Java -> Subtype.subtypes in
let create_ptsto footprint_part off0 = match root, off0, typ with let create_ptsto footprint_part off0 = match root, off0, typ with
| Sil.Lvar pvar, [], Typ.Tfun _ -> | Exp.Lvar pvar, [], Typ.Tfun _ ->
let fun_name = Procname.from_string_c_fun (Mangled.to_string (Pvar.get_name pvar)) in let fun_name = Procname.from_string_c_fun (Mangled.to_string (Pvar.get_name pvar)) in
let fun_exp = Sil.Const (Const.Cfun fun_name) in let fun_exp = Exp.Const (Const.Cfun fun_name) in
([], Prop.mk_ptsto root (Sil.Eexp (fun_exp, inst)) (Sil.Sizeof (typ, None, st))) ([], Prop.mk_ptsto root (Sil.Eexp (fun_exp, inst)) (Exp.Sizeof (typ, None, st)))
| _, [], Typ.Tfun _ -> | _, [], Typ.Tfun _ ->
let atoms, se, t = let atoms, se, t =
create_struct_values create_struct_values
pname tenv orig_prop footprint_part Ident.kfootprint max_stamp typ off0 inst in pname tenv orig_prop footprint_part Ident.kfootprint max_stamp typ off0 inst in
(atoms, Prop.mk_ptsto root se (Sil.Sizeof (t, None, st))) (atoms, Prop.mk_ptsto root se (Exp.Sizeof (t, None, st)))
| _ -> | _ ->
let atoms, se, t = let atoms, se, t =
create_struct_values create_struct_values
pname tenv orig_prop footprint_part Ident.kfootprint max_stamp typ off0 inst in pname tenv orig_prop footprint_part Ident.kfootprint max_stamp typ off0 inst in
(atoms, Prop.mk_ptsto root se (Sil.Sizeof (t, None, st))) in (atoms, Prop.mk_ptsto root se (Exp.Sizeof (t, None, st))) in
let atoms, ptsto_foot = create_ptsto true off_foot in let atoms, ptsto_foot = create_ptsto true off_foot in
let sub = Sil.sub_of_list eqs in let sub = Sil.sub_of_list eqs in
let ptsto = Sil.hpred_sub sub ptsto_foot in let ptsto = Sil.hpred_sub sub ptsto_foot in
let atoms' = IList.map (fun (id, e) -> Prop.mk_eq (Sil.Var id) e) eqs in let atoms' = IList.map (fun (id, e) -> Prop.mk_eq (Exp.Var id) e) eqs in
(ptsto, ptsto_foot, atoms @ atoms') (ptsto, ptsto_foot, atoms @ atoms')
(** Check if the path in exp exists already in the current ptsto predicate. (** Check if the path in exp exists already in the current ptsto predicate.
@ -528,8 +528,8 @@ let prop_iter_extend_ptsto pname tenv orig_prop iter lexp inst =
L.d_ln (); L.d_ln () L.d_ln (); L.d_ln ()
end; end;
let extend_kind = match e with (* Determine whether to extend the footprint part or just the normal part *) let extend_kind = match e with (* Determine whether to extend the footprint part or just the normal part *)
| Sil.Var id when not (Ident.is_footprint id) -> Ident.kprimed | Exp.Var id when not (Ident.is_footprint id) -> Ident.kprimed
| Sil.Lvar pvar when Pvar.is_local pvar -> Ident.kprimed | Exp.Lvar pvar when Pvar.is_local pvar -> Ident.kprimed
| _ -> Ident.kfootprint in | _ -> Ident.kfootprint in
let iter_list = let iter_list =
let atoms_se_te_list = let atoms_se_te_list =
@ -675,10 +675,10 @@ let add_guarded_by_constraints prop lexp pdesc =
Ident.fieldname_to_string fld = guarded_by_str in Ident.fieldname_to_string fld = guarded_by_str in
IList.find_map_opt IList.find_map_opt
(function (function
| Sil.Hpointsto ((Const (Cclass clazz) as lhs_exp), _, Sil.Sizeof (typ, _, _)) | Sil.Hpointsto ((Const (Cclass clazz) as lhs_exp), _, Exp.Sizeof (typ, _, _))
when guarded_by_str_is_class guarded_by_str (Ident.name_to_string clazz) -> when guarded_by_str_is_class guarded_by_str (Ident.name_to_string clazz) ->
Some (Sil.Eexp (lhs_exp, Sil.inst_none), typ) Some (Sil.Eexp (lhs_exp, Sil.inst_none), typ)
| Sil.Hpointsto (_, Estruct (flds, _), Sil.Sizeof (typ, _, _)) -> | Sil.Hpointsto (_, Estruct (flds, _), Exp.Sizeof (typ, _, _)) ->
let get_fld_strexp_and_typ f flds = let get_fld_strexp_and_typ f flds =
try try
let fld, strexp = IList.find f flds in let fld, strexp = IList.find f flds in
@ -701,7 +701,7 @@ let add_guarded_by_constraints prop lexp pdesc =
| res -> | res ->
res res
end end
| Sil.Hpointsto (Lvar pvar, rhs_exp, Sil.Sizeof (typ, _, _)) | Sil.Hpointsto (Lvar pvar, rhs_exp, Exp.Sizeof (typ, _, _))
when guarded_by_str_is_current_class_this guarded_by_str pname && Pvar.is_this pvar -> when guarded_by_str_is_current_class_this guarded_by_str pname && Pvar.is_this pvar ->
Some (rhs_exp, typ) Some (rhs_exp, typ)
| _ -> | _ ->
@ -819,7 +819,7 @@ let add_guarded_by_constraints prop lexp pdesc =
| _ -> | _ ->
prop_acc in prop_acc in
match lexp with match lexp with
| Sil.Lfield (_, fld, typ) -> | Exp.Lfield (_, fld, typ) ->
(* check for direct access to field annotated with @GuardedBy *) (* check for direct access to field annotated with @GuardedBy *)
enforce_guarded_access fld typ prop enforce_guarded_access fld typ prop
| _ -> | _ ->
@ -919,7 +919,7 @@ let iter_rearrange_ptsto pname tenv orig_prop iter lexp inst =
let iter_rearrange_ne_lseg recurse_on_iters iter para e1 e2 elist = let iter_rearrange_ne_lseg recurse_on_iters iter para e1 e2 elist =
if Config.nelseg then if Config.nelseg then
let iter_inductive_case = let iter_inductive_case =
let n' = Sil.Var (Ident.create_fresh Ident.kprimed) in let n' = Exp.Var (Ident.create_fresh Ident.kprimed) in
let (_, para_inst1) = Sil.hpara_instantiate para e1 n' elist in let (_, para_inst1) = Sil.hpara_instantiate para e1 n' elist in
let hpred_list1 = para_inst1@[Prop.mk_lseg Sil.Lseg_NE para n' e2 elist] in let hpred_list1 = para_inst1@[Prop.mk_lseg Sil.Lseg_NE para n' e2 elist] in
Prop.prop_iter_update_current_by_list iter hpred_list1 in Prop.prop_iter_update_current_by_list iter hpred_list1 in
@ -929,7 +929,7 @@ let iter_rearrange_ne_lseg recurse_on_iters iter para e1 e2 elist =
recurse_on_iters [iter_inductive_case; iter_base_case] recurse_on_iters [iter_inductive_case; iter_base_case]
else else
let iter_inductive_case = let iter_inductive_case =
let n' = Sil.Var (Ident.create_fresh Ident.kprimed) in let n' = Exp.Var (Ident.create_fresh Ident.kprimed) in
let (_, para_inst1) = Sil.hpara_instantiate para e1 n' elist in let (_, para_inst1) = Sil.hpara_instantiate para e1 n' elist in
let hpred_list1 = para_inst1@[Prop.mk_lseg Sil.Lseg_PE para n' e2 elist] in let hpred_list1 = para_inst1@[Prop.mk_lseg Sil.Lseg_PE para n' e2 elist] in
Prop.prop_iter_update_current_by_list iter hpred_list1 in Prop.prop_iter_update_current_by_list iter hpred_list1 in
@ -938,7 +938,7 @@ let iter_rearrange_ne_lseg recurse_on_iters iter para e1 e2 elist =
(** do re-arrangment for an iter whose current element is a nonempty dllseg to be unrolled from lhs *) (** do re-arrangment for an iter whose current element is a nonempty dllseg to be unrolled from lhs *)
let iter_rearrange_ne_dllseg_first recurse_on_iters iter para_dll e1 e2 e3 e4 elist = let iter_rearrange_ne_dllseg_first recurse_on_iters iter para_dll e1 e2 e3 e4 elist =
let iter_inductive_case = let iter_inductive_case =
let n' = Sil.Var (Ident.create_fresh Ident.kprimed) in let n' = Exp.Var (Ident.create_fresh Ident.kprimed) in
let (_, para_dll_inst1) = Sil.hpara_dll_instantiate para_dll e1 e2 n' elist in let (_, para_dll_inst1) = Sil.hpara_dll_instantiate para_dll e1 e2 n' elist in
let hpred_list1 = para_dll_inst1@[Prop.mk_dllseg Sil.Lseg_NE para_dll n' e1 e3 e4 elist] in let hpred_list1 = para_dll_inst1@[Prop.mk_dllseg Sil.Lseg_NE para_dll n' e1 e3 e4 elist] in
Prop.prop_iter_update_current_by_list iter hpred_list1 in Prop.prop_iter_update_current_by_list iter hpred_list1 in
@ -955,7 +955,7 @@ let iter_rearrange_ne_dllseg_first recurse_on_iters iter para_dll e1 e2 e3 e4 el
(** do re-arrangment for an iter whose current element is a nonempty dllseg to be unrolled from rhs *) (** do re-arrangment for an iter whose current element is a nonempty dllseg to be unrolled from rhs *)
let iter_rearrange_ne_dllseg_last recurse_on_iters iter para_dll e1 e2 e3 e4 elist = let iter_rearrange_ne_dllseg_last recurse_on_iters iter para_dll e1 e2 e3 e4 elist =
let iter_inductive_case = let iter_inductive_case =
let n' = Sil.Var (Ident.create_fresh Ident.kprimed) in let n' = Exp.Var (Ident.create_fresh Ident.kprimed) in
let (_, para_dll_inst1) = Sil.hpara_dll_instantiate para_dll e4 n' e3 elist in let (_, para_dll_inst1) = Sil.hpara_dll_instantiate para_dll e4 n' e3 elist in
let hpred_list1 = para_dll_inst1@[Prop.mk_dllseg Sil.Lseg_NE para_dll e1 e2 e4 n' elist] in let hpred_list1 = para_dll_inst1@[Prop.mk_dllseg Sil.Lseg_NE para_dll e1 e2 e4 n' elist] in
Prop.prop_iter_update_current_by_list iter hpred_list1 in Prop.prop_iter_update_current_by_list iter hpred_list1 in
@ -972,7 +972,7 @@ let iter_rearrange_ne_dllseg_last recurse_on_iters iter para_dll e1 e2 e3 e4 eli
(** do re-arrangment for an iter whose current element is a possibly empty listseg *) (** do re-arrangment for an iter whose current element is a possibly empty listseg *)
let iter_rearrange_pe_lseg recurse_on_iters default_case_iter iter para e1 e2 elist = let iter_rearrange_pe_lseg recurse_on_iters default_case_iter iter para e1 e2 elist =
let iter_nonemp_case = let iter_nonemp_case =
let n' = Sil.Var (Ident.create_fresh Ident.kprimed) in let n' = Exp.Var (Ident.create_fresh Ident.kprimed) in
let (_, para_inst1) = Sil.hpara_instantiate para e1 n' elist in let (_, para_inst1) = Sil.hpara_instantiate para e1 n' elist in
let hpred_list1 = para_inst1@[Prop.mk_lseg Sil.Lseg_PE para n' e2 elist] in let hpred_list1 = para_inst1@[Prop.mk_lseg Sil.Lseg_PE para n' e2 elist] in
Prop.prop_iter_update_current_by_list iter hpred_list1 in Prop.prop_iter_update_current_by_list iter hpred_list1 in
@ -989,7 +989,7 @@ let iter_rearrange_pe_lseg recurse_on_iters default_case_iter iter para e1 e2 el
(** do re-arrangment for an iter whose current element is a possibly empty dllseg to be unrolled from lhs *) (** do re-arrangment for an iter whose current element is a possibly empty dllseg to be unrolled from lhs *)
let iter_rearrange_pe_dllseg_first recurse_on_iters default_case_iter iter para_dll e1 e2 e3 e4 elist = let iter_rearrange_pe_dllseg_first recurse_on_iters default_case_iter iter para_dll e1 e2 e3 e4 elist =
let iter_inductive_case = let iter_inductive_case =
let n' = Sil.Var (Ident.create_fresh Ident.kprimed) in let n' = Exp.Var (Ident.create_fresh Ident.kprimed) in
let (_, para_dll_inst1) = Sil.hpara_dll_instantiate para_dll e1 e2 n' elist in let (_, para_dll_inst1) = Sil.hpara_dll_instantiate para_dll e1 e2 n' elist in
let hpred_list1 = para_dll_inst1@[Prop.mk_dllseg Sil.Lseg_PE para_dll n' e1 e3 e4 elist] in let hpred_list1 = para_dll_inst1@[Prop.mk_dllseg Sil.Lseg_PE para_dll n' e1 e3 e4 elist] in
Prop.prop_iter_update_current_by_list iter hpred_list1 in Prop.prop_iter_update_current_by_list iter hpred_list1 in
@ -1007,7 +1007,7 @@ let iter_rearrange_pe_dllseg_first recurse_on_iters default_case_iter iter para_
(** do re-arrangment for an iter whose current element is a possibly empty dllseg to be unrolled from rhs *) (** do re-arrangment for an iter whose current element is a possibly empty dllseg to be unrolled from rhs *)
let iter_rearrange_pe_dllseg_last recurse_on_iters default_case_iter iter para_dll e1 e2 e3 e4 elist = let iter_rearrange_pe_dllseg_last recurse_on_iters default_case_iter iter para_dll e1 e2 e3 e4 elist =
let iter_inductive_case = let iter_inductive_case =
let n' = Sil.Var (Ident.create_fresh Ident.kprimed) in let n' = Exp.Var (Ident.create_fresh Ident.kprimed) in
let (_, para_dll_inst1) = Sil.hpara_dll_instantiate para_dll e4 n' e3 elist in let (_, para_dll_inst1) = Sil.hpara_dll_instantiate para_dll e4 n' e3 elist in
let hpred_list1 = para_dll_inst1@[Prop.mk_dllseg Sil.Lseg_PE para_dll e1 e2 e4 n' elist] in let hpred_list1 = para_dll_inst1@[Prop.mk_dllseg Sil.Lseg_PE para_dll e1 e2 e4 n' elist] in
Prop.prop_iter_update_current_by_list iter hpred_list1 in Prop.prop_iter_update_current_by_list iter hpred_list1 in
@ -1037,7 +1037,7 @@ let type_at_offset texp off =
strip_offset off' typ' strip_offset off' typ'
| _ -> None in | _ -> None in
match texp with match texp with
| Sil.Sizeof(typ, _, _) -> | Exp.Sizeof(typ, _, _) ->
strip_offset off typ strip_offset off typ
| _ -> None | _ -> None
@ -1187,7 +1187,7 @@ let check_dereference_error pdesc (prop : Prop.normal Prop.t) lexp loc =
IList.for_all IList.for_all
(fun hpred -> (fun hpred ->
match hpred with match hpred with
| Sil.Hpointsto (Sil.Lvar pvar, Sil.Eexp (Sil.Var _ as exp, _), _) | Sil.Hpointsto (Exp.Lvar pvar, Sil.Eexp (Exp.Var _ as exp, _), _)
when Sil.exp_equal exp deref_exp -> when Sil.exp_equal exp deref_exp ->
let is_weak_captured_var = is_weak_captured_var pdesc pvar in let is_weak_captured_var = is_weak_captured_var pdesc pvar in
let is_nullable = let is_nullable =
@ -1208,14 +1208,14 @@ let check_dereference_error pdesc (prop : Prop.normal Prop.t) lexp loc =
IList.exists is_nullable_attr (Prop.get_attributes prop exp) in IList.exists is_nullable_attr (Prop.get_attributes prop exp) in
(* it's ok for a non-nullable local to point to deref_exp *) (* it's ok for a non-nullable local to point to deref_exp *)
is_nullable || Pvar.is_local pvar is_nullable || Pvar.is_local pvar
| Sil.Hpointsto (_, Sil.Estruct (flds, _), Sil.Sizeof (typ, _, _)) -> | Sil.Hpointsto (_, Sil.Estruct (flds, _), Exp.Sizeof (typ, _, _)) ->
let fld_is_nullable fld = let fld_is_nullable fld =
match Annotations.get_field_type_and_annotation fld typ with match Annotations.get_field_type_and_annotation fld typ with
| Some (_, annot) -> Annotations.ia_is_nullable annot | Some (_, annot) -> Annotations.ia_is_nullable annot
| _ -> false in | _ -> false in
let is_strexp_pt_by_nullable_fld (fld, strexp) = let is_strexp_pt_by_nullable_fld (fld, strexp) =
match strexp with match strexp with
| Sil.Eexp (Sil.Var _ as exp, _) when Sil.exp_equal exp deref_exp -> | Sil.Eexp (Exp.Var _ as exp, _) when Sil.exp_equal exp deref_exp ->
let is_nullable = fld_is_nullable fld in let is_nullable = fld_is_nullable fld in
if is_nullable then if is_nullable then
nullable_obj_str := Some (Ident.fieldname_to_simplified_string fld); nullable_obj_str := Some (Ident.fieldname_to_simplified_string fld);
@ -1246,7 +1246,7 @@ let check_dereference_error pdesc (prop : Prop.normal Prop.t) lexp loc =
| Some att -> Some att | Some att -> Some att
| None -> (* try to remove an offset if any, and find the attribute there *) | None -> (* try to remove an offset if any, and find the attribute there *)
let root_no_offset = match root with let root_no_offset = match root with
| Sil.BinOp((Binop.PlusPI | Binop.PlusA | Binop.MinusPI | Binop.MinusA), base, _) -> base | Exp.BinOp((Binop.PlusPI | Binop.PlusA | Binop.MinusPI | Binop.MinusA), base, _) -> base
| _ -> root in | _ -> root in
get_relevant_attributes root_no_offset in get_relevant_attributes root_no_offset in
if Prover.check_zero (Sil.root_of_lexp root) || is_deref_of_nullable then if Prover.check_zero (Sil.root_of_lexp root) || is_deref_of_nullable then
@ -1299,27 +1299,27 @@ let check_call_to_objc_block_error pdesc prop fun_exp loc =
not (Prover.check_disequal prop (Sil.root_of_lexp fun_exp) Sil.exp_zero) in not (Prover.check_disequal prop (Sil.root_of_lexp fun_exp) Sil.exp_zero) in
let try_explaining_exp e = (* when e is a temp var, try to find the pvar defining e*) let try_explaining_exp e = (* when e is a temp var, try to find the pvar defining e*)
match e with match e with
| Sil.Var id -> | Exp.Var id ->
(match (Errdesc.find_ident_assignment (State.get_node ()) id) with (match (Errdesc.find_ident_assignment (State.get_node ()) id) with
| Some (_, e') -> e' | Some (_, e') -> e'
| None -> e) | None -> e)
| _ -> e in | _ -> e in
let get_exp_called () = (* Exp called in the block's function call*) let get_exp_called () = (* Exp called in the block's function call*)
match State.get_instr () with match State.get_instr () with
| Some Sil.Call(_, Sil.Var id, _, _, _) -> | Some Sil.Call(_, Exp.Var id, _, _, _) ->
Errdesc.find_ident_assignment (State.get_node ()) id Errdesc.find_ident_assignment (State.get_node ()) id
| _ -> None in | _ -> None in
let is_fun_exp_captured_var () = (* Called expression is a captured variable of the block *) let is_fun_exp_captured_var () = (* Called expression is a captured variable of the block *)
match get_exp_called () with match get_exp_called () with
| Some (_, Sil.Lvar pvar) -> (* pvar is the block *) | Some (_, Exp.Lvar pvar) -> (* pvar is the block *)
let name = Pvar.get_name pvar in let name = Pvar.get_name pvar in
IList.exists (fun (cn, _) -> (Mangled.equal name cn)) (Cfg.Procdesc.get_captured pdesc) IList.exists (fun (cn, _) -> (Mangled.equal name cn)) (Cfg.Procdesc.get_captured pdesc)
| _ -> false in | _ -> false in
let is_field_deref () = (*Called expression is a field *) let is_field_deref () = (*Called expression is a field *)
match get_exp_called () with match get_exp_called () with
| Some (_, (Sil.Lfield(e', fn, t))) -> | Some (_, (Exp.Lfield(e', fn, t))) ->
let e'' = try_explaining_exp e' in let e'' = try_explaining_exp e' in
Some (Sil.Lfield(e'', fn, t)), true (* the block dereferences is a field of an object*) Some (Exp.Lfield(e'', fn, t)), true (* the block dereferences is a field of an object*)
| Some (_, e) -> Some e, false | Some (_, e) -> Some e, false
| _ -> None, false in | _ -> None, false in
if (!Config.curr_language = Config.Clang) && if (!Config.curr_language = Config.Clang) &&
@ -1329,7 +1329,7 @@ let check_call_to_objc_block_error pdesc prop fun_exp loc =
let deref_str = Localise.deref_str_null None in let deref_str = Localise.deref_str_null None in
let err_desc_nobuckets = Errdesc.explain_dereference ~is_nullable: true deref_str prop loc in let err_desc_nobuckets = Errdesc.explain_dereference ~is_nullable: true deref_str prop loc in
match fun_exp with match fun_exp with
| Sil.Var id when Ident.is_footprint id -> | Exp.Var id when Ident.is_footprint id ->
let e_opt, is_field_deref = is_field_deref () in let e_opt, is_field_deref = is_field_deref () in
let err_desc_nobuckets' = (match e_opt with let err_desc_nobuckets' = (match e_opt with
| Some e -> Localise.parameter_field_not_null_checked_desc err_desc_nobuckets e | Some e -> Localise.parameter_field_not_null_checked_desc err_desc_nobuckets e
@ -1362,8 +1362,8 @@ let rearrange ?(report_deref_errors=true) pdesc tenv lexp typ prop loc
: (Sil.offset list) Prop.prop_iter list = : (Sil.offset list) Prop.prop_iter list =
let nlexp = match Prop.exp_normalize_prop prop lexp with let nlexp = match Prop.exp_normalize_prop prop lexp with
| Sil.BinOp(Binop.PlusPI, ep, e) -> (* array access with pointer arithmetic *) | Exp.BinOp(Binop.PlusPI, ep, e) -> (* array access with pointer arithmetic *)
Sil.Lindex(ep, e) Exp.Lindex(ep, e)
| e -> e in | e -> e in
let ptr_tested_for_zero = let ptr_tested_for_zero =
Prover.check_disequal prop (Sil.root_of_lexp nlexp) Sil.exp_zero in Prover.check_disequal prop (Sil.root_of_lexp nlexp) Sil.exp_zero in

@ -16,17 +16,17 @@ exception ARRAY_ACCESS
(** Check for dereference errors: dereferencing 0, a freed value, or an undefined value *) (** Check for dereference errors: dereferencing 0, a freed value, or an undefined value *)
val check_dereference_error : val check_dereference_error :
Cfg.Procdesc.t -> Prop.normal Prop.t -> Sil.exp -> Location.t -> unit Cfg.Procdesc.t -> Prop.normal Prop.t -> Exp.t -> Location.t -> unit
(** Check that an expression representing an objc block can be null and raise a [B1] null exception. (** Check that an expression representing an objc block can be null and raise a [B1] null exception.
It's used to check that we don't call possibly null blocks *) It's used to check that we don't call possibly null blocks *)
val check_call_to_objc_block_error : val check_call_to_objc_block_error :
Cfg.Procdesc.t -> Prop.normal Prop.t -> Sil.exp -> Location.t -> unit Cfg.Procdesc.t -> Prop.normal Prop.t -> Exp.t -> Location.t -> unit
(** [rearrange lexp prop] rearranges [prop] into the form [prop' * lexp|->strexp:typ]. (** [rearrange lexp prop] rearranges [prop] into the form [prop' * lexp|->strexp:typ].
It returns an iterator with [lexp |-> strexp: typ] as current predicate It returns an iterator with [lexp |-> strexp: typ] as current predicate
and the path (an [offsetlist]) which leads to [lexp] as the iterator state. *) and the path (an [offsetlist]) which leads to [lexp] as the iterator state. *)
val rearrange : val rearrange :
?report_deref_errors:bool -> Cfg.Procdesc.t -> Tenv.t -> Sil.exp -> ?report_deref_errors:bool -> Cfg.Procdesc.t -> Tenv.t -> Exp.t ->
Typ.t -> Prop.normal Prop.t -> Typ.t -> Prop.normal Prop.t ->
Location.t -> (Sil.offset list) Prop.prop_iter list Location.t -> (Sil.offset list) Prop.prop_iter list

@ -200,7 +200,9 @@ end = struct
let fav = spec_fav spec in let fav = spec_fav spec in
let idlist = Sil.fav_to_list fav in let idlist = Sil.fav_to_list fav in
let count = ref 0 in let count = ref 0 in
let sub = Sil.sub_of_list (IList.map (fun id -> incr count; (id, Sil.Var (Ident.create_normal Ident.name_spec !count))) idlist) in let sub =
Sil.sub_of_list (IList.map (fun id ->
incr count; (id, Exp.Var (Ident.create_normal Ident.name_spec !count))) idlist) in
spec_sub sub spec spec_sub sub spec
(** Return a compact representation of the spec *) (** Return a compact representation of the spec *)

@ -15,7 +15,7 @@ open! Utils
module L = Logging module L = Logging
module F = Format module F = Format
type const_map = Cfg.Node.t -> Sil.exp -> Const.t option type const_map = Cfg.Node.t -> Exp.t -> Const.t option
(** failure statistics for symbolic execution on a given node *) (** failure statistics for symbolic execution on a given node *)
type failure_stats = { type failure_stats = {
@ -156,7 +156,7 @@ let instrs_normalize instrs =
let gensym id = let gensym id =
incr count; incr count;
Ident.set_stamp id !count in Ident.set_stamp id !count in
Sil.sub_of_list (IList.map (fun id -> (id, Sil.Var (gensym id))) bound_ids) in Sil.sub_of_list (IList.map (fun id -> (id, Exp.Var (gensym id))) bound_ids) in
IList.map (Sil.instr_sub subst) instrs IList.map (Sil.instr_sub subst) instrs
(** Create a function to find duplicate nodes. (** Create a function to find duplicate nodes.
@ -254,7 +254,8 @@ let extract_pre p tenv pdesc abstract_fun =
let fav = Prop.prop_fav p in let fav = Prop.prop_fav p in
let idlist = Sil.fav_to_list fav in let idlist = Sil.fav_to_list fav in
let count = ref 0 in let count = ref 0 in
Sil.sub_of_list (IList.map (fun id -> incr count; (id, Sil.Var (Ident.create_normal Ident.name_spec !count))) idlist) in Sil.sub_of_list (IList.map (fun id ->
incr count; (id, Exp.Var (Ident.create_normal Ident.name_spec !count))) idlist) in
let _, p' = Cfg.remove_locals_formals pdesc p in let _, p' = Cfg.remove_locals_formals pdesc p in
let pre, _ = Prop.extract_spec p' in let pre, _ = Prop.extract_spec p' in
let pre' = try abstract_fun tenv pre with exn when SymOp.exn_not_failure exn -> pre in let pre' = try abstract_fun tenv pre with exn when SymOp.exn_not_failure exn -> pre in

@ -18,7 +18,7 @@ type t
(** Add diverging states *) (** Add diverging states *)
val add_diverging_states : Paths.PathSet.t -> unit val add_diverging_states : Paths.PathSet.t -> unit
type const_map = Cfg.Node.t -> Sil.exp -> Const.t option type const_map = Cfg.Node.t -> Exp.t -> Const.t option
(** Get the constant map for the current procedure. *) (** Get the constant map for the current procedure. *)
val get_const_map : unit -> const_map val get_const_map : unit -> const_map

@ -35,7 +35,7 @@ let rec unroll_type tenv typ off =
end end
| Typ.Tarray (typ', _), Sil.Off_index _ -> | Typ.Tarray (typ', _), Sil.Off_index _ ->
typ' typ'
| _, Sil.Off_index (Sil.Const (Const.Cint i)) when IntLit.iszero i -> | _, Sil.Off_index (Exp.Const (Const.Cint i)) when IntLit.iszero i ->
typ typ
| _ -> | _ ->
L.d_strln ".... Invalid Field Access ...."; L.d_strln ".... Invalid Field Access ....";
@ -82,7 +82,7 @@ let check_block_retain_cycle tenv caller_pname prop block_nullified =
false cases for field and array accesses. *) false cases for field and array accesses. *)
let rec apply_offlist let rec apply_offlist
pdesc tenv p fp_root nullify_struct (root_lexp, strexp, typ) offlist pdesc tenv p fp_root nullify_struct (root_lexp, strexp, typ) offlist
(f: Sil.exp option -> Sil.exp) inst lookup_inst = (f: Exp.t option -> Exp.t) inst lookup_inst =
let pname = Cfg.Procdesc.get_proc_name pdesc in let pname = Cfg.Procdesc.get_proc_name pdesc in
let pp_error () = let pp_error () =
L.d_strln ".... Invalid Field ...."; L.d_strln ".... Invalid Field ....";
@ -100,7 +100,7 @@ let rec apply_offlist
| _ -> false in | _ -> false in
let is_hidden_field () = let is_hidden_field () =
match State.get_instr () with match State.get_instr () with
| Some (Sil.Letderef (_, Sil.Lfield (_, fieldname, _), _, _)) -> | Some (Sil.Letderef (_, Exp.Lfield (_, fieldname, _), _, _)) ->
Ident.fieldname_is_hidden fieldname Ident.fieldname_is_hidden fieldname
| _ -> false in | _ -> false in
let inst_new = match inst with let inst_new = match inst with
@ -194,7 +194,7 @@ let rec apply_offlist
(* return a nondeterministic value if the index is not found after rearrangement *) (* return a nondeterministic value if the index is not found after rearrangement *)
L.d_str "apply_offlist: index "; Sil.d_exp idx; L.d_str "apply_offlist: index "; Sil.d_exp idx;
L.d_strln " not materialized -- returning nondeterministic value"; L.d_strln " not materialized -- returning nondeterministic value";
let res_e' = Sil.Var (Ident.create_fresh Ident.kprimed) in let res_e' = Exp.Var (Ident.create_fresh Ident.kprimed) in
(res_e', strexp, typ, None) (res_e', strexp, typ, None)
end end
| (Sil.Off_index _):: _, _ -> | (Sil.Off_index _):: _, _ ->
@ -217,9 +217,9 @@ let rec apply_offlist
extensions of se are done before this function. *) extensions of se are done before this function. *)
let ptsto_lookup pdesc tenv p (lexp, se, typ, len, st) offlist id = let ptsto_lookup pdesc tenv p (lexp, se, typ, len, st) offlist id =
let f = let f =
function Some exp -> exp | None -> Sil.Var id in function Some exp -> exp | None -> Exp.Var id in
let fp_root = let fp_root =
match lexp with Sil.Var id -> Ident.is_footprint id | _ -> false in match lexp with Exp.Var id -> Ident.is_footprint id | _ -> false in
let lookup_inst = ref None in let lookup_inst = ref None in
let e', se', typ', pred_insts_op' = let e', se', typ', pred_insts_op' =
apply_offlist apply_offlist
@ -228,7 +228,7 @@ let ptsto_lookup pdesc tenv p (lexp, se, typ, len, st) offlist id =
match !lookup_inst with match !lookup_inst with
| Some (Sil.Iinitial | Sil.Ialloc | Sil.Ilookup) -> true | Some (Sil.Iinitial | Sil.Ialloc | Sil.Ilookup) -> true
| _ -> false in | _ -> false in
let ptsto' = Prop.mk_ptsto lexp se' (Sil.Sizeof (typ', len, st)) in let ptsto' = Prop.mk_ptsto lexp se' (Exp.Sizeof (typ', len, st)) in
(e', ptsto', pred_insts_op', lookup_uninitialized) (e', ptsto', pred_insts_op', lookup_uninitialized)
(** [ptsto_update p (lexp,se,typ) offlist exp] takes (** [ptsto_update p (lexp,se,typ) offlist exp] takes
@ -245,13 +245,13 @@ let ptsto_lookup pdesc tenv p (lexp, se, typ, len, st) offlist id =
let ptsto_update pdesc tenv p (lexp, se, typ, len, st) offlist exp = let ptsto_update pdesc tenv p (lexp, se, typ, len, st) offlist exp =
let f _ = exp in let f _ = exp in
let fp_root = let fp_root =
match lexp with Sil.Var id -> Ident.is_footprint id | _ -> false in match lexp with Exp.Var id -> Ident.is_footprint id | _ -> false in
let lookup_inst = ref None in let lookup_inst = ref None in
let _, se', typ', pred_insts_op' = let _, se', typ', pred_insts_op' =
let pos = State.get_path_pos () in let pos = State.get_path_pos () in
apply_offlist apply_offlist
pdesc tenv p fp_root true (lexp, se, typ) offlist f (State.get_inst_update pos) lookup_inst in pdesc tenv p fp_root true (lexp, se, typ) offlist f (State.get_inst_update pos) lookup_inst in
let ptsto' = Prop.mk_ptsto lexp se' (Sil.Sizeof (typ', len, st)) in let ptsto' = Prop.mk_ptsto lexp se' (Exp.Sizeof (typ', len, st)) in
(ptsto', pred_insts_op') (ptsto', pred_insts_op')
let update_iter iter pi sigma = let update_iter iter pi sigma =
@ -297,10 +297,10 @@ let prune_ineq ~is_strict ~positive prop e1 e2 =
the comment above *) the comment above *)
(* build [e1] CMP [e2] *) (* build [e1] CMP [e2] *)
let cmp = if is_strict then Binop.Lt else Binop.Le in let cmp = if is_strict then Binop.Lt else Binop.Le in
let e1_cmp_e2 = Sil.BinOp (cmp, e1, e2) in let e1_cmp_e2 = Exp.BinOp (cmp, e1, e2) in
(* build !([e1] CMP [e2]) *) (* build !([e1] CMP [e2]) *)
let dual_cmp = if is_strict then Binop.Le else Binop.Lt in let dual_cmp = if is_strict then Binop.Le else Binop.Lt in
let not_e1_cmp_e2 = Sil.BinOp (dual_cmp, e2, e1) in let not_e1_cmp_e2 = Exp.BinOp (dual_cmp, e2, e1) in
(* take polarity into account *) (* take polarity into account *)
let (prune_cond, not_prune_cond) = let (prune_cond, not_prune_cond) =
if positive then (e1_cmp_e2, not_e1_cmp_e2) if positive then (e1_cmp_e2, not_e1_cmp_e2)
@ -314,47 +314,47 @@ let prune_ineq ~is_strict ~positive prop e1 e2 =
let rec prune ~positive condition prop = let rec prune ~positive condition prop =
match condition with match condition with
| Sil.Var _ | Sil.Lvar _ -> | Exp.Var _ | Exp.Lvar _ ->
prune_ne ~positive condition Sil.exp_zero prop prune_ne ~positive condition Sil.exp_zero prop
| Sil.Const (Const.Cint i) when IntLit.iszero i -> | Exp.Const (Const.Cint i) when IntLit.iszero i ->
if positive then Propset.empty else Propset.singleton prop if positive then Propset.empty else Propset.singleton prop
| Sil.Const (Const.Cint _ | Const.Cstr _ | Const.Cclass _) | Sil.Sizeof _ -> | Exp.Const (Const.Cint _ | Const.Cstr _ | Const.Cclass _) | Exp.Sizeof _ ->
if positive then Propset.singleton prop else Propset.empty if positive then Propset.singleton prop else Propset.empty
| Sil.Const _ -> | Exp.Const _ ->
assert false assert false
| Sil.Cast (_, condition') -> | Exp.Cast (_, condition') ->
prune ~positive condition' prop prune ~positive condition' prop
| Sil.UnOp (Unop.LNot, condition', _) -> | Exp.UnOp (Unop.LNot, condition', _) ->
prune ~positive:(not positive) condition' prop prune ~positive:(not positive) condition' prop
| Sil.UnOp _ -> | Exp.UnOp _ ->
assert false assert false
| Sil.BinOp (Binop.Eq, e, Sil.Const (Const.Cint i)) | Exp.BinOp (Binop.Eq, e, Exp.Const (Const.Cint i))
| Sil.BinOp (Binop.Eq, Sil.Const (Const.Cint i), e) | Exp.BinOp (Binop.Eq, Exp.Const (Const.Cint i), e)
when IntLit.iszero i && not (IntLit.isnull i) -> when IntLit.iszero i && not (IntLit.isnull i) ->
prune ~positive:(not positive) e prop prune ~positive:(not positive) e prop
| Sil.BinOp (Binop.Eq, e1, e2) -> | Exp.BinOp (Binop.Eq, e1, e2) ->
prune_ne ~positive:(not positive) e1 e2 prop prune_ne ~positive:(not positive) e1 e2 prop
| Sil.BinOp (Binop.Ne, e, Sil.Const (Const.Cint i)) | Exp.BinOp (Binop.Ne, e, Exp.Const (Const.Cint i))
| Sil.BinOp (Binop.Ne, Sil.Const (Const.Cint i), e) | Exp.BinOp (Binop.Ne, Exp.Const (Const.Cint i), e)
when IntLit.iszero i && not (IntLit.isnull i) -> when IntLit.iszero i && not (IntLit.isnull i) ->
prune ~positive e prop prune ~positive e prop
| Sil.BinOp (Binop.Ne, e1, e2) -> | Exp.BinOp (Binop.Ne, e1, e2) ->
prune_ne ~positive e1 e2 prop prune_ne ~positive e1 e2 prop
| Sil.BinOp (Binop.Ge, e2, e1) | Sil.BinOp (Binop.Le, e1, e2) -> | Exp.BinOp (Binop.Ge, e2, e1) | Exp.BinOp (Binop.Le, e1, e2) ->
prune_ineq ~is_strict:false ~positive prop e1 e2 prune_ineq ~is_strict:false ~positive prop e1 e2
| Sil.BinOp (Binop.Gt, e2, e1) | Sil.BinOp (Binop.Lt, e1, e2) -> | Exp.BinOp (Binop.Gt, e2, e1) | Exp.BinOp (Binop.Lt, e1, e2) ->
prune_ineq ~is_strict:true ~positive prop e1 e2 prune_ineq ~is_strict:true ~positive prop e1 e2
| Sil.BinOp (Binop.LAnd, condition1, condition2) -> | Exp.BinOp (Binop.LAnd, condition1, condition2) ->
let pruner = if positive then prune_inter else prune_union in let pruner = if positive then prune_inter else prune_union in
pruner ~positive condition1 condition2 prop pruner ~positive condition1 condition2 prop
| Sil.BinOp (Binop.LOr, condition1, condition2) -> | Exp.BinOp (Binop.LOr, condition1, condition2) ->
let pruner = if positive then prune_union else prune_inter in let pruner = if positive then prune_union else prune_inter in
pruner ~positive condition1 condition2 prop pruner ~positive condition1 condition2 prop
| Sil.BinOp _ | Sil.Lfield _ | Sil.Lindex _ -> | Exp.BinOp _ | Exp.Lfield _ | Exp.Lindex _ ->
prune_ne ~positive condition Sil.exp_zero prop prune_ne ~positive condition Sil.exp_zero prop
| Sil.Exn _ -> | Exp.Exn _ ->
assert false assert false
| Sil.Closure _ -> | Exp.Closure _ ->
assert false assert false
and prune_inter ~positive condition1 condition2 prop = and prune_inter ~positive condition1 condition2 prop =
@ -403,16 +403,16 @@ let check_constant_string_dereference lexp =
let c = try Char.code (String.get s (IntLit.to_int n)) with Invalid_argument _ -> 0 in let c = try Char.code (String.get s (IntLit.to_int n)) with Invalid_argument _ -> 0 in
Sil.exp_int (IntLit.of_int c) in Sil.exp_int (IntLit.of_int c) in
match lexp with match lexp with
| Sil.BinOp(Binop.PlusPI, Sil.Const (Const.Cstr s), e) | Exp.BinOp(Binop.PlusPI, Exp.Const (Const.Cstr s), e)
| Sil.Lindex (Sil.Const (Const.Cstr s), e) -> | Exp.Lindex (Exp.Const (Const.Cstr s), e) ->
let value = match e with let value = match e with
| Sil.Const (Const.Cint n) | Exp.Const (Const.Cint n)
when IntLit.geq n IntLit.zero && when IntLit.geq n IntLit.zero &&
IntLit.leq n (IntLit.of_int (String.length s)) -> IntLit.leq n (IntLit.of_int (String.length s)) ->
string_lookup s n string_lookup s n
| _ -> Sil.exp_get_undefined false in | _ -> Sil.exp_get_undefined false in
Some value Some value
| Sil.Const (Const.Cstr s) -> | Exp.Const (Const.Cstr s) ->
Some (string_lookup s IntLit.zero) Some (string_lookup s IntLit.zero)
| _ -> None | _ -> None
@ -443,17 +443,17 @@ let check_already_dereferenced pname cond prop =
| _ -> false) (Prop.get_sigma prop)) | _ -> false) (Prop.get_sigma prop))
with Not_found -> None in with Not_found -> None in
let rec is_check_zero = function let rec is_check_zero = function
| Sil.Var id -> | Exp.Var id ->
Some id Some id
| Sil.UnOp(Unop.LNot, e, _) -> | Exp.UnOp(Unop.LNot, e, _) ->
is_check_zero e is_check_zero e
| Sil.BinOp ((Binop.Eq | Binop.Ne), Sil.Const Const.Cint i, Sil.Var id) | Exp.BinOp ((Binop.Eq | Binop.Ne), Exp.Const Const.Cint i, Exp.Var id)
| Sil.BinOp ((Binop.Eq | Binop.Ne), Sil.Var id, Sil.Const Const.Cint i) when IntLit.iszero i -> | Exp.BinOp ((Binop.Eq | Binop.Ne), Exp.Var id, Exp.Const Const.Cint i) when IntLit.iszero i ->
Some id Some id
| _ -> None in | _ -> None in
let dereferenced_line = match is_check_zero cond with let dereferenced_line = match is_check_zero cond with
| Some id -> | Some id ->
(match find_hpred (Prop.exp_normalize_prop prop (Sil.Var id)) with (match find_hpred (Prop.exp_normalize_prop prop (Exp.Var id)) with
| Some (Sil.Hpointsto (_, se, _)) -> | Some (Sil.Hpointsto (_, se, _)) ->
(match Tabulation.find_dereference_without_null_check_in_sexp se with (match Tabulation.find_dereference_without_null_check_in_sexp se with
| Some n -> Some (id, n) | Some n -> Some (id, n)
@ -465,7 +465,7 @@ let check_already_dereferenced pname cond prop =
| Some (id, (n, _)) -> | Some (id, (n, _)) ->
let desc = let desc =
Errdesc.explain_null_test_after_dereference Errdesc.explain_null_test_after_dereference
(Sil.Var id) (State.get_node ()) n (State.get_loc ()) in (Exp.Var id) (State.get_node ()) n (State.get_loc ()) in
let exn = let exn =
(Exceptions.Null_test_after_dereference (desc, __POS__)) in (Exceptions.Null_test_after_dereference (desc, __POS__)) in
let pre_opt = State.get_normalized_pre (Abs.abstract_no_symop pname) in let pre_opt = State.get_normalized_pre (Abs.abstract_no_symop pname) in
@ -534,8 +534,8 @@ let resolve_typename prop receiver_exp =
| _ :: hpreds -> loop hpreds in | _ :: hpreds -> loop hpreds in
loop (Prop.get_sigma prop) in loop (Prop.get_sigma prop) in
match typexp_opt with match typexp_opt with
| Some (Sil.Sizeof (Typ.Tstruct { Typ.struct_name = None }, _, _)) -> None | Some (Exp.Sizeof (Typ.Tstruct { Typ.struct_name = None }, _, _)) -> None
| Some (Sil.Sizeof (Typ.Tstruct { Typ.csu = Csu.Class ck; struct_name = Some name }, _, _)) -> | Some (Exp.Sizeof (Typ.Tstruct { Typ.csu = Csu.Class ck; struct_name = Some name }, _, _)) ->
Some (Typename.TN_csu (Csu.Class ck, name)) Some (Typename.TN_csu (Csu.Class ck, name))
| _ -> None | _ -> None
@ -693,7 +693,7 @@ let call_constructor_url_update_args pname actual_params =
[(Some "java.lang"), "String"] Procname.Non_Static) in [(Some "java.lang"), "String"] Procname.Non_Static) in
if (Procname.equal url_pname pname) then if (Procname.equal url_pname pname) then
(match actual_params with (match actual_params with
| [this; (Sil.Const (Const.Cstr s), atype)] -> | [this; (Exp.Const (Const.Cstr s), atype)] ->
let parts = Str.split (Str.regexp_string "://") s in let parts = Str.split (Str.regexp_string "://") s in
(match parts with (match parts with
| frst:: _ -> | frst:: _ ->
@ -703,10 +703,10 @@ let call_constructor_url_update_args pname actual_params =
frst = "mailto" || frst = "mailto" ||
frst = "jar" frst = "jar"
then then
[this; (Sil.Const (Const.Cstr frst), atype)] [this; (Exp.Const (Const.Cstr frst), atype)]
else actual_params else actual_params
| _ -> actual_params) | _ -> actual_params)
| [this; _, atype] -> [this; (Sil.Const (Const.Cstr "file"), atype)] | [this; _, atype] -> [this; (Exp.Const (Const.Cstr "file"), atype)]
| _ -> actual_params) | _ -> actual_params)
else actual_params else actual_params
@ -738,9 +738,9 @@ let handle_objc_instance_method_call_or_skip actual_pars path callee_pname pre r
| [ret_id] -> ( | [ret_id] -> (
match Prop.find_equal_formal_path receiver prop with match Prop.find_equal_formal_path receiver prop with
| Some vfs -> | Some vfs ->
Prop.add_or_replace_attribute prop (Apred (Aobjc_null, [Sil.Var ret_id; vfs])) Prop.add_or_replace_attribute prop (Apred (Aobjc_null, [Exp.Var ret_id; vfs]))
| None -> | None ->
Prop.conjoin_eq (Sil.Var ret_id) Sil.exp_zero prop Prop.conjoin_eq (Exp.Var ret_id) Sil.exp_zero prop
) )
| _ -> prop in | _ -> prop in
if is_receiver_null then if is_receiver_null then
@ -792,15 +792,15 @@ let do_error_checks node_opt instr pname pdesc = match node_opt with
() ()
let add_strexp_to_footprint strexp abducted_pv typ prop = let add_strexp_to_footprint strexp abducted_pv typ prop =
let abducted_lvar = Sil.Lvar abducted_pv in let abducted_lvar = Exp.Lvar abducted_pv in
let lvar_pt_fpvar = let lvar_pt_fpvar =
let sizeof_exp = Sil.Sizeof (typ, None, Subtype.subtypes) in let sizeof_exp = Exp.Sizeof (typ, None, Subtype.subtypes) in
Prop.mk_ptsto abducted_lvar strexp sizeof_exp in Prop.mk_ptsto abducted_lvar strexp sizeof_exp in
let sigma_fp = Prop.get_sigma_footprint prop in let sigma_fp = Prop.get_sigma_footprint prop in
Prop.normalize (Prop.replace_sigma_footprint (lvar_pt_fpvar :: sigma_fp) prop) Prop.normalize (Prop.replace_sigma_footprint (lvar_pt_fpvar :: sigma_fp) prop)
let add_to_footprint abducted_pv typ prop = let add_to_footprint abducted_pv typ prop =
let fresh_fp_var = Sil.Var (Ident.create_fresh Ident.kfootprint) in let fresh_fp_var = Exp.Var (Ident.create_fresh Ident.kfootprint) in
let prop' = add_strexp_to_footprint (Sil.Eexp (fresh_fp_var, Sil.Inone)) abducted_pv typ prop in let prop' = add_strexp_to_footprint (Sil.Eexp (fresh_fp_var, Sil.Inone)) abducted_pv typ prop in
prop', fresh_fp_var prop', fresh_fp_var
@ -822,13 +822,13 @@ let add_constraints_on_retval pdesc prop ret_exp ~has_nullable_annot typ callee_
let already_has_abducted_retval p abducted_ret_pv = let already_has_abducted_retval p abducted_ret_pv =
IList.exists IList.exists
(fun hpred -> match hpred with (fun hpred -> match hpred with
| Sil.Hpointsto (Sil.Lvar pv, _, _) -> Pvar.equal pv abducted_ret_pv | Sil.Hpointsto (Exp.Lvar pv, _, _) -> Pvar.equal pv abducted_ret_pv
| _ -> false) | _ -> false)
(Prop.get_sigma_footprint p) in (Prop.get_sigma_footprint p) in
(* find an hpred [abducted] |-> A in [prop] and add [exp] = A to prop *) (* find an hpred [abducted] |-> A in [prop] and add [exp] = A to prop *)
let bind_exp_to_abducted_val exp_to_bind abducted prop = let bind_exp_to_abducted_val exp_to_bind abducted prop =
let bind_exp prop = function let bind_exp prop = function
| Sil.Hpointsto (Sil.Lvar pv, Sil.Eexp (rhs, _), _) | Sil.Hpointsto (Exp.Lvar pv, Sil.Eexp (rhs, _), _)
when Pvar.equal pv abducted -> when Pvar.equal pv abducted ->
Prop.conjoin_eq exp_to_bind rhs prop Prop.conjoin_eq exp_to_bind rhs prop
| _ -> prop in | _ -> prop in
@ -872,15 +872,15 @@ let add_taint prop lhs_id rhs_exp pname tenv =
if Taint.has_taint_annotation fieldname struct_typ if Taint.has_taint_annotation fieldname struct_typ
then then
let taint_info = { Sil.taint_source = pname; taint_kind = Tk_unknown; } in let taint_info = { Sil.taint_source = pname; taint_kind = Tk_unknown; } in
Prop.add_or_replace_attribute prop (Apred (Ataint taint_info, [Sil.Var lhs_id])) Prop.add_or_replace_attribute prop (Apred (Ataint taint_info, [Exp.Var lhs_id]))
else else
prop in prop in
match rhs_exp with match rhs_exp with
| Sil.Lfield (_, fieldname, Tptr (Tstruct struct_typ, _)) | Exp.Lfield (_, fieldname, Tptr (Tstruct struct_typ, _))
| Sil.Lfield (_, fieldname, Tstruct struct_typ) -> | Exp.Lfield (_, fieldname, Tstruct struct_typ) ->
add_attribute_if_field_tainted prop fieldname struct_typ add_attribute_if_field_tainted prop fieldname struct_typ
| Sil.Lfield (_, fieldname, Tptr (Tvar typname, _)) | Exp.Lfield (_, fieldname, Tptr (Tvar typname, _))
| Sil.Lfield (_, fieldname, Tvar typname) -> | Exp.Lfield (_, fieldname, Tvar typname) ->
begin begin
match Tenv.lookup tenv typname with match Tenv.lookup tenv typname with
| Some struct_typ -> add_attribute_if_field_tainted prop fieldname struct_typ | Some struct_typ -> add_attribute_if_field_tainted prop fieldname struct_typ
@ -893,17 +893,17 @@ let execute_letderef ?(report_deref_errors=true) pname pdesc tenv id rhs_exp typ
let iter_ren = Prop.prop_iter_make_id_primed id iter in let iter_ren = Prop.prop_iter_make_id_primed id iter in
let prop_ren = Prop.prop_iter_to_prop iter_ren in let prop_ren = Prop.prop_iter_to_prop iter_ren in
match Prop.prop_iter_current iter_ren with match Prop.prop_iter_current iter_ren with
| (Sil.Hpointsto(lexp, strexp, Sil.Sizeof (typ, len, st)), offlist) -> | (Sil.Hpointsto(lexp, strexp, Exp.Sizeof (typ, len, st)), offlist) ->
let contents, new_ptsto, pred_insts_op, lookup_uninitialized = let contents, new_ptsto, pred_insts_op, lookup_uninitialized =
ptsto_lookup pdesc tenv prop_ren (lexp, strexp, typ, len, st) offlist id in ptsto_lookup pdesc tenv prop_ren (lexp, strexp, typ, len, st) offlist id in
let update acc (pi, sigma) = let update acc (pi, sigma) =
let pi' = Sil.Aeq (Sil.Var(id), contents):: pi in let pi' = Sil.Aeq (Exp.Var(id), contents):: pi in
let sigma' = new_ptsto:: sigma in let sigma' = new_ptsto:: sigma in
let iter' = update_iter iter_ren pi' sigma' in let iter' = update_iter iter_ren pi' sigma' in
let prop' = Prop.prop_iter_to_prop iter' in let prop' = Prop.prop_iter_to_prop iter' in
let prop'' = let prop'' =
if lookup_uninitialized then if lookup_uninitialized then
Prop.add_or_replace_attribute prop' (Apred (Adangling DAuninit, [Sil.Var id])) Prop.add_or_replace_attribute prop' (Apred (Adangling DAuninit, [Exp.Var id]))
else prop' in else prop' in
let prop''' = let prop''' =
if Config.taint_analysis if Config.taint_analysis
@ -929,7 +929,7 @@ let execute_letderef ?(report_deref_errors=true) pname pdesc tenv id rhs_exp typ
let n_rhs_exp' = Prop.exp_collapse_consecutive_indices_prop typ n_rhs_exp in let n_rhs_exp' = Prop.exp_collapse_consecutive_indices_prop typ n_rhs_exp in
match check_constant_string_dereference n_rhs_exp' with match check_constant_string_dereference n_rhs_exp' with
| Some value -> | Some value ->
[Prop.conjoin_eq (Sil.Var id) value prop] [Prop.conjoin_eq (Exp.Var id) value prop]
| None -> | None ->
let exp_get_undef_attr exp = let exp_get_undef_attr exp =
let fold_undef_pname callee_opt atom = let fold_undef_pname callee_opt atom =
@ -954,7 +954,7 @@ let execute_letderef ?(report_deref_errors=true) pname pdesc tenv id rhs_exp typ
if (Config.array_level = 0) then assert false if (Config.array_level = 0) then assert false
else else
let undef = Sil.exp_get_undefined false in let undef = Sil.exp_get_undefined false in
[Prop.conjoin_eq (Sil.Var id) undef prop_] [Prop.conjoin_eq (Exp.Var id) undef prop_]
let load_ret_annots pname = let load_ret_annots pname =
match AttributesTable.load_attributes pname with match AttributesTable.load_attributes pname with
@ -968,7 +968,7 @@ let execute_set ?(report_deref_errors=true) pname pdesc tenv lhs_exp typ rhs_exp
let execute_set_ pdesc tenv rhs_exp acc_in iter = let execute_set_ pdesc tenv rhs_exp acc_in iter =
let (lexp, strexp, typ, len, st, offlist) = let (lexp, strexp, typ, len, st, offlist) =
match Prop.prop_iter_current iter with match Prop.prop_iter_current iter with
| (Sil.Hpointsto(lexp, strexp, Sil.Sizeof (typ, len, st)), offlist) -> | (Sil.Hpointsto(lexp, strexp, Exp.Sizeof (typ, len, st)), offlist) ->
(lexp, strexp, typ, len, st, offlist) (lexp, strexp, typ, len, st, offlist)
| _ -> assert false in | _ -> assert false in
let p = Prop.prop_iter_to_prop iter in let p = Prop.prop_iter_to_prop iter in
@ -1006,8 +1006,8 @@ let rec sym_exec tenv current_pdesc _instr (prop_: Prop.normal Prop.t) path
| Sil.Call (ret, exp, par, loc, call_flags) -> | Sil.Call (ret, exp, par, loc, call_flags) ->
let exp' = Prop.exp_normalize_prop prop_ exp in let exp' = Prop.exp_normalize_prop prop_ exp in
let instr' = match exp' with let instr' = match exp' with
| Sil.Closure c -> | Exp.Closure c ->
let proc_exp = Sil.Const (Const.Cfun c.name) in let proc_exp = Exp.Const (Const.Cfun c.name) in
let proc_exp' = Prop.exp_normalize_prop prop_ proc_exp in let proc_exp' = Prop.exp_normalize_prop prop_ proc_exp in
let par' = IList.map (fun (id_exp, _, typ) -> (id_exp, typ)) c.captured_vars in let par' = IList.map (fun (id_exp, _, typ) -> (id_exp, typ)) c.captured_vars in
Sil.Call (ret, proc_exp', par' @ par, loc, call_flags) Sil.Call (ret, proc_exp', par' @ par, loc, call_flags)
@ -1058,7 +1058,7 @@ let rec sym_exec tenv current_pdesc _instr (prop_: Prop.normal Prop.t) path
| _ -> false in | _ -> false in
true_branch && not skip_loop in true_branch && not skip_loop in
match Prop.exp_normalize_prop Prop.prop_emp cond with match Prop.exp_normalize_prop Prop.prop_emp cond with
| Sil.Const (Const.Cint i) when report_condition_always_true_false i -> | Exp.Const (Const.Cint i) when report_condition_always_true_false i ->
let node = State.get_node () in let node = State.get_node () in
let desc = Errdesc.explain_condition_always_true_false i cond node loc in let desc = Errdesc.explain_condition_always_true_false i cond node loc in
let exn = let exn =
@ -1071,12 +1071,12 @@ let rec sym_exec tenv current_pdesc _instr (prop_: Prop.normal Prop.t) path
check_condition_always_true_false (); check_condition_always_true_false ();
let n_cond, prop = check_arith_norm_exp current_pname cond prop__ in let n_cond, prop = check_arith_norm_exp current_pname cond prop__ in
ret_old_path (Propset.to_proplist (prune ~positive:true n_cond prop)) ret_old_path (Propset.to_proplist (prune ~positive:true n_cond prop))
| Sil.Call (ret_ids, Sil.Const (Const.Cfun callee_pname), args, loc, _) | Sil.Call (ret_ids, Exp.Const (Const.Cfun callee_pname), args, loc, _)
when Builtin.is_registered callee_pname -> when Builtin.is_registered callee_pname ->
let sym_exe_builtin = Builtin.get callee_pname in let sym_exe_builtin = Builtin.get callee_pname in
sym_exe_builtin (call_args prop_ callee_pname args ret_ids loc) sym_exe_builtin (call_args prop_ callee_pname args ret_ids loc)
| Sil.Call (ret_ids, | Sil.Call (ret_ids,
Sil.Const (Const.Cfun ((Procname.Java callee_pname_java) as callee_pname)), Exp.Const (Const.Cfun ((Procname.Java callee_pname_java) as callee_pname)),
actual_params, loc, call_flags) actual_params, loc, call_flags)
when Config.lazy_dynamic_dispatch -> when Config.lazy_dynamic_dispatch ->
let norm_prop, norm_args = normalize_params current_pname prop_ actual_params in let norm_prop, norm_args = normalize_params current_pname prop_ actual_params in
@ -1103,7 +1103,7 @@ let rec sym_exec tenv current_pdesc _instr (prop_: Prop.normal Prop.t) path
end end
| Sil.Call (ret_ids, | Sil.Call (ret_ids,
Sil.Const (Const.Cfun ((Procname.Java callee_pname_java) as callee_pname)), Exp.Const (Const.Cfun ((Procname.Java callee_pname_java) as callee_pname)),
actual_params, loc, call_flags) -> actual_params, loc, call_flags) ->
do_error_checks (Paths.Path.curr_node path) instr current_pname current_pdesc; do_error_checks (Paths.Path.curr_node path) instr current_pname current_pdesc;
let norm_prop, norm_args = normalize_params current_pname prop_ actual_params in let norm_prop, norm_args = normalize_params current_pname prop_ actual_params in
@ -1132,7 +1132,7 @@ let rec sym_exec tenv current_pdesc _instr (prop_: Prop.normal Prop.t) path
proc_call summary (call_args norm_prop pname url_handled_args ret_ids loc) in proc_call summary (call_args norm_prop pname url_handled_args ret_ids loc) in
IList.fold_left (fun acc pname -> exec_one_pname pname @ acc) [] resolved_pnames IList.fold_left (fun acc pname -> exec_one_pname pname @ acc) [] resolved_pnames
| Sil.Call (ret_ids, Sil.Const (Const.Cfun callee_pname), actual_params, loc, call_flags) -> | Sil.Call (ret_ids, Exp.Const (Const.Cfun callee_pname), actual_params, loc, call_flags) ->
(* Generic fun call with known name *) (* Generic fun call with known name *)
let (prop_r, n_actual_params) = normalize_params current_pname prop_ actual_params in let (prop_r, n_actual_params) = normalize_params current_pname prop_ actual_params in
let resolved_pname = let resolved_pname =
@ -1216,7 +1216,7 @@ let rec sym_exec tenv current_pdesc _instr (prop_: Prop.normal Prop.t) path
let eprop = Prop.expose prop_ in let eprop = Prop.expose prop_ in
match IList.partition match IList.partition
(function (function
| Sil.Hpointsto (Sil.Lvar pvar', _, _) -> Pvar.equal pvar pvar' | Sil.Hpointsto (Exp.Lvar pvar', _, _) -> Pvar.equal pvar pvar'
| _ -> false) (Prop.get_sigma eprop) with | _ -> false) (Prop.get_sigma eprop) with
| [Sil.Hpointsto(e, se, typ)], sigma' -> | [Sil.Hpointsto(e, se, typ)], sigma' ->
let sigma'' = let sigma'' =
@ -1245,7 +1245,7 @@ let rec sym_exec tenv current_pdesc _instr (prop_: Prop.normal Prop.t) path
ret_old_path [Prop.exist_quantify (Sil.fav_from_list temps) prop_] ret_old_path [Prop.exist_quantify (Sil.fav_from_list temps) prop_]
| Sil.Declare_locals (ptl, _) -> | Sil.Declare_locals (ptl, _) ->
let sigma_locals = let sigma_locals =
let add_None (x, y) = (x, Sil.Sizeof (y, None, Subtype.exact), None) in let add_None (x, y) = (x, Exp.Sizeof (y, None, Subtype.exact), None) in
let sigma_locals () = let sigma_locals () =
IList.map IList.map
(Prop.mk_ptsto_lvar (Some tenv) Prop.Fld_init Sil.inst_initial) (Prop.mk_ptsto_lvar (Some tenv) Prop.Fld_init Sil.inst_initial)
@ -1292,14 +1292,14 @@ and add_constraints_on_actuals_by_ref tenv prop actuals_by_ref callee_pname call
if Config.angelic_execution then if Config.angelic_execution then
let add_actual_by_ref_to_footprint prop (actual, actual_typ) = let add_actual_by_ref_to_footprint prop (actual, actual_typ) =
match actual with match actual with
| Sil.Lvar actual_pv -> | Exp.Lvar actual_pv ->
(* introduce a fresh program variable to allow abduction on the return value *) (* introduce a fresh program variable to allow abduction on the return value *)
let abducted_ref_pv = let abducted_ref_pv =
Pvar.mk_abducted_ref_param callee_pname actual_pv callee_loc in Pvar.mk_abducted_ref_param callee_pname actual_pv callee_loc in
let already_has_abducted_retval p = let already_has_abducted_retval p =
IList.exists IList.exists
(fun hpred -> match hpred with (fun hpred -> match hpred with
| Sil.Hpointsto (Sil.Lvar pv, _, _) -> Pvar.equal pv abducted_ref_pv | Sil.Hpointsto (Exp.Lvar pv, _, _) -> Pvar.equal pv abducted_ref_pv
| _ -> false) | _ -> false)
(Prop.get_sigma_footprint p) in (Prop.get_sigma_footprint p) in
(* prevent introducing multiple abducted retvals for a single call site in a loop *) (* prevent introducing multiple abducted retvals for a single call site in a loop *)
@ -1343,7 +1343,7 @@ and add_constraints_on_actuals_by_ref tenv prop actuals_by_ref callee_pname call
IList.fold_left IList.fold_left
(fun p hpred -> (fun p hpred ->
match hpred with match hpred with
| Sil.Hpointsto (Sil.Lvar pv, rhs, texp) when Pvar.equal pv abducted_ref_pv -> | Sil.Hpointsto (Exp.Lvar pv, rhs, texp) when Pvar.equal pv abducted_ref_pv ->
let new_hpred = Sil.Hpointsto (actual, rhs, texp) in let new_hpred = Sil.Hpointsto (actual, rhs, texp) in
Prop.normalize (Prop.replace_sigma (new_hpred :: (Prop.get_sigma prop')) p) Prop.normalize (Prop.replace_sigma (new_hpred :: (Prop.get_sigma prop')) p)
| _ -> p) | _ -> p)
@ -1355,8 +1355,8 @@ and add_constraints_on_actuals_by_ref tenv prop actuals_by_ref callee_pname call
(* non-angelic mode; havoc each var passed by reference by assigning it to a fresh id *) (* non-angelic mode; havoc each var passed by reference by assigning it to a fresh id *)
let havoc_actual_by_ref (actual, actual_typ) prop = let havoc_actual_by_ref (actual, actual_typ) prop =
let actual_pt_havocd_var = let actual_pt_havocd_var =
let havocd_var = Sil.Var (Ident.create_fresh Ident.kprimed) in let havocd_var = Exp.Var (Ident.create_fresh Ident.kprimed) in
let sizeof_exp = Sil.Sizeof (Typ.strip_ptr actual_typ, None, Subtype.subtypes) in let sizeof_exp = Exp.Sizeof (Typ.strip_ptr actual_typ, None, Subtype.subtypes) in
Prop.mk_ptsto actual (Sil.Eexp (havocd_var, Sil.Inone)) sizeof_exp in Prop.mk_ptsto actual (Sil.Eexp (havocd_var, Sil.Inone)) sizeof_exp in
replace_actual_hpred actual actual_pt_havocd_var prop in replace_actual_hpred actual actual_pt_havocd_var prop in
IList.fold_left (fun p var -> havoc_actual_by_ref var p) prop actuals_by_ref IList.fold_left (fun p var -> havoc_actual_by_ref var p) prop actuals_by_ref
@ -1422,7 +1422,7 @@ and unknown_or_scan_call ~is_scan ret_type_option ret_annots
let actuals_by_ref = let actuals_by_ref =
IList.filter IList.filter
(function (function
| Sil.Lvar _, Typ.Tptr _ -> true | Exp.Lvar _, Typ.Tptr _ -> true
| _ -> false) | _ -> false)
args in args in
let has_nullable_annot = Annotations.ia_is_nullable ret_annots in let has_nullable_annot = Annotations.ia_is_nullable ret_annots in
@ -1435,7 +1435,7 @@ and unknown_or_scan_call ~is_scan ret_type_option ret_annots
let pre_2 = match ret_ids, ret_type_option with let pre_2 = match ret_ids, ret_type_option with
| [ret_id], Some ret_typ -> | [ret_id], Some ret_typ ->
add_constraints_on_retval add_constraints_on_retval
pdesc pre_1 (Sil.Var ret_id) ret_typ ~has_nullable_annot callee_pname loc pdesc pre_1 (Exp.Var ret_id) ret_typ ~has_nullable_annot callee_pname loc
| _ -> | _ ->
pre_1 in pre_1 in
let pre_3 = add_constraints_on_actuals_by_ref tenv pre_2 actuals_by_ref callee_pname loc in let pre_3 = add_constraints_on_actuals_by_ref tenv pre_2 actuals_by_ref callee_pname loc in
@ -1446,7 +1446,7 @@ and unknown_or_scan_call ~is_scan ret_type_option ret_annots
else else
(* otherwise, add undefined attribute to retvals and actuals passed by ref *) (* otherwise, add undefined attribute to retvals and actuals passed by ref *)
let exps_to_mark = let exps_to_mark =
let ret_exps = IList.map (fun ret_id -> Sil.Var ret_id) ret_ids in let ret_exps = IList.map (fun ret_id -> Exp.Var ret_id) ret_ids in
IList.fold_left IList.fold_left
(fun exps_to_mark (exp, _) -> exp :: exps_to_mark) ret_exps actuals_by_ref in (fun exps_to_mark (exp, _) -> exp :: exps_to_mark) ret_exps actuals_by_ref in
let prop_with_undef_attr = let prop_with_undef_attr =
@ -1517,7 +1517,7 @@ and sym_exec_objc_getter field_name ret_typ tenv ret_ids pdesc pname loc args pr
| Typ.Tstruct _ as s -> s | Typ.Tstruct _ as s -> s
| Typ.Tptr (t, _) -> Tenv.expand_type tenv t | Typ.Tptr (t, _) -> Tenv.expand_type tenv t
| _ -> assert false) in | _ -> assert false) in
let field_access_exp = Sil.Lfield (lexp, field_name, typ') in let field_access_exp = Exp.Lfield (lexp, field_name, typ') in
execute_letderef execute_letderef
~report_deref_errors:false pname pdesc tenv ret_id field_access_exp ret_typ loc prop ~report_deref_errors:false pname pdesc tenv ret_id field_access_exp ret_typ loc prop
| _ -> raise (Exceptions.Wrong_argument_number __POS__) | _ -> raise (Exceptions.Wrong_argument_number __POS__)
@ -1531,7 +1531,7 @@ and sym_exec_objc_setter field_name _ tenv _ pdesc pname loc args prop =
| Typ.Tstruct _ as s -> s | Typ.Tstruct _ as s -> s
| Typ.Tptr (t, _) -> Tenv.expand_type tenv t | Typ.Tptr (t, _) -> Tenv.expand_type tenv t
| _ -> assert false) in | _ -> assert false) in
let field_access_exp = Sil.Lfield (lexp1, field_name, typ1') in let field_access_exp = Exp.Lfield (lexp1, field_name, typ1') in
execute_set ~report_deref_errors:false pname pdesc tenv field_access_exp typ2 lexp2 loc prop execute_set ~report_deref_errors:false pname pdesc tenv field_access_exp typ2 lexp2 loc prop
| _ -> raise (Exceptions.Wrong_argument_number __POS__) | _ -> raise (Exceptions.Wrong_argument_number __POS__)
@ -1623,7 +1623,7 @@ and sym_exec_wrapper handle_exn tenv pdesc instr ((prop: Prop.normal Prop.t), pa
IList.map (fun id -> (id, Ident.create_fresh Ident.knormal)) ids_primed in IList.map (fun id -> (id, Ident.create_fresh Ident.knormal)) ids_primed in
let ren_sub = let ren_sub =
Sil.sub_of_list (IList.map Sil.sub_of_list (IList.map
(fun (id1, id2) -> (id1, Sil.Var id2)) ids_primed_normal) in (fun (id1, id2) -> (id1, Exp.Var id2)) ids_primed_normal) in
let p' = Prop.normalize (Prop.prop_sub ren_sub p) in let p' = Prop.normalize (Prop.prop_sub ren_sub p) in
let fav_normal = Sil.fav_from_list (IList.map snd ids_primed_normal) in let fav_normal = Sil.fav_from_list (IList.map snd ids_primed_normal) in
p', fav_normal in p', fav_normal in

@ -31,13 +31,13 @@ val unknown_or_scan_call : is_scan:bool -> Typ.t option -> Typ.item_annotation -
val check_variadic_sentinel : ?fails_on_nil:bool -> int -> int * int -> Builtin.t val check_variadic_sentinel : ?fails_on_nil:bool -> int -> int * int -> Builtin.t
val check_untainted : val check_untainted :
Sil.exp -> Sil.taint_kind -> Procname.t -> Procname.t -> Prop.normal Prop.t -> Prop.normal Prop.t Exp.t -> Sil.taint_kind -> Procname.t -> Procname.t -> Prop.normal Prop.t -> Prop.normal Prop.t
(** Check for arithmetic problems and normalize an expression. *) (** Check for arithmetic problems and normalize an expression. *)
val check_arith_norm_exp : val check_arith_norm_exp :
Procname.t -> Sil.exp -> Prop.normal Prop.t -> Sil.exp * Prop.normal Prop.t Procname.t -> Exp.t -> Prop.normal Prop.t -> Exp.t * Prop.normal Prop.t
val prune : positive:bool -> Sil.exp -> Prop.normal Prop.t -> Propset.t val prune : positive:bool -> Exp.t -> Prop.normal Prop.t -> Propset.t
(** OO method resolution: given a class name and a method name, climb the class hierarchy to find (** OO method resolution: given a class name and a method name, climb the class hierarchy to find
the procname that the method name will actually resolve to at runtime. For example, if we have a the procname that the method name will actually resolve to at runtime. For example, if we have a

@ -22,8 +22,8 @@ type splitting = {
missing_sigma: Sil.hpred list; missing_sigma: Sil.hpred list;
frame_fld : Sil.hpred list; frame_fld : Sil.hpred list;
missing_fld : Sil.hpred list; missing_fld : Sil.hpred list;
frame_typ : (Sil.exp * Sil.exp) list; frame_typ : (Exp.t * Exp.t) list;
missing_typ : (Sil.exp * Sil.exp) list; missing_typ : (Exp.t * Exp.t) list;
} }
type deref_error = type deref_error =
@ -93,8 +93,8 @@ let print_results actual_pre results =
let spec_rename_vars pname spec = let spec_rename_vars pname spec =
let prop_add_callee_suffix p = let prop_add_callee_suffix p =
let f = function let f = function
| Sil.Lvar pv -> | Exp.Lvar pv ->
Sil.Lvar (Pvar.to_callee pname pv) Exp.Lvar (Pvar.to_callee pname pv)
| e -> e in | e -> e in
Prop.prop_expmap f p in Prop.prop_expmap f p in
let jprop_add_callee_suffix = function let jprop_add_callee_suffix = function
@ -107,7 +107,7 @@ let spec_rename_vars pname spec =
IList.iter (fun (p, _) -> Prop.prop_fav_add fav p) spec.Specs.posts; IList.iter (fun (p, _) -> Prop.prop_fav_add fav p) spec.Specs.posts;
let ids = Sil.fav_to_list fav in let ids = Sil.fav_to_list fav in
let ids' = IList.map (fun i -> (i, Ident.create_fresh Ident.kprimed)) ids in let ids' = IList.map (fun i -> (i, Ident.create_fresh Ident.kprimed)) ids in
let ren_sub = Sil.sub_of_list (IList.map (fun (i, i') -> (i, Sil.Var i')) ids') in let ren_sub = Sil.sub_of_list (IList.map (fun (i, i') -> (i, Exp.Var i')) ids') in
let pre' = Specs.Jprop.jprop_sub ren_sub spec.Specs.pre in let pre' = Specs.Jprop.jprop_sub ren_sub spec.Specs.pre in
let posts' = IList.map (fun (p, path) -> (Prop.prop_sub ren_sub p, path)) spec.Specs.posts in let posts' = IList.map (fun (p, path) -> (Prop.prop_sub ren_sub p, path)) spec.Specs.posts in
let pre'' = jprop_add_callee_suffix pre' in let pre'' = jprop_add_callee_suffix pre' in
@ -156,10 +156,10 @@ let process_splitting
let sub = Sil.sub_join sub1 sub2 in let sub = Sil.sub_join sub1 sub2 in
let sub1_inverse = let sub1_inverse =
let sub1_list = Sil.sub_to_list sub1 in let sub1_list = Sil.sub_to_list sub1 in
let sub1_list' = IList.filter (function (_, Sil.Var _) -> true | _ -> false) sub1_list in let sub1_list' = IList.filter (function (_, Exp.Var _) -> true | _ -> false) sub1_list in
let sub1_inverse_list = let sub1_inverse_list =
IList.map IList.map
(function (id, Sil.Var id') -> (id', Sil.Var id) | _ -> assert false) (function (id, Exp.Var id') -> (id', Exp.Var id) | _ -> assert false)
sub1_list' sub1_list'
in Sil.sub_of_list_duplicates sub1_inverse_list in in Sil.sub_of_list_duplicates sub1_inverse_list in
let fav_actual_pre = let fav_actual_pre =
@ -181,12 +181,12 @@ let process_splitting
let fav_missing_fld = Prop.sigma_fav (Prop.sigma_sub sub missing_fld) in let fav_missing_fld = Prop.sigma_fav (Prop.sigma_sub sub missing_fld) in
let map_var_to_pre_var_or_fresh id = let map_var_to_pre_var_or_fresh id =
match Sil.exp_sub sub1_inverse (Sil.Var id) with match Sil.exp_sub sub1_inverse (Exp.Var id) with
| Sil.Var id' -> | Exp.Var id' ->
if Sil.fav_mem fav_actual_pre id' || Ident.is_path id' if Sil.fav_mem fav_actual_pre id' || Ident.is_path id'
(* a path id represents a position in the pre *) (* a path id represents a position in the pre *)
then Sil.Var id' then Exp.Var id'
else Sil.Var (Ident.create_fresh Ident.kprimed) else Exp.Var (Ident.create_fresh Ident.kprimed)
| _ -> assert false in | _ -> assert false in
let sub_list = Sil.sub_to_list sub in let sub_list = Sil.sub_to_list sub in
@ -196,27 +196,27 @@ let process_splitting
Sil.fav_to_list fav_sub in Sil.fav_to_list fav_sub in
let sub1 = let sub1 =
let f id = let f id =
if Sil.fav_mem fav_actual_pre id then (id, Sil.Var id) if Sil.fav_mem fav_actual_pre id then (id, Exp.Var id)
else if Ident.is_normal id then (id, map_var_to_pre_var_or_fresh id) else if Ident.is_normal id then (id, map_var_to_pre_var_or_fresh id)
else if Sil.fav_mem fav_missing_fld id then (id, Sil.Var id) else if Sil.fav_mem fav_missing_fld id then (id, Exp.Var id)
else if Ident.is_footprint id then (id, Sil.Var id) else if Ident.is_footprint id then (id, Exp.Var id)
else begin else begin
let dom1 = Sil.sub_domain sub1 in let dom1 = Sil.sub_domain sub1 in
let rng1 = Sil.sub_range sub1 in let rng1 = Sil.sub_range sub1 in
let dom2 = Sil.sub_domain sub2 in let dom2 = Sil.sub_domain sub2 in
let rng2 = Sil.sub_range sub2 in let rng2 = Sil.sub_range sub2 in
let vars_actual_pre = IList.map (fun id -> Sil.Var id) (Sil.fav_to_list fav_actual_pre) in let vars_actual_pre = IList.map (fun id -> Exp.Var id) (Sil.fav_to_list fav_actual_pre) in
L.d_str "fav_actual_pre: "; Sil.d_exp_list vars_actual_pre; L.d_ln (); L.d_str "fav_actual_pre: "; Sil.d_exp_list vars_actual_pre; L.d_ln ();
L.d_str "Dom(Sub1): "; Sil.d_exp_list (IList.map (fun id -> Sil.Var id) dom1); L.d_ln (); L.d_str "Dom(Sub1): "; Sil.d_exp_list (IList.map (fun id -> Exp.Var id) dom1); L.d_ln ();
L.d_str "Ran(Sub1): "; Sil.d_exp_list rng1; L.d_ln (); L.d_str "Ran(Sub1): "; Sil.d_exp_list rng1; L.d_ln ();
L.d_str "Dom(Sub2): "; Sil.d_exp_list (IList.map (fun id -> Sil.Var id) dom2); L.d_ln (); L.d_str "Dom(Sub2): "; Sil.d_exp_list (IList.map (fun id -> Exp.Var id) dom2); L.d_ln ();
L.d_str "Ran(Sub2): "; Sil.d_exp_list rng2; L.d_ln (); L.d_str "Ran(Sub2): "; Sil.d_exp_list rng2; L.d_ln ();
L.d_str "Don't know about id: "; Sil.d_exp (Sil.Var id); L.d_ln (); L.d_str "Don't know about id: "; Sil.d_exp (Exp.Var id); L.d_ln ();
assert false; assert false;
end end
in Sil.sub_of_list (IList.map f fav_sub_list) in in Sil.sub_of_list (IList.map f fav_sub_list) in
let sub2_list = let sub2_list =
let f id = (id, Sil.Var (Ident.create_fresh Ident.kfootprint)) let f id = (id, Exp.Var (Ident.create_fresh Ident.kfootprint))
in IList.map f (Sil.fav_to_list fav_missing_primed) in in IList.map f (Sil.fav_to_list fav_missing_primed) in
let sub_list' = let sub_list' =
IList.map (fun (id, e) -> (id, Sil.exp_sub sub1 e)) sub_list in IList.map (fun (id, e) -> (id, Sil.exp_sub sub1 e)) sub_list in
@ -238,8 +238,8 @@ let process_splitting
false false
end end
else match hpred with else match hpred with
| Sil.Hpointsto(Sil.Var _, _, _) -> true | Sil.Hpointsto(Exp.Var _, _, _) -> true
| Sil.Hpointsto(Sil.Lvar pvar, _, _) -> Pvar.is_global pvar | Sil.Hpointsto(Exp.Lvar pvar, _, _) -> Pvar.is_global pvar
| _ -> | _ ->
L.d_warning "Missing fields in complex pred: "; Sil.d_hpred hpred; L.d_ln (); L.d_warning "Missing fields in complex pred: "; Sil.d_hpred hpred; L.d_ln ();
false in false in
@ -472,8 +472,8 @@ let texp_star texp1 texp2 =
if ftal_sub instance_fields1 instance_fields2 then t2 else t1 if ftal_sub instance_fields1 instance_fields2 then t2 else t1
| _ -> t1 in | _ -> t1 in
match texp1, texp2 with match texp1, texp2 with
| Sil.Sizeof (t1, len1, st1), Sil.Sizeof (t2, _, st2) -> | Exp.Sizeof (t1, len1, st1), Exp.Sizeof (t2, _, st2) ->
Sil.Sizeof (typ_star t1 t2, len1, Subtype.join st1 st2) Exp.Sizeof (typ_star t1 t2, len1, Subtype.join st1 st2)
| _ -> | _ ->
texp1 texp1
@ -520,7 +520,7 @@ let hpred_star_typing (hpred1 : Sil.hpred) (_, te2) : Sil.hpred =
(** Implementation of [*] between predicates and typings *) (** Implementation of [*] between predicates and typings *)
let sigma_star_typ let sigma_star_typ
(sigma1 : Sil.hpred list) (typings2 : (Sil.exp * Sil.exp) list) : Sil.hpred list = (sigma1 : Sil.hpred list) (typings2 : (Exp.t * Exp.t) list) : Sil.hpred list =
let typing_lhs_compare (e1, _) (e2, _) = Sil.exp_compare e1 e2 in let typing_lhs_compare (e1, _) (e2, _) = Sil.exp_compare e1 e2 in
let sigma1 = IList.stable_sort hpred_lhs_compare sigma1 in let sigma1 = IList.stable_sort hpred_lhs_compare sigma1 in
let typings2 = IList.stable_sort typing_lhs_compare typings2 in let typings2 = IList.stable_sort typing_lhs_compare typings2 in
@ -611,12 +611,12 @@ let prop_copy_footprint_pure p1 p2 =
(** check if an expression is an exception *) (** check if an expression is an exception *)
let exp_is_exn = function let exp_is_exn = function
| Sil.Exn _ -> true | Exp.Exn _ -> true
| _ -> false | _ -> false
(** check if a prop is an exception *) (** check if a prop is an exception *)
let prop_is_exn pname prop = let prop_is_exn pname prop =
let ret_pvar = Sil.Lvar (Pvar.get_ret_pvar pname) in let ret_pvar = Exp.Lvar (Pvar.get_ret_pvar pname) in
let is_exn = function let is_exn = function
| Sil.Hpointsto (e1, Sil.Eexp(e2, _), _) when Sil.exp_equal e1 ret_pvar -> | Sil.Hpointsto (e1, Sil.Eexp(e2, _), _) when Sil.exp_equal e1 ret_pvar ->
exp_is_exn e2 exp_is_exn e2
@ -625,16 +625,16 @@ let prop_is_exn pname prop =
(** when prop is an exception, return the exception name *) (** when prop is an exception, return the exception name *)
let prop_get_exn_name pname prop = let prop_get_exn_name pname prop =
let ret_pvar = Sil.Lvar (Pvar.get_ret_pvar pname) in let ret_pvar = Exp.Lvar (Pvar.get_ret_pvar pname) in
let rec search_exn e = function let rec search_exn e = function
| [] -> None | [] -> None
| Sil.Hpointsto (e1, _, Sil.Sizeof (Typ.Tstruct { Typ.struct_name = Some name }, _, _)) :: _ | Sil.Hpointsto (e1, _, Exp.Sizeof (Typ.Tstruct { Typ.struct_name = Some name }, _, _)) :: _
when Sil.exp_equal e1 e -> when Sil.exp_equal e1 e ->
Some (Typename.TN_csu (Csu.Class Csu.Java, name)) Some (Typename.TN_csu (Csu.Class Csu.Java, name))
| _ :: tl -> search_exn e tl in | _ :: tl -> search_exn e tl in
let rec find_exn_name hpreds = function let rec find_exn_name hpreds = function
| [] -> None | [] -> None
| Sil.Hpointsto (e1, Sil.Eexp (Sil.Exn e2, _), _) :: _ | Sil.Hpointsto (e1, Sil.Eexp (Exp.Exn e2, _), _) :: _
when Sil.exp_equal e1 ret_pvar -> when Sil.exp_equal e1 ret_pvar ->
search_exn e2 hpreds search_exn e2 hpreds
| _ :: tl -> find_exn_name hpreds tl in | _ :: tl -> find_exn_name hpreds tl in
@ -646,14 +646,14 @@ let prop_get_exn_name pname prop =
let lookup_custom_errors prop = let lookup_custom_errors prop =
let rec search_error = function let rec search_error = function
| [] -> None | [] -> None
| Sil.Hpointsto (Sil.Lvar var, Sil.Eexp (Sil.Const (Const.Cstr error_str), _), _) :: _ | Sil.Hpointsto (Exp.Lvar var, Sil.Eexp (Exp.Const (Const.Cstr error_str), _), _) :: _
when Pvar.equal var Sil.custom_error -> Some error_str when Pvar.equal var Sil.custom_error -> Some error_str
| _ :: tl -> search_error tl in | _ :: tl -> search_error tl in
search_error (Prop.get_sigma prop) search_error (Prop.get_sigma prop)
(** set a prop to an exception sexp *) (** set a prop to an exception sexp *)
let prop_set_exn pname prop se_exn = let prop_set_exn pname prop se_exn =
let ret_pvar = Sil.Lvar (Pvar.get_ret_pvar pname) in let ret_pvar = Exp.Lvar (Pvar.get_ret_pvar pname) in
let map_hpred = function let map_hpred = function
| Sil.Hpointsto (e, _, t) when Sil.exp_equal e ret_pvar -> | Sil.Hpointsto (e, _, t) when Sil.exp_equal e ret_pvar ->
Sil.Hpointsto(e, se_exn, t) Sil.Hpointsto(e, se_exn, t)
@ -720,12 +720,12 @@ let combine
let handle_null_case_analysis sigma = let handle_null_case_analysis sigma =
let id_assigned_to_null id = let id_assigned_to_null id =
let filter = function let filter = function
| Sil.Aeq (Sil.Var id', Sil.Const (Const.Cint i)) -> | Sil.Aeq (Exp.Var id', Exp.Const (Const.Cint i)) ->
Ident.equal id id' && IntLit.isnull i Ident.equal id id' && IntLit.isnull i
| _ -> false in | _ -> false in
IList.exists filter split.missing_pi in IList.exists filter split.missing_pi in
let f (e, inst_opt) = match e, inst_opt with let f (e, inst_opt) = match e, inst_opt with
| Sil.Var id, Some inst when id_assigned_to_null id -> | Exp.Var id, Some inst when id_assigned_to_null id ->
let inst' = Sil.inst_set_null_case_flag inst in let inst' = Sil.inst_set_null_case_flag inst in
(e, Some inst') (e, Some inst')
| _ -> (e, inst_opt) in | _ -> (e, inst_opt) in
@ -739,7 +739,7 @@ let combine
let post_p3 = (* replace [result|callee] with an aux variable dedicated to this proc *) let post_p3 = (* replace [result|callee] with an aux variable dedicated to this proc *)
let callee_ret_pvar = let callee_ret_pvar =
Sil.Lvar (Pvar.to_callee callee_pname (Pvar.get_ret_pvar callee_pname)) in Exp.Lvar (Pvar.to_callee callee_pname (Pvar.get_ret_pvar callee_pname)) in
match Prop.prop_iter_create post_p2 with match Prop.prop_iter_create post_p2 with
| None -> post_p2 | None -> post_p2
| Some iter -> | Some iter ->
@ -756,13 +756,13 @@ let combine
prop_set_exn caller_pname p (Sil.Eexp (e', inst)) prop_set_exn caller_pname p (Sil.Eexp (e', inst))
| Sil.Hpointsto (_, Sil.Eexp (e', _), _) when IList.length ret_ids = 1 -> | Sil.Hpointsto (_, Sil.Eexp (e', _), _) when IList.length ret_ids = 1 ->
let p = Prop.prop_iter_remove_curr_then_to_prop iter' in let p = Prop.prop_iter_remove_curr_then_to_prop iter' in
Prop.conjoin_eq e' (Sil.Var (IList.hd ret_ids)) p Prop.conjoin_eq e' (Exp.Var (IList.hd ret_ids)) p
| Sil.Hpointsto (_, Sil.Estruct (ftl, _), _) | Sil.Hpointsto (_, Sil.Estruct (ftl, _), _)
when IList.length ftl = IList.length ret_ids -> when IList.length ftl = IList.length ret_ids ->
let rec do_ftl_ids p = function let rec do_ftl_ids p = function
| [], [] -> p | [], [] -> p
| (_, Sil.Eexp (e', _)):: ftl', ret_id:: ret_ids' -> | (_, Sil.Eexp (e', _)):: ftl', ret_id:: ret_ids' ->
let p' = Prop.conjoin_eq e' (Sil.Var ret_id) p in let p' = Prop.conjoin_eq e' (Exp.Var ret_id) p in
do_ftl_ids p' (ftl', ret_ids') do_ftl_ids p' (ftl', ret_ids')
| _ -> p in | _ -> p in
let p = Prop.prop_iter_remove_curr_then_to_prop iter' in let p = Prop.prop_iter_remove_curr_then_to_prop iter' in
@ -866,9 +866,9 @@ let mk_actual_precondition prop actual_params formal_params =
comb formal_params actual_params in comb formal_params actual_params in
let mk_instantiation (formal_var, (actual_e, actual_t)) = let mk_instantiation (formal_var, (actual_e, actual_t)) =
Prop.mk_ptsto Prop.mk_ptsto
(Sil.Lvar formal_var) (Exp.Lvar formal_var)
(Sil.Eexp (actual_e, Sil.inst_actual_precondition)) (Sil.Eexp (actual_e, Sil.inst_actual_precondition))
(Sil.Sizeof (actual_t, None, Subtype.exact)) in (Exp.Sizeof (actual_t, None, Subtype.exact)) in
let instantiated_formals = IList.map mk_instantiation formals_actuals in let instantiated_formals = IList.map mk_instantiation formals_actuals in
let actual_pre = Prop.prop_sigma_star prop instantiated_formals in let actual_pre = Prop.prop_sigma_star prop instantiated_formals in
Prop.normalize actual_pre Prop.normalize actual_pre
@ -892,7 +892,7 @@ let mk_posts ret_ids prop callee_pname callee_attrs posts =
let returns_null prop = let returns_null prop =
IList.exists IList.exists
(function (function
| Sil.Hpointsto (Sil.Lvar pvar, Sil.Eexp (e, _), _) when Pvar.is_return pvar -> | Sil.Hpointsto (Exp.Lvar pvar, Sil.Eexp (e, _), _) when Pvar.is_return pvar ->
Prover.check_equal (Prop.normalize prop) e Sil.exp_zero Prover.check_equal (Prop.normalize prop) e Sil.exp_zero
| _ -> false) | _ -> false)
(Prop.get_sigma prop) in (Prop.get_sigma prop) in
@ -905,7 +905,7 @@ let mk_posts ret_ids prop callee_pname callee_attrs posts =
let prop_normal = Prop.normalize prop in let prop_normal = Prop.normalize prop in
let prop' = let prop' =
Prop.add_or_replace_attribute prop_normal Prop.add_or_replace_attribute prop_normal
(Apred (Ataint { taint_source = callee_pname; taint_kind; }, [Sil.Var ret_id])) (Apred (Ataint { taint_source = callee_pname; taint_kind; }, [Exp.Var ret_id]))
|> Prop.expose in |> Prop.expose in
(prop', path) in (prop', path) in
IList.map taint_retval posts IList.map taint_retval posts
@ -1091,7 +1091,7 @@ let exe_spec
let remove_constant_string_class prop = let remove_constant_string_class prop =
let filter = function let filter = function
| Sil.Hpointsto (Sil.Const (Const.Cstr _ | Const.Cclass _), _, _) -> false | Sil.Hpointsto (Exp.Const (Const.Cstr _ | Const.Cclass _), _, _) -> false
| _ -> true in | _ -> true in
let sigma = IList.filter filter (Prop.get_sigma prop) in let sigma = IList.filter filter (Prop.get_sigma prop) in
let sigmafp = IList.filter filter (Prop.get_sigma_footprint prop) in let sigmafp = IList.filter filter (Prop.get_sigma_footprint prop) in
@ -1259,7 +1259,7 @@ let exe_call_postprocess ret_ids trace_call callee_pname callee_attrs loc result
match ret_ids with match ret_ids with
| [ret_id] when should_add_ret_attr ()-> | [ret_id] when should_add_ret_attr ()->
(* add attribute to remember what function call a return id came from *) (* add attribute to remember what function call a return id came from *)
let ret_var = Sil.Var ret_id in let ret_var = Exp.Var ret_id in
let mark_id_as_retval (p, path) = let mark_id_as_retval (p, path) =
let att_retval = Sil.Aretval (callee_pname, ret_annot) in let att_retval = Sil.Aretval (callee_pname, ret_annot) in
Prop.set_attribute p att_retval [ret_var], path in Prop.set_attribute p att_retval [ret_var], path in
@ -1310,9 +1310,9 @@ let check_splitting_precondition sub1 sub2 =
let rng2 = Sil.sub_range sub2 in let rng2 = Sil.sub_range sub2 in
let overlap = IList.exists (fun id -> IList.exists (Ident.equal id) dom1) dom2 in let overlap = IList.exists (fun id -> IList.exists (Ident.equal id) dom1) dom2 in
if overlap then begin if overlap then begin
L.d_str "Dom(Sub1): "; Sil.d_exp_list (IList.map (fun id -> Sil.Var id) dom1); L.d_ln (); L.d_str "Dom(Sub1): "; Sil.d_exp_list (IList.map (fun id -> Exp.Var id) dom1); L.d_ln ();
L.d_str "Ran(Sub1): "; Sil.d_exp_list rng1; L.d_ln (); L.d_str "Ran(Sub1): "; Sil.d_exp_list rng1; L.d_ln ();
L.d_str "Dom(Sub2): "; Sil.d_exp_list (IList.map (fun id -> Sil.Var id) dom2); L.d_ln (); L.d_str "Dom(Sub2): "; Sil.d_exp_list (IList.map (fun id -> Exp.Var id) dom2); L.d_ln ();
L.d_str "Ran(Sub2): "; Sil.d_exp_list rng2; L.d_ln (); L.d_str "Ran(Sub2): "; Sil.d_exp_list rng2; L.d_ln ();
assert false assert false
end end

@ -28,7 +28,7 @@ val find_dereference_without_null_check_in_sexp : Sil.strexp -> (int * Sil.path_
(** raise a cast exception *) (** raise a cast exception *)
val raise_cast_exception : val raise_cast_exception :
Logging.ml_loc -> Procname.t option -> Sil.exp -> Sil.exp -> Sil.exp -> 'a Logging.ml_loc -> Procname.t option -> Exp.t -> Exp.t -> Exp.t -> 'a
(** check if a prop is an exception *) (** check if a prop is an exception *)
val prop_is_exn : Procname.t -> 'a Prop.t -> bool val prop_is_exn : Procname.t -> 'a Prop.t -> bool
@ -45,5 +45,5 @@ val d_splitting : splitting -> unit
(** Execute the function call and return the list of results with return value *) (** Execute the function call and return the list of results with return value *)
val exe_function_call: val exe_function_call:
ProcAttributes.t -> Tenv.t -> Ident.t list -> Cfg.Procdesc.t -> Procname.t -> Location.t -> ProcAttributes.t -> Tenv.t -> Ident.t list -> Cfg.Procdesc.t -> Procname.t -> Location.t ->
(Sil.exp * Typ.t) list -> Prop.normal Prop.t -> Paths.Path.t -> (Exp.t * Typ.t) list -> Prop.normal Prop.t -> Paths.Path.t ->
(Prop.normal Prop.t * Paths.Path.t) list (Prop.normal Prop.t * Paths.Path.t) list

@ -375,7 +375,7 @@ let add_tainting_attribute att pvar_param prop =
IList.fold_left IList.fold_left
(fun prop_acc hpred -> (fun prop_acc hpred ->
match hpred with match hpred with
| Sil.Hpointsto (Sil.Lvar pvar, (Sil.Eexp (rhs, _)), _) | Sil.Hpointsto (Exp.Lvar pvar, (Sil.Eexp (rhs, _)), _)
when Pvar.equal pvar pvar_param -> when Pvar.equal pvar pvar_param ->
L.d_strln ("TAINT ANALYSIS: setting taint/untaint attribute of parameter " ^ L.d_strln ("TAINT ANALYSIS: setting taint/untaint attribute of parameter " ^
(Pvar.to_string pvar)); (Pvar.to_string pvar));

@ -83,18 +83,18 @@ let of_exp exp typ ~(f_resolve_id : Ident.t -> raw option) =
(* [typ] is the type of the last element of the access path (e.g., typeof(g) for x.f.g) *) (* [typ] is the type of the last element of the access path (e.g., typeof(g) for x.f.g) *)
let rec of_exp_ exp typ accesses = let rec of_exp_ exp typ accesses =
match exp with match exp with
| Sil.Var id -> | Exp.Var id ->
begin begin
match f_resolve_id id with match f_resolve_id id with
| Some (base, base_accesses) -> Some (base, base_accesses @ accesses) | Some (base, base_accesses) -> Some (base, base_accesses @ accesses)
| None -> Some (base_of_id id typ, accesses) | None -> Some (base_of_id id typ, accesses)
end end
| Sil.Lvar pvar -> | Exp.Lvar pvar ->
Some (base_of_pvar pvar typ, accesses) Some (base_of_pvar pvar typ, accesses)
| Sil.Lfield (root_exp, fld, root_exp_typ) -> | Exp.Lfield (root_exp, fld, root_exp_typ) ->
let field_access = FieldAccess (fld, typ) in let field_access = FieldAccess (fld, typ) in
of_exp_ root_exp root_exp_typ (field_access :: accesses) of_exp_ root_exp root_exp_typ (field_access :: accesses)
| Sil.Lindex (root_exp, _) -> | Exp.Lindex (root_exp, _) ->
let array_access = ArrayAccess typ in let array_access = ArrayAccess typ in
let array_typ = Typ.Tarray (typ, None) in let array_typ = Typ.Tarray (typ, None) in
of_exp_ root_exp array_typ (array_access :: accesses) of_exp_ root_exp array_typ (array_access :: accesses)

@ -48,7 +48,7 @@ val of_pvar : Pvar.t -> Typ.t -> raw
val of_id : Ident.t -> Typ.t -> raw val of_id : Ident.t -> Typ.t -> raw
(** convert [exp] to a raw access path, resolving identifiers using [f_resolve_id] *) (** convert [exp] to a raw access path, resolving identifiers using [f_resolve_id] *)
val of_exp : Sil.exp -> Typ.t -> f_resolve_id:(Ident.t -> raw option) -> raw option val of_exp : Exp.t -> Typ.t -> f_resolve_id:(Ident.t -> raw option) -> raw option
(** append a new access to an existing access path; e.g., `append_access g x.f` produces `x.f.g` *) (** append a new access to an existing access path; e.g., `append_access g x.f` produces `x.f.g` *)
val append : raw -> access -> raw val append : raw -> access -> raw

@ -23,17 +23,17 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
type extras = ProcData.no_extras type extras = ProcData.no_extras
let rec add_address_taken_pvars exp astate = match exp with let rec add_address_taken_pvars exp astate = match exp with
| Sil.Lvar pvar -> | Exp.Lvar pvar ->
Domain.add pvar astate Domain.add pvar astate
| Sil.Cast (_, e) | UnOp (_, e, _) | Lfield (e, _, _) -> | Exp.Cast (_, e) | UnOp (_, e, _) | Lfield (e, _, _) ->
add_address_taken_pvars e astate add_address_taken_pvars e astate
| Sil.BinOp (_, e1, e2) | Lindex (e1, e2) -> | Exp.BinOp (_, e1, e2) | Lindex (e1, e2) ->
add_address_taken_pvars e1 astate add_address_taken_pvars e1 astate
|> add_address_taken_pvars e2 |> add_address_taken_pvars e2
| Sil.Exn _ | Exp.Exn _
| Sil.Closure _ | Exp.Closure _
| Sil.Const (Cint _ | Cfun _ | Cstr _ | Cfloat _ | Cclass _ | Cptr_to_fld _) | Exp.Const (Cint _ | Cfun _ | Cstr _ | Cfloat _ | Cclass _ | Cptr_to_fld _)
| Sil.Var _ | Sil.Sizeof _ -> | Exp.Var _ | Exp.Sizeof _ ->
astate astate
let exec_instr astate _ _ = function let exec_instr astate _ _ = function

@ -287,15 +287,15 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
| _ -> false | _ -> false
let is_tracking_exp astate = function let is_tracking_exp astate = function
| Sil.Var id -> Domain.is_tracked_var (Var.of_id id) astate | Exp.Var id -> Domain.is_tracked_var (Var.of_id id) astate
| Sil.Lvar pvar -> Domain.is_tracked_var (Var.of_pvar pvar) astate | Exp.Lvar pvar -> Domain.is_tracked_var (Var.of_pvar pvar) astate
| _ -> false | _ -> false
let prunes_tracking_var astate = function let prunes_tracking_var astate = function
| Sil.BinOp (Binop.Eq, lhs, rhs) | Exp.BinOp (Binop.Eq, lhs, rhs)
when is_tracking_exp astate lhs -> when is_tracking_exp astate lhs ->
Sil.exp_equal rhs Sil.exp_one Sil.exp_equal rhs Sil.exp_one
| Sil.UnOp (Unop.LNot, Sil.BinOp (Binop.Eq, lhs, rhs), _) | Exp.UnOp (Unop.LNot, Exp.BinOp (Binop.Eq, lhs, rhs), _)
when is_tracking_exp astate lhs -> when is_tracking_exp astate lhs ->
Sil.exp_equal rhs Sil.exp_zero Sil.exp_equal rhs Sil.exp_zero
| _ -> | _ ->
@ -349,10 +349,10 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
| Sil.Letderef (id, exp, _, _) | Sil.Letderef (id, exp, _, _)
when is_tracking_exp astate exp -> when is_tracking_exp astate exp ->
Domain.add_tracking_var (Var.of_id id) astate Domain.add_tracking_var (Var.of_id id) astate
| Sil.Set (Sil.Lvar pvar, _, exp, _) | Sil.Set (Exp.Lvar pvar, _, exp, _)
when is_tracking_exp astate exp -> when is_tracking_exp astate exp ->
Domain.add_tracking_var (Var.of_pvar pvar) astate Domain.add_tracking_var (Var.of_pvar pvar) astate
| Sil.Set (Sil.Lvar pvar, _, _, _) -> | Sil.Set (Exp.Lvar pvar, _, _, _) ->
Domain.remove_tracking_var (Var.of_pvar pvar) astate Domain.remove_tracking_var (Var.of_pvar pvar) astate
| Sil.Prune (exp, _, _, _) | Sil.Prune (exp, _, _, _)
when prunes_tracking_var astate exp -> when prunes_tracking_var astate exp ->

@ -210,7 +210,7 @@ module Automaton = struct
(** Transfer function for an instruction. *) (** Transfer function for an instruction. *)
let do_instr pn pd (instr : Sil.instr) (state : State.t) : State.t = let do_instr pn pd (instr : Sil.instr) (state : State.t) : State.t =
match instr with match instr with
| Sil.Call (_, Sil.Const (Const.Cfun callee_pn), _, loc, _) -> | Sil.Call (_, Exp.Const (Const.Cfun callee_pn), _, loc, _) ->
do_call pn pd callee_pn state loc do_call pn pd callee_pn state loc
| _ -> state | _ -> state
@ -232,7 +232,7 @@ module BooleanVars = struct
(** Check if the expression exp is one of the listed boolean variables. *) (** Check if the expression exp is one of the listed boolean variables. *)
let exp_boolean_var exp = match exp with let exp_boolean_var exp = match exp with
| Sil.Lvar pvar when Pvar.is_local pvar -> | Exp.Lvar pvar when Pvar.is_local pvar ->
let name = Mangled.to_string (Pvar.get_name pvar) in let name = Mangled.to_string (Pvar.get_name pvar) in
if IList.mem string_equal name boolean_variables if IList.mem string_equal name boolean_variables
then Some name then Some name
@ -244,10 +244,10 @@ module BooleanVars = struct
(* Normalize a boolean condition. *) (* Normalize a boolean condition. *)
let normalize_condition cond_e = let normalize_condition cond_e =
match cond_e with match cond_e with
| Sil.UnOp (Unop.LNot, Sil.BinOp (Binop.Eq, e1, e2), _) -> | Exp.UnOp (Unop.LNot, Exp.BinOp (Binop.Eq, e1, e2), _) ->
Sil.BinOp (Binop.Ne, e1, e2) Exp.BinOp (Binop.Ne, e1, e2)
| Sil.UnOp (Unop.LNot, Sil.BinOp (Binop.Ne, e1, e2), _) -> | Exp.UnOp (Unop.LNot, Exp.BinOp (Binop.Ne, e1, e2), _) ->
Sil.BinOp (Binop.Eq, e1, e2) Exp.BinOp (Binop.Eq, e1, e2)
| _ -> cond_e in | _ -> cond_e in
(* Normalize an instruction. *) (* Normalize an instruction. *)
@ -258,7 +258,7 @@ module BooleanVars = struct
| instr -> instr in | instr -> instr in
match normalize_instr instr with match normalize_instr instr with
| Sil.Prune (Sil.BinOp (Binop.Eq, _cond_e, Sil.Const (Const.Cint i)), _, _, _) | Sil.Prune (Exp.BinOp (Binop.Eq, _cond_e, Exp.Const (Const.Cint i)), _, _, _)
when IntLit.iszero i -> when IntLit.iszero i ->
let cond_e = Idenv.expand_expr idenv _cond_e in let cond_e = Idenv.expand_expr idenv _cond_e in
let state' = match exp_boolean_var cond_e with let state' = match exp_boolean_var cond_e with
@ -267,7 +267,7 @@ module BooleanVars = struct
State.prune state name false State.prune state name false
| None -> state in | None -> state in
state' state'
| Sil.Prune (Sil.BinOp (Binop.Ne, _cond_e, Sil.Const (Const.Cint i)), _, _, _) | Sil.Prune (Exp.BinOp (Binop.Ne, _cond_e, Exp.Const (Const.Cint i)), _, _, _)
when IntLit.iszero i -> when IntLit.iszero i ->
let cond_e = Idenv.expand_expr idenv _cond_e in let cond_e = Idenv.expand_expr idenv _cond_e in
let state' = match exp_boolean_var cond_e with let state' = match exp_boolean_var cond_e with
@ -281,7 +281,7 @@ module BooleanVars = struct
let state' = match exp_boolean_var e1 with let state' = match exp_boolean_var e1 with
| Some name -> | Some name ->
let b_opt = match e2 with let b_opt = match e2 with
| Sil.Const (Const.Cint i) -> Some (not (IntLit.iszero i)) | Exp.Const (Const.Cint i) -> Some (not (IntLit.iszero i))
| _ -> None in | _ -> None in
if verbose then if verbose then
begin begin

@ -282,7 +282,7 @@ let callback_check_write_to_parcel_java
check_match (r_call_descs, w_call_descs) in check_match (r_call_descs, w_call_descs) in
let do_instr _ instr = match instr with let do_instr _ instr = match instr with
| Sil.Call (_, Sil.Const (Const.Cfun _), (_this_exp, this_type):: _, _, _) -> | Sil.Call (_, Exp.Const (Const.Cfun _), (_this_exp, this_type):: _, _, _) ->
let this_exp = Idenv.expand_expr idenv _this_exp in let this_exp = Idenv.expand_expr idenv _this_exp in
if is_write_to_parcel this_exp this_type then begin if is_write_to_parcel this_exp this_type then begin
if !verbose then if !verbose then
@ -327,7 +327,7 @@ let callback_monitor_nullcheck { Callbacks.proc_desc; idenv; proc_name } =
IList.filter is_class_type formals in IList.filter is_class_type formals in
IList.map fst class_formals) in IList.map fst class_formals) in
let equal_formal_param exp formal_name = match exp with let equal_formal_param exp formal_name = match exp with
| Sil.Lvar pvar -> | Exp.Lvar pvar ->
let name = Pvar.get_name pvar in let name = Pvar.get_name pvar in
Mangled.equal name formal_name Mangled.equal name formal_name
| _ -> false in | _ -> false in
@ -373,7 +373,7 @@ let callback_monitor_nullcheck { Callbacks.proc_desc; idenv; proc_name } =
end in end in
let do_instr _ instr = match instr with let do_instr _ instr = match instr with
| Sil.Call (_, Sil.Const (Const.Cfun pn), (_arg1, _):: _, _, _) when is_nullcheck pn -> | Sil.Call (_, Exp.Const (Const.Cfun pn), (_arg1, _):: _, _, _) when is_nullcheck pn ->
let arg1 = Idenv.expand_expr idenv _arg1 in let arg1 = Idenv.expand_expr idenv _arg1 in
if is_formal_param arg1 then handle_check_of_formal arg1; if is_formal_param arg1 then handle_check_of_formal arg1;
if !verbose then if !verbose then
@ -427,24 +427,24 @@ let callback_find_deserialization { Callbacks.proc_desc; get_proc_desc; idenv; p
match get_proc_desc proc_name' with match get_proc_desc proc_name' with
Some proc_desc' -> Some proc_desc' ->
let is_return_instr = function let is_return_instr = function
| Sil.Set (Sil.Lvar p, _, _, _) | Sil.Set (Exp.Lvar p, _, _, _)
when Pvar.equal p (Cfg.Procdesc.get_ret_var proc_desc') -> true when Pvar.equal p (Cfg.Procdesc.get_ret_var proc_desc') -> true
| _ -> false in | _ -> false in
(match reverse_find_instr is_return_instr (Cfg.Procdesc.get_exit_node proc_desc') with (match reverse_find_instr is_return_instr (Cfg.Procdesc.get_exit_node proc_desc') with
| Some (Sil.Set (_, _, Sil.Const (Const.Cclass n), _)) -> Ident.name_to_string n | Some (Sil.Set (_, _, Exp.Const (Const.Cclass n), _)) -> Ident.name_to_string n
| _ -> "<" ^ (Procname.to_string proc_name') ^ ">") | _ -> "<" ^ (Procname.to_string proc_name') ^ ">")
| None -> "?" in | None -> "?" in
let get_actual_arguments node instr = match instr with let get_actual_arguments node instr = match instr with
| Sil.Call (_, Sil.Const (Const.Cfun _), _:: args, _, _) -> | Sil.Call (_, Exp.Const (Const.Cfun _), _:: args, _, _) ->
(try (try
let find_const exp = let find_const exp =
let expanded = Idenv.expand_expr idenv exp in let expanded = Idenv.expand_expr idenv exp in
match expanded with match expanded with
| Sil.Const (Const.Cclass n) -> Ident.name_to_string n | Exp.Const (Const.Cclass n) -> Ident.name_to_string n
| Sil.Lvar _ -> ( | Exp.Lvar _ -> (
let is_call_instr set call = match set, call with let is_call_instr set call = match set, call with
| Sil.Set (_, _, Sil.Var (i1), _), Sil.Call (i2::[], _, _, _, _) | Sil.Set (_, _, Exp.Var (i1), _), Sil.Call (i2::[], _, _, _, _)
when Ident.equal i1 i2 -> true when Ident.equal i1 i2 -> true
| _ -> false in | _ -> false in
let is_set_instr = function let is_set_instr = function
@ -455,7 +455,7 @@ let callback_find_deserialization { Callbacks.proc_desc; get_proc_desc; idenv; p
| Some s -> ( | Some s -> (
match reverse_find_instr (is_call_instr s) node with match reverse_find_instr (is_call_instr s) node with
(* Look for tmp := foo() *) (* Look for tmp := foo() *)
| Some (Sil.Call (_, Sil.Const (Const.Cfun pn), _, _, _)) -> | Some (Sil.Call (_, Exp.Const (Const.Cfun pn), _, _, _)) ->
get_return_const pn get_return_const pn
| _ -> "?") | _ -> "?")
| _ -> "?") | _ -> "?")
@ -500,26 +500,26 @@ let callback_find_deserialization { Callbacks.proc_desc; get_proc_desc; idenv; p
(** Check field accesses. *) (** Check field accesses. *)
let callback_check_field_access { Callbacks.proc_desc } = let callback_check_field_access { Callbacks.proc_desc } =
let rec do_exp is_read = function let rec do_exp is_read = function
| Sil.Var _ -> () | Exp.Var _ -> ()
| Sil.UnOp (_, e, _) -> | Exp.UnOp (_, e, _) ->
do_exp is_read e do_exp is_read e
| Sil.BinOp (_, e1, e2) -> | Exp.BinOp (_, e1, e2) ->
do_exp is_read e1; do_exp is_read e1;
do_exp is_read e2 do_exp is_read e2
| Sil.Exn _ -> () | Exp.Exn _ -> ()
| Sil.Closure _ -> () | Exp.Closure _ -> ()
| Sil.Const _ -> () | Exp.Const _ -> ()
| Sil.Cast (_, e) -> | Exp.Cast (_, e) ->
do_exp is_read e do_exp is_read e
| Sil.Lvar _ -> () | Exp.Lvar _ -> ()
| Sil.Lfield (e, fn, _) -> | Exp.Lfield (e, fn, _) ->
if not (Ident.java_fieldname_is_outer_instance fn) then if not (Ident.java_fieldname_is_outer_instance fn) then
L.stdout "field %s %s@." (Ident.fieldname_to_string fn) (if is_read then "reading" else "writing"); L.stdout "field %s %s@." (Ident.fieldname_to_string fn) (if is_read then "reading" else "writing");
do_exp is_read e do_exp is_read e
| Sil.Lindex (e1, e2) -> | Exp.Lindex (e1, e2) ->
do_exp is_read e1; do_exp is_read e1;
do_exp is_read e2 do_exp is_read e2
| Sil.Sizeof _ -> () in | Exp.Sizeof _ -> () in
let do_read_exp = do_exp true in let do_read_exp = do_exp true in
let do_write_exp = do_exp false in let do_write_exp = do_exp false in
let do_instr _ = function let do_instr _ = function
@ -544,7 +544,7 @@ let callback_check_field_access { Callbacks.proc_desc } =
(** Print c method calls. *) (** Print c method calls. *)
let callback_print_c_method_calls { Callbacks.proc_desc; proc_name } = let callback_print_c_method_calls { Callbacks.proc_desc; proc_name } =
let do_instr node = function let do_instr node = function
| Sil.Call (_, Sil.Const (Const.Cfun pn), (e, _):: _, loc, _) | Sil.Call (_, Exp.Const (Const.Cfun pn), (e, _):: _, loc, _)
when Procname.is_c_method pn -> when Procname.is_c_method pn ->
let receiver = match Errdesc.exp_rv_dexp node e with let receiver = match Errdesc.exp_rv_dexp node e with
| Some de -> DecompiledExp.to_string de | Some de -> DecompiledExp.to_string de
@ -557,7 +557,7 @@ let callback_print_c_method_calls { Callbacks.proc_desc; proc_name } =
"CHECKERS_PRINT_OBJC_METHOD_CALLS" "CHECKERS_PRINT_OBJC_METHOD_CALLS"
loc loc
description description
| Sil.Call (_, Sil.Const (Const.Cfun pn), _, loc, _) -> | Sil.Call (_, Exp.Const (Const.Cfun pn), _, loc, _) ->
let description = let description =
Printf.sprintf "call to %s" (Procname.to_string pn) in Printf.sprintf "call to %s" (Procname.to_string pn) in
ST.report_error ST.report_error
@ -583,9 +583,9 @@ let callback_print_access_to_globals { Callbacks.proc_desc; proc_name } =
loc loc
description in description in
let rec get_global_var = function let rec get_global_var = function
| Sil.Lvar pvar when Pvar.is_global pvar -> | Exp.Lvar pvar when Pvar.is_global pvar ->
Some pvar Some pvar
| Sil.Lfield (e, _, _) -> | Exp.Lfield (e, _, _) ->
get_global_var e get_global_var e
| _ -> | _ ->
None in None in

@ -69,7 +69,7 @@ end
module Match = struct module Match = struct
type value = type value =
| Vfun of Procname.t | Vfun of Procname.t
| Vval of Sil.exp | Vval of Exp.t
let pp_value fmt = function let pp_value fmt = function
| Vval e -> F.fprintf fmt "%a" (Sil.pp_exp pe_text) e | Vval e -> F.fprintf fmt "%a" (Sil.pp_exp pe_text) e
@ -123,14 +123,14 @@ module Match = struct
| _ -> false | _ -> false
let rec cond_match env idenv cond (ae1, op, ae2) = match cond with let rec cond_match env idenv cond (ae1, op, ae2) = match cond with
| Sil.BinOp (bop, _e1, _e2) -> | Exp.BinOp (bop, _e1, _e2) ->
let e1 = Idenv.expand_expr idenv _e1 in let e1 = Idenv.expand_expr idenv _e1 in
let e2 = Idenv.expand_expr idenv _e2 in let e2 = Idenv.expand_expr idenv _e2 in
binop_match bop op && exp_match env ae1 (Vval e1) && exp_match env ae2 (Vval e2) binop_match bop op && exp_match env ae1 (Vval e1) && exp_match env ae2 (Vval e2)
| Sil.UnOp (Unop.LNot, (Sil.BinOp (Binop.Eq, e1, e2)), _) -> | Exp.UnOp (Unop.LNot, (Exp.BinOp (Binop.Eq, e1, e2)), _) ->
cond_match env idenv (Sil.BinOp (Binop.Ne, e1, e2)) (ae1, op, ae2) cond_match env idenv (Exp.BinOp (Binop.Ne, e1, e2)) (ae1, op, ae2)
| Sil.UnOp (Unop.LNot, (Sil.BinOp (Binop.Ne, e1, e2)), _) -> | Exp.UnOp (Unop.LNot, (Exp.BinOp (Binop.Ne, e1, e2)), _) ->
cond_match env idenv (Sil.BinOp (Binop.Eq, e1, e2)) (ae1, op, ae2) cond_match env idenv (Exp.BinOp (Binop.Eq, e1, e2)) (ae1, op, ae2)
| _ -> false | _ -> false
(** Iterate over the instructions of the linearly succ nodes. *) (** Iterate over the instructions of the linearly succ nodes. *)
@ -161,7 +161,7 @@ module Match = struct
let rec match_query show env idenv caller_pn (rule, action) proc_name node instr = let rec match_query show env idenv caller_pn (rule, action) proc_name node instr =
match rule, instr with match rule, instr with
| CodeQueryAst.Call (ae1, ae2), Sil.Call (_, Sil.Const (Const.Cfun pn), _, loc, _) -> | CodeQueryAst.Call (ae1, ae2), Sil.Call (_, Exp.Const (Const.Cfun pn), _, loc, _) ->
if exp_match env ae1 (Vfun caller_pn) && exp_match env ae2 (Vfun pn) then if exp_match env ae1 (Vfun caller_pn) && exp_match env ae2 (Vfun pn) then
begin begin
if show then print_action env action proc_name node loc; if show then print_action env action proc_name node loc;
@ -170,7 +170,7 @@ module Match = struct
else false else false
| CodeQueryAst.Call _, _ -> false | CodeQueryAst.Call _, _ -> false
| CodeQueryAst.MethodCall (ae1, ae2, ael_opt), | CodeQueryAst.MethodCall (ae1, ae2, ael_opt),
Sil.Call (_, Sil.Const (Const.Cfun pn), (_e1, _) :: params, Sil.Call (_, Exp.Const (Const.Cfun pn), (_e1, _) :: params,
loc, { CallFlags.cf_virtual = true }) -> loc, { CallFlags.cf_virtual = true }) ->
let e1 = Idenv.expand_expr idenv _e1 in let e1 = Idenv.expand_expr idenv _e1 in
let vl = IList.map (function _e, _ -> Vval (Idenv.expand_expr idenv _e)) params in let vl = IList.map (function _e, _ -> Vval (Idenv.expand_expr idenv _e)) params in

@ -69,33 +69,33 @@ module ConstantFlow = Dataflow.MakeDF(struct
false in false in
match instr with match instr with
| Sil.Letderef (i, Sil.Lvar p, _, _) -> (* tmp = var *) | Sil.Letderef (i, Exp.Lvar p, _, _) -> (* tmp = var *)
update (Sil.Var i) (ConstantMap.find (Sil.Lvar p) constants) constants update (Exp.Var i) (ConstantMap.find (Exp.Lvar p) constants) constants
| Sil.Set (Sil.Lvar p, _, Sil.Const c, _) -> (* var = const *) | Sil.Set (Exp.Lvar p, _, Exp.Const c, _) -> (* var = const *)
update (Sil.Lvar p) (Some c) constants update (Exp.Lvar p) (Some c) constants
| Sil.Set (Sil.Lvar p, _, Sil.Var i, _) -> (* var = tmp *) | Sil.Set (Exp.Lvar p, _, Exp.Var i, _) -> (* var = tmp *)
update (Sil.Lvar p) (ConstantMap.find (Sil.Var i) constants) constants update (Exp.Lvar p) (ConstantMap.find (Exp.Var i) constants) constants
(* Handle propagation of string with StringBuilder. Does not handle null case *) (* Handle propagation of string with StringBuilder. Does not handle null case *)
| Sil.Call (_, Sil.Const (Const.Cfun pn), (Sil.Var sb, _):: [], _, _) | Sil.Call (_, Exp.Const (Const.Cfun pn), (Exp.Var sb, _):: [], _, _)
when has_class pn "java.lang.StringBuilder" when has_class pn "java.lang.StringBuilder"
&& has_method pn "<init>" -> (* StringBuilder.<init> *) && has_method pn "<init>" -> (* StringBuilder.<init> *)
update (Sil.Var sb) (Some (Const.Cstr "")) constants update (Exp.Var sb) (Some (Const.Cstr "")) constants
| Sil.Call (i:: [], Sil.Const (Const.Cfun pn), (Sil.Var i1, _):: [], _, _) | Sil.Call (i:: [], Exp.Const (Const.Cfun pn), (Exp.Var i1, _):: [], _, _)
when has_class pn "java.lang.StringBuilder" when has_class pn "java.lang.StringBuilder"
&& has_method pn "toString" -> (* StringBuilder.toString *) && has_method pn "toString" -> (* StringBuilder.toString *)
update (Sil.Var i) (ConstantMap.find (Sil.Var i1) constants) constants update (Exp.Var i) (ConstantMap.find (Exp.Var i1) constants) constants
| Sil.Call | Sil.Call
(i:: [], Sil.Const (Const.Cfun pn), (Sil.Var i1, _):: (Sil.Var i2, _):: [], _, _) (i:: [], Exp.Const (Const.Cfun pn), (Exp.Var i1, _):: (Exp.Var i2, _):: [], _, _)
when has_class pn "java.lang.StringBuilder" when has_class pn "java.lang.StringBuilder"
&& has_method pn "append" -> (* StringBuilder.append *) && has_method pn "append" -> (* StringBuilder.append *)
(match (match
ConstantMap.find (Sil.Var i1) constants, ConstantMap.find (Exp.Var i1) constants,
ConstantMap.find (Sil.Var i2) constants with ConstantMap.find (Exp.Var i2) constants with
| Some (Const.Cstr s1), Some (Const.Cstr s2) -> | Some (Const.Cstr s1), Some (Const.Cstr s2) ->
begin begin
let s = s1 ^ s2 in let s = s1 ^ s2 in
@ -104,7 +104,7 @@ module ConstantFlow = Dataflow.MakeDF(struct
Some (Const.Cstr s) Some (Const.Cstr s)
else else
None in None in
update (Sil.Var i) u constants update (Exp.Var i) u constants
end end
| _ -> constants) | _ -> constants)
@ -136,7 +136,7 @@ let run tenv proc_desc =
| ConstantFlow.Dead_state -> ConstantMap.empty in | ConstantFlow.Dead_state -> ConstantMap.empty in
get_constants get_constants
type const_map = Cfg.Node.t -> Sil.exp -> Const.t option type const_map = Cfg.Node.t -> Exp.t -> Const.t option
(** Build a const map lazily. *) (** Build a const map lazily. *)
let build_const_map tenv pdesc = let build_const_map tenv pdesc =

@ -9,7 +9,7 @@
open! Utils open! Utils
type const_map = Cfg.Node.t -> Sil.exp -> Const.t option type const_map = Cfg.Node.t -> Exp.t -> Const.t option
(** Build a const map lazily. *) (** Build a const map lazily. *)
val build_const_map : Tenv.t -> Cfg.Procdesc.t -> const_map val build_const_map : Tenv.t -> Cfg.Procdesc.t -> const_map

@ -86,11 +86,11 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
type extras = ProcData.no_extras type extras = ProcData.no_extras
let exec_instr astate _ _ = function let exec_instr astate _ _ = function
| Sil.Letderef (lhs_id, Sil.Lvar rhs_pvar, _, _) when not (Pvar.is_global rhs_pvar) -> | Sil.Letderef (lhs_id, Exp.Lvar rhs_pvar, _, _) when not (Pvar.is_global rhs_pvar) ->
Domain.gen (Var.of_id lhs_id) (Var.of_pvar rhs_pvar) astate Domain.gen (Var.of_id lhs_id) (Var.of_pvar rhs_pvar) astate
| Sil.Set (Sil.Lvar lhs_pvar, _, Sil.Var rhs_id, _) when not (Pvar.is_global lhs_pvar) -> | Sil.Set (Exp.Lvar lhs_pvar, _, Exp.Var rhs_id, _) when not (Pvar.is_global lhs_pvar) ->
Domain.kill_then_gen (Var.of_pvar lhs_pvar) (Var.of_id rhs_id) astate Domain.kill_then_gen (Var.of_pvar lhs_pvar) (Var.of_id rhs_id) astate
| Sil.Set (Sil.Lvar lhs_pvar, _, _, _) -> | Sil.Set (Exp.Lvar lhs_pvar, _, _, _) ->
(* non-copy assignment; can only kill *) (* non-copy assignment; can only kill *)
Domain.kill_copies_with_var (Var.of_pvar lhs_pvar) astate Domain.kill_copies_with_var (Var.of_pvar lhs_pvar) astate
| Sil.Letderef _ | Sil.Letderef _
@ -103,7 +103,7 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
let kill_ret_ids astate_acc id = let kill_ret_ids astate_acc id =
Domain.kill_copies_with_var (Var.of_id id) astate_acc in Domain.kill_copies_with_var (Var.of_id id) astate_acc in
let kill_actuals_by_ref astate_acc = function let kill_actuals_by_ref astate_acc = function
| (Sil.Lvar pvar, Typ.Tptr _) -> Domain.kill_copies_with_var (Var.of_pvar pvar) astate_acc | (Exp.Lvar pvar, Typ.Tptr _) -> Domain.kill_copies_with_var (Var.of_pvar pvar) astate_acc
| _ -> astate_acc in | _ -> astate_acc in
let astate' = IList.fold_left kill_ret_ids astate ret_ids in let astate' = IList.fold_left kill_ret_ids astate ret_ids in
if !Config.curr_language = Config.Java if !Config.curr_language = Config.Java

@ -54,15 +54,15 @@ let node_throws node (proc_throws : Procname.t -> throws) : throws =
let ret_pvar = Cfg.Procdesc.get_ret_var pdesc in let ret_pvar = Cfg.Procdesc.get_ret_var pdesc in
Pvar.equal pvar ret_pvar in Pvar.equal pvar ret_pvar in
match instr with match instr with
| Sil.Set (Sil.Lvar pvar, _, Sil.Exn _, _) when is_return pvar -> | Sil.Set (Exp.Lvar pvar, _, Exp.Exn _, _) when is_return pvar ->
(* assignment to return variable is an artifact of a throw instruction *) (* assignment to return variable is an artifact of a throw instruction *)
Throws Throws
| Sil.Call (_, Sil.Const (Const.Cfun callee_pn), _, _, _) | Sil.Call (_, Exp.Const (Const.Cfun callee_pn), _, _, _)
when Builtin.is_registered callee_pn -> when Builtin.is_registered callee_pn ->
if Procname.equal callee_pn ModelBuiltins.__cast if Procname.equal callee_pn ModelBuiltins.__cast
then DontKnow then DontKnow
else DoesNotThrow else DoesNotThrow
| Sil.Call (_, Sil.Const (Const.Cfun callee_pn), _, _, _) -> | Sil.Call (_, Exp.Const (Const.Cfun callee_pn), _, _, _) ->
proc_throws callee_pn proc_throws callee_pn
| _ -> | _ ->
DoesNotThrow in DoesNotThrow in

@ -13,7 +13,7 @@ open! Utils
Lazy implementation: only created when actually used. *) Lazy implementation: only created when actually used. *)
type t = (Sil.exp Ident.IdentHash.t) Lazy.t type t = (Exp.t Ident.IdentHash.t) Lazy.t
let create_ proc_desc = let create_ proc_desc =
let map = Ident.IdentHash.create 1 in let map = Ident.IdentHash.create 1 in
@ -41,7 +41,7 @@ let lookup map_ id =
with Not_found -> None with Not_found -> None
let expand_expr idenv e = match e with let expand_expr idenv e = match e with
| Sil.Var id -> | Exp.Var id ->
(match lookup idenv id with (match lookup idenv id with
| Some e' -> e' | Some e' -> e'
| None -> e) | None -> e)
@ -50,16 +50,16 @@ let expand_expr idenv e = match e with
let expand_expr_temps idenv node _exp = let expand_expr_temps idenv node _exp =
let exp = expand_expr idenv _exp in let exp = expand_expr idenv _exp in
match exp with match exp with
| Sil.Lvar pvar when Pvar.is_frontend_tmp pvar -> | Exp.Lvar pvar when Pvar.is_frontend_tmp pvar ->
(match Errdesc.find_program_variable_assignment node pvar with (match Errdesc.find_program_variable_assignment node pvar with
| None -> exp | None -> exp
| Some (_, id) -> | Some (_, id) ->
expand_expr idenv (Sil.Var id)) expand_expr idenv (Exp.Var id))
| _ -> exp | _ -> exp
(** Return true if the expression is a temporary variable introduced by the front-end. *) (** Return true if the expression is a temporary variable introduced by the front-end. *)
let exp_is_temp idenv e = let exp_is_temp idenv e =
match expand_expr idenv e with match expand_expr idenv e with
| Sil.Lvar pvar -> | Exp.Lvar pvar ->
Pvar.is_frontend_tmp pvar Pvar.is_frontend_tmp pvar
| _ -> false | _ -> false

@ -17,10 +17,10 @@ type t
val create : Cfg.Procdesc.t -> t val create : Cfg.Procdesc.t -> t
val create_from_idenv : t -> Cfg.Procdesc.t -> t val create_from_idenv : t -> Cfg.Procdesc.t -> t
val lookup : t -> Ident.t -> Sil.exp option val lookup : t -> Ident.t -> Exp.t option
val expand_expr : t -> Sil.exp -> Sil.exp val expand_expr : t -> Exp.t -> Exp.t
val exp_is_temp : t -> Sil.exp -> bool val exp_is_temp : t -> Exp.t -> bool
(** Stronger version of expand_expr which also expands a temporary variable. *) (** Stronger version of expand_expr which also expands a temporary variable. *)
val expand_expr_temps : t -> Cfg.Node.t -> Sil.exp -> Sil.exp val expand_expr_temps : t -> Cfg.Node.t -> Exp.t -> Exp.t

@ -178,8 +178,8 @@ let get_vararg_type_names
(* Is this the node creating ivar? *) (* Is this the node creating ivar? *)
let rec initializes_array instrs = let rec initializes_array instrs =
match instrs with match instrs with
| Sil.Call ([t1], Sil.Const (Const.Cfun pn), _, _, _):: | Sil.Call ([t1], Exp.Const (Const.Cfun pn), _, _, _)::
Sil.Set (Sil.Lvar iv, _, Sil.Var t2, _):: is -> Sil.Set (Exp.Lvar iv, _, Exp.Var t2, _):: is ->
(Pvar.equal ivar iv && Ident.equal t1 t2 && (Pvar.equal ivar iv && Ident.equal t1 t2 &&
Procname.equal pn (Procname.from_string_c_fun "__new_array")) Procname.equal pn (Procname.from_string_c_fun "__new_array"))
|| initializes_array is || initializes_array is
@ -190,7 +190,7 @@ let get_vararg_type_names
let added_type_name node = let added_type_name node =
let rec nvar_type_name nvar instrs = let rec nvar_type_name nvar instrs =
match instrs with match instrs with
| Sil.Letderef (nv, Sil.Lfield (_, id, t), _, _):: _ | Sil.Letderef (nv, Exp.Lfield (_, id, t), _, _):: _
when Ident.equal nv nvar -> get_field_type_name t id when Ident.equal nv nvar -> get_field_type_name t id
| Sil.Letderef (nv, _, t, _):: _ | Sil.Letderef (nv, _, t, _):: _
when Ident.equal nv nvar -> when Ident.equal nv nvar ->
@ -199,15 +199,15 @@ let get_vararg_type_names
| _ -> None in | _ -> None in
let rec added_nvar array_nvar instrs = let rec added_nvar array_nvar instrs =
match instrs with match instrs with
| Sil.Set (Sil.Lindex (Sil.Var iv, _), _, Sil.Var nvar, _):: _ | Sil.Set (Exp.Lindex (Exp.Var iv, _), _, Exp.Var nvar, _):: _
when Ident.equal iv array_nvar -> nvar_type_name nvar (Cfg.Node.get_instrs node) when Ident.equal iv array_nvar -> nvar_type_name nvar (Cfg.Node.get_instrs node)
| Sil.Set (Sil.Lindex (Sil.Var iv, _), _, Sil.Const c, _):: _ | Sil.Set (Exp.Lindex (Exp.Var iv, _), _, Exp.Const c, _):: _
when Ident.equal iv array_nvar -> Some (java_get_const_type_name c) when Ident.equal iv array_nvar -> Some (java_get_const_type_name c)
| _:: is -> added_nvar array_nvar is | _:: is -> added_nvar array_nvar is
| _ -> None in | _ -> None in
let rec array_nvar instrs = let rec array_nvar instrs =
match instrs with match instrs with
| Sil.Letderef (nv, Sil.Lvar iv, _, _):: _ | Sil.Letderef (nv, Exp.Lvar iv, _, _):: _
when Pvar.equal iv ivar -> when Pvar.equal iv ivar ->
added_nvar nv instrs added_nvar nv instrs
| _:: is -> array_nvar is | _:: is -> array_nvar is
@ -245,14 +245,14 @@ let is_setter pname_java =
(** Returns the signature of a field access (class name, field name, field type name) *) (** Returns the signature of a field access (class name, field name, field type name) *)
let get_java_field_access_signature = function let get_java_field_access_signature = function
| Sil.Letderef (_, Sil.Lfield (_, fn, ft), bt, _) -> | Sil.Letderef (_, Exp.Lfield (_, fn, ft), bt, _) ->
Some (get_type_name bt, Ident.java_fieldname_get_field fn, get_type_name ft) Some (get_type_name bt, Ident.java_fieldname_get_field fn, get_type_name ft)
| _ -> None | _ -> None
(** Returns the formal signature (class name, method name, (** Returns the formal signature (class name, method name,
argument type names and return type name) *) argument type names and return type name) *)
let get_java_method_call_formal_signature = function let get_java_method_call_formal_signature = function
| Sil.Call (_, Sil.Const (Const.Cfun pn), (_, tt):: args, _, _) -> | Sil.Call (_, Exp.Const (Const.Cfun pn), (_, tt):: args, _, _) ->
(match pn with (match pn with
| Procname.Java pn_java -> | Procname.Java pn_java ->
let arg_names = IList.map (function | _, t -> get_type_name t) args in let arg_names = IList.map (function | _, t -> get_type_name t) args in
@ -317,8 +317,8 @@ let method_is_initializer
let java_get_vararg_values node pvar idenv = let java_get_vararg_values node pvar idenv =
let values = ref [] in let values = ref [] in
let do_instr = function let do_instr = function
| Sil.Set (Sil.Lindex (array_exp, _), _, content_exp, _) | Sil.Set (Exp.Lindex (array_exp, _), _, content_exp, _)
when Sil.exp_equal (Sil.Lvar pvar) (Idenv.expand_expr idenv array_exp) -> when Sil.exp_equal (Exp.Lvar pvar) (Idenv.expand_expr idenv array_exp) ->
(* Each vararg argument is an assigment to a pvar denoting an array of objects. *) (* Each vararg argument is an assigment to a pvar denoting an array of objects. *)
values := content_exp :: !values values := content_exp :: !values
| _ -> () in | _ -> () in
@ -333,7 +333,7 @@ let java_get_vararg_values node pvar idenv =
let proc_calls resolve_attributes pdesc filter : (Procname.t * ProcAttributes.t) list = let proc_calls resolve_attributes pdesc filter : (Procname.t * ProcAttributes.t) list =
let res = ref [] in let res = ref [] in
let do_instruction _ instr = match instr with let do_instruction _ instr = match instr with
| Sil.Call (_, Sil.Const (Const.Cfun callee_pn), _, _, _) -> | Sil.Call (_, Exp.Const (Const.Cfun callee_pn), _, _, _) ->
begin begin
match resolve_attributes callee_pn with match resolve_attributes callee_pn with
| Some callee_attributes -> | Some callee_attributes ->
@ -387,7 +387,7 @@ let proc_iter_overridden_methods f tenv proc_name =
let get_fields_nullified procdesc = let get_fields_nullified procdesc =
(* walk through the instructions and look for instance fields that are assigned to null *) (* walk through the instructions and look for instance fields that are assigned to null *)
let collect_nullified_flds (nullified_flds, this_ids) _ = function let collect_nullified_flds (nullified_flds, this_ids) _ = function
| Sil.Set (Sil.Lfield (Sil.Var lhs, fld, _), _, rhs, _) | Sil.Set (Exp.Lfield (Exp.Var lhs, fld, _), _, rhs, _)
when Sil.exp_is_null_literal rhs && Ident.IdentSet.mem lhs this_ids -> when Sil.exp_is_null_literal rhs && Ident.IdentSet.mem lhs this_ids ->
(Ident.FieldSet.add fld nullified_flds, this_ids) (Ident.FieldSet.add fld nullified_flds, this_ids)
| Sil.Letderef (id, rhs, _, _) when Sil.exp_is_this rhs -> | Sil.Letderef (id, rhs, _, _) when Sil.exp_is_this rhs ->

@ -69,7 +69,7 @@ val strict_supertype_exists : Tenv.t -> (Typ.struct_typ -> bool) -> Typ.struct_t
val java_get_const_type_name : Const.t -> string val java_get_const_type_name : Const.t -> string
(** Get the values of a vararg parameter given the pvar used to assign the elements. *) (** Get the values of a vararg parameter given the pvar used to assign the elements. *)
val java_get_vararg_values : Cfg.Node.t -> Pvar.t -> Idenv.t -> Sil.exp list val java_get_vararg_values : Cfg.Node.t -> Pvar.t -> Idenv.t -> Exp.t list
val java_proc_name_with_class_method : Procname.java -> string -> string -> bool val java_proc_name_with_class_method : Procname.java -> string -> string -> bool

@ -85,10 +85,10 @@ let format_type_matches_given_type
(* The format string and the nvar for the fixed arguments and the nvar of the varargs array *) (* The format string and the nvar for the fixed arguments and the nvar of the varargs array *)
let format_arguments let format_arguments
(printf: printf_signature) (printf: printf_signature)
(args: (Sil.exp * Typ.t) list): (string option * (Sil.exp list) * (Sil.exp option)) = (args: (Exp.t * Typ.t) list): (string option * (Exp.t list) * (Exp.t option)) =
let format_string = match IList.nth args printf.format_pos with let format_string = match IList.nth args printf.format_pos with
| Sil.Const (Const.Cstr fmt), _ -> Some fmt | Exp.Const (Const.Cstr fmt), _ -> Some fmt
| _ -> None in | _ -> None in
let fixed_nvars = IList.map let fixed_nvars = IList.map
@ -158,24 +158,24 @@ let check_printf_args_ok
(* Get the array ivar for a given nvar *) (* Get the array ivar for a given nvar *)
let rec array_ivar instrs nvar = let rec array_ivar instrs nvar =
match instrs, nvar with match instrs, nvar with
| Sil.Letderef (id, Sil.Lvar iv, _, _):: _, Sil.Var nid | Sil.Letderef (id, Exp.Lvar iv, _, _):: _, Exp.Var nid
when Ident.equal id nid -> iv when Ident.equal id nid -> iv
| _:: is, _ -> array_ivar is nvar | _:: is, _ -> array_ivar is nvar
| _ -> raise Not_found in | _ -> raise Not_found in
let rec fixed_nvar_type_name instrs nvar = let rec fixed_nvar_type_name instrs nvar =
match nvar with match nvar with
| Sil.Var nid -> ( | Exp.Var nid -> (
match instrs with match instrs with
| Sil.Letderef (id, Sil.Lvar _, t, _):: _ | Sil.Letderef (id, Exp.Lvar _, t, _):: _
when Ident.equal id nid -> PatternMatch.get_type_name t when Ident.equal id nid -> PatternMatch.get_type_name t
| _:: is -> fixed_nvar_type_name is nvar | _:: is -> fixed_nvar_type_name is nvar
| _ -> raise Not_found) | _ -> raise Not_found)
| Sil.Const c -> PatternMatch.java_get_const_type_name c | Exp.Const c -> PatternMatch.java_get_const_type_name c
| _ -> raise (Failure "Could not resolve fixed type name") in | _ -> raise (Failure "Could not resolve fixed type name") in
match instr with match instr with
| Sil.Call (_, Sil.Const (Const.Cfun pn), args, cl, _) -> ( | Sil.Call (_, Exp.Const (Const.Cfun pn), args, cl, _) -> (
match printf_like_function pn with match printf_like_function pn with
| Some printf -> ( | Some printf -> (
try try

@ -73,7 +73,7 @@ struct
Procname.equal pn ModelBuiltins.__new_array in Procname.equal pn ModelBuiltins.__new_array in
let do_instr instr = let do_instr instr =
match instr with match instr with
| Sil.Call (_, Sil.Const (Const.Cfun pn), _, loc, _) when proc_is_new pn -> | Sil.Call (_, Exp.Const (Const.Cfun pn), _, loc, _) when proc_is_new pn ->
found := Some loc found := Some loc
| _ -> () in | _ -> () in
IList.iter do_instr (Cfg.Node.get_instrs node); IList.iter do_instr (Cfg.Node.get_instrs node);
@ -111,18 +111,18 @@ struct
(* Arguments are not temporary variables. *) (* Arguments are not temporary variables. *)
let arguments_not_temp args = let arguments_not_temp args =
let filter_arg (e, _) = match e with let filter_arg (e, _) = match e with
| Sil.Lvar pvar -> | Exp.Lvar pvar ->
(* same temporary variable does not imply same value *) (* same temporary variable does not imply same value *)
not (Pvar.is_frontend_tmp pvar) not (Pvar.is_frontend_tmp pvar)
| _ -> true in | _ -> true in
IList.for_all filter_arg args in IList.for_all filter_arg args in
match instr with match instr with
| Sil.Call (ret_ids, Sil.Const (Const.Cfun callee_pname), _, loc, call_flags) | Sil.Call (ret_ids, Exp.Const (Const.Cfun callee_pname), _, loc, call_flags)
when ret_ids <> [] && arguments_not_temp normalized_etl -> when ret_ids <> [] && arguments_not_temp normalized_etl ->
let instr_normalized_args = Sil.Call ( let instr_normalized_args = Sil.Call (
ret_ids, ret_ids,
Sil.Const (Const.Cfun callee_pname), Exp.Const (Const.Cfun callee_pname),
normalized_etl, normalized_etl,
loc, loc,
call_flags) in call_flags) in

@ -33,8 +33,8 @@ let callback_sql { Callbacks.proc_desc; proc_name; tenv } =
&& Procname.java_get_method pn_java = "append" && Procname.java_get_method pn_java = "append"
then then
begin begin
let rvar1 = Sil.Var i1 in let rvar1 = Exp.Var i1 in
let rvar2 = Sil.Var i2 in let rvar2 = Exp.Var i2 in
begin begin
let matches s r = Str.string_match r s 0 in let matches s r = Str.string_match r s 0 in
match const_map node rvar1, const_map node rvar2 with match const_map node rvar1, const_map node rvar2 with
@ -53,7 +53,7 @@ let callback_sql { Callbacks.proc_desc; proc_name; tenv } =
end in end in
match instr with match instr with
| Sil.Call (_, Sil.Const (Const.Cfun pn), (Sil.Var i1, _):: (Sil.Var i2, _):: [], l, _) -> | Sil.Call (_, Exp.Const (Const.Cfun pn), (Exp.Var i1, _):: (Exp.Var i2, _):: [], l, _) ->
begin begin
match pn with match pn with
| Procname.Java pn_java -> | Procname.Java pn_java ->

@ -22,8 +22,8 @@ let of_pvar pvar =
ProgramVar pvar ProgramVar pvar
let to_exp = function let to_exp = function
| ProgramVar pvar -> Sil.Lvar pvar | ProgramVar pvar -> Exp.Lvar pvar
| LogicalVar id -> Sil.Var id | LogicalVar id -> Exp.Var id
let compare v1 v2 = match v1, v2 with let compare v1 v2 = match v1, v2 with
| ProgramVar pv1, ProgramVar pv2 -> Pvar.compare pv1 pv2 | ProgramVar pv1, ProgramVar pv2 -> Pvar.compare pv1 pv2

@ -17,7 +17,7 @@ val of_id : Ident.t -> t
val of_pvar : Pvar.t -> t val of_pvar : Pvar.t -> t
val to_exp : t -> Sil.exp val to_exp : t -> Exp.t
val equal : t -> t -> bool val equal : t -> t -> bool

@ -26,7 +26,7 @@ let assignment_arc_mode e1 typ e2 loc rhs_owning_method is_e1_decl =
let release_pname = ModelBuiltins.__objc_release in let release_pname = ModelBuiltins.__objc_release in
let autorelease_pname = ModelBuiltins.__set_autorelease_attribute in let autorelease_pname = ModelBuiltins.__set_autorelease_attribute in
let mk_call procname e t = let mk_call procname e t =
let bi_retain = Sil.Const (Const.Cfun procname) in let bi_retain = Exp.Const (Const.Cfun procname) in
Sil.Call([], bi_retain, [(e, t)], loc, CallFlags.default) in Sil.Call([], bi_retain, [(e, t)], loc, CallFlags.default) in
match typ with match typ with
| Typ.Tptr (_, Typ.Pk_pointer) when not rhs_owning_method && not is_e1_decl -> | Typ.Tptr (_, Typ.Pk_pointer) when not rhs_owning_method && not is_e1_decl ->
@ -35,7 +35,7 @@ let assignment_arc_mode e1 typ e2 loc rhs_owning_method is_e1_decl =
let retain = mk_call retain_pname e2 typ in let retain = mk_call retain_pname e2 typ in
let id = Ident.create_fresh Ident.knormal in let id = Ident.create_fresh Ident.knormal in
let tmp_assign = Sil.Letderef(id, e1, typ, loc) in let tmp_assign = Sil.Letderef(id, e1, typ, loc) in
let release = mk_call release_pname (Sil.Var id) typ in let release = mk_call release_pname (Exp.Var id) typ in
(e1,[retain; tmp_assign; assign; release]) (e1,[retain; tmp_assign; assign; release])
| Typ.Tptr (_, Typ.Pk_pointer) when not rhs_owning_method && is_e1_decl -> | Typ.Tptr (_, Typ.Pk_pointer) when not rhs_owning_method && is_e1_decl ->
(* for A __strong *e1 = e2 the semantics is*) (* for A __strong *e1 = e2 the semantics is*)
@ -62,34 +62,34 @@ let compound_assignment_binary_operation_instruction boi e1 typ e2 loc =
let instr1 = Sil.Letderef (id, e1, typ, loc) in let instr1 = Sil.Letderef (id, e1, typ, loc) in
let e_res, instr_op = match boi.Clang_ast_t.boi_kind with let e_res, instr_op = match boi.Clang_ast_t.boi_kind with
| `AddAssign -> | `AddAssign ->
let e1_plus_e2 = Sil.BinOp(Binop.PlusA, Sil.Var id, e2) in let e1_plus_e2 = Exp.BinOp(Binop.PlusA, Exp.Var id, e2) in
(e1, [Sil.Set (e1, typ, e1_plus_e2, loc)]) (e1, [Sil.Set (e1, typ, e1_plus_e2, loc)])
| `SubAssign -> | `SubAssign ->
let e1_sub_e2 = Sil.BinOp(Binop.MinusA, Sil.Var id, e2) in let e1_sub_e2 = Exp.BinOp(Binop.MinusA, Exp.Var id, e2) in
(e1, [Sil.Set (e1, typ, e1_sub_e2, loc)]) (e1, [Sil.Set (e1, typ, e1_sub_e2, loc)])
| `MulAssign -> | `MulAssign ->
let e1_mul_e2 = Sil.BinOp(Binop.Mult, Sil.Var id, e2) in let e1_mul_e2 = Exp.BinOp(Binop.Mult, Exp.Var id, e2) in
(e1, [Sil.Set (e1, typ, e1_mul_e2, loc)]) (e1, [Sil.Set (e1, typ, e1_mul_e2, loc)])
| `DivAssign -> | `DivAssign ->
let e1_div_e2 = Sil.BinOp(Binop.Div, Sil.Var id, e2) in let e1_div_e2 = Exp.BinOp(Binop.Div, Exp.Var id, e2) in
(e1, [Sil.Set (e1, typ, e1_div_e2, loc)]) (e1, [Sil.Set (e1, typ, e1_div_e2, loc)])
| `ShlAssign -> | `ShlAssign ->
let e1_shl_e2 = Sil.BinOp(Binop.Shiftlt, Sil.Var id, e2) in let e1_shl_e2 = Exp.BinOp(Binop.Shiftlt, Exp.Var id, e2) in
(e1, [Sil.Set (e1, typ, e1_shl_e2, loc)]) (e1, [Sil.Set (e1, typ, e1_shl_e2, loc)])
| `ShrAssign -> | `ShrAssign ->
let e1_shr_e2 = Sil.BinOp(Binop.Shiftrt, Sil.Var id, e2) in let e1_shr_e2 = Exp.BinOp(Binop.Shiftrt, Exp.Var id, e2) in
(e1, [Sil.Set (e1, typ, e1_shr_e2, loc)]) (e1, [Sil.Set (e1, typ, e1_shr_e2, loc)])
| `RemAssign -> | `RemAssign ->
let e1_mod_e2 = Sil.BinOp(Binop.Mod, Sil.Var id, e2) in let e1_mod_e2 = Exp.BinOp(Binop.Mod, Exp.Var id, e2) in
(e1, [Sil.Set (e1, typ, e1_mod_e2, loc)]) (e1, [Sil.Set (e1, typ, e1_mod_e2, loc)])
| `AndAssign -> | `AndAssign ->
let e1_and_e2 = Sil.BinOp(Binop.BAnd, Sil.Var id, e2) in let e1_and_e2 = Exp.BinOp(Binop.BAnd, Exp.Var id, e2) in
(e1, [Sil.Set (e1, typ, e1_and_e2, loc)]) (e1, [Sil.Set (e1, typ, e1_and_e2, loc)])
| `OrAssign -> | `OrAssign ->
let e1_or_e2 = Sil.BinOp(Binop.BOr, Sil.Var id, e2) in let e1_or_e2 = Exp.BinOp(Binop.BOr, Exp.Var id, e2) in
(e1, [Sil.Set (e1, typ, e1_or_e2, loc)]) (e1, [Sil.Set (e1, typ, e1_or_e2, loc)])
| `XorAssign -> | `XorAssign ->
let e1_xor_e2 = Sil.BinOp(Binop.BXor, Sil.Var id, e2) in let e1_xor_e2 = Exp.BinOp(Binop.BXor, Exp.Var id, e2) in
(e1, [Sil.Set (e1, typ, e1_xor_e2, loc)]) (e1, [Sil.Set (e1, typ, e1_xor_e2, loc)])
| _ -> assert false in | _ -> assert false in
(e_res, instr1:: instr_op) (e_res, instr1:: instr_op)
@ -99,7 +99,7 @@ let compound_assignment_binary_operation_instruction boi e1 typ e2 loc =
(* empty when the binary operator is actually a statement like an *) (* empty when the binary operator is actually a statement like an *)
(* assignment. *) (* assignment. *)
let binary_operation_instruction context boi e1 typ e2 loc rhs_owning_method = let binary_operation_instruction context boi e1 typ e2 loc rhs_owning_method =
let binop_exp op = Sil.BinOp(op, e1, e2) in let binop_exp op = Exp.BinOp(op, e1, e2) in
match boi.Clang_ast_t.boi_kind with match boi.Clang_ast_t.boi_kind with
| `Add -> (binop_exp (Binop.PlusA), []) | `Add -> (binop_exp (Binop.PlusA), [])
| `Mul -> (binop_exp (Binop.Mult), []) | `Mul -> (binop_exp (Binop.Mult), [])
@ -139,17 +139,17 @@ let binary_operation_instruction context boi e1 typ e2 loc rhs_owning_method =
let unary_operation_instruction uoi e typ loc = let unary_operation_instruction uoi e typ loc =
let uok = Clang_ast_j.string_of_unary_operator_kind (uoi.Clang_ast_t.uoi_kind) in let uok = Clang_ast_j.string_of_unary_operator_kind (uoi.Clang_ast_t.uoi_kind) in
let un_exp op = let un_exp op =
Sil.UnOp(op, e, Some typ) in Exp.UnOp(op, e, Some typ) in
match uoi.Clang_ast_t.uoi_kind with match uoi.Clang_ast_t.uoi_kind with
| `PostInc -> | `PostInc ->
let id = Ident.create_fresh Ident.knormal in let id = Ident.create_fresh Ident.knormal in
let instr1 = Sil.Letderef (id, e, typ, loc) in let instr1 = Sil.Letderef (id, e, typ, loc) in
let e_plus_1 = Sil.BinOp(Binop.PlusA, Sil.Var id, Sil.Const(Const.Cint (IntLit.one))) in let e_plus_1 = Exp.BinOp(Binop.PlusA, Exp.Var id, Exp.Const(Const.Cint (IntLit.one))) in
(Sil.Var id, instr1::[Sil.Set (e, typ, e_plus_1, loc)]) (Exp.Var id, instr1::[Sil.Set (e, typ, e_plus_1, loc)])
| `PreInc -> | `PreInc ->
let id = Ident.create_fresh Ident.knormal in let id = Ident.create_fresh Ident.knormal in
let instr1 = Sil.Letderef (id, e, typ, loc) in let instr1 = Sil.Letderef (id, e, typ, loc) in
let e_plus_1 = Sil.BinOp(Binop.PlusA, Sil.Var id, Sil.Const(Const.Cint (IntLit.one))) in let e_plus_1 = Exp.BinOp(Binop.PlusA, Exp.Var id, Exp.Const(Const.Cint (IntLit.one))) in
let exp = if General_utils.is_cpp_translation Config.clang_lang then let exp = if General_utils.is_cpp_translation Config.clang_lang then
e e
else else
@ -158,12 +158,12 @@ let unary_operation_instruction uoi e typ loc =
| `PostDec -> | `PostDec ->
let id = Ident.create_fresh Ident.knormal in let id = Ident.create_fresh Ident.knormal in
let instr1 = Sil.Letderef (id, e, typ, loc) in let instr1 = Sil.Letderef (id, e, typ, loc) in
let e_minus_1 = Sil.BinOp(Binop.MinusA, Sil.Var id, Sil.Const(Const.Cint (IntLit.one))) in let e_minus_1 = Exp.BinOp(Binop.MinusA, Exp.Var id, Exp.Const(Const.Cint (IntLit.one))) in
(Sil.Var id, instr1::[Sil.Set (e, typ, e_minus_1, loc)]) (Exp.Var id, instr1::[Sil.Set (e, typ, e_minus_1, loc)])
| `PreDec -> | `PreDec ->
let id = Ident.create_fresh Ident.knormal in let id = Ident.create_fresh Ident.knormal in
let instr1 = Sil.Letderef (id, e, typ, loc) in let instr1 = Sil.Letderef (id, e, typ, loc) in
let e_minus_1 = Sil.BinOp(Binop.MinusA, Sil.Var id, Sil.Const(Const.Cint (IntLit.one))) in let e_minus_1 = Exp.BinOp(Binop.MinusA, Exp.Var id, Exp.Const(Const.Cint (IntLit.one))) in
let exp = if General_utils.is_cpp_translation Config.clang_lang then let exp = if General_utils.is_cpp_translation Config.clang_lang then
e e
else else
@ -219,6 +219,6 @@ let bin_op_to_string boi =
let sil_const_plus_one const = let sil_const_plus_one const =
match const with match const with
| Sil.Const (Const.Cint n) -> | Exp.Const (Const.Cint n) ->
Sil.Const (Const.Cint (IntLit.add n IntLit.one)) Exp.Const (Const.Cint (IntLit.add n IntLit.one))
| _ -> Sil.BinOp (Binop.PlusA, const, Sil.Const (Const.Cint (IntLit.one))) | _ -> Exp.BinOp (Binop.PlusA, const, Exp.Const (Const.Cint (IntLit.one)))

@ -14,13 +14,13 @@ open! Utils
val bin_op_to_string : Clang_ast_t.binary_operator_info -> string val bin_op_to_string : Clang_ast_t.binary_operator_info -> string
val binary_operation_instruction : val binary_operation_instruction :
CContext.t -> Clang_ast_t.binary_operator_info -> Sil.exp -> Typ.t -> Sil.exp -> CContext.t -> Clang_ast_t.binary_operator_info -> Exp.t -> Typ.t -> Exp.t ->
Location.t -> bool -> Sil.exp * Sil.instr list Location.t -> bool -> Exp.t * Sil.instr list
val unary_operation_instruction : val unary_operation_instruction :
Clang_ast_t.unary_operator_info -> Sil.exp -> Typ.t -> Location.t -> Sil.exp * Sil.instr list Clang_ast_t.unary_operator_info -> Exp.t -> Typ.t -> Location.t -> Exp.t * Sil.instr list
val assignment_arc_mode : val assignment_arc_mode :
Sil.exp -> Typ.t -> Sil.exp -> Location.t -> bool -> bool -> Sil.exp * Sil.instr list Exp.t -> Typ.t -> Exp.t -> Location.t -> bool -> bool -> Exp.t * Sil.instr list
val sil_const_plus_one : Sil.exp -> Sil.exp val sil_const_plus_one : Exp.t -> Exp.t

@ -76,7 +76,7 @@ val void : string
(** Global state *) (** Global state *)
(** Map from enum constants pointers to their predecesor and their sil value *) (** Map from enum constants pointers to their predecesor and their sil value *)
val enum_map : (Clang_ast_t.pointer option * Sil.exp option) Clang_ast_main.PointerMap.t ref val enum_map : (Clang_ast_t.pointer option * Exp.t option) Clang_ast_main.PointerMap.t ref
val global_translation_unit_decls : Clang_ast_t.decl list ref val global_translation_unit_decls : Clang_ast_t.decl list ref
val ivar_to_property_index : Clang_ast_t.decl Clang_ast_main.PointerMap.t ref val ivar_to_property_index : Clang_ast_t.decl Clang_ast_main.PointerMap.t ref
val json : string ref val json : string ref

@ -90,11 +90,11 @@ sig
val update_sil_types_map : Clang_ast_t.type_ptr -> Typ.t -> unit val update_sil_types_map : Clang_ast_t.type_ptr -> Typ.t -> unit
val update_enum_map : Clang_ast_t.pointer -> Sil.exp -> unit val update_enum_map : Clang_ast_t.pointer -> Exp.t -> unit
val add_enum_constant : Clang_ast_t.pointer -> Clang_ast_t.pointer option -> unit val add_enum_constant : Clang_ast_t.pointer -> Clang_ast_t.pointer option -> unit
val get_enum_constant_exp : Clang_ast_t.pointer -> Clang_ast_t.pointer option * Sil.exp option val get_enum_constant_exp : Clang_ast_t.pointer -> Clang_ast_t.pointer option * Exp.t option
(** returns sanitized, fully qualified name given name info *) (** returns sanitized, fully qualified name given name info *)
val get_qualified_name : Clang_ast_t.named_decl_info -> string val get_qualified_name : Clang_ast_t.named_decl_info -> string
@ -182,7 +182,7 @@ sig
(Mangled.t * Typ.t) list -> (Mangled.t * Typ.t) list -> (Mangled.t * Typ.t) list (Mangled.t * Typ.t) list -> (Mangled.t * Typ.t) list -> (Mangled.t * Typ.t) list
val append_no_duplicateds : val append_no_duplicateds :
(Sil.exp * Typ.t) list -> (Sil.exp * Typ.t) list -> (Sil.exp * Typ.t) list (Exp.t * Typ.t) list -> (Exp.t * Typ.t) list -> (Exp.t * Typ.t) list
val sort_fields : val sort_fields :
(Ident.fieldname * Typ.t * Typ.item_annotation) list -> (Ident.fieldname * Typ.t * Typ.item_annotation) list ->

@ -32,7 +32,7 @@ val get_objc_method_data : Clang_ast_t.obj_c_message_expr_info ->
(string * Clang_ast_t.pointer option * method_call_type) (string * Clang_ast_t.pointer option * method_call_type)
val get_class_name_method_call_from_receiver_kind : CContext.t -> val get_class_name_method_call_from_receiver_kind : CContext.t ->
Clang_ast_t.obj_c_message_expr_info -> (Sil.exp * Typ.t) list -> string Clang_ast_t.obj_c_message_expr_info -> (Exp.t * Typ.t) list -> string
val get_class_name_method_call_from_clang : Tenv.t -> Clang_ast_t.obj_c_message_expr_info -> val get_class_name_method_call_from_clang : Tenv.t -> Clang_ast_t.obj_c_message_expr_info ->
string option string option

@ -85,7 +85,7 @@ struct
let ret_id = Ident.create_fresh Ident.knormal in let ret_id = Ident.create_fresh Ident.knormal in
let stmt_call = let stmt_call =
Sil.Call Sil.Call
([ret_id], Sil.Const (Const.Cfun fname), [(exp, typ)], sil_loc, CallFlags.default) in ([ret_id], Exp.Const (Const.Cfun fname), [(exp, typ)], sil_loc, CallFlags.default) in
[stmt_call] [stmt_call]
else [] else []
@ -142,19 +142,19 @@ struct
CTrans_utils.alloc_trans CTrans_utils.alloc_trans
trans_state loc (Ast_expressions.dummy_stmt_info ()) block_type true None in trans_state loc (Ast_expressions.dummy_stmt_info ()) block_type true None in
let id_block = match trans_res.exps with let id_block = match trans_res.exps with
| [(Sil.Var id, _)] -> id | [(Exp.Var id, _)] -> id
| _ -> assert false in | _ -> assert false in
let block_var = Pvar.mk mblock procname in let block_var = Pvar.mk mblock procname in
let declare_block_local = let declare_block_local =
Sil.Declare_locals ([(block_var, Typ.Tptr (block_type, Typ.Pk_pointer))], loc) in Sil.Declare_locals ([(block_var, Typ.Tptr (block_type, Typ.Pk_pointer))], loc) in
let set_instr = Sil.Set (Sil.Lvar block_var, block_type, Sil.Var id_block, loc) in let set_instr = Sil.Set (Exp.Lvar block_var, block_type, Exp.Var id_block, loc) in
let create_field_exp (var, typ) = let create_field_exp (var, typ) =
let id = Ident.create_fresh Ident.knormal in let id = Ident.create_fresh Ident.knormal in
id, Sil.Letderef (id, Sil.Lvar var, typ, loc) in id, Sil.Letderef (id, Exp.Lvar var, typ, loc) in
let ids, captured_instrs = IList.split (IList.map create_field_exp captured_vars) in let ids, captured_instrs = IList.split (IList.map create_field_exp captured_vars) in
let fields_ids = IList.combine fields ids in let fields_ids = IList.combine fields ids in
let set_fields = IList.map (fun ((f, t, _), id) -> let set_fields = IList.map (fun ((f, t, _), id) ->
Sil.Set (Sil.Lfield (Sil.Var id_block, f, block_type), t, Sil.Var id, loc)) fields_ids in Sil.Set (Exp.Lfield (Exp.Var id_block, f, block_type), t, Exp.Var id, loc)) fields_ids in
(declare_block_local :: trans_res.instrs) @ (declare_block_local :: trans_res.instrs) @
[set_instr] @ [set_instr] @
captured_instrs @ captured_instrs @
@ -167,15 +167,15 @@ struct
let make_function_name typ bn = let make_function_name typ bn =
let bn'= Procname.to_string bn in let bn'= Procname.to_string bn in
let bn''= Mangled.from_string bn' in let bn''= Mangled.from_string bn' in
let block = Sil.Lvar (Pvar.mk bn'' procname) in let block = Exp.Lvar (Pvar.mk bn'' procname) in
let id = Ident.create_fresh Ident.knormal in let id = Ident.create_fresh Ident.knormal in
insts := Sil.Letderef (id, block, typ, loc) :: !insts; insts := Sil.Letderef (id, block, typ, loc) :: !insts;
(Sil.Var id, typ) in (Exp.Var id, typ) in
let make_arg typ (id, _, _) = (id, typ) in let make_arg typ (id, _, _) = (id, typ) in
let rec f es = let rec f es =
match es with match es with
| [] -> [] | [] -> []
| (Sil.Closure {name; captured_vars}, | (Exp.Closure {name; captured_vars},
(Typ.Tptr((Typ.Tfun _), _ ) as t)) :: es' -> (Typ.Tptr((Typ.Tfun _), _ ) as t)) :: es' ->
let app = let app =
let function_name = make_function_name t name in let function_name = make_function_name t name in
@ -215,7 +215,7 @@ struct
CTypes_decl.objc_class_name_to_sil_type trans_state.context.CContext.tenv class_name in CTypes_decl.objc_class_name_to_sil_type trans_state.context.CContext.tenv class_name in
let expanded_type = CTypes.expand_structured_type trans_state.context.CContext.tenv typ in let expanded_type = CTypes.expand_structured_type trans_state.context.CContext.tenv typ in
{ empty_res_trans with { empty_res_trans with
exps = [(Sil.Sizeof(expanded_type, None, Subtype.exact), Typ.Tint Typ.IULong)] } exps = [(Exp.Sizeof(expanded_type, None, Subtype.exact), Typ.Tint Typ.IULong)] }
let add_reference_if_glvalue typ expr_info = let add_reference_if_glvalue typ expr_info =
(* glvalue definition per C++11:*) (* glvalue definition per C++11:*)
@ -276,7 +276,7 @@ struct
let (pvar, typ) = mk_temp_sil_var_for_expr context.CContext.tenv procdesc let (pvar, typ) = mk_temp_sil_var_for_expr context.CContext.tenv procdesc
var_name expr_info in var_name expr_info in
Cfg.Procdesc.append_locals procdesc [(Pvar.get_name pvar, typ)]; Cfg.Procdesc.append_locals procdesc [(Pvar.get_name pvar, typ)];
Sil.Lvar pvar, typ Exp.Lvar pvar, typ
let create_call_instr trans_state return_type function_sil params_sil sil_loc let create_call_instr trans_state return_type function_sil params_sil sil_loc
call_flags ~is_objc_method = call_flags ~is_objc_method =
@ -292,7 +292,7 @@ struct
let procdesc = trans_state.context.CContext.procdesc in let procdesc = trans_state.context.CContext.procdesc in
let pvar = mk_temp_sil_var procdesc "__temp_return_" in let pvar = mk_temp_sil_var procdesc "__temp_return_" in
Cfg.Procdesc.append_locals procdesc [(Pvar.get_name pvar, return_type)]; Cfg.Procdesc.append_locals procdesc [(Pvar.get_name pvar, return_type)];
Sil.Lvar pvar in Exp.Lvar pvar in
(* It is very confusing - same expression has two different types in two contexts:*) (* It is very confusing - same expression has two different types in two contexts:*)
(* 1. if passed as parameter it's RETURN_TYPE* since we are passing it as rvalue *) (* 1. if passed as parameter it's RETURN_TYPE* since we are passing it as rvalue *)
(* 2. for return expression it's RETURN_TYPE since backend allows to treat it as lvalue*) (* 2. for return expression it's RETURN_TYPE since backend allows to treat it as lvalue*)
@ -310,7 +310,7 @@ struct
let ret_param = (var_exp, param_type) in let ret_param = (var_exp, param_type) in
let ret_exp = (var_exp, return_type) in let ret_exp = (var_exp, return_type) in
[], params_sil @ [ret_param], [var_exp], [ret_exp] [], params_sil @ [ret_param], [var_exp], [ret_exp]
else ret_id, params_sil, [], match ret_id with [x] -> [(Sil.Var x, return_type)] | _ -> [] in else ret_id, params_sil, [], match ret_id with [x] -> [(Exp.Var x, return_type)] | _ -> [] in
let call_instr = Sil.Call (ret_id', function_sil, params, sil_loc, call_flags) in let call_instr = Sil.Call (ret_id', function_sil, params, sil_loc, call_flags) in
{ empty_res_trans with { empty_res_trans with
instrs = [call_instr]; instrs = [call_instr];
@ -329,7 +329,7 @@ struct
let stringLiteral_trans trans_state expr_info str = let stringLiteral_trans trans_state expr_info str =
let typ = CTypes_decl.get_type_from_expr_info expr_info trans_state.context.CContext.tenv in let typ = CTypes_decl.get_type_from_expr_info expr_info trans_state.context.CContext.tenv in
let exp = Sil.Const (Const.Cstr (str)) in let exp = Exp.Const (Const.Cstr (str)) in
{ empty_res_trans with exps = [(exp, typ)]} { empty_res_trans with exps = [(exp, typ)]}
(* FROM CLANG DOCS: "Implements the GNU __null extension, (* FROM CLANG DOCS: "Implements the GNU __null extension,
@ -342,7 +342,7 @@ struct
So we implement it as the constant zero *) So we implement it as the constant zero *)
let gNUNullExpr_trans trans_state expr_info = let gNUNullExpr_trans trans_state expr_info =
let typ = CTypes_decl.get_type_from_expr_info expr_info trans_state.context.CContext.tenv in let typ = CTypes_decl.get_type_from_expr_info expr_info trans_state.context.CContext.tenv in
let exp = Sil.Const (Const.Cint (IntLit.zero)) in let exp = Exp.Const (Const.Cint (IntLit.zero)) in
{ empty_res_trans with exps = [(exp, typ)]} { empty_res_trans with exps = [(exp, typ)]}
let nullPtrExpr_trans trans_state expr_info = let nullPtrExpr_trans trans_state expr_info =
@ -363,7 +363,7 @@ struct
let characterLiteral_trans trans_state expr_info n = let characterLiteral_trans trans_state expr_info n =
let typ = CTypes_decl.get_type_from_expr_info expr_info trans_state.context.CContext.tenv in let typ = CTypes_decl.get_type_from_expr_info expr_info trans_state.context.CContext.tenv in
let exp = Sil.Const (Const.Cint (IntLit.of_int n)) in let exp = Exp.Const (Const.Cint (IntLit.of_int n)) in
{ empty_res_trans with exps = [(exp, typ)]} { empty_res_trans with exps = [(exp, typ)]}
let booleanValue_trans trans_state expr_info b = let booleanValue_trans trans_state expr_info b =
@ -371,7 +371,7 @@ struct
let floatingLiteral_trans trans_state expr_info float_string = let floatingLiteral_trans trans_state expr_info float_string =
let typ = CTypes_decl.get_type_from_expr_info expr_info trans_state.context.CContext.tenv in let typ = CTypes_decl.get_type_from_expr_info expr_info trans_state.context.CContext.tenv in
let exp = Sil.Const (Const.Cfloat (float_of_string float_string)) in let exp = Exp.Const (Const.Cfloat (float_of_string float_string)) in
{ empty_res_trans with exps = [(exp, typ)]} { empty_res_trans with exps = [(exp, typ)]}
(* Note currently we don't have support for different qual *) (* Note currently we don't have support for different qual *)
@ -387,7 +387,7 @@ struct
| Failure _ -> | Failure _ ->
(* Parse error: return a nondeterministic value *) (* Parse error: return a nondeterministic value *)
let id = Ident.create_fresh Ident.knormal in let id = Ident.create_fresh Ident.knormal in
Sil.Var id in Exp.Var id in
{ empty_res_trans with { empty_res_trans with
exps = [(exp, typ)]; exps = [(exp, typ)];
} }
@ -398,7 +398,7 @@ struct
let zero_opt = match typ with let zero_opt = match typ with
| Typ.Tfloat _ | Typ.Tptr _ | Typ.Tint _ -> Some (Sil.zero_value_of_numerical_type typ) | Typ.Tfloat _ | Typ.Tptr _ | Typ.Tint _ -> Some (Sil.zero_value_of_numerical_type typ)
| Typ.Tvoid -> None | Typ.Tvoid -> None
| _ -> Some (Sil.Const (Const.Cint IntLit.zero)) in | _ -> Some (Exp.Const (Const.Cint IntLit.zero)) in
match zero_opt with match zero_opt with
| Some zero -> { empty_res_trans with exps = [(zero, typ)] } | Some zero -> { empty_res_trans with exps = [(zero, typ)] }
| _ -> empty_res_trans | _ -> empty_res_trans
@ -427,7 +427,7 @@ struct
| Some tp -> CTypes_decl.type_ptr_to_sil_type tenv tp | Some tp -> CTypes_decl.type_ptr_to_sil_type tenv tp
| None -> typ (* Some default type since the type is missing *) in | None -> typ (* Some default type since the type is missing *) in
{ empty_res_trans with { empty_res_trans with
exps = [(Sil.Sizeof (sizeof_typ, None, Subtype.exact), sizeof_typ)] } exps = [(Exp.Sizeof (sizeof_typ, None, Subtype.exact), sizeof_typ)] }
| k -> Printing.log_stats | k -> Printing.log_stats
"\nWARNING: Missing translation of Uniry_Expression_Or_Trait of kind: \ "\nWARNING: Missing translation of Uniry_Expression_Or_Trait of kind: \
%s . Expression ignored, returned -1... \n" %s . Expression ignored, returned -1... \n"
@ -465,11 +465,11 @@ struct
else Procname.from_string_c_fun name in else Procname.from_string_c_fun name in
let is_builtin = Builtin.is_registered non_mangled_func_name in let is_builtin = Builtin.is_registered non_mangled_func_name in
if is_builtin then (* malloc, free, exit, scanf, ... *) if is_builtin then (* malloc, free, exit, scanf, ... *)
{ empty_res_trans with exps = [(Sil.Const (Const.Cfun non_mangled_func_name), typ)] } { empty_res_trans with exps = [(Exp.Const (Const.Cfun non_mangled_func_name), typ)] }
else else
begin begin
if address_of_function then Cfg.set_procname_priority context.cfg pname; if address_of_function then Cfg.set_procname_priority context.cfg pname;
{ empty_res_trans with exps = [(Sil.Const (Const.Cfun pname), typ)] } { empty_res_trans with exps = [(Exp.Const (Const.Cfun pname), typ)] }
end end
let var_deref_trans trans_state stmt_info decl_ref = let var_deref_trans trans_state stmt_info decl_ref =
@ -487,7 +487,7 @@ struct
let sil_loc = CLocation.get_sil_location stmt_info context in let sil_loc = CLocation.get_sil_location stmt_info context in
let pvar = CVar_decl.sil_var_of_decl_ref context decl_ref procname in let pvar = CVar_decl.sil_var_of_decl_ref context decl_ref procname in
CContext.add_block_static_var context procname (pvar, typ); CContext.add_block_static_var context procname (pvar, typ);
let e = Sil.Lvar pvar in let e = Exp.Lvar pvar in
let exps = if Self.is_var_self pvar (CContext.is_objc_method context) then let exps = if Self.is_var_self pvar (CContext.is_objc_method context) then
let curr_class = CContext.get_curr_class context in let curr_class = CContext.get_curr_class context in
if (CTypes.is_class typ) then if (CTypes.is_class typ) then
@ -523,7 +523,7 @@ struct
| t -> t in | t -> t in
Printing.log_out "Type is '%s' @." (Typ.to_string class_typ); Printing.log_out "Type is '%s' @." (Typ.to_string class_typ);
let field_name = General_utils.mk_class_field_name name_info in let field_name = General_utils.mk_class_field_name name_info in
let field_exp = Sil.Lfield (obj_sil, field_name, class_typ) in let field_exp = Exp.Lfield (obj_sil, field_name, class_typ) in
(* In certain cases, there is be no LValueToRValue cast, but backend needs dereference*) (* In certain cases, there is be no LValueToRValue cast, but backend needs dereference*)
(* there either way:*) (* there either way:*)
(* 1. Class is not a pointer type - it means that it's rvalue struct most likely coming from*) (* 1. Class is not a pointer type - it means that it's rvalue struct most likely coming from*)
@ -536,7 +536,7 @@ struct
let exp, deref_instrs = if should_add_deref then let exp, deref_instrs = if should_add_deref then
let id = Ident.create_fresh Ident.knormal in let id = Ident.create_fresh Ident.knormal in
let deref_instr = Sil.Letderef (id, field_exp, field_typ, sil_loc) in let deref_instr = Sil.Letderef (id, field_exp, field_typ, sil_loc) in
Sil.Var id, [deref_instr] Exp.Var id, [deref_instr]
else else
field_exp, [] in field_exp, [] in
let instrs = pre_trans_result.instrs @ deref_instrs in let instrs = pre_trans_result.instrs @ deref_instrs in
@ -586,7 +586,7 @@ struct
(* unlike field access, for method calls there is no need to expand class type *) (* unlike field access, for method calls there is no need to expand class type *)
let pname = CMethod_trans.create_procdesc_with_pointer context decl_ptr (Some class_name) let pname = CMethod_trans.create_procdesc_with_pointer context decl_ptr (Some class_name)
method_name in method_name in
let method_exp = (Sil.Const (Const.Cfun pname), method_typ) in let method_exp = (Exp.Const (Const.Cfun pname), method_typ) in
Cfg.set_procname_priority context.CContext.cfg pname; Cfg.set_procname_priority context.CContext.cfg pname;
{ pre_trans_result with { pre_trans_result with
is_cpp_call_virtual = is_cpp_virtual; is_cpp_call_virtual = is_cpp_virtual;
@ -610,7 +610,7 @@ struct
let procname = Cfg.Procdesc.get_proc_name context.CContext.procdesc in let procname = Cfg.Procdesc.get_proc_name context.CContext.procdesc in
let name = CFrontend_config.this in let name = CFrontend_config.this in
let pvar = Pvar.mk (Mangled.from_string name) procname in let pvar = Pvar.mk (Mangled.from_string name) procname in
let exp = Sil.Lvar pvar in let exp = Exp.Lvar pvar in
let typ = CTypes_decl.type_ptr_to_sil_type context.CContext.tenv class_type_ptr in let typ = CTypes_decl.type_ptr_to_sil_type context.CContext.tenv class_type_ptr in
let exps = [(exp, typ)] in let exps = [(exp, typ)] in
(* there is no cast operation in AST, but backend needs it *) (* there is no cast operation in AST, but backend needs it *)
@ -678,7 +678,7 @@ struct
(* get the sil value of the enum constant from the map or by evaluating it *) (* get the sil value of the enum constant from the map or by evaluating it *)
and get_enum_constant_expr context enum_constant_pointer = and get_enum_constant_expr context enum_constant_pointer =
let zero = Sil.Const (Const.Cint IntLit.zero) in let zero = Exp.Const (Const.Cint IntLit.zero) in
try try
let (prev_enum_constant_opt, sil_exp_opt) = let (prev_enum_constant_opt, sil_exp_opt) =
Ast_utils.get_enum_constant_exp enum_constant_pointer in Ast_utils.get_enum_constant_exp enum_constant_pointer in
@ -709,7 +709,7 @@ struct
"WARNING: In ArraySubscriptExpr there was a problem in translating array exp.\n" in "WARNING: In ArraySubscriptExpr there was a problem in translating array exp.\n" in
let (i_exp, _) = extract_exp_from_list res_trans_idx.exps let (i_exp, _) = extract_exp_from_list res_trans_idx.exps
"WARNING: In ArraySubscriptExpr there was a problem in translating index exp.\n" in "WARNING: In ArraySubscriptExpr there was a problem in translating index exp.\n" in
let array_exp = Sil.Lindex (a_exp, i_exp) in let array_exp = Exp.Lindex (a_exp, i_exp) in
let root_nodes = let root_nodes =
if res_trans_a.root_nodes <> [] if res_trans_a.root_nodes <> []
@ -788,7 +788,7 @@ struct
(* As no node is created here ids are passed to the parent *) (* As no node is created here ids are passed to the parent *)
let id = Ident.create_fresh Ident.knormal in let id = Ident.create_fresh Ident.knormal in
let res_instr = Sil.Letderef (id, var_exp, var_exp_typ, sil_loc) in let res_instr = Sil.Letderef (id, var_exp, var_exp_typ, sil_loc) in
[res_instr], Sil.Var id [res_instr], Exp.Var id
) else ( ) else (
[], exp_op) in [], exp_op) in
let binop_res_trans = { empty_res_trans with let binop_res_trans = { empty_res_trans with
@ -821,7 +821,7 @@ struct
Returning -1. NEED TO BE FIXED" in Returning -1. NEED TO BE FIXED" in
let callee_pname_opt = let callee_pname_opt =
match sil_fe with match sil_fe with
| Sil.Const (Const.Cfun pn) -> | Exp.Const (Const.Cfun pn) ->
Some pn Some pn
| _ -> None (* function pointer *) in | _ -> None (* function pointer *) in
(* we cannot translate the arguments of __builtin_object_size because preprocessing copies (* we cannot translate the arguments of __builtin_object_size because preprocessing copies
@ -854,10 +854,10 @@ struct
NEED TO BE FIXED\n\n"; NEED TO BE FIXED\n\n";
fix_param_exps_mismatch params_stmt params) in fix_param_exps_mismatch params_stmt params) in
let act_params = if is_cf_retain_release then let act_params = if is_cf_retain_release then
(Sil.Const (Const.Cint IntLit.one), Typ.Tint Typ.IBool) :: act_params (Exp.Const (Const.Cint IntLit.one), Typ.Tint Typ.IBool) :: act_params
else act_params in else act_params in
let sil_fe' = match callee_pname_opt' with let sil_fe' = match callee_pname_opt' with
| Some pn -> Sil.Const (Const.Cfun pn) | Some pn -> Exp.Const (Const.Cfun pn)
| _ -> sil_fe in | _ -> sil_fe in
let res_trans_call = let res_trans_call =
let cast_trans_fun = cast_trans context act_params sil_loc function_type in let cast_trans_fun = cast_trans context act_params sil_loc function_type in
@ -894,7 +894,7 @@ struct
let (sil_method, _) = IList.hd result_trans_callee.exps in let (sil_method, _) = IList.hd result_trans_callee.exps in
let callee_pname = let callee_pname =
match sil_method with match sil_method with
| Sil.Const (Const.Cfun pn) -> pn | Exp.Const (Const.Cfun pn) -> pn
| _ -> assert false (* method pointer not implemented, this shouldn't happen *) in | _ -> assert false (* method pointer not implemented, this shouldn't happen *) in
(* As we may have nodes coming from different parameters we need to *) (* As we may have nodes coming from different parameters we need to *)
(* call instruction for each parameter and collect the results *) (* call instruction for each parameter and collect the results *)
@ -954,7 +954,7 @@ struct
let pvar = Pvar.mk_tmp "__temp_construct_" (Cfg.Procdesc.get_proc_name procdesc) in let pvar = Pvar.mk_tmp "__temp_construct_" (Cfg.Procdesc.get_proc_name procdesc) in
let class_type = CTypes_decl.get_type_from_expr_info ei context.CContext.tenv in let class_type = CTypes_decl.get_type_from_expr_info ei context.CContext.tenv in
Cfg.Procdesc.append_locals procdesc [(Pvar.get_name pvar, class_type)]; Cfg.Procdesc.append_locals procdesc [(Pvar.get_name pvar, class_type)];
Sil.Lvar pvar, class_type in Exp.Lvar pvar, class_type in
let this_type = Typ.Tptr (class_type, Typ.Pk_pointer) in let this_type = Typ.Tptr (class_type, Typ.Pk_pointer) in
let this_res_trans = { empty_res_trans with let this_res_trans = { empty_res_trans with
exps = [(var_exp, this_type)]; exps = [(var_exp, this_type)];
@ -1053,7 +1053,7 @@ struct
instrs = instr_block_param; instrs = instr_block_param;
} in } in
let call_flags = { CallFlags.default with CallFlags.cf_virtual = is_virtual; } in let call_flags = { CallFlags.default with CallFlags.cf_virtual = is_virtual; } in
let method_sil = Sil.Const (Const.Cfun callee_name) in let method_sil = Exp.Const (Const.Cfun callee_name) in
let res_trans_call = create_call_instr trans_state method_type method_sil param_exps let res_trans_call = create_call_instr trans_state method_type method_sil param_exps
sil_loc call_flags ~is_objc_method:true in sil_loc call_flags ~is_objc_method:true in
let selector = obj_c_message_expr_info.Clang_ast_t.omei_selector in let selector = obj_c_message_expr_info.Clang_ast_t.omei_selector in
@ -1093,7 +1093,7 @@ struct
let (e', _) = extract_exp_from_list res_trans_b.exps let (e', _) = extract_exp_from_list res_trans_b.exps
"\nWARNING: Missing branch expression for Conditional operator. Need to be fixed\n" in "\nWARNING: Missing branch expression for Conditional operator. Need to be fixed\n" in
let set_temp_var = [ let set_temp_var = [
Sil.Set (Sil.Lvar pvar, var_typ, e', sil_loc) Sil.Set (Exp.Lvar pvar, var_typ, e', sil_loc)
] in ] in
let tmp_var_res_trans = { empty_res_trans with instrs = set_temp_var } in let tmp_var_res_trans = { empty_res_trans with instrs = set_temp_var } in
let trans_state'' = { trans_state' with succ_nodes = [join_node] } in let trans_state'' = { trans_state' with succ_nodes = [join_node] } in
@ -1120,12 +1120,12 @@ struct
do_branch true exp1 var_typ res_trans_cond.leaf_nodes join_node pvar; do_branch true exp1 var_typ res_trans_cond.leaf_nodes join_node pvar;
do_branch false exp2 var_typ res_trans_cond.leaf_nodes join_node pvar; do_branch false exp2 var_typ res_trans_cond.leaf_nodes join_node pvar;
let id = Ident.create_fresh Ident.knormal in let id = Ident.create_fresh Ident.knormal in
let instrs = [Sil.Letderef (id, Sil.Lvar pvar, var_typ, sil_loc)] in let instrs = [Sil.Letderef (id, Exp.Lvar pvar, var_typ, sil_loc)] in
{ empty_res_trans with { empty_res_trans with
root_nodes = res_trans_cond.root_nodes; root_nodes = res_trans_cond.root_nodes;
leaf_nodes = [join_node]; leaf_nodes = [join_node];
instrs = instrs; instrs = instrs;
exps = [(Sil.Var id, typ)]; exps = [(Exp.Var id, typ)];
initd_exps = []; (* TODO we should get exps from branches+cond *) initd_exps = []; (* TODO we should get exps from branches+cond *)
} }
| _ -> assert false) | _ -> assert false)
@ -1173,7 +1173,7 @@ struct
Printing.log_out " No short-circuit condition\n"; Printing.log_out " No short-circuit condition\n";
let res_trans_cond = let res_trans_cond =
if is_null_stmt cond then { if is_null_stmt cond then {
empty_res_trans with exps = [(Sil.Const (Const.Cint IntLit.one), (Typ.Tint Typ.IBool))] empty_res_trans with exps = [(Exp.Const (Const.Cint IntLit.one), (Typ.Tint Typ.IBool))]
} }
(* Assumption: If it's a null_stmt, it is a loop with no bound, so we set condition to 1 *) (* Assumption: If it's a null_stmt, it is a loop with no bound, so we set condition to 1 *)
else else
@ -1224,7 +1224,7 @@ struct
else res_trans_s1.root_nodes in else res_trans_s1.root_nodes in
let (exp1, typ1) = extract_exp res_trans_s1.exps in let (exp1, typ1) = extract_exp res_trans_s1.exps in
let (exp2, _) = extract_exp res_trans_s2.exps in let (exp2, _) = extract_exp res_trans_s2.exps in
let e_cond = Sil.BinOp (binop, exp1, exp2) in let e_cond = Exp.BinOp (binop, exp1, exp2) in
{ empty_res_trans with { empty_res_trans with
root_nodes = root_nodes_to_parent; root_nodes = root_nodes_to_parent;
leaf_nodes = prune_to_short_c@res_trans_s2.leaf_nodes; leaf_nodes = prune_to_short_c@res_trans_s2.leaf_nodes;
@ -1386,7 +1386,7 @@ struct
match e_const with match e_const with
| [(head, _)] -> head | [(head, _)] -> head
| _ -> assert false in | _ -> assert false in
let sil_eq_cond = Sil.BinOp (Binop.Eq, switch_e_cond', e_const') in let sil_eq_cond = Exp.BinOp (Binop.Eq, switch_e_cond', e_const') in
let sil_loc = CLocation.get_sil_location stmt_info context in let sil_loc = CLocation.get_sil_location stmt_info context in
let true_prune_node = let true_prune_node =
create_prune_node true [(sil_eq_cond, switch_e_cond'_typ)] create_prune_node true [(sil_eq_cond, switch_e_cond'_typ)]
@ -1685,7 +1685,7 @@ struct
let typ = CTypes_decl.type_ptr_to_sil_type context.CContext.tenv type_ptr in let typ = CTypes_decl.type_ptr_to_sil_type context.CContext.tenv type_ptr in
CVar_decl.add_var_to_locals procdesc var_decl typ pvar; CVar_decl.add_var_to_locals procdesc var_decl typ pvar;
let trans_state' = { trans_state with succ_nodes = next_node } in let trans_state' = { trans_state with succ_nodes = next_node } in
init_expr_trans trans_state' (Sil.Lvar pvar, typ) stmt_info vdi.Clang_ast_t.vdi_init_expr in init_expr_trans trans_state' (Exp.Lvar pvar, typ) stmt_info vdi.Clang_ast_t.vdi_init_expr in
match var_decls with match var_decls with
| [] -> { empty_res_trans with root_nodes = next_nodes } | [] -> { empty_res_trans with root_nodes = next_nodes }
@ -1861,11 +1861,11 @@ struct
let procname = Cfg.Procdesc.get_proc_name procdesc in let procname = Cfg.Procdesc.get_proc_name procdesc in
let pvar = Pvar.mk (Mangled.from_string name) procname in let pvar = Pvar.mk (Mangled.from_string name) procname in
let id = Ident.create_fresh Ident.knormal in let id = Ident.create_fresh Ident.knormal in
let instr = Sil.Letderef (id, Sil.Lvar pvar, ret_param_typ, sil_loc) in let instr = Sil.Letderef (id, Exp.Lvar pvar, ret_param_typ, sil_loc) in
let ret_typ = match ret_param_typ with Typ.Tptr (t, _) -> t | _ -> assert false in let ret_typ = match ret_param_typ with Typ.Tptr (t, _) -> t | _ -> assert false in
Sil.Var id, ret_typ, [instr] Exp.Var id, ret_typ, [instr]
| None -> | None ->
Sil.Lvar (Cfg.Procdesc.get_ret_var procdesc), ret_type, [] in Exp.Lvar (Cfg.Procdesc.get_ret_var procdesc), ret_type, [] in
let trans_state' = { trans_state_pri with let trans_state' = { trans_state_pri with
succ_nodes = []; succ_nodes = [];
var_exp_typ = Some (ret_exp, ret_typ) } in var_exp_typ = Some (ret_exp, ret_typ) } in
@ -1962,7 +1962,7 @@ struct
let ret_id = Ident.create_fresh Ident.knormal in let ret_id = Ident.create_fresh Ident.knormal in
let autorelease_pool_vars = CVar_decl.compute_autorelease_pool_vars context stmts in let autorelease_pool_vars = CVar_decl.compute_autorelease_pool_vars context stmts in
let stmt_call = let stmt_call =
Sil.Call([ret_id], (Sil.Const (Const.Cfun fname)), Sil.Call([ret_id], (Exp.Const (Const.Cfun fname)),
autorelease_pool_vars, sil_loc, CallFlags.default) in autorelease_pool_vars, sil_loc, CallFlags.default) in
let node_kind = Cfg.Node.Stmt_node ("Release the autorelease pool") in let node_kind = Cfg.Node.Stmt_node ("Release the autorelease pool") in
let call_node = create_node node_kind [stmt_call] sil_loc context in let call_node = create_node node_kind [stmt_call] sil_loc context in
@ -1989,7 +1989,7 @@ struct
(* Given a captured var, return the instruction to assign it to a temp *) (* Given a captured var, return the instruction to assign it to a temp *)
let assign_captured_var (cvar, typ) = let assign_captured_var (cvar, typ) =
let id = Ident.create_fresh Ident.knormal in let id = Ident.create_fresh Ident.knormal in
let instr = Sil.Letderef (id, (Sil.Lvar cvar), typ, loc) in let instr = Sil.Letderef (id, (Exp.Lvar cvar), typ, loc) in
(id, instr) in (id, instr) in
match decl with match decl with
| Clang_ast_t.BlockDecl (_, block_decl_info) -> | Clang_ast_t.BlockDecl (_, block_decl_info) ->
@ -2008,8 +2008,8 @@ struct
F.function_decl context.tenv context.cfg context.cg decl (Some block_data); F.function_decl context.tenv context.cfg context.cg decl (Some block_data);
Cfg.set_procname_priority context.cfg block_pname; Cfg.set_procname_priority context.cfg block_pname;
let captured_vars = let captured_vars =
IList.map2 (fun id (pvar, typ) -> (Sil.Var id, pvar, typ)) ids captureds in IList.map2 (fun id (pvar, typ) -> (Exp.Var id, pvar, typ)) ids captureds in
let closure = Sil.Closure { name=block_pname; captured_vars } in let closure = Exp.Closure { name=block_pname; captured_vars } in
let block_name = Procname.to_string block_pname in let block_name = Procname.to_string block_pname in
let static_vars = CContext.static_vars_for_block context block_pname in let static_vars = CContext.static_vars_for_block context block_pname in
let captured_static_vars = captureds @ static_vars in let captured_static_vars = captureds @ static_vars in
@ -2024,9 +2024,9 @@ struct
and initListExpr_initializers_trans trans_state var_exp n stmts typ is_dyn_array stmt_info = and initListExpr_initializers_trans trans_state var_exp n stmts typ is_dyn_array stmt_info =
let (var_exp_inside, typ_inside) = match typ with let (var_exp_inside, typ_inside) = match typ with
| Typ.Tarray (t, _) when Typ.is_array_of_cpp_class typ -> | Typ.Tarray (t, _) when Typ.is_array_of_cpp_class typ ->
Sil.Lindex (var_exp, Sil.Const (Const.Cint (IntLit.of_int n))), t Exp.Lindex (var_exp, Exp.Const (Const.Cint (IntLit.of_int n))), t
| _ when is_dyn_array -> | _ when is_dyn_array ->
Sil.Lindex (var_exp, Sil.Const (Const.Cint (IntLit.of_int n))), typ Exp.Lindex (var_exp, Exp.Const (Const.Cint (IntLit.of_int n))), typ
| _ -> var_exp, typ in | _ -> var_exp, typ in
let trans_state' = { trans_state with var_exp_typ = Some (var_exp_inside, typ_inside) } in let trans_state' = { trans_state with var_exp_typ = Some (var_exp_inside, typ_inside) } in
match stmts with match stmts with
@ -2059,7 +2059,7 @@ struct
(* defining procedure. We add an edge in the call graph.*) (* defining procedure. We add an edge in the call graph.*)
Cg.add_edge context.cg procname lambda_pname; Cg.add_edge context.cg procname lambda_pname;
let captured_vars = [] in (* TODO *) let captured_vars = [] in (* TODO *)
let closure = Sil.Closure { name = lambda_pname; captured_vars } in let closure = Exp.Closure { name = lambda_pname; captured_vars } in
{ empty_res_trans with exps = [(closure, typ)] } { empty_res_trans with exps = [(closure, typ)] }
and cxxNewExpr_trans trans_state stmt_info expr_info cxx_new_expr_info = and cxxNewExpr_trans trans_state stmt_info expr_info cxx_new_expr_info =
@ -2077,7 +2077,7 @@ struct
(match res_trans_size.exps with (match res_trans_size.exps with
| [(exp, _)] -> Some exp, res_trans_size | [(exp, _)] -> Some exp, res_trans_size
| _ -> None, empty_res_trans) | _ -> None, empty_res_trans)
| None -> Some (Sil.Const (Const.Cint (IntLit.minus_one))), empty_res_trans | None -> Some (Exp.Const (Const.Cint (IntLit.minus_one))), empty_res_trans
else None, empty_res_trans in else None, empty_res_trans in
let res_trans_new = cpp_new_trans trans_state_pri sil_loc typ size_exp_opt in let res_trans_new = cpp_new_trans trans_state_pri sil_loc typ size_exp_opt in
let stmt_opt = Ast_utils.get_stmt_opt cxx_new_expr_info.Clang_ast_t.xnei_initializer_expr in let stmt_opt = Ast_utils.get_stmt_opt cxx_new_expr_info.Clang_ast_t.xnei_initializer_expr in
@ -2093,8 +2093,8 @@ struct
if is_dyn_array && Typ.is_pointer_to_cpp_class typ then if is_dyn_array && Typ.is_pointer_to_cpp_class typ then
let rec create_stmts stmt_opt size_exp_opt = let rec create_stmts stmt_opt size_exp_opt =
match stmt_opt, size_exp_opt with match stmt_opt, size_exp_opt with
| Some stmt, Some (Sil.Const (Const.Cint n)) when not (IntLit.iszero n) -> | Some stmt, Some (Exp.Const (Const.Cint n)) when not (IntLit.iszero n) ->
let n_minus_1 = Some ((Sil.Const (Const.Cint (IntLit.sub n IntLit.one)))) in let n_minus_1 = Some ((Exp.Const (Const.Cint (IntLit.sub n IntLit.one)))) in
stmt :: create_stmts stmt_opt n_minus_1 stmt :: create_stmts stmt_opt n_minus_1
| _ -> [] in | _ -> [] in
let stmts = create_stmts stmt_opt size_exp_opt in let stmts = create_stmts stmt_opt size_exp_opt in
@ -2123,7 +2123,7 @@ struct
let exp = extract_exp_from_list result_trans_param.exps let exp = extract_exp_from_list result_trans_param.exps
"WARNING: There should be one expression to delete. \n" in "WARNING: There should be one expression to delete. \n" in
let call_instr = let call_instr =
Sil.Call ([], Sil.Const (Const.Cfun fname), [exp], sil_loc, CallFlags.default) in Sil.Call ([], Exp.Const (Const.Cfun fname), [exp], sil_loc, CallFlags.default) in
let call_res_trans = { empty_res_trans with instrs = [call_instr] } in let call_res_trans = { empty_res_trans with instrs = [call_instr] } in
let all_res_trans = if false then let all_res_trans = if false then
(* FIXME (t10135167): call destructor on deleted pointer if it's not null *) (* FIXME (t10135167): call destructor on deleted pointer if it's not null *)
@ -2153,7 +2153,7 @@ struct
"SIL_materialize_temp__" expr_info in "SIL_materialize_temp__" expr_info in
let temp_exp = match stmt_list with [p] -> p | _ -> assert false in let temp_exp = match stmt_list with [p] -> p | _ -> assert false in
Cfg.Procdesc.append_locals procdesc [(Pvar.get_name pvar, typ)]; Cfg.Procdesc.append_locals procdesc [(Pvar.get_name pvar, typ)];
let var_exp_typ = (Sil.Lvar pvar, typ) in let var_exp_typ = (Exp.Lvar pvar, typ) in
let res_trans = init_expr_trans trans_state var_exp_typ stmt_info (Some temp_exp) in let res_trans = init_expr_trans trans_state var_exp_typ stmt_info (Some temp_exp) in
{ res_trans with exps = [var_exp_typ] } { res_trans with exps = [var_exp_typ] }
@ -2175,16 +2175,16 @@ struct
let sil_loc = CLocation.get_sil_location stmt_info context in let sil_loc = CLocation.get_sil_location stmt_info context in
let cast_type = CTypes_decl.type_ptr_to_sil_type tenv cast_type_ptr in let cast_type = CTypes_decl.type_ptr_to_sil_type tenv cast_type_ptr in
let sizeof_expr = match cast_type with let sizeof_expr = match cast_type with
| Typ.Tptr (typ, _) -> Sil.Sizeof (typ, None, subtypes) | Typ.Tptr (typ, _) -> Exp.Sizeof (typ, None, subtypes)
| _ -> assert false in | _ -> assert false in
let builtin = Sil.Const (Const.Cfun ModelBuiltins.__cast) in let builtin = Exp.Const (Const.Cfun ModelBuiltins.__cast) in
let stmt = match stmts with [stmt] -> stmt | _ -> assert false in let stmt = match stmts with [stmt] -> stmt | _ -> assert false in
let res_trans_stmt = exec_with_glvalue_as_reference instruction trans_state' stmt in let res_trans_stmt = exec_with_glvalue_as_reference instruction trans_state' stmt in
let exp = match res_trans_stmt.exps with | [e] -> e | _ -> assert false in let exp = match res_trans_stmt.exps with | [e] -> e | _ -> assert false in
let args = [exp; (sizeof_expr, Typ.Tvoid)] in let args = [exp; (sizeof_expr, Typ.Tvoid)] in
let ret_id = Ident.create_fresh Ident.knormal in let ret_id = Ident.create_fresh Ident.knormal in
let call = Sil.Call ([ret_id], builtin, args, sil_loc, CallFlags.default) in let call = Sil.Call ([ret_id], builtin, args, sil_loc, CallFlags.default) in
let res_ex = Sil.Var ret_id in let res_ex = Exp.Var ret_id in
let res_trans_dynamic_cast = { empty_res_trans with instrs = [call]; } in let res_trans_dynamic_cast = { empty_res_trans with instrs = [call]; } in
let all_res_trans = [ res_trans_stmt; res_trans_dynamic_cast ] in let all_res_trans = [ res_trans_stmt; res_trans_dynamic_cast ] in
let nname = "CxxDynamicCast" in let nname = "CxxDynamicCast" in
@ -2204,7 +2204,7 @@ struct
let res_trans_subexpr_list = let res_trans_subexpr_list =
IList.map (exec_with_glvalue_as_reference instruction trans_state_param) stmts in IList.map (exec_with_glvalue_as_reference instruction trans_state_param) stmts in
let params = collect_exprs res_trans_subexpr_list in let params = collect_exprs res_trans_subexpr_list in
let sil_fun = Sil.Const (Const.Cfun pname) in let sil_fun = Exp.Const (Const.Cfun pname) in
let call_instr = Sil.Call ([], sil_fun, params, sil_loc, CallFlags.default) in let call_instr = Sil.Call ([], sil_fun, params, sil_loc, CallFlags.default) in
let res_trans_call = { empty_res_trans with let res_trans_call = { empty_res_trans with
instrs = [call_instr]; instrs = [call_instr];
@ -2222,7 +2222,7 @@ struct
and cxxPseudoDestructorExpr_trans () = and cxxPseudoDestructorExpr_trans () =
let fun_name = Procname.from_string_c_fun CFrontend_config.infer_skip_fun in let fun_name = Procname.from_string_c_fun CFrontend_config.infer_skip_fun in
{ empty_res_trans with exps = [(Sil.Const (Const.Cfun fun_name), Typ.Tvoid)] } { empty_res_trans with exps = [(Exp.Const (Const.Cfun fun_name), Typ.Tvoid)] }
and cxxTypeidExpr_trans trans_state stmt_info stmts expr_info = and cxxTypeidExpr_trans trans_state stmt_info stmts expr_info =
let tenv = trans_state.context.CContext.tenv in let tenv = trans_state.context.CContext.tenv in
@ -2236,13 +2236,13 @@ struct
instruction trans_state_param stmt instruction trans_state_param stmt
| _ -> empty_res_trans in | _ -> empty_res_trans in
let fun_name = ModelBuiltins.__cxx_typeid in let fun_name = ModelBuiltins.__cxx_typeid in
let sil_fun = Sil.Const (Const.Cfun fun_name) in let sil_fun = Exp.Const (Const.Cfun fun_name) in
let ret_id = Ident.create_fresh Ident.knormal in let ret_id = Ident.create_fresh Ident.knormal in
let type_info_objc = (Sil.Sizeof (typ, None, Subtype.exact), Typ.Tvoid) in let type_info_objc = (Exp.Sizeof (typ, None, Subtype.exact), Typ.Tvoid) in
let field_name_decl = Ast_utils.make_qual_name_decl ["type_info"; "std"] "__type_name" in let field_name_decl = Ast_utils.make_qual_name_decl ["type_info"; "std"] "__type_name" in
let field_name = General_utils.mk_class_field_name field_name_decl in let field_name = General_utils.mk_class_field_name field_name_decl in
let ret_exp = Sil.Var ret_id in let ret_exp = Exp.Var ret_id in
let field_exp = Sil.Lfield (ret_exp, field_name, typ) in let field_exp = Exp.Lfield (ret_exp, field_name, typ) in
let args = [type_info_objc; (field_exp, Typ.Tvoid)] @ res_trans_subexpr.exps in let args = [type_info_objc; (field_exp, Typ.Tvoid)] @ res_trans_subexpr.exps in
let call_instr = Sil.Call ([ret_id], sil_fun, args, sil_loc, CallFlags.default) in let call_instr = Sil.Call ([ret_id], sil_fun, args, sil_loc, CallFlags.default) in
let res_trans_call = { empty_res_trans with let res_trans_call = { empty_res_trans with
@ -2264,9 +2264,9 @@ struct
let trans_state_param = { trans_state_pri with succ_nodes = [] } in let trans_state_param = { trans_state_pri with succ_nodes = [] } in
let res_trans_subexpr_list = IList.map (instruction trans_state_param) stmts in let res_trans_subexpr_list = IList.map (instruction trans_state_param) stmts in
let params = collect_exprs res_trans_subexpr_list in let params = collect_exprs res_trans_subexpr_list in
let sil_fun = Sil.Const (Const.Cfun fun_name) in let sil_fun = Exp.Const (Const.Cfun fun_name) in
let ret_id = Ident.create_fresh Ident.knormal in let ret_id = Ident.create_fresh Ident.knormal in
let ret_exp = Sil.Var ret_id in let ret_exp = Exp.Var ret_id in
let call_instr = Sil.Call ([ret_id], sil_fun, params, sil_loc, CallFlags.default) in let call_instr = Sil.Call ([ret_id], sil_fun, params, sil_loc, CallFlags.default) in
let res_trans_call = { empty_res_trans with let res_trans_call = { empty_res_trans with
instrs = [call_instr]; instrs = [call_instr];

@ -61,9 +61,9 @@ struct
"\nWARNING: Missing expression for Conditional operator. Need to be fixed" in "\nWARNING: Missing expression for Conditional operator. Need to be fixed" in
let e_cond'' = let e_cond'' =
if branch then if branch then
Sil.BinOp(Binop.Ne, e_cond', Sil.exp_zero) Exp.BinOp(Binop.Ne, e_cond', Sil.exp_zero)
else else
Sil.BinOp(Binop.Eq, e_cond', Sil.exp_zero) in Exp.BinOp(Binop.Eq, e_cond', Sil.exp_zero) in
let instrs_cond'= instrs_cond @ [Sil.Prune(e_cond'', loc, branch, ik)] in let instrs_cond'= instrs_cond @ [Sil.Prune(e_cond'', loc, branch, ik)] in
create_node (prune_kind branch) instrs_cond' loc context create_node (prune_kind branch) instrs_cond' loc context
@ -130,8 +130,8 @@ type trans_state = {
succ_nodes: Cfg.Node.t list; (* successor nodes in the cfg *) succ_nodes: Cfg.Node.t list; (* successor nodes in the cfg *)
continuation: continuation option; (* current continuation *) continuation: continuation option; (* current continuation *)
priority: priority_node; priority: priority_node;
var_exp_typ: (Sil.exp * Typ.t) option; var_exp_typ: (Exp.t * Typ.t) option;
opaque_exp: (Sil.exp * Typ.t) option; opaque_exp: (Exp.t * Typ.t) option;
obj_bridged_cast_typ : Typ.t option obj_bridged_cast_typ : Typ.t option
} }
@ -140,8 +140,8 @@ type trans_result = {
root_nodes: Cfg.Node.t list; (* Top cfg nodes (root) created by the translation *) root_nodes: Cfg.Node.t list; (* Top cfg nodes (root) created by the translation *)
leaf_nodes: Cfg.Node.t list; (* Bottom cfg nodes (leaf) created by the translate *) leaf_nodes: Cfg.Node.t list; (* Bottom cfg nodes (leaf) created by the translate *)
instrs: Sil.instr list; (* list of SIL instruction that need to be placed in cfg nodes of the parent*) instrs: Sil.instr list; (* list of SIL instruction that need to be placed in cfg nodes of the parent*)
exps: (Sil.exp * Typ.t) list; (* SIL expressions resulting from translation of clang stmt *) exps: (Exp.t * Typ.t) list; (* SIL expressions resulting from translation of clang stmt *)
initd_exps: Sil.exp list; initd_exps: Exp.t list;
is_cpp_call_virtual : bool; is_cpp_call_virtual : bool;
} }
@ -155,7 +155,7 @@ let empty_res_trans = {
is_cpp_call_virtual = false; is_cpp_call_virtual = false;
} }
let undefined_expression () = Sil.Var (Ident.create_fresh Ident.knormal) let undefined_expression () = Exp.Var (Ident.create_fresh Ident.knormal)
(** Collect the results of translating a list of instructions, and link up the nodes created. *) (** Collect the results of translating a list of instructions, and link up the nodes created. *)
let collect_res_trans cfg l = let collect_res_trans cfg l =
@ -298,19 +298,19 @@ let create_alloc_instrs context sil_loc function_type fname size_exp_opt procnam
function_type, styp function_type, styp
| _ -> Typ.Tptr (function_type, Typ.Pk_pointer), function_type in | _ -> Typ.Tptr (function_type, Typ.Pk_pointer), function_type in
let function_type_np = CTypes.expand_structured_type context.CContext.tenv function_type_np in let function_type_np = CTypes.expand_structured_type context.CContext.tenv function_type_np in
let sizeof_exp_ = Sil.Sizeof (function_type_np, None, Subtype.exact) in let sizeof_exp_ = Exp.Sizeof (function_type_np, None, Subtype.exact) in
let sizeof_exp = match size_exp_opt with let sizeof_exp = match size_exp_opt with
| Some exp -> Sil.BinOp (Binop.Mult, sizeof_exp_, exp) | Some exp -> Exp.BinOp (Binop.Mult, sizeof_exp_, exp)
| None -> sizeof_exp_ in | None -> sizeof_exp_ in
let exp = (sizeof_exp, Typ.Tint Typ.IULong) in let exp = (sizeof_exp, Typ.Tint Typ.IULong) in
let procname_arg = match procname_opt with let procname_arg = match procname_opt with
| Some procname -> [Sil.Const (Const.Cfun (procname)), Typ.Tvoid] | Some procname -> [Exp.Const (Const.Cfun (procname)), Typ.Tvoid]
| None -> [] in | None -> [] in
let args = exp :: procname_arg in let args = exp :: procname_arg in
let ret_id = Ident.create_fresh Ident.knormal in let ret_id = Ident.create_fresh Ident.knormal in
let stmt_call = let stmt_call =
Sil.Call([ret_id], Sil.Const (Const.Cfun fname), args, sil_loc, CallFlags.default) in Sil.Call([ret_id], Exp.Const (Const.Cfun fname), args, sil_loc, CallFlags.default) in
(function_type, stmt_call, Sil.Var ret_id) (function_type, stmt_call, Exp.Var ret_id)
let alloc_trans trans_state loc stmt_info function_type is_cf_non_null_alloc procname_opt = let alloc_trans trans_state loc stmt_info function_type is_cf_non_null_alloc procname_opt =
let fname = if is_cf_non_null_alloc then let fname = if is_cf_non_null_alloc then
@ -338,13 +338,13 @@ let objc_new_trans trans_state loc stmt_info cls_name function_type =
CMethod_trans.create_external_procdesc trans_state.context.CContext.cfg pname is_instance None; CMethod_trans.create_external_procdesc trans_state.context.CContext.cfg pname is_instance None;
let args = [(alloc_ret_exp, alloc_ret_type)] in let args = [(alloc_ret_exp, alloc_ret_type)] in
let init_stmt_call = let init_stmt_call =
Sil.Call ([init_ret_id], Sil.Const (Const.Cfun pname), args, loc, call_flags) in Sil.Call ([init_ret_id], Exp.Const (Const.Cfun pname), args, loc, call_flags) in
let instrs = [alloc_stmt_call; init_stmt_call] in let instrs = [alloc_stmt_call; init_stmt_call] in
let res_trans_tmp = { empty_res_trans with instrs = instrs } in let res_trans_tmp = { empty_res_trans with instrs = instrs } in
let res_trans = let res_trans =
let nname = "Call objC new" in let nname = "Call objC new" in
PriorityNode.compute_results_to_parent trans_state loc nname stmt_info [res_trans_tmp] in PriorityNode.compute_results_to_parent trans_state loc nname stmt_info [res_trans_tmp] in
{ res_trans with exps = [(Sil.Var init_ret_id, alloc_ret_type)]} { res_trans with exps = [(Exp.Var init_ret_id, alloc_ret_type)]}
let new_or_alloc_trans trans_state loc stmt_info type_ptr class_name_opt selector = let new_or_alloc_trans trans_state loc stmt_info type_ptr class_name_opt selector =
let tenv = trans_state.context.CContext.tenv in let tenv = trans_state.context.CContext.tenv in
@ -372,12 +372,12 @@ let create_cast_instrs context exp cast_from_typ cast_to_typ sil_loc =
let ret_id = Ident.create_fresh Ident.knormal in let ret_id = Ident.create_fresh Ident.knormal in
let typ = CTypes.remove_pointer_to_typ cast_to_typ in let typ = CTypes.remove_pointer_to_typ cast_to_typ in
let cast_typ_no_pointer = CTypes.expand_structured_type context.CContext.tenv typ in let cast_typ_no_pointer = CTypes.expand_structured_type context.CContext.tenv typ in
let sizeof_exp = Sil.Sizeof (cast_typ_no_pointer, None, Subtype.exact) in let sizeof_exp = Exp.Sizeof (cast_typ_no_pointer, None, Subtype.exact) in
let pname = ModelBuiltins.__objc_cast in let pname = ModelBuiltins.__objc_cast in
let args = [(exp, cast_from_typ); (sizeof_exp, Typ.Tint Typ.IULong)] in let args = [(exp, cast_from_typ); (sizeof_exp, Typ.Tint Typ.IULong)] in
let stmt_call = let stmt_call =
Sil.Call ([ret_id], Sil.Const (Const.Cfun pname), args, sil_loc, CallFlags.default) in Sil.Call ([ret_id], Exp.Const (Const.Cfun pname), args, sil_loc, CallFlags.default) in
(stmt_call, Sil.Var ret_id) (stmt_call, Exp.Var ret_id)
let cast_trans context exps sil_loc function_type pname = let cast_trans context exps sil_loc function_type pname =
if CTrans_models.is_toll_free_bridging pname then if CTrans_models.is_toll_free_bridging pname then
@ -390,7 +390,7 @@ let cast_trans context exps sil_loc function_type pname =
let dereference_var_sil (exp, typ) sil_loc = let dereference_var_sil (exp, typ) sil_loc =
let id = Ident.create_fresh Ident.knormal in let id = Ident.create_fresh Ident.knormal in
let sil_instr = Sil.Letderef (id, exp, typ, sil_loc) in let sil_instr = Sil.Letderef (id, exp, typ, sil_loc) in
([sil_instr], Sil.Var id) ([sil_instr], Exp.Var id)
(** Given trans_result with ONE expression, create temporary variable with value of an expression (** Given trans_result with ONE expression, create temporary variable with value of an expression
assigned to it *) assigned to it *)
@ -439,8 +439,8 @@ let cast_operation trans_state cast_kind exps cast_typ sil_loc is_objc_bridged =
([], (exp, cast_typ)) ([], (exp, cast_typ))
let trans_assertion_failure sil_loc context = let trans_assertion_failure sil_loc context =
let assert_fail_builtin = Sil.Const (Const.Cfun ModelBuiltins.__infer_fail) in let assert_fail_builtin = Exp.Const (Const.Cfun ModelBuiltins.__infer_fail) in
let args = [Sil.Const (Const.Cstr Config.default_failure_name), Typ.Tvoid] in let args = [Exp.Const (Const.Cstr Config.default_failure_name), Typ.Tvoid] in
let call_instr = Sil.Call ([], assert_fail_builtin, args, sil_loc, CallFlags.default) in let call_instr = Sil.Call ([], assert_fail_builtin, args, sil_loc, CallFlags.default) in
let exit_node = Cfg.Procdesc.get_exit_node (CContext.get_procdesc context) let exit_node = Cfg.Procdesc.get_exit_node (CContext.get_procdesc context)
and failure_node = and failure_node =
@ -488,10 +488,10 @@ let cxx_method_builtin_trans trans_state loc pname =
let define_condition_side_effects e_cond instrs_cond sil_loc = let define_condition_side_effects e_cond instrs_cond sil_loc =
let (e', typ) = extract_exp_from_list e_cond "\nWARNING: Missing expression in IfStmt. Need to be fixed\n" in let (e', typ) = extract_exp_from_list e_cond "\nWARNING: Missing expression in IfStmt. Need to be fixed\n" in
match e' with match e' with
| Sil.Lvar pvar -> | Exp.Lvar pvar ->
let id = Ident.create_fresh Ident.knormal in let id = Ident.create_fresh Ident.knormal in
[(Sil.Var id, typ)], [(Exp.Var id, typ)],
[Sil.Letderef (id, Sil.Lvar pvar, typ, sil_loc)] [Sil.Letderef (id, Exp.Lvar pvar, typ, sil_loc)]
| _ -> [(e', typ)], instrs_cond | _ -> [(e', typ)], instrs_cond
let fix_param_exps_mismatch params_stmt exps_param = let fix_param_exps_mismatch params_stmt exps_param =
@ -569,9 +569,9 @@ struct
let t' = CTypes.add_pointer_to_typ let t' = CTypes.add_pointer_to_typ
(CTypes_decl.get_type_curr_class_objc (CTypes_decl.get_type_curr_class_objc
context.CContext.tenv context.CContext.curr_class) in context.CContext.tenv context.CContext.curr_class) in
let e = Sil.Lvar (Pvar.mk (Mangled.from_string CFrontend_config.self) procname) in let e = Exp.Lvar (Pvar.mk (Mangled.from_string CFrontend_config.self) procname) in
let id = Ident.create_fresh Ident.knormal in let id = Ident.create_fresh Ident.knormal in
t', Sil.Var id, [Sil.Letderef (id, e, t', loc)] in t', Exp.Var id, [Sil.Letderef (id, e, t', loc)] in
{ empty_res_trans with { empty_res_trans with
exps = [(self_expr, typ)]; exps = [(self_expr, typ)];
instrs = ins } instrs = ins }
@ -704,7 +704,7 @@ let var_or_zero_in_init_list tenv e typ ~return_zero:return_zero =
| _ -> [[(e, typ)]] (*This case is an error, shouldn't happen.*)) | _ -> [[(e, typ)]] (*This case is an error, shouldn't happen.*))
| Typ.Tstruct { Typ.instance_fields } as type_struct -> | Typ.Tstruct { Typ.instance_fields } as type_struct ->
let lh_exprs = IList.map ( fun (fieldname, _, _) -> let lh_exprs = IList.map ( fun (fieldname, _, _) ->
Sil.Lfield (e, fieldname, type_struct) ) instance_fields in Exp.Lfield (e, fieldname, type_struct) ) instance_fields in
let lh_types = IList.map ( fun (_, fieldtype, _) -> fieldtype) instance_fields in let lh_types = IList.map ( fun (_, fieldtype, _) -> fieldtype) instance_fields in
let exp_types = zip lh_exprs lh_types in let exp_types = zip lh_exprs lh_types in
IList.map (fun (e, t) -> IList.map (fun (e, t) ->
@ -713,9 +713,9 @@ let var_or_zero_in_init_list tenv e typ ~return_zero:return_zero =
let size = IntLit.to_int n in let size = IntLit.to_int n in
let indices = list_range 0 (size - 1) in let indices = list_range 0 (size - 1) in
let index_constants = let index_constants =
IList.map (fun i -> (Sil.Const (Const.Cint (IntLit.of_int i)))) indices in IList.map (fun i -> (Exp.Const (Const.Cint (IntLit.of_int i)))) indices in
let lh_exprs = let lh_exprs =
IList.map (fun index_expr -> Sil.Lindex (e, index_expr)) index_constants in IList.map (fun index_expr -> Exp.Lindex (e, index_expr)) index_constants in
let lh_types = replicate size arrtyp in let lh_types = replicate size arrtyp in
let exp_types = zip lh_exprs lh_types in let exp_types = zip lh_exprs lh_types in
IList.map (fun (e, t) -> IList.map (fun (e, t) ->

@ -26,8 +26,8 @@ type trans_state = {
succ_nodes: Cfg.Node.t list; succ_nodes: Cfg.Node.t list;
continuation: continuation option; continuation: continuation option;
priority: priority_node; priority: priority_node;
var_exp_typ: (Sil.exp * Typ.t) option; var_exp_typ: (Exp.t * Typ.t) option;
opaque_exp: (Sil.exp * Typ.t) option; opaque_exp: (Exp.t * Typ.t) option;
obj_bridged_cast_typ : Typ.t option obj_bridged_cast_typ : Typ.t option
} }
@ -35,18 +35,18 @@ type trans_result = {
root_nodes: Cfg.Node.t list; root_nodes: Cfg.Node.t list;
leaf_nodes: Cfg.Node.t list; leaf_nodes: Cfg.Node.t list;
instrs: Sil.instr list; instrs: Sil.instr list;
exps: (Sil.exp * Typ.t) list; exps: (Exp.t * Typ.t) list;
initd_exps: Sil.exp list; initd_exps: Exp.t list;
is_cpp_call_virtual : bool; is_cpp_call_virtual : bool;
} }
val empty_res_trans: trans_result val empty_res_trans: trans_result
val undefined_expression: unit -> Sil.exp val undefined_expression: unit -> Exp.t
val collect_res_trans : Cfg.cfg -> trans_result list -> trans_result val collect_res_trans : Cfg.cfg -> trans_result list -> trans_result
val extract_var_exp_or_fail : trans_state -> Sil.exp * Typ.t val extract_var_exp_or_fail : trans_state -> Exp.t * Typ.t
val is_return_temp: continuation option -> bool val is_return_temp: continuation option -> bool
@ -58,15 +58,15 @@ val mk_cond_continuation : continuation option -> continuation option
val extract_item_from_singleton : 'a list -> string -> 'a -> 'a val extract_item_from_singleton : 'a list -> string -> 'a -> 'a
val extract_exp_from_list : (Sil.exp * Typ.t) list -> string -> (Sil.exp * Typ.t) val extract_exp_from_list : (Exp.t * Typ.t) list -> string -> (Exp.t * Typ.t)
val fix_param_exps_mismatch : 'a list -> (Sil.exp * Typ.t) list -> (Sil.exp * Typ.t)list val fix_param_exps_mismatch : 'a list -> (Exp.t * Typ.t) list -> (Exp.t * Typ.t)list
val get_selector_receiver : Clang_ast_t.obj_c_message_expr_info -> string * Clang_ast_t.receiver_kind val get_selector_receiver : Clang_ast_t.obj_c_message_expr_info -> string * Clang_ast_t.receiver_kind
val define_condition_side_effects : val define_condition_side_effects :
(Sil.exp * Typ.t) list -> Sil.instr list -> Location.t -> (Exp.t * Typ.t) list -> Sil.instr list -> Location.t ->
(Sil.exp * Typ.t) list * Sil.instr list (Exp.t * Typ.t) list * Sil.instr list
val extract_stmt_from_singleton : Clang_ast_t.stmt list -> string -> Clang_ast_t.stmt val extract_stmt_from_singleton : Clang_ast_t.stmt list -> string -> Clang_ast_t.stmt
@ -83,8 +83,8 @@ val get_type_from_exp_stmt : Clang_ast_t.stmt -> Clang_ast_t.type_ptr
val dereference_value_from_result : Location.t -> trans_result -> strip_pointer:bool -> trans_result val dereference_value_from_result : Location.t -> trans_result -> strip_pointer:bool -> trans_result
val cast_operation : val cast_operation :
trans_state -> Clang_ast_t.cast_kind -> (Sil.exp * Typ.t) list -> Typ.t -> Location.t -> trans_state -> Clang_ast_t.cast_kind -> (Exp.t * Typ.t) list -> Typ.t -> Location.t ->
bool -> Sil.instr list * (Sil.exp * Typ.t) bool -> Sil.instr list * (Exp.t * Typ.t)
val trans_assertion: trans_state -> Location.t -> trans_result val trans_assertion: trans_state -> Location.t -> trans_result
@ -111,13 +111,13 @@ val alloc_trans :
val new_or_alloc_trans : trans_state -> Location.t -> Clang_ast_t.stmt_info -> val new_or_alloc_trans : trans_state -> Location.t -> Clang_ast_t.stmt_info ->
Clang_ast_t.type_ptr -> string option -> string -> trans_result Clang_ast_t.type_ptr -> string option -> string -> trans_result
val cpp_new_trans : trans_state -> Location.t -> Typ.t -> Sil.exp option -> trans_result val cpp_new_trans : trans_state -> Location.t -> Typ.t -> Exp.t option -> trans_result
val cast_trans : val cast_trans :
CContext.t -> (Sil.exp * Typ.t) list -> Location.t -> Typ.t -> Procname.t -> CContext.t -> (Exp.t * Typ.t) list -> Location.t -> Typ.t -> Procname.t ->
(Sil.instr * Sil.exp) option (Sil.instr * Exp.t) option
val dereference_var_sil : Sil.exp * Typ.t -> Location.t -> Sil.instr list * Sil.exp val dereference_var_sil : Exp.t * Typ.t -> Location.t -> Sil.instr list * Exp.t
(** Module for creating cfg nodes and other utility functions related to them. *) (** Module for creating cfg nodes and other utility functions related to them. *)
module Nodes : module Nodes :
@ -131,7 +131,7 @@ sig
val is_join_node : Cfg.Node.t -> bool val is_join_node : Cfg.Node.t -> bool
val create_prune_node : val create_prune_node :
bool -> (Sil.exp * Typ.t) list -> Sil.instr list -> Location.t -> Sil.if_kind -> bool -> (Exp.t * Typ.t) list -> Sil.instr list -> Location.t -> Sil.if_kind ->
CContext.t -> Cfg.Node.t CContext.t -> Cfg.Node.t
val is_prune_node : Cfg.Node.t -> bool val is_prune_node : Cfg.Node.t -> bool
@ -218,5 +218,5 @@ val is_dispatch_function : Clang_ast_t.stmt list -> int option
val is_block_enumerate_function : Clang_ast_t.obj_c_message_expr_info -> bool val is_block_enumerate_function : Clang_ast_t.obj_c_message_expr_info -> bool
val var_or_zero_in_init_list : Tenv.t -> Sil.exp -> Typ.t -> return_zero:bool -> val var_or_zero_in_init_list : Tenv.t -> Exp.t -> Typ.t -> return_zero:bool ->
(Sil.exp * Typ.t) list (Exp.t * Typ.t) list

@ -71,7 +71,7 @@ let rec compute_autorelease_pool_vars context stmts =
let typ = CTypes_decl.type_ptr_to_sil_type context.CContext.tenv type_ptr in let typ = CTypes_decl.type_ptr_to_sil_type context.CContext.tenv type_ptr in
let pvar = sil_var_of_decl_ref context decl_ref procname in let pvar = sil_var_of_decl_ref context decl_ref procname in
if Pvar.is_local pvar then if Pvar.is_local pvar then
General_utils.append_no_duplicateds [(Sil.Lvar pvar, typ)] res General_utils.append_no_duplicateds [(Exp.Lvar pvar, typ)] res
else res else res
| _ -> res) | _ -> res)
| _ -> res) | _ -> res)

@ -18,7 +18,7 @@ val sil_var_of_decl_ref : CContext.t -> Clang_ast_t.decl_ref -> Procname.t -> Pv
val add_var_to_locals : Cfg.Procdesc.t -> Clang_ast_t.decl -> Typ.t -> Pvar.t -> unit val add_var_to_locals : Cfg.Procdesc.t -> Clang_ast_t.decl -> Typ.t -> Pvar.t -> unit
val compute_autorelease_pool_vars : CContext.t -> Clang_ast_t.stmt list -> (Sil.exp * Typ.t) list val compute_autorelease_pool_vars : CContext.t -> Clang_ast_t.stmt list -> (Exp.t * Typ.t) list
val captured_vars_from_block_info : CContext.t -> Clang_ast_t.block_captured_variable list -> val captured_vars_from_block_info : CContext.t -> Clang_ast_t.block_captured_variable list ->
(Pvar.t * Typ.t) list (Pvar.t * Typ.t) list

@ -17,7 +17,7 @@ val callback_check_return_type : TypeCheck.check_return_type -> Callbacks.proc_c
(** Parameters of a call. *) (** Parameters of a call. *)
type parameters = (Sil.exp * Typ.t) list type parameters = (Exp.t * Typ.t) list
(** Type for a module that provides a main callback function *) (** Type for a module that provides a main callback function *)

@ -140,7 +140,7 @@ let check_condition case_zero find_canonical_duplicate curr_pname
Mangled.equal c throwable_class Mangled.equal c throwable_class
| _ -> false in | _ -> false in
let do_instr = function let do_instr = function
| Sil.Call (_, Sil.Const (Const.Cfun pn), [_; (Sil.Sizeof(t, _, _), _)], _, _) when | Sil.Call (_, Exp.Const (Const.Cfun pn), [_; (Exp.Sizeof(t, _, _), _)], _, _) when
Procname.equal pn ModelBuiltins.__instanceof && typ_is_throwable t -> Procname.equal pn ModelBuiltins.__instanceof && typ_is_throwable t ->
throwable_found := true throwable_found := true
| _ -> () in | _ -> () in

@ -162,30 +162,30 @@ type checks =
let rec typecheck_expr let rec typecheck_expr
find_canonical_duplicate visited checks node instr_ref curr_pname find_canonical_duplicate visited checks node instr_ref curr_pname
typestate e tr_default loc : TypeState.range = match e with typestate e tr_default loc : TypeState.range = match e with
| Sil.Lvar pvar -> | Exp.Lvar pvar ->
(match TypeState.lookup_pvar pvar typestate with (match TypeState.lookup_pvar pvar typestate with
| Some tr -> TypeState.range_add_locs tr [loc] | Some tr -> TypeState.range_add_locs tr [loc]
| None -> tr_default) | None -> tr_default)
| Sil.Var id -> | Exp.Var id ->
(match TypeState.lookup_id id typestate with (match TypeState.lookup_id id typestate with
| Some tr -> TypeState.range_add_locs tr [loc] | Some tr -> TypeState.range_add_locs tr [loc]
| None -> tr_default) | None -> tr_default)
| Sil.Const (Const.Cint i) when IntLit.iszero i -> | Exp.Const (Const.Cint i) when IntLit.iszero i ->
let (typ, _, locs) = tr_default in let (typ, _, locs) = tr_default in
if PatternMatch.type_is_class typ if PatternMatch.type_is_class typ
then (typ, TypeAnnotation.const Annotations.Nullable true (TypeOrigin.Const loc), locs) then (typ, TypeAnnotation.const Annotations.Nullable true (TypeOrigin.Const loc), locs)
else else
let t, ta, ll = tr_default in let t, ta, ll = tr_default in
(t, TypeAnnotation.with_origin ta (TypeOrigin.Const loc), ll) (t, TypeAnnotation.with_origin ta (TypeOrigin.Const loc), ll)
| Sil.Exn e1 -> | Exp.Exn e1 ->
typecheck_expr typecheck_expr
find_canonical_duplicate visited checks find_canonical_duplicate visited checks
node instr_ref curr_pname node instr_ref curr_pname
typestate e1 tr_default loc typestate e1 tr_default loc
| Sil.Const _ -> | Exp.Const _ ->
let (typ, _, locs) = tr_default in let (typ, _, locs) = tr_default in
(typ, TypeAnnotation.const Annotations.Nullable false (TypeOrigin.Const loc), locs) (typ, TypeAnnotation.const Annotations.Nullable false (TypeOrigin.Const loc), locs)
| Sil.Lfield (exp, fn, typ) -> | Exp.Lfield (exp, fn, typ) ->
let _, _, locs = tr_default in let _, _, locs = tr_default in
let (_, ta, locs') = let (_, ta, locs') =
typecheck_expr typecheck_expr
@ -203,7 +203,7 @@ let rec typecheck_expr
EradicateChecks.check_field_access EradicateChecks.check_field_access
find_canonical_duplicate curr_pname node instr_ref exp fn ta loc; find_canonical_duplicate curr_pname node instr_ref exp fn ta loc;
tr_new tr_new
| Sil.Lindex (array_exp, index_exp) -> | Exp.Lindex (array_exp, index_exp) ->
let (_, ta, _) = let (_, ta, _) =
typecheck_expr typecheck_expr
find_canonical_duplicate find_canonical_duplicate
@ -260,20 +260,20 @@ let typecheck_instr
Some (TypeAnnotation.get_origin ta) Some (TypeAnnotation.get_origin ta)
| None -> None in | None -> None in
let handle_temporary e = match Idenv.expand_expr idenv e with let handle_temporary e = match Idenv.expand_expr idenv e with
| Sil.Lvar pvar when name_is_temporary (Pvar.to_string pvar) -> | Exp.Lvar pvar when name_is_temporary (Pvar.to_string pvar) ->
begin begin
match pvar_get_origin pvar with match pvar_get_origin pvar with
| Some (TypeOrigin.Formal s) -> | Some (TypeOrigin.Formal s) ->
let pvar' = Pvar.mk s curr_pname in let pvar' = Pvar.mk s curr_pname in
Some (Sil.Lvar pvar') Some (Exp.Lvar pvar')
| _ -> None | _ -> None
end end
| _ -> None in | _ -> None in
match exp with match exp with
| Sil.Lfield (e, fn, typ) -> | Exp.Lfield (e, fn, typ) ->
let exp' = match handle_temporary e with let exp' = match handle_temporary e with
| Some e' -> | Some e' ->
Sil.Lfield (e', fn, typ) Exp.Lfield (e', fn, typ)
| None -> exp in | None -> exp in
exp' exp'
| _ -> exp in | _ -> exp in
@ -303,7 +303,7 @@ let typecheck_instr
(* Convert a function call to a pvar. *) (* Convert a function call to a pvar. *)
let handle_function_call call_node id = let handle_function_call call_node id =
match Errdesc.find_normal_variable_funcall call_node id with match Errdesc.find_normal_variable_funcall call_node id with
| Some (Sil.Const (Const.Cfun pn), _, _, _) | Some (Exp.Const (Const.Cfun pn), _, _, _)
when not (ComplexExpressions.procname_used_in_condition pn) -> when not (ComplexExpressions.procname_used_in_condition pn) ->
begin begin
match ComplexExpressions.exp_to_string node' exp with match ComplexExpressions.exp_to_string node' exp with
@ -319,16 +319,16 @@ let typecheck_instr
if is_assignment && already_defined_in_typestate if is_assignment && already_defined_in_typestate
then default (* Don't overwrite pvar representing result of function call. *) then default (* Don't overwrite pvar representing result of function call. *)
else Sil.Lvar pvar, typestate else Exp.Lvar pvar, typestate
end end
| _ -> default in | _ -> default in
match exp with match exp with
| Sil.Var id when | Exp.Var id when
ComplexExpressions.functions_idempotent () && ComplexExpressions.functions_idempotent () &&
Errdesc.find_normal_variable_funcall node' id <> None -> Errdesc.find_normal_variable_funcall node' id <> None ->
handle_function_call node' id handle_function_call node' id
| Sil.Lvar pvar when | Exp.Lvar pvar when
ComplexExpressions.functions_idempotent () && Pvar.is_frontend_tmp pvar -> ComplexExpressions.functions_idempotent () && Pvar.is_frontend_tmp pvar ->
let frontend_variable_assignment = let frontend_variable_assignment =
Errdesc.find_program_variable_assignment node pvar in Errdesc.find_program_variable_assignment node pvar in
@ -340,9 +340,9 @@ let typecheck_instr
| _ -> default | _ -> default
end end
| Sil.Lvar _ -> | Exp.Lvar _ ->
default default
| Sil.Lfield (_exp, fn, typ) when ComplexExpressions.parameter_and_static_field () -> | Exp.Lfield (_exp, fn, typ) when ComplexExpressions.parameter_and_static_field () ->
let exp' = Idenv.expand_expr_temps idenv node _exp in let exp' = Idenv.expand_expr_temps idenv node _exp in
let is_parameter_field pvar = (* parameter.field *) let is_parameter_field pvar = (* parameter.field *)
@ -354,29 +354,29 @@ let typecheck_instr
Pvar.is_global pvar in Pvar.is_global pvar in
let pvar_to_str pvar = let pvar_to_str pvar =
if Sil.exp_is_this (Sil.Lvar pvar) then "" if Sil.exp_is_this (Exp.Lvar pvar) then ""
else Pvar.to_string pvar ^ "_" in else Pvar.to_string pvar ^ "_" in
let res = match exp' with let res = match exp' with
| Sil.Lvar pv when is_parameter_field pv || is_static_field pv -> | Exp.Lvar pv when is_parameter_field pv || is_static_field pv ->
let fld_name = pvar_to_str pv ^ Ident.fieldname_to_string fn in let fld_name = pvar_to_str pv ^ Ident.fieldname_to_string fn in
let pvar = Pvar.mk (Mangled.from_string fld_name) curr_pname in let pvar = Pvar.mk (Mangled.from_string fld_name) curr_pname in
let typestate' = update_typestate_fld pvar fn typ in let typestate' = update_typestate_fld pvar fn typ in
(Sil.Lvar pvar, typestate') (Exp.Lvar pvar, typestate')
| Sil.Lfield (_exp', fn', _) when Ident.java_fieldname_is_outer_instance fn' -> | Exp.Lfield (_exp', fn', _) when Ident.java_fieldname_is_outer_instance fn' ->
(* handle double dereference when accessing a field from an outer class *) (* handle double dereference when accessing a field from an outer class *)
let fld_name = Ident.fieldname_to_string fn' ^ "_" ^ Ident.fieldname_to_string fn in let fld_name = Ident.fieldname_to_string fn' ^ "_" ^ Ident.fieldname_to_string fn in
let pvar = Pvar.mk (Mangled.from_string fld_name) curr_pname in let pvar = Pvar.mk (Mangled.from_string fld_name) curr_pname in
let typestate' = update_typestate_fld pvar fn typ in let typestate' = update_typestate_fld pvar fn typ in
(Sil.Lvar pvar, typestate') (Exp.Lvar pvar, typestate')
| Sil.Lvar _ | Sil.Lfield _ when ComplexExpressions.all_nested_fields () -> | Exp.Lvar _ | Exp.Lfield _ when ComplexExpressions.all_nested_fields () ->
(* treat var.field1. ... .fieldn as a constant *) (* treat var.field1. ... .fieldn as a constant *)
begin begin
match ComplexExpressions.exp_to_string node' exp with match ComplexExpressions.exp_to_string node' exp with
| Some exp_str -> | Some exp_str ->
let pvar = Pvar.mk (Mangled.from_string exp_str) curr_pname in let pvar = Pvar.mk (Mangled.from_string exp_str) curr_pname in
let typestate' = update_typestate_fld pvar fn typ in let typestate' = update_typestate_fld pvar fn typ in
(Sil.Lvar pvar, typestate') (Exp.Lvar pvar, typestate')
| None -> | None ->
default default
end end
@ -449,10 +449,10 @@ let typecheck_instr
typestate' typestate'
| Some (node', id) -> | Some (node', id) ->
(* handle the case where pvar is a frontend-generated program variable *) (* handle the case where pvar is a frontend-generated program variable *)
let exp = Idenv.expand_expr idenv (Sil.Var id) in let exp = Idenv.expand_expr idenv (Exp.Var id) in
begin begin
match convert_complex_exp_to_pvar node' false exp typestate' loc with match convert_complex_exp_to_pvar node' false exp typestate' loc with
| Sil.Lvar pvar', _ -> handle_pvar typestate' pvar' | Exp.Lvar pvar', _ -> handle_pvar typestate' pvar'
| _ -> typestate' | _ -> typestate'
end in end in
@ -482,14 +482,14 @@ let typecheck_instr
TypeState.add_id id TypeState.add_id id
(typecheck_expr_simple typestate' e' typ TypeOrigin.Undef loc) (typecheck_expr_simple typestate' e' typ TypeOrigin.Undef loc)
typestate' typestate'
| Sil.Set (Sil.Lvar pvar, _, Sil.Exn _, _) when is_return pvar -> | Sil.Set (Exp.Lvar pvar, _, Exp.Exn _, _) when is_return pvar ->
(* skip assignment to return variable where it is an artifact of a throw instruction *) (* skip assignment to return variable where it is an artifact of a throw instruction *)
typestate typestate
| Sil.Set (e1, typ, e2, loc) -> | Sil.Set (e1, typ, e2, loc) ->
typecheck_expr_for_errors typestate e1 loc; typecheck_expr_for_errors typestate e1 loc;
let e1', typestate1 = convert_complex_exp_to_pvar node true e1 typestate loc in let e1', typestate1 = convert_complex_exp_to_pvar node true e1 typestate loc in
let check_field_assign () = match e1 with let check_field_assign () = match e1 with
| Sil.Lfield (_, fn, f_typ) -> | Exp.Lfield (_, fn, f_typ) ->
let t_ia_opt = EradicateChecks.get_field_annotation fn f_typ in let t_ia_opt = EradicateChecks.get_field_annotation fn f_typ in
if checks.eradicate then if checks.eradicate then
EradicateChecks.check_field_assignment EradicateChecks.check_field_assignment
@ -499,25 +499,25 @@ let typecheck_instr
| _ -> () in | _ -> () in
let typestate2 = let typestate2 =
match e1' with match e1' with
| Sil.Lvar pvar -> | Exp.Lvar pvar ->
TypeState.add TypeState.add
pvar pvar
(typecheck_expr_simple typestate1 e2 typ TypeOrigin.Undef loc) (typecheck_expr_simple typestate1 e2 typ TypeOrigin.Undef loc)
typestate1 typestate1
| Sil.Lfield _ -> | Exp.Lfield _ ->
typestate1 typestate1
| _ -> | _ ->
typestate1 in typestate1 in
check_field_assign (); check_field_assign ();
typestate2 typestate2
| Sil.Call ([id], Sil.Const (Const.Cfun pn), [(_, typ)], loc, _) | Sil.Call ([id], Exp.Const (Const.Cfun pn), [(_, typ)], loc, _)
when Procname.equal pn ModelBuiltins.__new || when Procname.equal pn ModelBuiltins.__new ||
Procname.equal pn ModelBuiltins.__new_array -> Procname.equal pn ModelBuiltins.__new_array ->
TypeState.add_id TypeState.add_id
id id
(typ, TypeAnnotation.const Annotations.Nullable false TypeOrigin.New, [loc]) (typ, TypeAnnotation.const Annotations.Nullable false TypeOrigin.New, [loc])
typestate (* new never returns null *) typestate (* new never returns null *)
| Sil.Call ([id], Sil.Const (Const.Cfun pn), (e, typ):: _, loc, _) | Sil.Call ([id], Exp.Const (Const.Cfun pn), (e, typ):: _, loc, _)
when Procname.equal pn ModelBuiltins.__cast -> when Procname.equal pn ModelBuiltins.__cast ->
typecheck_expr_for_errors typestate e loc; typecheck_expr_for_errors typestate e loc;
let e', typestate' = let e', typestate' =
@ -526,7 +526,7 @@ let typecheck_instr
TypeState.add_id id TypeState.add_id id
(typecheck_expr_simple typestate' e' typ TypeOrigin.ONone loc) (typecheck_expr_simple typestate' e' typ TypeOrigin.ONone loc)
typestate' typestate'
| Sil.Call ([id], Sil.Const (Const.Cfun pn), [(array_exp, t)], loc, _) | Sil.Call ([id], Exp.Const (Const.Cfun pn), [(array_exp, t)], loc, _)
when Procname.equal pn ModelBuiltins.__get_array_length -> when Procname.equal pn ModelBuiltins.__get_array_length ->
let (_, ta, _) = typecheck_expr let (_, ta, _) = typecheck_expr
find_canonical_duplicate find_canonical_duplicate
@ -558,11 +558,11 @@ let typecheck_instr
[loc] [loc]
) )
typestate typestate
| Sil.Call (_, Sil.Const (Const.Cfun pn), _, _, _) when Builtin.is_registered pn -> | Sil.Call (_, Exp.Const (Const.Cfun pn), _, _, _) when Builtin.is_registered pn ->
typestate (* skip othe builtins *) typestate (* skip othe builtins *)
| Sil.Call | Sil.Call
(ret_ids, (ret_ids,
Sil.Const (Const.Cfun ((Procname.Java callee_pname_java) as callee_pname)), Exp.Const (Const.Cfun ((Procname.Java callee_pname_java) as callee_pname)),
etl_, etl_,
loc, loc,
cflags) cflags)
@ -651,7 +651,7 @@ let typecheck_instr
not (TypeAnnotation.origin_is_fun_library ta) in not (TypeAnnotation.origin_is_fun_library ta) in
if checks.eradicate && should_report then if checks.eradicate && should_report then
begin begin
let cond = Sil.BinOp (Binop.Ne, Sil.Lvar pvar, Sil.exp_null) in let cond = Exp.BinOp (Binop.Ne, Exp.Lvar pvar, Sil.exp_null) in
EradicateChecks.report_error EradicateChecks.report_error
find_canonical_duplicate find_canonical_duplicate
node node
@ -668,7 +668,7 @@ let typecheck_instr
typestate' in typestate' in
let rec find_parameter n eetl1 = match n, eetl1 with let rec find_parameter n eetl1 = match n, eetl1 with
| n, _ :: eetl2 when n > 1 -> find_parameter (n -1) eetl2 | n, _ :: eetl2 when n > 1 -> find_parameter (n -1) eetl2
| 1, ((_, Sil.Lvar pvar), typ):: _ -> Some (pvar, typ) | 1, ((_, Exp.Lvar pvar), typ):: _ -> Some (pvar, typ)
| _ -> None in | _ -> None in
match find_parameter parameter_num call_params with match find_parameter parameter_num call_params with
@ -676,7 +676,7 @@ let typecheck_instr
if is_vararg if is_vararg
then then
let do_vararg_value e ts = match Idenv.expand_expr idenv e with let do_vararg_value e ts = match Idenv.expand_expr idenv e with
| Sil.Lvar pvar1 -> | Exp.Lvar pvar1 ->
pvar_apply loc clear_nullable_flag ts pvar1 pvar_apply loc clear_nullable_flag ts pvar1
| _ -> ts in | _ -> ts in
let vararg_values = PatternMatch.java_get_vararg_values node pvar idenv in let vararg_values = PatternMatch.java_get_vararg_values node pvar idenv in
@ -705,13 +705,13 @@ let typecheck_instr
let handle_negated_condition cond_node = let handle_negated_condition cond_node =
let do_instr = function let do_instr = function
| Sil.Prune (Sil.BinOp (Binop.Eq, _cond_e, Sil.Const (Const.Cint i)), _, _, _) | Sil.Prune (Exp.BinOp (Binop.Eq, _cond_e, Exp.Const (Const.Cint i)), _, _, _)
| Sil.Prune (Sil.BinOp (Binop.Eq, Sil.Const (Const.Cint i), _cond_e), _, _, _) | Sil.Prune (Exp.BinOp (Binop.Eq, Exp.Const (Const.Cint i), _cond_e), _, _, _)
when IntLit.iszero i -> when IntLit.iszero i ->
let cond_e = Idenv.expand_expr_temps idenv cond_node _cond_e in let cond_e = Idenv.expand_expr_temps idenv cond_node _cond_e in
begin begin
match convert_complex_exp_to_pvar cond_node false cond_e typestate' loc with match convert_complex_exp_to_pvar cond_node false cond_e typestate' loc with
| Sil.Lvar pvar', _ -> | Exp.Lvar pvar', _ ->
set_flag pvar' Annotations.Nullable false set_flag pvar' Annotations.Nullable false
| _ -> () | _ -> ()
end end
@ -719,11 +719,11 @@ let typecheck_instr
IList.iter do_instr (Cfg.Node.get_instrs cond_node) in IList.iter do_instr (Cfg.Node.get_instrs cond_node) in
let handle_optional_isPresent node' e = let handle_optional_isPresent node' e =
match convert_complex_exp_to_pvar node' false e typestate' loc with match convert_complex_exp_to_pvar node' false e typestate' loc with
| Sil.Lvar pvar', _ -> | Exp.Lvar pvar', _ ->
set_flag pvar' Annotations.Present true set_flag pvar' Annotations.Present true
| _ -> () in | _ -> () in
match call_params with match call_params with
| ((_, Sil.Lvar pvar), _):: _ -> | ((_, Exp.Lvar pvar), _):: _ ->
(* temporary variable for the value of the boolean condition *) (* temporary variable for the value of the boolean condition *)
begin begin
let curr_node = TypeErr.InstrRef.get_node instr_ref in let curr_node = TypeErr.InstrRef.get_node instr_ref in
@ -741,7 +741,7 @@ let typecheck_instr
() ()
| Some (node', id) -> | Some (node', id) ->
let () = match Errdesc.find_normal_variable_funcall node' id with let () = match Errdesc.find_normal_variable_funcall node' id with
| Some (Sil.Const (Const.Cfun pn), [e], _, _) | Some (Exp.Const (Const.Cfun pn), [e], _, _)
when ComplexExpressions.procname_optional_isPresent pn -> when ComplexExpressions.procname_optional_isPresent pn ->
handle_optional_isPresent node' e handle_optional_isPresent node' e
| _ -> () in | _ -> () in
@ -763,7 +763,7 @@ let typecheck_instr
object_t) object_t)
parameters in parameters in
match call_params with match call_params with
| ((_, Sil.Lvar pv_map), _) :: | ((_, Exp.Lvar pv_map), _) ::
((_, exp_key), _) :: ((_, exp_key), _) ::
((_, exp_value), typ_value) :: _ -> ((_, exp_value), typ_value) :: _ ->
(* Convert the dexp for k to the dexp for m.get(k) *) (* Convert the dexp for k to the dexp for m.get(k) *)
@ -867,12 +867,12 @@ let typecheck_instr
| Sil.Prune (cond, loc, true_branch, _) -> | Sil.Prune (cond, loc, true_branch, _) ->
let rec check_condition node' c : _ TypeState.t = let rec check_condition node' c : _ TypeState.t =
(* check if the expression is coming from a call, and return the argument *) (* check if the expression is coming from a call, and return the argument *)
let from_call filter_callee e : Sil.exp option = let from_call filter_callee e : Exp.t option =
match e with match e with
| Sil.Var id -> | Exp.Var id ->
begin begin
match Errdesc.find_normal_variable_funcall node' id with match Errdesc.find_normal_variable_funcall node' id with
| Some (Sil.Const (Const.Cfun pn), e1:: _, _, _) when | Some (Exp.Const (Const.Cfun pn), e1:: _, _, _) when
filter_callee pn -> filter_callee pn ->
Some e1 Some e1
| _ -> None | _ -> None
@ -880,23 +880,23 @@ let typecheck_instr
| _ -> None in | _ -> None in
(* check if the expression is coming from instanceof *) (* check if the expression is coming from instanceof *)
let from_instanceof e : Sil.exp option = let from_instanceof e : Exp.t option =
from_call ComplexExpressions.procname_instanceof e in from_call ComplexExpressions.procname_instanceof e in
(* check if the expression is coming from Optional.isPresent *) (* check if the expression is coming from Optional.isPresent *)
let from_optional_isPresent e : Sil.exp option = let from_optional_isPresent e : Exp.t option =
from_call ComplexExpressions.procname_optional_isPresent e in from_call ComplexExpressions.procname_optional_isPresent e in
(* check if the expression is coming from a procedure returning false on null *) (* check if the expression is coming from a procedure returning false on null *)
let from_is_false_on_null e : Sil.exp option = let from_is_false_on_null e : Exp.t option =
from_call ComplexExpressions.procname_is_false_on_null e in from_call ComplexExpressions.procname_is_false_on_null e in
(* check if the expression is coming from a procedure returning true on null *) (* check if the expression is coming from a procedure returning true on null *)
let from_is_true_on_null e : Sil.exp option = let from_is_true_on_null e : Exp.t option =
from_call ComplexExpressions.procname_is_true_on_null e in from_call ComplexExpressions.procname_is_true_on_null e in
(* check if the expression is coming from Map.containsKey *) (* check if the expression is coming from Map.containsKey *)
let from_containsKey e : Sil.exp option = let from_containsKey e : Exp.t option =
from_call ComplexExpressions.procname_containsKey e in from_call ComplexExpressions.procname_containsKey e in
(* Turn x.containsKey(e) into the pvar for x.get(e) *) (* Turn x.containsKey(e) into the pvar for x.get(e) *)
@ -919,7 +919,7 @@ let typecheck_instr
| Some e_str -> | Some e_str ->
let pvar = let pvar =
Pvar.mk (Mangled.from_string e_str) curr_pname in Pvar.mk (Mangled.from_string e_str) curr_pname in
let e1 = Sil.Lvar pvar in let e1 = Exp.Lvar pvar in
let (typ, ta, _) = let (typ, ta, _) =
typecheck_expr_simple typestate e1 Typ.Tvoid TypeOrigin.ONone loc in typecheck_expr_simple typestate e1 Typ.Tvoid TypeOrigin.ONone loc in
let range = (typ, ta, [loc]) in let range = (typ, ta, [loc]) in
@ -939,13 +939,13 @@ let typecheck_instr
else typestate' else typestate'
| None -> typestate' in | None -> typestate' in
match e' with match e' with
| Sil.Lvar pvar -> | Exp.Lvar pvar ->
pvar_apply loc handle_pvar typestate2 pvar pvar_apply loc handle_pvar typestate2 pvar
| _ -> typestate2 in | _ -> typestate2 in
match c with match c with
| Sil.BinOp (Binop.Eq, Sil.Const (Const.Cint i), e) | Exp.BinOp (Binop.Eq, Exp.Const (Const.Cint i), e)
| Sil.BinOp (Binop.Eq, e, Sil.Const (Const.Cint i)) when IntLit.iszero i -> | Exp.BinOp (Binop.Eq, e, Exp.Const (Const.Cint i)) when IntLit.iszero i ->
typecheck_expr_for_errors typestate e loc; typecheck_expr_for_errors typestate e loc;
let typestate1, e1, from_call = match from_is_true_on_null e with let typestate1, e1, from_call = match from_is_true_on_null e with
| Some e1 -> | Some e1 ->
@ -973,8 +973,8 @@ let typecheck_instr
typestate2 typestate2
end end
| Sil.BinOp (Binop.Ne, Sil.Const (Const.Cint i), e) | Exp.BinOp (Binop.Ne, Exp.Const (Const.Cint i), e)
| Sil.BinOp (Binop.Ne, e, Sil.Const (Const.Cint i)) when IntLit.iszero i -> | Exp.BinOp (Binop.Ne, e, Exp.Const (Const.Cint i)) when IntLit.iszero i ->
typecheck_expr_for_errors typestate e loc; typecheck_expr_for_errors typestate e loc;
let typestate1, e1, from_call = match from_instanceof e with let typestate1, e1, from_call = match from_instanceof e with
| Some e1 -> (* (e1 instanceof C) implies (e1 != null) *) | Some e1 -> (* (e1 instanceof C) implies (e1 != null) *)
@ -1023,10 +1023,10 @@ let typecheck_instr
else typestate2 else typestate2
end end
| Sil.UnOp (Unop.LNot, (Sil.BinOp (Binop.Eq, e1, e2)), _) -> | Exp.UnOp (Unop.LNot, (Exp.BinOp (Binop.Eq, e1, e2)), _) ->
check_condition node' (Sil.BinOp (Binop.Ne, e1, e2)) check_condition node' (Exp.BinOp (Binop.Ne, e1, e2))
| Sil.UnOp (Unop.LNot, (Sil.BinOp (Binop.Ne, e1, e2)), _) -> | Exp.UnOp (Unop.LNot, (Exp.BinOp (Binop.Ne, e1, e2)), _) ->
check_condition node' (Sil.BinOp (Binop.Eq, e1, e2)) check_condition node' (Exp.BinOp (Binop.Eq, e1, e2))
| _ -> typestate in | _ -> typestate in
(* Handle assigment fron a temp pvar in a condition. (* Handle assigment fron a temp pvar in a condition.
@ -1037,7 +1037,7 @@ let typecheck_instr
let found = ref None in let found = ref None in
let do_instr i = match i with let do_instr i = match i with
| Sil.Set (e, _, e', _) | Sil.Set (e, _, e', _)
when Sil.exp_equal (Sil.Lvar pvar) (Idenv.expand_expr idenv e') -> when Sil.exp_equal (Exp.Lvar pvar) (Idenv.expand_expr idenv e') ->
found := Some e found := Some e
| _ -> () in | _ -> () in
IList.iter do_instr (Cfg.Node.get_instrs prev_node); IList.iter do_instr (Cfg.Node.get_instrs prev_node);
@ -1046,22 +1046,22 @@ let typecheck_instr
(* Normalize the condition by resolving temp variables. *) (* Normalize the condition by resolving temp variables. *)
let rec normalize_cond _node _cond = match _cond with let rec normalize_cond _node _cond = match _cond with
| Sil.UnOp (Unop.LNot, c, top) -> | Exp.UnOp (Unop.LNot, c, top) ->
let node', c' = normalize_cond _node c in let node', c' = normalize_cond _node c in
node', Sil.UnOp (Unop.LNot, c', top) node', Exp.UnOp (Unop.LNot, c', top)
| Sil.BinOp (bop, c1, c2) -> | Exp.BinOp (bop, c1, c2) ->
let node', c1' = normalize_cond _node c1 in let node', c1' = normalize_cond _node c1 in
let node'', c2' = normalize_cond node' c2 in let node'', c2' = normalize_cond node' c2 in
node'', Sil.BinOp (bop, c1', c2') node'', Exp.BinOp (bop, c1', c2')
| Sil.Var _ -> | Exp.Var _ ->
let c' = Idenv.expand_expr idenv _cond in let c' = Idenv.expand_expr idenv _cond in
if not (Sil.exp_equal c' _cond) then normalize_cond _node c' if not (Sil.exp_equal c' _cond) then normalize_cond _node c'
else _node, c' else _node, c'
| Sil.Lvar pvar when Pvar.is_frontend_tmp pvar -> | Exp.Lvar pvar when Pvar.is_frontend_tmp pvar ->
(match handle_assignment_in_condition pvar with (match handle_assignment_in_condition pvar with
| None -> | None ->
(match Errdesc.find_program_variable_assignment _node pvar with (match Errdesc.find_program_variable_assignment _node pvar with
| Some (node', id) -> node', Sil.Var id | Some (node', id) -> node', Exp.Var id
| None -> _node, _cond) | None -> _node, _cond)
| Some e2 -> _node, e2) | Some e2 -> _node, e2)
| c -> _node, c in | c -> _node, c in
@ -1081,7 +1081,7 @@ let typecheck_node
let typestates_exn = ref [] in let typestates_exn = ref [] in
let handle_exceptions typestate instr = match instr with let handle_exceptions typestate instr = match instr with
| Sil.Call (_, Sil.Const (Const.Cfun callee_pname), _, _, _) -> | Sil.Call (_, Exp.Const (Const.Cfun callee_pname), _, _, _) ->
let callee_attributes_opt = let callee_attributes_opt =
Specs.proc_resolve_attributes callee_pname in Specs.proc_resolve_attributes callee_pname in
(* check if the call might throw an exception *) (* check if the call might throw an exception *)
@ -1091,7 +1091,7 @@ let typecheck_node
| None -> false in | None -> false in
if has_exceptions then if has_exceptions then
typestates_exn := typestate :: !typestates_exn typestates_exn := typestate :: !typestates_exn
| Sil.Set (Sil.Lvar pv, _, _, _) when | Sil.Set (Exp.Lvar pv, _, _, _) when
Pvar.is_return pv && Pvar.is_return pv &&
Cfg.Node.get_kind node = Cfg.Node.throw_kind -> Cfg.Node.get_kind node = Cfg.Node.throw_kind ->
(* throw instruction *) (* throw instruction *)

@ -16,7 +16,7 @@ module P = Printf
(** Module for typestates: maps from expressions to annotated types, with extensions. *) (** Module for typestates: maps from expressions to annotated types, with extensions. *)
(** Parameters of a call. *) (** Parameters of a call. *)
type parameters = (Sil.exp * Typ.t) list type parameters = (Exp.t * Typ.t) list
type get_proc_desc = Procname.t -> Cfg.Procdesc.t option type get_proc_desc = Procname.t -> Cfg.Procdesc.t option
@ -34,7 +34,7 @@ type 'a ext =
module M = Map.Make (struct module M = Map.Make (struct
type t = Sil.exp type t = Exp.t
let compare = Sil.exp_compare end) let compare = Sil.exp_compare end)
type range = Typ.t * TypeAnnotation.t * (Location.t list) type range = Typ.t * TypeAnnotation.t * (Location.t list)
@ -130,25 +130,25 @@ let join ext t1 t2 =
} }
let lookup_id id typestate = let lookup_id id typestate =
try Some (M.find (Sil.Var id) typestate.map) try Some (M.find (Exp.Var id) typestate.map)
with Not_found -> None with Not_found -> None
let lookup_pvar pvar typestate = let lookup_pvar pvar typestate =
try Some (M.find (Sil.Lvar pvar) typestate.map) try Some (M.find (Exp.Lvar pvar) typestate.map)
with Not_found -> None with Not_found -> None
let add_id id range typestate = let add_id id range typestate =
let map' = M.add (Sil.Var id) range typestate.map in let map' = M.add (Exp.Var id) range typestate.map in
if map' == typestate.map then typestate if map' == typestate.map then typestate
else { typestate with map = map' } else { typestate with map = map' }
let add pvar range typestate = let add pvar range typestate =
let map' = M.add (Sil.Lvar pvar) range typestate.map in let map' = M.add (Exp.Lvar pvar) range typestate.map in
if map' == typestate.map then typestate if map' == typestate.map then typestate
else { typestate with map = map' } else { typestate with map = map' }
let remove_id id typestate = let remove_id id typestate =
let map' = M.remove (Sil.Var id) typestate.map in let map' = M.remove (Exp.Var id) typestate.map in
if map' == typestate.map then typestate if map' == typestate.map then typestate
else { typestate with map = map' } else { typestate with map = map' }

@ -12,7 +12,7 @@ open! Utils
(** Module for typestates: maps from expressions to annotated types, with extensions. *) (** Module for typestates: maps from expressions to annotated types, with extensions. *)
(** Parameters of a call. *) (** Parameters of a call. *)
type parameters = (Sil.exp * Typ.t) list type parameters = (Exp.t * Typ.t) list
type get_proc_desc = Procname.t -> Cfg.Procdesc.t option type get_proc_desc = Procname.t -> Cfg.Procdesc.t option

@ -24,7 +24,7 @@ type lifecycle_trace = (Procname.t * Typ.t option) list
(** list of instrs and temporary variables created during inhabitation and a cache of types that (** list of instrs and temporary variables created during inhabitation and a cache of types that
* have already been inhabited *) * have already been inhabited *)
type env = { instrs : Sil.instr list; type env = { instrs : Sil.instr list;
cache : Sil.exp TypMap.t; cache : Exp.t TypMap.t;
(* set of types currently being inhabited. consult to prevent infinite recursion *) (* set of types currently being inhabited. consult to prevent infinite recursion *)
cur_inhabiting : TypSet.t; cur_inhabiting : TypSet.t;
pc : Location.t; pc : Location.t;
@ -52,7 +52,7 @@ let env_add_instr instr env =
(** call flags for an allocation or call to a constructor *) (** call flags for an allocation or call to a constructor *)
let cf_alloc = CallFlags.default let cf_alloc = CallFlags.default
let fun_exp_from_name proc_name = Sil.Const (Const.Cfun (proc_name)) let fun_exp_from_name proc_name = Exp.Const (Const.Cfun (proc_name))
let local_name_cntr = ref 0 let local_name_cntr = ref 0
@ -70,10 +70,10 @@ let get_non_receiver_formals formals = tl_or_empty formals
* component but the size component of ret_typ is always -1. *) * component but the size component of ret_typ is always -1. *)
let inhabit_alloc sizeof_typ sizeof_len ret_typ alloc_kind env = let inhabit_alloc sizeof_typ sizeof_len ret_typ alloc_kind env =
let retval = Ident.create_fresh Ident.knormal in let retval = Ident.create_fresh Ident.knormal in
let inhabited_exp = Sil.Var retval in let inhabited_exp = Exp.Var retval in
let call_instr = let call_instr =
let fun_new = fun_exp_from_name alloc_kind in let fun_new = fun_exp_from_name alloc_kind in
let sizeof_exp = Sil.Sizeof (sizeof_typ, sizeof_len, Subtype.exact) in let sizeof_exp = Exp.Sizeof (sizeof_typ, sizeof_len, Subtype.exact) in
let args = [(sizeof_exp, Typ.Tptr (ret_typ, Typ.Pk_pointer))] in let args = [(sizeof_exp, Typ.Tptr (ret_typ, Typ.Pk_pointer))] in
Sil.Call ([retval], fun_new, args, env.pc, cf_alloc) in Sil.Call ([retval], fun_new, args, env.pc, cf_alloc) in
(inhabited_exp, env_add_instr call_instr env) (inhabited_exp, env_add_instr call_instr env)
@ -85,7 +85,7 @@ let rec inhabit_typ typ cfg env =
with Not_found -> with Not_found ->
let inhabit_internal typ env = match typ with let inhabit_internal typ env = match typ with
| Typ.Tptr (Typ.Tarray (inner_typ, Some _), Typ.Pk_pointer) -> | Typ.Tptr (Typ.Tarray (inner_typ, Some _), Typ.Pk_pointer) ->
let len = Sil.Const (Const.Cint (IntLit.one)) in let len = Exp.Const (Const.Cint (IntLit.one)) in
let arr_typ = Typ.Tarray (inner_typ, Some IntLit.one) in let arr_typ = Typ.Tarray (inner_typ, Some IntLit.one) in
inhabit_alloc arr_typ (Some len) typ ModelBuiltins.__new_array env inhabit_alloc arr_typ (Some len) typ ModelBuiltins.__new_array env
| Typ.Tptr (typ, Typ.Pk_pointer) as ptr_to_typ -> | Typ.Tptr (typ, Typ.Pk_pointer) as ptr_to_typ ->
@ -123,15 +123,15 @@ let rec inhabit_typ typ cfg env =
* both fresh. the only point of this is to add a descriptive local name that makes error * both fresh. the only point of this is to add a descriptive local name that makes error
* reports from the harness look nicer -- it's not necessary to make symbolic execution work *) * reports from the harness look nicer -- it's not necessary to make symbolic execution work *)
let fresh_local_exp = let fresh_local_exp =
Sil.Lvar (Pvar.mk typ_class_name (Procname.Java env.harness_name)) in Exp.Lvar (Pvar.mk typ_class_name (Procname.Java env.harness_name)) in
let write_to_local_instr = let write_to_local_instr =
Sil.Set (fresh_local_exp, ptr_to_typ, allocated_obj_exp, env.pc) in Sil.Set (fresh_local_exp, ptr_to_typ, allocated_obj_exp, env.pc) in
let env' = env_add_instr write_to_local_instr env in let env' = env_add_instr write_to_local_instr env in
let fresh_id = Ident.create_fresh Ident.knormal in let fresh_id = Ident.create_fresh Ident.knormal in
let read_from_local_instr = Sil.Letderef (fresh_id, fresh_local_exp, ptr_to_typ, env'.pc) in let read_from_local_instr = Sil.Letderef (fresh_id, fresh_local_exp, ptr_to_typ, env'.pc) in
(Sil.Var fresh_id, env_add_instr read_from_local_instr env') (Exp.Var fresh_id, env_add_instr read_from_local_instr env')
| Typ.Tint (_) -> (Sil.Const (Const.Cint (IntLit.zero)), env) | Typ.Tint (_) -> (Exp.Const (Const.Cint (IntLit.zero)), env)
| Typ.Tfloat (_) -> (Sil.Const (Const.Cfloat 0.0), env) | Typ.Tfloat (_) -> (Exp.Const (Const.Cfloat 0.0), env)
| typ -> | typ ->
L.err "Couldn't inhabit typ: %a@." (Typ.pp pe_text) typ; L.err "Couldn't inhabit typ: %a@." (Typ.pp pe_text) typ;
assert false in assert false in

@ -398,10 +398,10 @@ let use_static_final_fields context =
(not Config.no_static_final) && (JContext.get_meth_kind context) <> JContext.Init (not Config.no_static_final) && (JContext.get_meth_kind context) <> JContext.Init
let builtin_new = let builtin_new =
Sil.Const (Const.Cfun ModelBuiltins.__new) Exp.Const (Const.Cfun ModelBuiltins.__new)
let builtin_get_array_length = let builtin_get_array_length =
Sil.Const (Const.Cfun ModelBuiltins.__get_array_length) Exp.Const (Const.Cfun ModelBuiltins.__get_array_length)
let create_sil_deref exp typ loc = let create_sil_deref exp typ loc =
let no_id = Ident.create_none () in let no_id = Ident.create_none () in
@ -417,8 +417,8 @@ let rec expression context pc expr =
let type_of_expr = JTransType.expr_type context expr in let type_of_expr = JTransType.expr_type context expr in
let trans_var pvar = let trans_var pvar =
let id = Ident.create_fresh Ident.knormal in let id = Ident.create_fresh Ident.knormal in
let sil_instr = Sil.Letderef (id, Sil.Lvar pvar, type_of_expr, loc) in let sil_instr = Sil.Letderef (id, Exp.Lvar pvar, type_of_expr, loc) in
([sil_instr], Sil.Var id, type_of_expr) in ([sil_instr], Exp.Var id, type_of_expr) in
match expr with match expr with
| JBir.Var (_, var) -> | JBir.Var (_, var) ->
let pvar = (JContext.set_pvar context var type_of_expr) in let pvar = (JContext.set_pvar context var type_of_expr) in
@ -431,14 +431,14 @@ let rec expression context pc expr =
let procname = (Cfg.Procdesc.get_proc_name (JContext.get_procdesc context)) in let procname = (Cfg.Procdesc.get_proc_name (JContext.get_procdesc context)) in
let pvar = Pvar.mk varname procname in let pvar = Pvar.mk varname procname in
trans_var pvar trans_var pvar
| _ -> ([], Sil.Const (get_constant c), type_of_expr) | _ -> ([], Exp.Const (get_constant c), type_of_expr)
end end
| JBir.Unop (unop, ex) -> | JBir.Unop (unop, ex) ->
let type_of_ex = JTransType.expr_type context ex in let type_of_ex = JTransType.expr_type context ex in
let (instrs, sil_ex, _) = expression context pc ex in let (instrs, sil_ex, _) = expression context pc ex in
begin begin
match unop with match unop with
| JBir.Neg _ -> (instrs, Sil.UnOp (Unop.Neg, sil_ex, Some type_of_expr), type_of_expr) | JBir.Neg _ -> (instrs, Exp.UnOp (Unop.Neg, sil_ex, Some type_of_expr), type_of_expr)
| JBir.ArrayLength -> | JBir.ArrayLength ->
let array_typ_no_ptr = let array_typ_no_ptr =
match type_of_ex with match type_of_ex with
@ -449,9 +449,9 @@ let rec expression context pc expr =
let ret_id = Ident.create_fresh Ident.knormal in let ret_id = Ident.create_fresh Ident.knormal in
let call_instr = let call_instr =
Sil.Call ([ret_id], builtin_get_array_length, args, loc, CallFlags.default) in Sil.Call ([ret_id], builtin_get_array_length, args, loc, CallFlags.default) in
(instrs @ [deref; call_instr], Sil.Var ret_id, type_of_expr) (instrs @ [deref; call_instr], Exp.Var ret_id, type_of_expr)
| JBir.Conv conv -> | JBir.Conv conv ->
let cast_ex = Sil.Cast (JTransType.cast_type conv, sil_ex) in let cast_ex = Exp.Cast (JTransType.cast_type conv, sil_ex) in
(instrs, cast_ex, type_of_expr) (instrs, cast_ex, type_of_expr)
| JBir.InstanceOf ot | JBir.Cast ot -> | JBir.InstanceOf ot | JBir.Cast ot ->
let subtypes = let subtypes =
@ -463,13 +463,13 @@ let rec expression context pc expr =
JTransType.sizeof_of_object_type program tenv ot subtypes in JTransType.sizeof_of_object_type program tenv ot subtypes in
let builtin = let builtin =
(match unop with (match unop with
| JBir.InstanceOf _ -> Sil.Const (Const.Cfun ModelBuiltins.__instanceof) | JBir.InstanceOf _ -> Exp.Const (Const.Cfun ModelBuiltins.__instanceof)
| JBir.Cast _ -> Sil.Const (Const.Cfun ModelBuiltins.__cast) | JBir.Cast _ -> Exp.Const (Const.Cfun ModelBuiltins.__cast)
| _ -> assert false) in | _ -> assert false) in
let args = [(sil_ex, type_of_ex); (sizeof_expr, Typ.Tvoid)] in let args = [(sil_ex, type_of_ex); (sizeof_expr, Typ.Tvoid)] in
let ret_id = Ident.create_fresh Ident.knormal in let ret_id = Ident.create_fresh Ident.knormal in
let call = Sil.Call([ret_id], builtin, args, loc, CallFlags.default) in let call = Sil.Call([ret_id], builtin, args, loc, CallFlags.default) in
let res_ex = Sil.Var ret_id in let res_ex = Exp.Var ret_id in
(instrs @ [call], res_ex, type_of_expr) (instrs @ [call], res_ex, type_of_expr)
end end
| JBir.Binop (binop, ex1, ex2) -> | JBir.Binop (binop, ex1, ex2) ->
@ -483,27 +483,27 @@ let rec expression context pc expr =
let deref_array_instr = create_sil_deref sil_ex1 array_typ loc in let deref_array_instr = create_sil_deref sil_ex1 array_typ loc in
let id = Ident.create_fresh Ident.knormal in let id = Ident.create_fresh Ident.knormal in
let letderef_instr = let letderef_instr =
Sil.Letderef (id, Sil.Lindex (sil_ex1, sil_ex2), type_of_expr, loc) in Sil.Letderef (id, Exp.Lindex (sil_ex1, sil_ex2), type_of_expr, loc) in
let instrs = (instrs1 @ (deref_array_instr :: instrs2)) @ [letderef_instr] in let instrs = (instrs1 @ (deref_array_instr :: instrs2)) @ [letderef_instr] in
instrs, Sil.Var id, type_of_expr instrs, Exp.Var id, type_of_expr
| other_binop -> | other_binop ->
let sil_binop = get_binop other_binop in let sil_binop = get_binop other_binop in
let sil_expr = Sil.BinOp (sil_binop, sil_ex1, sil_ex2) in let sil_expr = Exp.BinOp (sil_binop, sil_ex1, sil_ex2) in
((instrs1 @ instrs2), sil_expr, type_of_expr) ((instrs1 @ instrs2), sil_expr, type_of_expr)
end end
| JBir.Field (ex, cn, fs) -> | JBir.Field (ex, cn, fs) ->
let (instrs, sil_expr, _) = expression context pc ex in let (instrs, sil_expr, _) = expression context pc ex in
let field_name = get_field_name program false tenv cn fs in let field_name = get_field_name program false tenv cn fs in
let sil_type = JTransType.get_class_type_no_pointer program tenv cn in let sil_type = JTransType.get_class_type_no_pointer program tenv cn in
let sil_expr = Sil.Lfield (sil_expr, field_name, sil_type) in let sil_expr = Exp.Lfield (sil_expr, field_name, sil_type) in
let tmp_id = Ident.create_fresh Ident.knormal in let tmp_id = Ident.create_fresh Ident.knormal in
let lderef_instr = Sil.Letderef (tmp_id, sil_expr, sil_type, loc) in let lderef_instr = Sil.Letderef (tmp_id, sil_expr, sil_type, loc) in
(instrs @ [lderef_instr], Sil.Var tmp_id, type_of_expr) (instrs @ [lderef_instr], Exp.Var tmp_id, type_of_expr)
| JBir.StaticField (cn, fs) -> | JBir.StaticField (cn, fs) ->
let class_exp = let class_exp =
let classname = Mangled.from_string (JBasics.cn_name cn) in let classname = Mangled.from_string (JBasics.cn_name cn) in
let var_name = Pvar.mk_global classname in let var_name = Pvar.mk_global classname in
Sil.Lvar var_name in Exp.Lvar var_name in
let (instrs, sil_expr) = [], class_exp in let (instrs, sil_expr) = [], class_exp in
let field_name = get_field_name program true tenv cn fs in let field_name = get_field_name program true tenv cn fs in
let sil_type = JTransType.get_class_type_no_pointer program tenv cn in let sil_type = JTransType.get_class_type_no_pointer program tenv cn in
@ -527,10 +527,10 @@ let rec expression context pc expr =
(* Infer to understand the assert keyword in the expected way *) (* Infer to understand the assert keyword in the expected way *)
(instrs, Sil.exp_zero, type_of_expr) (instrs, Sil.exp_zero, type_of_expr)
else else
let sil_expr = Sil.Lfield (sil_expr, field_name, sil_type) in let sil_expr = Exp.Lfield (sil_expr, field_name, sil_type) in
let tmp_id = Ident.create_fresh Ident.knormal in let tmp_id = Ident.create_fresh Ident.knormal in
let lderef_instr = Sil.Letderef (tmp_id, sil_expr, sil_type, loc) in let lderef_instr = Sil.Letderef (tmp_id, sil_expr, sil_type, loc) in
(instrs @ [lderef_instr], Sil.Var tmp_id, type_of_expr) (instrs @ [lderef_instr], Exp.Var tmp_id, type_of_expr)
let method_invocation context loc pc var_opt cn ms sil_obj_opt expr_list invoke_code method_kind = let method_invocation context loc pc var_opt cn ms sil_obj_opt expr_list invoke_code method_kind =
(* This function tries to recursively search for the classname of the class *) (* This function tries to recursively search for the classname of the class *)
@ -571,7 +571,7 @@ let method_invocation context loc pc var_opt cn ms sil_obj_opt expr_list invoke_
| I_Special -> false | I_Special -> false
| _ -> true in | _ -> true in
match sil_obj_expr with match sil_obj_expr with
| Sil.Var _ when is_non_constructor_call && not Config.report_runtime_exceptions -> | Exp.Var _ when is_non_constructor_call && not Config.report_runtime_exceptions ->
let obj_typ_no_ptr = let obj_typ_no_ptr =
match sil_obj_type with match sil_obj_type with
| Typ.Tptr (typ, _) -> typ | Typ.Tptr (typ, _) -> typ
@ -593,7 +593,7 @@ let method_invocation context loc pc var_opt cn ms sil_obj_opt expr_list invoke_
then proc then proc
else Procname.Java (JTransType.get_method_procname cn' ms method_kind) in else Procname.Java (JTransType.get_method_procname cn' ms method_kind) in
let call_instrs = let call_instrs =
let callee_fun = Sil.Const (Const.Cfun callee_procname) in let callee_fun = Exp.Const (Const.Cfun callee_procname) in
let return_type = let return_type =
match JBasics.ms_rtype ms with match JBasics.ms_rtype ms with
| None -> Typ.Tvoid | None -> Typ.Tvoid
@ -601,7 +601,7 @@ let method_invocation context loc pc var_opt cn ms sil_obj_opt expr_list invoke_
let call_ret_instrs sil_var = let call_ret_instrs sil_var =
let ret_id = Ident.create_fresh Ident.knormal in let ret_id = Ident.create_fresh Ident.knormal in
let call_instr = Sil.Call ([ret_id], callee_fun, call_args, loc, call_flags) in let call_instr = Sil.Call ([ret_id], callee_fun, call_args, loc, call_flags) in
let set_instr = Sil.Set (Sil.Lvar sil_var, return_type, Sil.Var ret_id, loc) in let set_instr = Sil.Set (Exp.Lvar sil_var, return_type, Exp.Var ret_id, loc) in
(instrs @ [call_instr; set_instr]) in (instrs @ [call_instr; set_instr]) in
match var_opt with match var_opt with
| None -> | None ->
@ -619,7 +619,7 @@ let method_invocation context loc pc var_opt cn ms sil_obj_opt expr_list invoke_
| (_, typ) as exp :: _ | (_, typ) as exp :: _
when Procname.is_constructor callee_procname && JTransType.is_closeable program tenv typ -> when Procname.is_constructor callee_procname && JTransType.is_closeable program tenv typ ->
let set_file_attr = let set_file_attr =
let set_builtin = Sil.Const (Const.Cfun ModelBuiltins.__set_file_attribute) in let set_builtin = Exp.Const (Const.Cfun ModelBuiltins.__set_file_attribute) in
Sil.Call ([], set_builtin, [exp], loc, CallFlags.default) in Sil.Call ([], set_builtin, [exp], loc, CallFlags.default) in
(* Exceptions thrown in the constructor should prevent adding the resource attribute *) (* Exceptions thrown in the constructor should prevent adding the resource attribute *)
call_instrs @ [set_file_attr] call_instrs @ [set_file_attr]
@ -628,7 +628,7 @@ let method_invocation context loc pc var_opt cn ms sil_obj_opt expr_list invoke_
| (_, typ) as exp :: [] | (_, typ) as exp :: []
when Procname.java_is_close callee_procname && JTransType.is_closeable program tenv typ -> when Procname.java_is_close callee_procname && JTransType.is_closeable program tenv typ ->
let set_mem_attr = let set_mem_attr =
let set_builtin = Sil.Const (Const.Cfun ModelBuiltins.__set_mem_attribute) in let set_builtin = Exp.Const (Const.Cfun ModelBuiltins.__set_mem_attribute) in
Sil.Call ([], set_builtin, [exp], loc, CallFlags.default) in Sil.Call ([], set_builtin, [exp], loc, CallFlags.default) in
(* Exceptions thrown in the close method should not prevent the resource from being *) (* Exceptions thrown in the close method should not prevent the resource from being *)
(* considered as closed *) (* considered as closed *)
@ -649,7 +649,7 @@ let get_array_length context pc expr_list content_type =
(Typ.Tarray (content_type, None), Some sil_len_expr) in (Typ.Tarray (content_type, None), Some sil_len_expr) in
let array_type, array_len = let array_type, array_len =
IList.fold_right get_array_type_len sil_len_exprs (content_type, None) in IList.fold_right get_array_type_len sil_len_exprs (content_type, None) in
let array_size = Sil.Sizeof (array_type, array_len, Subtype.exact) in let array_size = Exp.Sizeof (array_type, array_len, Subtype.exact) in
(instrs, array_size) (instrs, array_size)
let detect_loop entry_pc impl = let detect_loop entry_pc impl =
@ -759,9 +759,9 @@ let is_this expr =
let assume_not_null loc sil_expr = let assume_not_null loc sil_expr =
let builtin_infer_assume = Sil.Const (Const.Cfun ModelBuiltins.__infer_assume) in let builtin_infer_assume = Exp.Const (Const.Cfun ModelBuiltins.__infer_assume) in
let not_null_expr = let not_null_expr =
Sil.BinOp (Binop.Ne, sil_expr, Sil.exp_null) in Exp.BinOp (Binop.Ne, sil_expr, Sil.exp_null) in
let assume_call_flag = { CallFlags.default with CallFlags.cf_noreturn = true; } in let assume_call_flag = { CallFlags.default with CallFlags.cf_noreturn = true; } in
let call_args = [(not_null_expr, Typ.Tint Typ.IBool)] in let call_args = [(not_null_expr, Typ.Tint Typ.IBool)] in
Sil.Call ([], builtin_infer_assume, call_args, loc, assume_call_flag) Sil.Call ([], builtin_infer_assume, call_args, loc, assume_call_flag)
@ -793,7 +793,7 @@ let rec instruction context pc instr : translation =
JTransType.never_returning_null in JTransType.never_returning_null in
let trans_monitor_enter_exit context expr pc loc builtin node_desc = let trans_monitor_enter_exit context expr pc loc builtin node_desc =
let instrs, sil_expr, sil_type = expression context pc expr in let instrs, sil_expr, sil_type = expression context pc expr in
let builtin_const = Sil.Const (Const.Cfun builtin) in let builtin_const = Exp.Const (Const.Cfun builtin) in
let instr = Sil.Call ([], builtin_const, [(sil_expr, sil_type)], loc, CallFlags.default) in let instr = Sil.Call ([], builtin_const, [(sil_expr, sil_type)], loc, CallFlags.default) in
let typ_no_ptr = match sil_type with let typ_no_ptr = match sil_type with
| Typ.Tptr (typ, _) -> typ | Typ.Tptr (typ, _) -> typ
@ -806,7 +806,7 @@ let rec instruction context pc instr : translation =
| JBir.AffectVar (var, expr) -> | JBir.AffectVar (var, expr) ->
let (stml, sil_expr, sil_type) = expression context pc expr in let (stml, sil_expr, sil_type) = expression context pc expr in
let pvar = (JContext.set_pvar context var sil_type) in let pvar = (JContext.set_pvar context var sil_type) in
let sil_instr = Sil.Set (Sil.Lvar pvar, sil_type, sil_expr, loc) in let sil_instr = Sil.Set (Exp.Lvar pvar, sil_type, sil_expr, loc) in
let node_kind = Cfg.Node.Stmt_node "method_body" in let node_kind = Cfg.Node.Stmt_node "method_body" in
let node = create_node node_kind (stml @ [sil_instr]) in let node = create_node node_kind (stml @ [sil_instr]) in
Instr node Instr node
@ -819,7 +819,7 @@ let rec instruction context pc instr : translation =
| Some expr -> | Some expr ->
let (stml, sil_expr, _) = expression context pc expr in let (stml, sil_expr, _) = expression context pc expr in
let sil_instrs = let sil_instrs =
let return_instr = Sil.Set (Sil.Lvar ret_var, ret_type, sil_expr, loc) in let return_instr = Sil.Set (Exp.Lvar ret_var, ret_type, sil_expr, loc) in
if return_not_null () then if return_not_null () then
[assume_not_null loc sil_expr; return_instr] [assume_not_null loc sil_expr; return_instr]
else else
@ -832,7 +832,8 @@ let rec instruction context pc instr : translation =
and (instrs_index, sil_expr_index, _) = expression context pc index_ex and (instrs_index, sil_expr_index, _) = expression context pc index_ex
and (instrs_value, sil_expr_value, _) = expression context pc value_ex in and (instrs_value, sil_expr_value, _) = expression context pc value_ex in
let arr_type_np = JTransType.extract_cn_type_np arr_type in let arr_type_np = JTransType.extract_cn_type_np arr_type in
let sil_instr = Sil.Set (Sil.Lindex (sil_expr_array, sil_expr_index), arr_type_np, sil_expr_value, loc) in let sil_instr =
Sil.Set (Exp.Lindex (sil_expr_array, sil_expr_index), arr_type_np, sil_expr_value, loc) in
let final_instrs = instrs_array @ instrs_index @ instrs_value @ [sil_instr] in let final_instrs = instrs_array @ instrs_index @ instrs_value @ [sil_instr] in
let node_kind = Cfg.Node.Stmt_node "method_body" in let node_kind = Cfg.Node.Stmt_node "method_body" in
let node = create_node node_kind final_instrs in let node = create_node node_kind final_instrs in
@ -843,7 +844,7 @@ let rec instruction context pc instr : translation =
let field_name = get_field_name program false tenv cn fs in let field_name = get_field_name program false tenv cn fs in
let type_of_the_surrounding_class = JTransType.get_class_type_no_pointer program tenv cn in let type_of_the_surrounding_class = JTransType.get_class_type_no_pointer program tenv cn in
let type_of_the_root_of_e_lhs = type_of_the_surrounding_class in let type_of_the_root_of_e_lhs = type_of_the_surrounding_class in
let expr_off = Sil.Lfield(sil_expr_lhs, field_name, type_of_the_surrounding_class) in let expr_off = Exp.Lfield(sil_expr_lhs, field_name, type_of_the_surrounding_class) in
let sil_instr = Sil.Set (expr_off, type_of_the_root_of_e_lhs, sil_expr_rhs, loc) in let sil_instr = Sil.Set (expr_off, type_of_the_root_of_e_lhs, sil_expr_rhs, loc) in
let node_kind = Cfg.Node.Stmt_node "method_body" in let node_kind = Cfg.Node.Stmt_node "method_body" in
let node = create_node node_kind (stml1 @ stml2 @ [sil_instr]) in let node = create_node node_kind (stml1 @ stml2 @ [sil_instr]) in
@ -852,13 +853,13 @@ let rec instruction context pc instr : translation =
let class_exp = let class_exp =
let classname = Mangled.from_string (JBasics.cn_name cn) in let classname = Mangled.from_string (JBasics.cn_name cn) in
let var_name = Pvar.mk_global classname in let var_name = Pvar.mk_global classname in
Sil.Lvar var_name in Exp.Lvar var_name in
let (stml1, sil_expr_lhs) = [], class_exp in let (stml1, sil_expr_lhs) = [], class_exp in
let (stml2, sil_expr_rhs, _) = expression context pc e_rhs in let (stml2, sil_expr_rhs, _) = expression context pc e_rhs in
let field_name = get_field_name program true tenv cn fs in let field_name = get_field_name program true tenv cn fs in
let type_of_the_surrounding_class = JTransType.get_class_type_no_pointer program tenv cn in let type_of_the_surrounding_class = JTransType.get_class_type_no_pointer program tenv cn in
let type_of_the_root_of_e_lhs = type_of_the_surrounding_class in let type_of_the_root_of_e_lhs = type_of_the_surrounding_class in
let expr_off = Sil.Lfield(sil_expr_lhs, field_name, type_of_the_surrounding_class) in let expr_off = Exp.Lfield(sil_expr_lhs, field_name, type_of_the_surrounding_class) in
let sil_instr = Sil.Set (expr_off, type_of_the_root_of_e_lhs, sil_expr_rhs, loc) in let sil_instr = Sil.Set (expr_off, type_of_the_root_of_e_lhs, sil_expr_rhs, loc) in
let node_kind = Cfg.Node.Stmt_node "method_body" in let node_kind = Cfg.Node.Stmt_node "method_body" in
let node = create_node node_kind (stml1 @ stml2 @ [sil_instr]) in let node = create_node node_kind (stml1 @ stml2 @ [sil_instr]) in
@ -872,8 +873,8 @@ let rec instruction context pc instr : translation =
let (instrs1, sil_ex1, _) = expression context pc e1 let (instrs1, sil_ex1, _) = expression context pc e1
and (instrs2, sil_ex2, _) = expression context pc e2 in and (instrs2, sil_ex2, _) = expression context pc e2 in
let sil_op = get_test_operator op in let sil_op = get_test_operator op in
let sil_test_false = Sil.BinOp (sil_op, sil_ex1, sil_ex2) in let sil_test_false = Exp.BinOp (sil_op, sil_ex1, sil_ex2) in
let sil_test_true = Sil.UnOp(Unop.LNot, sil_test_false, None) in let sil_test_true = Exp.UnOp(Unop.LNot, sil_test_false, None) in
let sil_instrs_true = Sil.Prune (sil_test_true, loc, true, Sil.Ik_if) in let sil_instrs_true = Sil.Prune (sil_test_true, loc, true, Sil.Ik_if) in
let sil_instrs_false = Sil.Prune (sil_test_false, loc, false, Sil.Ik_if) in let sil_instrs_false = Sil.Prune (sil_test_false, loc, false, Sil.Ik_if) in
let node_kind_true = Cfg.Node.Prune_node (true, Sil.Ik_if, "method_body") in let node_kind_true = Cfg.Node.Prune_node (true, Sil.Ik_if, "method_body") in
@ -890,26 +891,26 @@ let rec instruction context pc instr : translation =
Prune (prune_node_true, prune_node_false) Prune (prune_node_true, prune_node_false)
| JBir.Throw expr -> | JBir.Throw expr ->
let (instrs, sil_expr, _) = expression context pc expr in let (instrs, sil_expr, _) = expression context pc expr in
let sil_exn = Sil.Exn sil_expr in let sil_exn = Exp.Exn sil_expr in
let sil_instr = Sil.Set (Sil.Lvar ret_var, ret_type, sil_exn, loc) in let sil_instr = Sil.Set (Exp.Lvar ret_var, ret_type, sil_exn, loc) in
let node = create_node Cfg.Node.throw_kind (instrs @ [sil_instr]) in let node = create_node Cfg.Node.throw_kind (instrs @ [sil_instr]) in
JContext.add_goto_jump context pc JContext.Exit; JContext.add_goto_jump context pc JContext.Exit;
Instr node Instr node
| JBir.New (var, cn, constr_type_list, constr_arg_list) -> | JBir.New (var, cn, constr_type_list, constr_arg_list) ->
let builtin_new = Sil.Const (Const.Cfun ModelBuiltins.__new) in let builtin_new = Exp.Const (Const.Cfun ModelBuiltins.__new) in
let class_type = JTransType.get_class_type program tenv cn in let class_type = JTransType.get_class_type program tenv cn in
let class_type_np = JTransType.get_class_type_no_pointer program tenv cn in let class_type_np = JTransType.get_class_type_no_pointer program tenv cn in
let sizeof_exp = Sil.Sizeof (class_type_np, None, Subtype.exact) in let sizeof_exp = Exp.Sizeof (class_type_np, None, Subtype.exact) in
let args = [(sizeof_exp, class_type)] in let args = [(sizeof_exp, class_type)] in
let ret_id = Ident.create_fresh Ident.knormal in let ret_id = Ident.create_fresh Ident.knormal in
let new_instr = Sil.Call([ret_id], builtin_new, args, loc, CallFlags.default) in let new_instr = Sil.Call([ret_id], builtin_new, args, loc, CallFlags.default) in
let constr_ms = JBasics.make_ms JConfig.constructor_name constr_type_list None in let constr_ms = JBasics.make_ms JConfig.constructor_name constr_type_list None in
let constr_procname, call_instrs = let constr_procname, call_instrs =
let ret_opt = Some (Sil.Var ret_id, class_type) in let ret_opt = Some (Exp.Var ret_id, class_type) in
method_invocation method_invocation
context loc pc None cn constr_ms ret_opt constr_arg_list I_Special Procname.Non_Static in context loc pc None cn constr_ms ret_opt constr_arg_list I_Special Procname.Non_Static in
let pvar = JContext.set_pvar context var class_type in let pvar = JContext.set_pvar context var class_type in
let set_instr = Sil.Set (Sil.Lvar pvar, class_type, Sil.Var ret_id, loc) in let set_instr = Sil.Set (Exp.Lvar pvar, class_type, Exp.Var ret_id, loc) in
let instrs = (new_instr :: call_instrs) @ [set_instr] in let instrs = (new_instr :: call_instrs) @ [set_instr] in
let node_kind = Cfg.Node.Stmt_node ("Call "^(Procname.to_string constr_procname)) in let node_kind = Cfg.Node.Stmt_node ("Call "^(Procname.to_string constr_procname)) in
let node = create_node node_kind instrs in let node = create_node node_kind instrs in
@ -917,7 +918,7 @@ let rec instruction context pc instr : translation =
Cg.add_edge cg caller_procname constr_procname; Cg.add_edge cg caller_procname constr_procname;
Instr node Instr node
| JBir.NewArray (var, vt, expr_list) -> | JBir.NewArray (var, vt, expr_list) ->
let builtin_new_array = Sil.Const (Const.Cfun ModelBuiltins.__new_array) in let builtin_new_array = Exp.Const (Const.Cfun ModelBuiltins.__new_array) in
let content_type = JTransType.value_type program tenv vt in let content_type = JTransType.value_type program tenv vt in
let array_type = JTransType.create_array_type content_type (IList.length expr_list) in let array_type = JTransType.create_array_type content_type (IList.length expr_list) in
let array_name = JContext.set_pvar context var array_type in let array_name = JContext.set_pvar context var array_type in
@ -925,7 +926,7 @@ let rec instruction context pc instr : translation =
let call_args = [(array_size, array_type)] in let call_args = [(array_size, array_type)] in
let ret_id = Ident.create_fresh Ident.knormal in let ret_id = Ident.create_fresh Ident.knormal in
let call_instr = Sil.Call([ret_id], builtin_new_array, call_args, loc, CallFlags.default) in let call_instr = Sil.Call([ret_id], builtin_new_array, call_args, loc, CallFlags.default) in
let set_instr = Sil.Set (Sil.Lvar array_name, array_type, Sil.Var ret_id, loc) in let set_instr = Sil.Set (Exp.Lvar array_name, array_type, Exp.Var ret_id, loc) in
let node_kind = Cfg.Node.Stmt_node "method_body" in let node_kind = Cfg.Node.Stmt_node "method_body" in
let node = create_node node_kind (instrs @ [call_instr; set_instr]) in let node = create_node node_kind (instrs @ [call_instr; set_instr]) in
Instr node Instr node
@ -1002,27 +1003,27 @@ let rec instruction context pc instr : translation =
| JBir.Check (JBir.CheckNullPointer expr) when Config.report_runtime_exceptions -> | JBir.Check (JBir.CheckNullPointer expr) when Config.report_runtime_exceptions ->
let (instrs, sil_expr, _) = expression context pc expr in let (instrs, sil_expr, _) = expression context pc expr in
let not_null_node = let not_null_node =
let sil_not_null = Sil.BinOp (Binop.Ne, sil_expr, Sil.exp_null) in let sil_not_null = Exp.BinOp (Binop.Ne, sil_expr, Sil.exp_null) in
let sil_prune_not_null = Sil.Prune (sil_not_null, loc, true, Sil.Ik_if) let sil_prune_not_null = Sil.Prune (sil_not_null, loc, true, Sil.Ik_if)
and not_null_kind = Cfg.Node.Prune_node (true, Sil.Ik_if, "Not null") in and not_null_kind = Cfg.Node.Prune_node (true, Sil.Ik_if, "Not null") in
create_node not_null_kind (instrs @ [sil_prune_not_null]) in create_node not_null_kind (instrs @ [sil_prune_not_null]) in
let throw_npe_node = let throw_npe_node =
let sil_is_null = Sil.BinOp (Binop.Eq, sil_expr, Sil.exp_null) in let sil_is_null = Exp.BinOp (Binop.Eq, sil_expr, Sil.exp_null) in
let sil_prune_null = Sil.Prune (sil_is_null, loc, true, Sil.Ik_if) let sil_prune_null = Sil.Prune (sil_is_null, loc, true, Sil.Ik_if)
and npe_kind = Cfg.Node.Stmt_node "Throw NPE" and npe_kind = Cfg.Node.Stmt_node "Throw NPE"
and npe_cn = JBasics.make_cn JConfig.npe_cl in and npe_cn = JBasics.make_cn JConfig.npe_cl in
let class_type = JTransType.get_class_type program tenv npe_cn let class_type = JTransType.get_class_type program tenv npe_cn
and class_type_np = JTransType.get_class_type_no_pointer program tenv npe_cn in and class_type_np = JTransType.get_class_type_no_pointer program tenv npe_cn in
let sizeof_exp = Sil.Sizeof (class_type_np, None, Subtype.exact) in let sizeof_exp = Exp.Sizeof (class_type_np, None, Subtype.exact) in
let args = [(sizeof_exp, class_type)] in let args = [(sizeof_exp, class_type)] in
let ret_id = Ident.create_fresh Ident.knormal in let ret_id = Ident.create_fresh Ident.knormal in
let new_instr = Sil.Call([ret_id], builtin_new, args, loc, CallFlags.default) in let new_instr = Sil.Call([ret_id], builtin_new, args, loc, CallFlags.default) in
let constr_ms = JBasics.make_ms JConfig.constructor_name [] None in let constr_ms = JBasics.make_ms JConfig.constructor_name [] None in
let _, call_instrs = let _, call_instrs =
let ret_opt = Some (Sil.Var ret_id, class_type) in let ret_opt = Some (Exp.Var ret_id, class_type) in
method_invocation context loc pc None npe_cn constr_ms ret_opt [] I_Special Procname.Static in method_invocation context loc pc None npe_cn constr_ms ret_opt [] I_Special Procname.Static in
let sil_exn = Sil.Exn (Sil.Var ret_id) in let sil_exn = Exp.Exn (Exp.Var ret_id) in
let set_instr = Sil.Set (Sil.Lvar ret_var, ret_type, sil_exn, loc) in let set_instr = Sil.Set (Exp.Lvar ret_var, ret_type, sil_exn, loc) in
let npe_instrs = instrs @ [sil_prune_null] @ (new_instr :: call_instrs) @ [set_instr] in let npe_instrs = instrs @ [sil_prune_null] @ (new_instr :: call_instrs) @ [set_instr] in
create_node npe_kind npe_instrs in create_node npe_kind npe_instrs in
Prune (not_null_node, throw_npe_node) Prune (not_null_node, throw_npe_node)
@ -1045,10 +1046,10 @@ let rec instruction context pc instr : translation =
let sil_assume_in_bound = let sil_assume_in_bound =
let sil_in_bound = let sil_in_bound =
let sil_positive_index = let sil_positive_index =
Sil.BinOp (Binop.Ge, sil_index_expr, Sil.Const (Const.Cint IntLit.zero)) Exp.BinOp (Binop.Ge, sil_index_expr, Exp.Const (Const.Cint IntLit.zero))
and sil_less_than_length = and sil_less_than_length =
Sil.BinOp (Binop.Lt, sil_index_expr, sil_length_expr) in Exp.BinOp (Binop.Lt, sil_index_expr, sil_length_expr) in
Sil.BinOp (Binop.LAnd, sil_positive_index, sil_less_than_length) in Exp.BinOp (Binop.LAnd, sil_positive_index, sil_less_than_length) in
Sil.Prune (sil_in_bound, loc, true, Sil.Ik_if) in Sil.Prune (sil_in_bound, loc, true, Sil.Ik_if) in
create_node in_bound_node_kind (instrs @ [sil_assume_in_bound]) create_node in_bound_node_kind (instrs @ [sil_assume_in_bound])
@ -1058,15 +1059,15 @@ let rec instruction context pc instr : translation =
let sil_assume_out_of_bound = let sil_assume_out_of_bound =
let sil_out_of_bound = let sil_out_of_bound =
let sil_negative_index = let sil_negative_index =
Sil.BinOp (Binop.Lt, sil_index_expr, Sil.Const (Const.Cint IntLit.zero)) Exp.BinOp (Binop.Lt, sil_index_expr, Exp.Const (Const.Cint IntLit.zero))
and sil_greater_than_length = and sil_greater_than_length =
Sil.BinOp (Binop.Gt, sil_index_expr, sil_length_expr) in Exp.BinOp (Binop.Gt, sil_index_expr, sil_length_expr) in
Sil.BinOp (Binop.LOr, sil_negative_index, sil_greater_than_length) in Exp.BinOp (Binop.LOr, sil_negative_index, sil_greater_than_length) in
Sil.Prune (sil_out_of_bound, loc, true, Sil.Ik_if) in Sil.Prune (sil_out_of_bound, loc, true, Sil.Ik_if) in
let out_of_bound_cn = JBasics.make_cn JConfig.out_of_bound_cl in let out_of_bound_cn = JBasics.make_cn JConfig.out_of_bound_cl in
let class_type = JTransType.get_class_type program tenv out_of_bound_cn let class_type = JTransType.get_class_type program tenv out_of_bound_cn
and class_type_np = JTransType.get_class_type_no_pointer program tenv out_of_bound_cn in and class_type_np = JTransType.get_class_type_no_pointer program tenv out_of_bound_cn in
let sizeof_exp = Sil.Sizeof (class_type_np, None, Subtype.exact) in let sizeof_exp = Exp.Sizeof (class_type_np, None, Subtype.exact) in
let args = [(sizeof_exp, class_type)] in let args = [(sizeof_exp, class_type)] in
let ret_id = Ident.create_fresh Ident.knormal in let ret_id = Ident.create_fresh Ident.knormal in
let new_instr = Sil.Call([ret_id], builtin_new, args, loc, CallFlags.default) in let new_instr = Sil.Call([ret_id], builtin_new, args, loc, CallFlags.default) in
@ -1074,9 +1075,9 @@ let rec instruction context pc instr : translation =
let _, call_instrs = let _, call_instrs =
method_invocation method_invocation
context loc pc None out_of_bound_cn constr_ms context loc pc None out_of_bound_cn constr_ms
(Some (Sil.Var ret_id, class_type)) [] I_Special Procname.Static in (Some (Exp.Var ret_id, class_type)) [] I_Special Procname.Static in
let sil_exn = Sil.Exn (Sil.Var ret_id) in let sil_exn = Exp.Exn (Exp.Var ret_id) in
let set_instr = Sil.Set (Sil.Lvar ret_var, ret_type, sil_exn, loc) in let set_instr = Sil.Set (Exp.Lvar ret_var, ret_type, sil_exn, loc) in
let out_of_bound_instrs = let out_of_bound_instrs =
instrs @ [sil_assume_out_of_bound] @ (new_instr :: call_instrs) @ [set_instr] in instrs @ [sil_assume_out_of_bound] @ (new_instr :: call_instrs) @ [set_instr] in
create_node out_of_bound_node_kind out_of_bound_instrs in create_node out_of_bound_node_kind out_of_bound_instrs in
@ -1089,32 +1090,32 @@ let rec instruction context pc instr : translation =
and ret_id = Ident.create_fresh Ident.knormal and ret_id = Ident.create_fresh Ident.knormal
and sizeof_expr = and sizeof_expr =
JTransType.sizeof_of_object_type program tenv object_type Subtype.subtypes_instof in JTransType.sizeof_of_object_type program tenv object_type Subtype.subtypes_instof in
let check_cast = Sil.Const (Const.Cfun ModelBuiltins.__instanceof) in let check_cast = Exp.Const (Const.Cfun ModelBuiltins.__instanceof) in
let args = [(sil_expr, sil_type); (sizeof_expr, Typ.Tvoid)] in let args = [(sil_expr, sil_type); (sizeof_expr, Typ.Tvoid)] in
let call = Sil.Call([ret_id], check_cast, args, loc, CallFlags.default) in let call = Sil.Call([ret_id], check_cast, args, loc, CallFlags.default) in
let res_ex = Sil.Var ret_id in let res_ex = Exp.Var ret_id in
let is_instance_node = let is_instance_node =
let check_is_false = Sil.BinOp (Binop.Ne, res_ex, Sil.exp_zero) in let check_is_false = Exp.BinOp (Binop.Ne, res_ex, Sil.exp_zero) in
let asssume_instance_of = Sil.Prune (check_is_false, loc, true, Sil.Ik_if) let asssume_instance_of = Sil.Prune (check_is_false, loc, true, Sil.Ik_if)
and instance_of_kind = Cfg.Node.Prune_node (true, Sil.Ik_if, "Is instance") in and instance_of_kind = Cfg.Node.Prune_node (true, Sil.Ik_if, "Is instance") in
create_node instance_of_kind (instrs @ [call; asssume_instance_of]) create_node instance_of_kind (instrs @ [call; asssume_instance_of])
and throw_cast_exception_node = and throw_cast_exception_node =
let check_is_true = Sil.BinOp (Binop.Ne, res_ex, Sil.exp_one) in let check_is_true = Exp.BinOp (Binop.Ne, res_ex, Sil.exp_one) in
let asssume_not_instance_of = Sil.Prune (check_is_true, loc, true, Sil.Ik_if) let asssume_not_instance_of = Sil.Prune (check_is_true, loc, true, Sil.Ik_if)
and throw_cast_exception_kind = Cfg.Node.Stmt_node "Class cast exception" and throw_cast_exception_kind = Cfg.Node.Stmt_node "Class cast exception"
and cce_cn = JBasics.make_cn JConfig.cce_cl in and cce_cn = JBasics.make_cn JConfig.cce_cl in
let class_type = JTransType.get_class_type program tenv cce_cn let class_type = JTransType.get_class_type program tenv cce_cn
and class_type_np = JTransType.get_class_type_no_pointer program tenv cce_cn in and class_type_np = JTransType.get_class_type_no_pointer program tenv cce_cn in
let sizeof_exp = Sil.Sizeof (class_type_np, None, Subtype.exact) in let sizeof_exp = Exp.Sizeof (class_type_np, None, Subtype.exact) in
let args = [(sizeof_exp, class_type)] in let args = [(sizeof_exp, class_type)] in
let ret_id = Ident.create_fresh Ident.knormal in let ret_id = Ident.create_fresh Ident.knormal in
let new_instr = Sil.Call([ret_id], builtin_new, args, loc, CallFlags.default) in let new_instr = Sil.Call([ret_id], builtin_new, args, loc, CallFlags.default) in
let constr_ms = JBasics.make_ms JConfig.constructor_name [] None in let constr_ms = JBasics.make_ms JConfig.constructor_name [] None in
let _, call_instrs = let _, call_instrs =
method_invocation context loc pc None cce_cn constr_ms method_invocation context loc pc None cce_cn constr_ms
(Some (Sil.Var ret_id, class_type)) [] I_Special Procname.Static in (Some (Exp.Var ret_id, class_type)) [] I_Special Procname.Static in
let sil_exn = Sil.Exn (Sil.Var ret_id) in let sil_exn = Exp.Exn (Exp.Var ret_id) in
let set_instr = Sil.Set (Sil.Lvar ret_var, ret_type, sil_exn, loc) in let set_instr = Sil.Set (Exp.Lvar ret_var, ret_type, sil_exn, loc) in
let cce_instrs = let cce_instrs =
instrs @ [call; asssume_not_instance_of] @ (new_instr :: call_instrs) @ [set_instr] in instrs @ [call; asssume_not_instance_of] @ (new_instr :: call_instrs) @ [set_instr] in
create_node throw_cast_exception_kind cce_instrs in create_node throw_cast_exception_kind cce_instrs in

@ -38,13 +38,13 @@ let translate_exceptions context exit_nodes get_body_nodes handler_table =
(* this is removed in the true branches, and in the false branch of the last handler *) (* this is removed in the true branches, and in the false branch of the last handler *)
let id_exn_val = Ident.create_fresh Ident.knormal in let id_exn_val = Ident.create_fresh Ident.knormal in
let create_entry_node loc = let create_entry_node loc =
let instr_get_ret_val = Sil.Letderef (id_ret_val, Sil.Lvar ret_var, ret_type, loc) in let instr_get_ret_val = Sil.Letderef (id_ret_val, Exp.Lvar ret_var, ret_type, loc) in
let id_deactivate = Ident.create_fresh Ident.knormal in let id_deactivate = Ident.create_fresh Ident.knormal in
let instr_deactivate_exn = Sil.Set (Sil.Lvar ret_var, ret_type, Sil.Var id_deactivate, loc) in let instr_deactivate_exn = Sil.Set (Exp.Lvar ret_var, ret_type, Exp.Var id_deactivate, loc) in
let instr_unwrap_ret_val = let instr_unwrap_ret_val =
let unwrap_builtin = Sil.Const (Const.Cfun ModelBuiltins.__unwrap_exception) in let unwrap_builtin = Exp.Const (Const.Cfun ModelBuiltins.__unwrap_exception) in
Sil.Call Sil.Call
([id_exn_val], unwrap_builtin, [(Sil.Var id_ret_val, ret_type)], loc, CallFlags.default) in ([id_exn_val], unwrap_builtin, [(Exp.Var id_ret_val, ret_type)], loc, CallFlags.default) in
create_node create_node
loc loc
Cfg.Node.exn_handler_kind Cfg.Node.exn_handler_kind
@ -68,20 +68,20 @@ let translate_exceptions context exit_nodes get_body_nodes handler_table =
| _ -> assert false in | _ -> assert false in
let id_instanceof = Ident.create_fresh Ident.knormal in let id_instanceof = Ident.create_fresh Ident.knormal in
let instr_call_instanceof = let instr_call_instanceof =
let instanceof_builtin = Sil.Const (Const.Cfun ModelBuiltins.__instanceof) in let instanceof_builtin = Exp.Const (Const.Cfun ModelBuiltins.__instanceof) in
let args = [ let args = [
(Sil.Var id_exn_val, Typ.Tptr(exn_type, Typ.Pk_pointer)); (Exp.Var id_exn_val, Typ.Tptr(exn_type, Typ.Pk_pointer));
(Sil.Sizeof (exn_type, None, Subtype.exact), Typ.Tvoid)] in (Exp.Sizeof (exn_type, None, Subtype.exact), Typ.Tvoid)] in
Sil.Call ([id_instanceof], instanceof_builtin, args, loc, CallFlags.default) in Sil.Call ([id_instanceof], instanceof_builtin, args, loc, CallFlags.default) in
let if_kind = Sil.Ik_switch in let if_kind = Sil.Ik_switch in
let instr_prune_true = Sil.Prune (Sil.Var id_instanceof, loc, true, if_kind) in let instr_prune_true = Sil.Prune (Exp.Var id_instanceof, loc, true, if_kind) in
let instr_prune_false = let instr_prune_false =
Sil.Prune (Sil.UnOp(Unop.LNot, Sil.Var id_instanceof, None), loc, false, if_kind) in Sil.Prune (Exp.UnOp(Unop.LNot, Exp.Var id_instanceof, None), loc, false, if_kind) in
let instr_set_catch_var = let instr_set_catch_var =
let catch_var = JContext.set_pvar context handler.JBir.e_catch_var ret_type in let catch_var = JContext.set_pvar context handler.JBir.e_catch_var ret_type in
Sil.Set (Sil.Lvar catch_var, ret_type, Sil.Var id_exn_val, loc) in Sil.Set (Exp.Lvar catch_var, ret_type, Exp.Var id_exn_val, loc) in
let instr_rethrow_exn = let instr_rethrow_exn =
Sil.Set (Sil.Lvar ret_var, ret_type, Sil.Exn (Sil.Var id_exn_val), loc) in Sil.Set (Exp.Lvar ret_var, ret_type, Exp.Exn (Exp.Var id_exn_val), loc) in
let node_kind_true = Cfg.Node.Prune_node (true, if_kind, exn_message) in let node_kind_true = Cfg.Node.Prune_node (true, if_kind, exn_message) in
let node_kind_false = Cfg.Node.Prune_node (false, if_kind, exn_message) in let node_kind_false = Cfg.Node.Prune_node (false, if_kind, exn_message) in
let node_true = let node_true =

@ -185,12 +185,12 @@ let translate_instr_static_field context callee_procdesc fs field_type loc =
let ret_id = Ident.create_fresh Ident.knormal in let ret_id = Ident.create_fresh Ident.knormal in
let caller_procname = (Cfg.Procdesc.get_proc_name caller_procdesc) in let caller_procname = (Cfg.Procdesc.get_proc_name caller_procdesc) in
let callee_procname = Cfg.Procdesc.get_proc_name callee_procdesc in let callee_procname = Cfg.Procdesc.get_proc_name callee_procdesc in
let callee_fun = Sil.Const (Const.Cfun callee_procname) in let callee_fun = Exp.Const (Const.Cfun callee_procname) in
let field_arg = Sil.Const (Const.Cstr (JBasics.fs_name fs)) in let field_arg = Exp.Const (Const.Cstr (JBasics.fs_name fs)) in
let call_instr = let call_instr =
Sil.Call ([ret_id], callee_fun, [field_arg, field_type], loc, CallFlags.default) in Sil.Call ([ret_id], callee_fun, [field_arg, field_type], loc, CallFlags.default) in
Cg.add_edge cg caller_procname callee_procname; Cg.add_edge cg caller_procname callee_procname;
([call_instr], Sil.Var ret_id) ([call_instr], Exp.Var ret_id)
let is_static_final_field context cn fs = let is_static_final_field context cn fs =

@ -20,7 +20,7 @@ val has_static_final_fields : JCode.jcode Javalib.interface_or_class -> bool
val translate_instr_static_field : val translate_instr_static_field :
JContext.t -> Cfg.Procdesc.t -> JBasics.field_signature -> Typ.t -> JContext.t -> Cfg.Procdesc.t -> JBasics.field_signature -> Typ.t ->
Location.t -> Sil.instr list * Sil.exp Location.t -> Sil.instr list * Exp.t
val static_field_init : JCode.jcode Javalib.interface_or_class -> JBasics.class_name -> JBir.instr array -> JBir.instr array val static_field_init : JCode.jcode Javalib.interface_or_class -> JBasics.class_name -> JBir.instr array -> JBir.instr array

@ -391,11 +391,11 @@ and value_type program tenv vt =
| JBasics.TObject ot -> object_type program tenv ot | JBasics.TObject ot -> object_type program tenv ot
(** Translate object types into Sil.Sizeof expressions *) (** Translate object types into Exp.Sizeof expressions *)
let sizeof_of_object_type program tenv ot subtypes = let sizeof_of_object_type program tenv ot subtypes =
match object_type program tenv ot with match object_type program tenv ot with
| Typ.Tptr (typ, _) -> | Typ.Tptr (typ, _) ->
Sil.Sizeof (typ, None, subtypes) Exp.Sizeof (typ, None, subtypes)
| _ -> | _ ->
raise (Type_tranlsation_error "Pointer or array type expected in tenv") raise (Type_tranlsation_error "Pointer or array type expected in tenv")

@ -46,7 +46,7 @@ val object_type : JClasspath.program -> Tenv.t -> JBasics.object_type -> Typ.t
(** create sizeof expressions from the object type and the list of subtypes *) (** create sizeof expressions from the object type and the list of subtypes *)
val sizeof_of_object_type : JClasspath.program -> Tenv.t -> JBasics.object_type -> Subtype.t val sizeof_of_object_type : JClasspath.program -> Tenv.t -> JBasics.object_type -> Subtype.t
-> Sil.exp -> Exp.t
(** transforms a Java type to a Typ.t. *) (** transforms a Java type to a Typ.t. *)
val value_type : JClasspath.program -> Tenv.t -> JBasics.value_type -> Typ.t val value_type : JClasspath.program -> Tenv.t -> JBasics.value_type -> Typ.t

@ -21,13 +21,13 @@ let source_only_location () : Location.t =
let ident_of_variable (var : LAst.variable) : Ident.t = (* TODO: use unique stamps *) let ident_of_variable (var : LAst.variable) : Ident.t = (* TODO: use unique stamps *)
Ident.create_normal (Ident.string_to_name (LAst.string_of_variable var)) 0 Ident.create_normal (Ident.string_to_name (LAst.string_of_variable var)) 0
let trans_variable (var : LAst.variable) : Sil.exp = Sil.Var (ident_of_variable var) let trans_variable (var : LAst.variable) : Exp.t = Exp.Var (ident_of_variable var)
let trans_constant : LAst.constant -> Sil.exp = function let trans_constant : LAst.constant -> Exp.t = function
| Cint i -> Sil.Const (Const.Cint (IntLit.of_int i)) | Cint i -> Exp.Const (Const.Cint (IntLit.of_int i))
| Cnull -> Sil.exp_null | Cnull -> Sil.exp_null
let trans_operand : LAst.operand -> Sil.exp = function let trans_operand : LAst.operand -> Exp.t = function
| Var var -> trans_variable var | Var var -> trans_variable var
| Const const -> trans_constant const | Const const -> trans_constant const
@ -73,7 +73,7 @@ let rec trans_annotated_instructions
let procname = Cfg.Procdesc.get_proc_name procdesc in let procname = Cfg.Procdesc.get_proc_name procdesc in
let ret_var = Pvar.get_ret_pvar procname in let ret_var = Pvar.get_ret_pvar procname in
let new_sil_instr = let new_sil_instr =
Sil.Set (Sil.Lvar ret_var, trans_typ tp, trans_operand exp, location) in Sil.Set (Exp.Lvar ret_var, trans_typ tp, trans_operand exp, location) in
(new_sil_instr :: sil_instrs, locals) (new_sil_instr :: sil_instrs, locals)
| Load (var, tp, ptr) -> | Load (var, tp, ptr) ->
let new_sil_instr = let new_sil_instr =
@ -97,7 +97,7 @@ let rec trans_annotated_instructions
| Call (ret_var, func_var, typed_args) -> | Call (ret_var, func_var, typed_args) ->
let new_sil_instr = Sil.Call ( let new_sil_instr = Sil.Call (
[ident_of_variable ret_var], [ident_of_variable ret_var],
Sil.Const (Const.Cfun (procname_of_function_variable func_var)), Exp.Const (Const.Cfun (procname_of_function_variable func_var)),
IList.map (fun (tp, arg) -> (trans_operand arg, trans_typ tp)) typed_args, IList.map (fun (tp, arg) -> (trans_operand arg, trans_typ tp)) typed_args,
location, CallFlags.default) in location, CallFlags.default) in
(new_sil_instr :: sil_instrs, locals) (new_sil_instr :: sil_instrs, locals)

@ -23,7 +23,7 @@ let tests =
let open AnalyzerTester.StructuredSil in let open AnalyzerTester.StructuredSil in
let f_proc_name = Procname.from_string_c_fun "f" in let f_proc_name = Procname.from_string_c_fun "f" in
let g_proc_name = Procname.from_string_c_fun "g" in let g_proc_name = Procname.from_string_c_fun "g" in
let g_args = [((Sil.Const (Const.Cint (IntLit.one))), (Typ.Tint IInt))] in let g_args = [((Exp.Const (Const.Cint (IntLit.one))), (Typ.Tint IInt))] in
let g_ret_ids = [(ident_of_str "r")] in let g_ret_ids = [(ident_of_str "r")] in
let class_name = "com.example.SomeClass" in let class_name = "com.example.SomeClass" in
let file_name = "SomeClass.java" in let file_name = "SomeClass.java" in

@ -94,19 +94,19 @@ let tests =
let of_exp_test_ _ = let of_exp_test_ _ =
let f_fieldname = make_fieldname "f" in let f_fieldname = make_fieldname "f" in
let g_fieldname = make_fieldname "g" in let g_fieldname = make_fieldname "g" in
let x_exp = Sil.Lvar (make_var "x") in let x_exp = Exp.Lvar (make_var "x") in
check_make_ap x_exp x ~f_resolve_id; check_make_ap x_exp x ~f_resolve_id;
let xF_exp = Sil.Lfield (x_exp, f_fieldname, dummy_typ) in let xF_exp = Exp.Lfield (x_exp, f_fieldname, dummy_typ) in
check_make_ap xF_exp xF ~f_resolve_id; check_make_ap xF_exp xF ~f_resolve_id;
let xFG_exp = Sil.Lfield (xF_exp, g_fieldname, dummy_typ) in let xFG_exp = Exp.Lfield (xF_exp, g_fieldname, dummy_typ) in
check_make_ap xFG_exp xFG ~f_resolve_id; check_make_ap xFG_exp xFG ~f_resolve_id;
let xArr_exp = Sil.Lindex (x_exp, Sil.exp_zero) in let xArr_exp = Exp.Lindex (x_exp, Sil.exp_zero) in
check_make_ap xArr_exp xArr ~f_resolve_id; check_make_ap xArr_exp xArr ~f_resolve_id;
(* make sure [f_resolve_id] works *) (* make sure [f_resolve_id] works *)
let f_resolve_id_to_xF _ = Some xF in let f_resolve_id_to_xF _ = Some xF in
let xFG_exp_with_id = let xFG_exp_with_id =
let id_exp = Sil.Var (Ident.create_normal (Ident.string_to_name "") 0) in let id_exp = Exp.Var (Ident.create_normal (Ident.string_to_name "") 0) in
Sil.Lfield (id_exp, g_fieldname, dummy_typ) in Exp.Lfield (id_exp, g_fieldname, dummy_typ) in
check_make_ap xFG_exp_with_id xFG ~f_resolve_id:f_resolve_id_to_xF; check_make_ap xFG_exp_with_id xFG ~f_resolve_id:f_resolve_id_to_xF;
() in () in
"of_exp">::of_exp_test_ in "of_exp">::of_exp_test_ in

@ -24,10 +24,10 @@ let tests =
let int_ptr_typ = Typ.Tptr (int_typ, Pk_pointer) in let int_ptr_typ = Typ.Tptr (int_typ, Pk_pointer) in
let fun_ptr_typ = Typ.Tptr (Tfun false, Pk_pointer) in let fun_ptr_typ = Typ.Tptr (Tfun false, Pk_pointer) in
let closure_exp captureds = let closure_exp captureds =
let mk_captured_var str = (Sil.Var (ident_of_str str), pvar_of_str str, int_ptr_typ) in let mk_captured_var str = (Exp.Var (ident_of_str str), pvar_of_str str, int_ptr_typ) in
let captured_vars = IList.map mk_captured_var captureds in let captured_vars = IList.map mk_captured_var captureds in
let closure = { Sil.name=dummy_procname; captured_vars; } in let closure = { Exp.name=dummy_procname; captured_vars; } in
Sil.Closure closure in Exp.Closure closure in
let test_list = [ let test_list = [
"address_taken_set_instr", "address_taken_set_instr",
[ [

@ -21,8 +21,8 @@ module StructuredSil = struct
type structured_instr = type structured_instr =
| Cmd of Sil.instr | Cmd of Sil.instr
| If of Sil.exp * structured_instr list * structured_instr list | If of Exp.t * structured_instr list * structured_instr list
| While of Sil.exp * structured_instr list | While of Exp.t * structured_instr list
(* try/catch/finally. note: there is no throw. the semantics are that every command in the try (* try/catch/finally. note: there is no throw. the semantics are that every command in the try
block is assumed to be possibly-excepting, and the catch block captures all exceptions *) block is assumed to be possibly-excepting, and the catch block captures all exceptions *)
| Try of structured_instr list * structured_instr list * structured_instr list | Try of structured_instr list * structured_instr list * structured_instr list
@ -76,7 +76,7 @@ module StructuredSil = struct
Pvar.mk (Mangled.from_string str) dummy_procname Pvar.mk (Mangled.from_string str) dummy_procname
let var_of_str str = let var_of_str str =
Sil.Lvar (pvar_of_str str) Exp.Lvar (pvar_of_str str)
let ident_of_str str = let ident_of_str str =
Ident.create_normal (Ident.string_to_name str) 0 Ident.create_normal (Ident.string_to_name str) 0
@ -91,12 +91,12 @@ module StructuredSil = struct
Cmd (Sil.Set (lhs_exp, rhs_typ, rhs_exp, dummy_loc)) Cmd (Sil.Set (lhs_exp, rhs_typ, rhs_exp, dummy_loc))
let make_call ?(procname=dummy_procname) ret_ids args = let make_call ?(procname=dummy_procname) ret_ids args =
let call_exp = Sil.Const (Const.Cfun procname) in let call_exp = Exp.Const (Const.Cfun procname) in
Cmd (Sil.Call (ret_ids, call_exp, args, dummy_loc, CallFlags.default)) Cmd (Sil.Call (ret_ids, call_exp, args, dummy_loc, CallFlags.default))
let id_assign_id ?(rhs_typ=dummy_typ) lhs rhs = let id_assign_id ?(rhs_typ=dummy_typ) lhs rhs =
let lhs_id = ident_of_str lhs in let lhs_id = ident_of_str lhs in
let rhs_exp = Sil.Var (ident_of_str rhs) in let rhs_exp = Exp.Var (ident_of_str rhs) in
make_letderef ~rhs_typ lhs_id rhs_exp make_letderef ~rhs_typ lhs_id rhs_exp
let id_assign_var ?(rhs_typ=dummy_typ) lhs rhs = let id_assign_var ?(rhs_typ=dummy_typ) lhs rhs =
@ -105,8 +105,8 @@ module StructuredSil = struct
make_letderef ~rhs_typ lhs_id rhs_exp make_letderef ~rhs_typ lhs_id rhs_exp
let id_set_id ?(rhs_typ=dummy_typ) lhs_id rhs_id = let id_set_id ?(rhs_typ=dummy_typ) lhs_id rhs_id =
let lhs_exp = Sil.Var (ident_of_str lhs_id) in let lhs_exp = Exp.Var (ident_of_str lhs_id) in
let rhs_exp = Sil.Var (ident_of_str rhs_id) in let rhs_exp = Exp.Var (ident_of_str rhs_id) in
make_set ~rhs_typ ~lhs_exp ~rhs_exp make_set ~rhs_typ ~lhs_exp ~rhs_exp
let var_assign_exp ~rhs_typ lhs rhs_exp = let var_assign_exp ~rhs_typ lhs rhs_exp =
@ -120,7 +120,7 @@ module StructuredSil = struct
let var_assign_id ?(rhs_typ=dummy_typ) lhs rhs = let var_assign_id ?(rhs_typ=dummy_typ) lhs rhs =
let lhs_exp = var_of_str lhs in let lhs_exp = var_of_str lhs in
let rhs_exp = Sil.Var (ident_of_str rhs) in let rhs_exp = Exp.Var (ident_of_str rhs) in
make_set ~rhs_typ ~lhs_exp ~rhs_exp make_set ~rhs_typ ~lhs_exp ~rhs_exp
(* x = &y *) (* x = &y *)
@ -165,7 +165,7 @@ module Make
create_node (Cfg.Node.Prune_node (true_branch, if_kind, "")) [prune_instr] in create_node (Cfg.Node.Prune_node (true_branch, if_kind, "")) [prune_instr] in
let true_prune_node = mk_prune_node cond_exp if_kind true in let true_prune_node = mk_prune_node cond_exp if_kind true in
let false_prune_node = let false_prune_node =
let negated_cond_exp = Sil.UnOp (Unop.LNot, cond_exp, None) in let negated_cond_exp = Exp.UnOp (Unop.LNot, cond_exp, None) in
mk_prune_node negated_cond_exp if_kind false in mk_prune_node negated_cond_exp if_kind false in
true_prune_node, false_prune_node in true_prune_node, false_prune_node in

@ -22,10 +22,10 @@ let tests =
let assert_empty = invariant "{ }" in let assert_empty = invariant "{ }" in
let fun_ptr_typ = Typ.Tptr (Tfun false, Pk_pointer) in let fun_ptr_typ = Typ.Tptr (Tfun false, Pk_pointer) in
let closure_exp captured_pvars = let closure_exp captured_pvars =
let mk_captured_var str = (Sil.Var (ident_of_str str), pvar_of_str str, dummy_typ) in let mk_captured_var str = (Exp.Var (ident_of_str str), pvar_of_str str, dummy_typ) in
let captured_vars = IList.map mk_captured_var captured_pvars in let captured_vars = IList.map mk_captured_var captured_pvars in
let closure = { Sil.name=dummy_procname; captured_vars; } in let closure = { Exp.name=dummy_procname; captured_vars; } in
Sil.Closure closure in Exp.Closure closure in
let unknown_cond = let unknown_cond =
(* don't want to use AnalyzerTest.unknown_exp because we'll treat it as a live var! *) (* don't want to use AnalyzerTest.unknown_exp because we'll treat it as a live var! *)
Sil.exp_zero in Sil.exp_zero in

Loading…
Cancel
Save