From cef75793eb3b261939ed77ab0e6238d3c29aa94f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Loi=CC=88c=20Correnson?= <loic.correnson@cea.fr> Date: Mon, 30 Mar 2020 15:29:27 +0200 Subject: [PATCH] [kernel] refactor expr-to-term --- .Makefile.lint | 1 - src/kernel_internals/typing/asm_contracts.ml | 240 +++++++-------- src/kernel_internals/typing/cabs2cil.ml | 6 +- src/kernel_services/ast_data/alarms.ml | 73 ++--- .../ast_data/statuses_by_call.ml | 2 +- .../ast_queries/logic_typing.ml | 2 +- .../ast_queries/logic_utils.ml | 273 ++++++++++-------- .../ast_queries/logic_utils.mli | 79 +++-- .../ast_transformations/inline.ml | 2 +- src/plugins/aorai/aorai_dataflow.ml | 2 +- src/plugins/aorai/aorai_utils.ml | 9 +- src/plugins/instantiate/basic_blocks.ml | 6 +- src/plugins/occurrence/register_gui.ml | 2 +- src/plugins/studia/studia_gui.ml | 2 +- src/plugins/value/domains/traces_domain.ml | 8 +- src/plugins/wp/LogicSemantics.ml | 2 +- tests/spec/expr_to_term.ml | 6 +- 17 files changed, 392 insertions(+), 323 deletions(-) diff --git a/.Makefile.lint b/.Makefile.lint index 0fffac31e24..140545ce013 100644 --- a/.Makefile.lint +++ b/.Makefile.lint @@ -10,7 +10,6 @@ ML_LINT_KO+=src/kernel_internals/runtime/messages.ml ML_LINT_KO+=src/kernel_internals/runtime/messages.mli ML_LINT_KO+=src/kernel_internals/runtime/special_hooks.ml ML_LINT_KO+=src/kernel_internals/typing/allocates.ml -ML_LINT_KO+=src/kernel_internals/typing/asm_contracts.ml ML_LINT_KO+=src/kernel_internals/typing/frontc.mli ML_LINT_KO+=src/kernel_internals/typing/infer_annotations.ml ML_LINT_KO+=src/kernel_internals/typing/mergecil.mli diff --git a/src/kernel_internals/typing/asm_contracts.ml b/src/kernel_internals/typing/asm_contracts.ml index 45ea1252e59..d87771d648f 100644 --- a/src/kernel_internals/typing/asm_contracts.ml +++ b/src/kernel_internals/typing/asm_contracts.ml @@ -33,24 +33,24 @@ let emitter = let find_out_lval l = let treat_one_lval (output, input) (_,constr, lv) = - let tlv = Logic_utils.lval_to_term_lval ~cast:false lv in + let tlv = Logic_utils.lval_to_term_lval lv in match constr with - | "" -> tlv :: output, input - | _ -> - (* '+' indicates that the lval is used both as input and as output. - GNU syntax allows it only at the beginning of the constraint, but - actual implementation is more liberal and emits only a warning. - *) - if String.contains constr '+' then begin - if constr.[0] <> '+' then - Kernel.warning - "output constraint '+' is not at the beginning in output operand"; - tlv::output, - (* avoid sharing ids *) - Visitor.visitFramacTermLval - (new Visitor.frama_c_refresh(Project.current())) tlv - :: input - end else tlv::output, input + | "" -> tlv :: output, input + | _ -> + (* '+' indicates that the lval is used both as input and as output. + GNU syntax allows it only at the beginning of the constraint, but + actual implementation is more liberal and emits only a warning. + *) + if String.contains constr '+' then begin + if constr.[0] <> '+' then + Kernel.warning + "output constraint '+' is not at the beginning in output operand"; + tlv::output, + (* avoid sharing ids *) + Visitor.visitFramacTermLval + (new Visitor.frama_c_refresh(Project.current())) tlv + :: input + end else tlv::output, input in let output, input = List.fold_left treat_one_lval ([],[]) l @@ -63,7 +63,7 @@ let extract_term_lval acc (_,_,e) = object inherit Visitor.frama_c_inplace method! vlval lv = - res := Logic_utils.lval_to_term_lval ~cast:false lv :: !res; + res := Logic_utils.lval_to_term_lval lv :: !res; Cil.SkipChildren end in @@ -112,123 +112,123 @@ let extract_mem_terms ~loc l = List.rev (List.fold_left (extract_mem_term ~loc) [] l) class visit_assembly = -object(self) - inherit Visitor.frama_c_inplace + object(self) + inherit Visitor.frama_c_inplace - method! vinst i = - let stmt = Extlib.the self#current_stmt in - let kf = Extlib.the self#current_kf in - match i with + method! vinst i = + let stmt = Extlib.the self#current_stmt in + let kf = Extlib.the self#current_kf in + match i with | Asm(_, _, Some { asm_outputs; asm_inputs; asm_clobbers }, loc) -> - let lv_out, lv_from = find_out_lval asm_outputs in - let lv_from = lv_from @ find_input_lval asm_inputs in - let mem_output = extract_mem_terms ~loc lv_from in - let lv_out = lv_out @ mem_output in - let lv_from = lv_from @ mem_output in - let lv_from = - List.filter - (fun lv -> - not (Logic_utils.isLogicArrayType (Cil.typeOfTermLval lv))) - lv_from + let lv_out, lv_from = find_out_lval asm_outputs in + let lv_from = lv_from @ find_input_lval asm_inputs in + let mem_output = extract_mem_terms ~loc lv_from in + let lv_out = lv_out @ mem_output in + let lv_from = lv_from @ mem_output in + let lv_from = + List.filter + (fun lv -> + not (Logic_utils.isLogicArrayType (Cil.typeOfTermLval lv))) + lv_from + in + (* the only interesting information for clobbers is the + presence of the "memory" keyword, which indicates that + memory may have been accessed (read or write) outside of + the locations explicitly referred to as output or + input. We can't do much more than emitting a warning and + considering that nothing is touched beyond normally + specified outputs and inputs. *) + let mem_clobbered = List.mem "memory" asm_clobbers in + if mem_clobbered then begin + let source = fst (Cil_datatype.Instr.loc i) in + let once = true in + Kernel.warning + ~once ~source + "Clobber list contains \"memory\" argument. Assuming no \ + side effects beyond those mentioned in operands." + end; + let to_id_term lv = + Logic_const.new_identified_term + (Logic_const.term ~loc (TLval lv) (Cil.typeOfTermLval lv)) + in + let to_id_from lv = + let typ = Cil.typeOfTermLval lv in + let base_term = Logic_const.term ~loc (TLval lv) typ in + let term = + if Logic_utils.isLogicPointerType typ || + Logic_utils.isLogicArrayType typ + then { base_term with term_name = ["indirect"] } + else base_term in - (* the only interesting information for clobbers is the - presence of the "memory" keyword, which indicates that - memory may have been accessed (read or write) outside of - the locations explicitly referred to as output or - input. We can't do much more than emitting a warning and - considering that nothing is touched beyond normally - specified outputs and inputs. *) - let mem_clobbered = List.mem "memory" asm_clobbers in - if mem_clobbered then begin - let source = fst (Cil_datatype.Instr.loc i) in - let once = true in - Kernel.warning - ~once ~source - "Clobber list contains \"memory\" argument. Assuming no \ - side effects beyond those mentioned in operands." - end; - let to_id_term lv = - Logic_const.new_identified_term - (Logic_const.term ~loc (TLval lv) (Cil.typeOfTermLval lv)) - in - let to_id_from lv = - let typ = Cil.typeOfTermLval lv in - let base_term = Logic_const.term ~loc (TLval lv) typ in - let term = - if Logic_utils.isLogicPointerType typ || - Logic_utils.isLogicArrayType typ - then { base_term with term_name = ["indirect"] } - else base_term - in - Logic_const.new_identified_term term - in - let assigns () = - Writes - (List.map - (fun x -> (to_id_term x, From (List.map to_id_from lv_from))) - lv_out) - in - let filter ca = - match ca.annot_content with - (* search for a statement contract that applies to all cases. *) - | AStmtSpec ([],_) -> true - | _ -> false - in - let contracts = Annotations.code_annot ~filter stmt in - (match contracts with - | [] -> - let assigns = assigns () in - let bhv = Cil.mk_behavior ~assigns () in - let spec = Cil.empty_funspec () in - spec.spec_behavior <- [ bhv ]; - let ca = - Logic_const.new_code_annotation (AStmtSpec ([],spec)) - in - Annotations.add_code_annot emitter ~kf stmt ca; - if not mem_clobbered && Kernel.AsmContractsAutoValidate.get() - then begin - let active = [] in - let ip_assigns = - Property.ip_assigns_of_behavior kf (Kstmt stmt) ~active bhv in - let ip_from = - Property.ip_from_of_behavior kf (Kstmt stmt) ~active bhv in - List.iter - Property_status.( - fun x -> emit emitter ~hyps:[] x True) - (Extlib.list_of_opt ip_assigns @ ip_from) - end - | [ { annot_content = AStmtSpec ([], spec) } ] -> - (* Already existing contracts. Just add assigns clause for - behaviors that do not already have one. *) + Logic_const.new_identified_term term + in + let assigns () = + Writes + (List.map + (fun x -> (to_id_term x, From (List.map to_id_from lv_from))) + lv_out) + in + let filter ca = + match ca.annot_content with + (* search for a statement contract that applies to all cases. *) + | AStmtSpec ([],_) -> true + | _ -> false + in + let contracts = Annotations.code_annot ~filter stmt in + (match contracts with + | [] -> + let assigns = assigns () in + let bhv = Cil.mk_behavior ~assigns () in + let spec = Cil.empty_funspec () in + spec.spec_behavior <- [ bhv ]; + let ca = + Logic_const.new_code_annotation (AStmtSpec ([],spec)) + in + Annotations.add_code_annot emitter ~kf stmt ca; + if not mem_clobbered && Kernel.AsmContractsAutoValidate.get() + then begin + let active = [] in + let ip_assigns = + Property.ip_assigns_of_behavior kf (Kstmt stmt) ~active bhv in + let ip_from = + Property.ip_from_of_behavior kf (Kstmt stmt) ~active bhv in List.iter - (fun bhv -> - match bhv.b_assigns with - | WritesAny -> - let behavior = bhv.b_name in - let assigns = assigns () in - let keep_empty = false in - Annotations.add_assigns - ~keep_empty emitter kf ~stmt ~behavior assigns; - | Writes _ -> ()) - spec.spec_behavior - | _ -> - Kernel.fatal "Several contracts found for the same statement %a" - Printer.pp_stmt stmt - ); - Cil.SkipChildren + Property_status.( + fun x -> emit emitter ~hyps:[] x True) + (Extlib.list_of_opt ip_assigns @ ip_from) + end + | [ { annot_content = AStmtSpec ([], spec) } ] -> + (* Already existing contracts. Just add assigns clause for + behaviors that do not already have one. *) + List.iter + (fun bhv -> + match bhv.b_assigns with + | WritesAny -> + let behavior = bhv.b_name in + let assigns = assigns () in + let keep_empty = false in + Annotations.add_assigns + ~keep_empty emitter kf ~stmt ~behavior assigns; + | Writes _ -> ()) + spec.spec_behavior + | _ -> + Kernel.fatal "Several contracts found for the same statement %a" + Printer.pp_stmt stmt + ); + Cil.SkipChildren | Asm(_,_,None,_) -> Kernel.feedback ~dkey:Kernel.dkey_asm_contracts "Ignoring basic assembly instruction"; Cil.SkipChildren | _ -> Cil.SkipChildren -end + end let transform file = if Kernel.AsmContractsGenerate.get() then Visitor.visitFramacFileSameGlobals (new visit_assembly) file let () = - File.add_code_transformation_after_cleanup + File.add_code_transformation_after_cleanup ~deps:[(module Kernel.AsmContractsGenerate); (module Kernel.AsmContractsAutoValidate) ] category diff --git a/src/kernel_internals/typing/cabs2cil.ml b/src/kernel_internals/typing/cabs2cil.ml index 57c91da7c3e..6dc8c4bda1a 100644 --- a/src/kernel_internals/typing/cabs2cil.ml +++ b/src/kernel_internals/typing/cabs2cil.ml @@ -8856,9 +8856,9 @@ and createLocal ghost ((_, sto, _, _) as specs) (se0 +++ ( let castloc = CurrentLoc.get () in let talloca_size = - let telt_size = Logic_utils.expr_to_term ~cast:false elt_size in - let tlen = Logic_utils.expr_to_term ~cast:false len in - Logic_const.term (TBinOp (Mult,telt_size,tlen)) telt_size.term_type + let size = Logic_utils.expr_to_term ~coerce:true elt_size in + let tlen = Logic_utils.expr_to_term ~coerce:true len in + Logic_const.term (TBinOp (Mult,size,tlen)) Linteger in let pos_size = let zero = Logic_const.tinteger ~loc:castloc 0 in diff --git a/src/kernel_services/ast_data/alarms.ml b/src/kernel_services/ast_data/alarms.ml index f251a750c84..903e79bb9f0 100644 --- a/src/kernel_services/ast_data/alarms.ml +++ b/src/kernel_services/ast_data/alarms.ml @@ -451,21 +451,21 @@ let overflowed_expr_to_term ~loc e = let loc = best_loc ~loc e.eloc in match e.enode with | UnOp(op, e, ty) -> - let t = Logic_utils.expr_to_term ~cast:true e in - let ty = Logic_utils.typ_to_logic_type ty in + let t = Logic_utils.expr_to_term ~coerce:true e in + let ty = Logic_utils.coerced ty in Logic_const.term ~loc (TUnOp(op, t)) ty | BinOp(op, e1, e2, ty) -> - let t1 = Logic_utils.expr_to_term ~cast:true e1 in - let t2 = Logic_utils.expr_to_term ~cast:true e2 in - let ty = Logic_utils.typ_to_logic_type ty in + let t1 = Logic_utils.expr_to_term ~coerce:true e1 in + let t2 = Logic_utils.expr_to_term ~coerce:true e2 in + let ty = Logic_utils.coerced ty in Logic_const.term ~loc (TBinOp(op, t1, t2)) ty - | _ -> Logic_utils.expr_to_term ~cast:true e + | _ -> Logic_utils.expr_to_term ~coerce:true e (* Creates \is_finite((fkind)e) or \is_nan((fkind)e) according to [predicate]. *) let create_special_float_predicate ~loc e fkind predicate = let loc = best_loc ~loc e.eloc in - let t = Logic_utils.expr_to_term ~cast:true e in + let t = Logic_utils.expr_to_term e in let typ = match fkind with | FFloat -> Cil.floatType | FDouble -> Cil.doubleType @@ -490,7 +490,7 @@ let create_predicate ?(loc=Location.unknown) alarm = | Division_by_zero e -> (* e != 0 *) let loc = best_loc ~loc e.eloc in - let t = Logic_utils.expr_to_term ~cast:true e in + let t = Logic_utils.expr_to_term ~coerce:true e in Logic_const.prel ~loc (Rneq, t, Cil.lzero ()) | Memory_access(lv, read) -> @@ -500,22 +500,23 @@ let create_predicate ?(loc=Location.unknown) alarm = | For_writing -> Logic_const.pvalid in let e = Cil.mkAddrOrStartOf ~loc lv in - let t = Logic_utils.expr_to_term ~cast:true e in + let t = Logic_utils.expr_to_term e in valid ~loc (Logic_const.here_label, t) | Index_out_of_bound(e1, e2) -> (* 0 <= e1 < e2, left part if None, right part if Some e *) let loc = best_loc ~loc e1.eloc in - let t1 = Logic_utils.expr_to_term ~cast:true e1 in + let t1 = Logic_utils.expr_to_term ~coerce:true e1 in (match e2 with - | None -> Logic_const.prel ~loc (Rle, Cil.lzero (), t1) + | None -> + Logic_const.prel ~loc (Rle, Cil.lzero (), t1) | Some e2 -> - let t2 = Logic_utils.expr_to_term ~cast:true e2 in + let t2 = Logic_utils.expr_to_term ~coerce:true e2 in Logic_const.prel ~loc (Rlt, t1, t2)) | Invalid_pointer e -> let loc = best_loc ~loc e.eloc in - let t = Logic_utils.expr_to_term ~cast:true e in + let t = Logic_utils.expr_to_term e in if Cil.isFunPtrType (Cil.typeOf e) then Logic_const.pvalid_function ~loc t else Logic_const.pobject_pointer ~loc (Logic_const.here_label, t) @@ -523,12 +524,12 @@ let create_predicate ?(loc=Location.unknown) alarm = | Invalid_shift(e, n) -> (* 0 <= e < n *) let loc = best_loc ~loc e.eloc in - let t = Logic_utils.expr_to_term ~cast:true e in + let t = Logic_utils.expr_to_term ~coerce:true e in let low_cmp = Logic_const.prel ~loc (Rle, Cil.lzero (), t) in (match n with | None -> low_cmp | Some n -> - let tn = Logic_const.tint ~loc (Integer.of_int n) in + let tn = Logic_const.tinteger ~loc n in let up_cmp = Logic_const.prel ~loc (Rlt, t, tn) in Logic_const.pand ~loc (low_cmp, up_cmp)) @@ -544,21 +545,21 @@ let create_predicate ?(loc=Location.unknown) alarm = let zero = Cil.lzero () in Logic_const.term (TCastE (typ, zero)) (Ctype typ) end - | Some e -> Logic_utils.expr_to_term ~cast:true e + | Some e -> Logic_utils.expr_to_term e in - let t2 = Logic_utils.expr_to_term ~cast:true e2 in + let t2 = Logic_utils.expr_to_term e2 in Logic_utils.pointer_comparable ~loc t1 t2 | Differing_blocks(e1, e2) -> (* \base_addr(e1) == \base_addr(e2) *) let loc = best_loc ~loc e1.eloc in - let t1 = Logic_utils.expr_to_term ~cast:true e1 in + let t1 = Logic_utils.expr_to_term e1 in let here = Logic_const.here_label in let typ = Ctype Cil.charPtrType in let t1 = Logic_const.term ~loc:(best_loc loc e1.eloc) (Tbase_addr(here, t1)) typ in - let t2 = Logic_utils.expr_to_term ~cast:true e2 in + let t2 = Logic_utils.expr_to_term e2 in let t2 = Logic_const.term ~loc:(best_loc loc e2.eloc) (Tbase_addr(here, t2)) typ in @@ -569,10 +570,10 @@ let create_predicate ?(loc=Location.unknown) alarm = let loc = best_loc ~loc e.eloc in let t = match kind with | Pointer_downcast -> - let t = Logic_utils.expr_to_term ~cast:true e in + let t = Logic_utils.expr_to_term e in Logic_const.tcast ~loc t Cil.theMachine.upointType | Signed_downcast | Unsigned_downcast -> - Logic_utils.expr_to_term ~cast:true e + Logic_utils.expr_to_term ~coerce:true e | _ -> (* For overflows, the computation must be done on mathematical types, else the value is necessarily in bounds. *) @@ -580,7 +581,9 @@ let create_predicate ?(loc=Location.unknown) alarm = in let tn = Logic_const.tint ~loc n in Logic_const.prel ~loc - (match bound with Lower_bound -> Rle, tn, t | Upper_bound -> Rle, t, tn) + (match bound with + | Lower_bound -> Rle, tn, t + | Upper_bound -> Rle, t, tn) | Float_to_int(e, n, bound) -> (* n < e or e < n according to bound *) @@ -588,27 +591,31 @@ let create_predicate ?(loc=Location.unknown) alarm = let te = overflowed_expr_to_term ~loc e in let t = Logic_const.tlogic_coerce ~loc te Lreal in let n = - (match bound with Lower_bound -> Integer.sub | Upper_bound -> Integer.add) + (match bound with + | Lower_bound -> Integer.sub + | Upper_bound -> Integer.add) n Integer.one in let tn = Logic_const.tlogic_coerce ~loc (Logic_const.tint ~loc n) Lreal in Logic_const.prel ~loc - (match bound with Lower_bound -> Rlt, tn, t | Upper_bound -> Rlt, t, tn) + (match bound with + | Lower_bound -> Rlt, tn, t + | Upper_bound -> Rlt, t, tn) | Not_separated(lv1, lv2) -> (* \separated(lv1, lv2) *) let e1 = Cil.mkAddrOf ~loc lv1 in - let t1 = Logic_utils.expr_to_term ~cast:true e1 in + let t1 = Logic_utils.expr_to_term e1 in let e2 = Cil.mkAddrOf ~loc lv2 in - let t2 = Logic_utils.expr_to_term ~cast:true e2 in + let t2 = Logic_utils.expr_to_term e2 in Logic_const.pseparated ~loc [ t1; t2 ] | Overlap(lv1, lv2) -> (* (lv1 == lv2) || \separated(lv1, lv2) *) let e1 = Cil.mkAddrOf ~loc lv1 in - let t1 = Logic_utils.expr_to_term ~cast:true e1 in + let t1 = Logic_utils.expr_to_term e1 in let e2 = Cil.mkAddrOf ~loc lv2 in - let t2 = Logic_utils.expr_to_term ~cast:true e2 in + let t2 = Logic_utils.expr_to_term e2 in let eq = Logic_const.prel ~loc (Req, t1, t2) in let sep = Logic_const.pseparated ~loc [ t1; t2 ] in Logic_const.por ~loc (eq, sep) @@ -616,13 +623,13 @@ let create_predicate ?(loc=Location.unknown) alarm = | Uninitialized lv -> (* \initialized(lv) *) let e = Cil.mkAddrOrStartOf ~loc lv in - let t = Logic_utils.expr_to_term ~cast:false e in + let t = Logic_utils.expr_to_term e in Logic_const.pinitialized ~loc (Logic_const.here_label, t) | Dangling lv -> (* !\dangling(lv) *) let e = Cil.mkAddrOrStartOf ~loc lv in - let t = Logic_utils.expr_to_term ~cast:false e in + let t = Logic_utils.expr_to_term e in Logic_const.(pnot ~loc (pdangling ~loc (Logic_const.here_label, t))) | Is_nan_or_infinite (e, fkind) -> @@ -648,14 +655,14 @@ let create_predicate ?(loc=Location.unknown) alarm = that has unexpected type %a (unrolled as %a)" Printer.pp_exp e Printer.pp_typ t Printer.pp_typ t' in - let t = Logic_utils.expr_to_term ~cast:true e in + let t = Logic_utils.expr_to_term e in Logic_const.(pvalid_function ~loc t) | Uninitialized_union llv -> (* \initialized(lv_1) || ... || \initialized(lv_n) *) let make_lval_predicate lv = let e = Cil.mkAddrOrStartOf ~loc lv in - let t = Logic_utils.expr_to_term ~cast:false e in + let t = Logic_utils.expr_to_term e in Logic_const.pinitialized ~loc (Logic_const.here_label, t) in List.fold_left (fun acc lv -> @@ -666,7 +673,7 @@ let create_predicate ?(loc=Location.unknown) alarm = | Invalid_bool lv -> let e = Cil.new_exp ~loc (Lval lv) in - let t = Logic_utils.expr_to_term ~cast:false e in + let t = Logic_utils.expr_to_term ~coerce:true e in let zero = Logic_const.prel ~loc (Req, t, Cil.lzero ()) in let one = Logic_const.prel ~loc (Req, t, Cil.lone ()) in Logic_const.por ~loc (zero, one) diff --git a/src/kernel_services/ast_data/statuses_by_call.ml b/src/kernel_services/ast_data/statuses_by_call.ml index d5deb1ab108..2487ade6c49 100644 --- a/src/kernel_services/ast_data/statuses_by_call.ml +++ b/src/kernel_services/ast_data/statuses_by_call.ml @@ -160,7 +160,7 @@ let rec associate acc ~formals ~concretes = | [], _ -> acc | _, [] -> raise Non_Transposable | formal :: formals, concrete :: concretes -> - let term = Logic_utils.expr_to_term ~cast:true concrete in + let term = Logic_utils.expr_to_term concrete in associate ((formal, term) :: acc) ~formals ~concretes let transpose_pred_at_callsite ~formals ~concretes pred = diff --git a/src/kernel_services/ast_queries/logic_typing.ml b/src/kernel_services/ast_queries/logic_typing.ml index f6a1c015fb9..27e77ae549a 100644 --- a/src/kernel_services/ast_queries/logic_typing.ml +++ b/src/kernel_services/ast_queries/logic_typing.ml @@ -801,7 +801,7 @@ struct let attrs = Cil.filter_qualifier_attributes attrs in let field = C.find_comp_field comp f in let typ = Cil.typeOffset ty field in - Logic_utils.offset_to_term_offset ~cast:false field, + Logic_utils.offset_to_term_offset field, Ctype (Cil.typeAddAttributes attrs typ) with Not_found -> C.error loc "cannot find field %s" f) | _ -> diff --git a/src/kernel_services/ast_queries/logic_utils.ml b/src/kernel_services/ast_queries/logic_utils.ml index a77518acee2..8a43475ab1c 100644 --- a/src/kernel_services/ast_queries/logic_utils.ml +++ b/src/kernel_services/ast_queries/logic_utils.ml @@ -123,11 +123,11 @@ let plain_array_to_ptr ty = let array_to_ptr = plain_or_set plain_array_to_ptr -let typ_to_logic_type e_typ = - let ty = Cil.unrollType e_typ in +let coerced typ = + let ty = Cil.unrollType typ in if Cil.isIntegralType ty then Linteger else if Cil.isFloatingType ty then Lreal - else Ctype e_typ + else Ctype typ let predicate_of_identified_predicate ip = ip.ip_content @@ -292,7 +292,6 @@ let lconstant_to_constant c = match c with | LReal r -> CReal (r.r_nearest,FDouble,Some r.r_literal) | LEnum e -> CEnum e - let string_to_float_lconstant string = let f = snd (Floating_point.parse string) in (* If the string has suffix 'F' or 'D', then it represents a single or double @@ -346,24 +345,27 @@ let is_zero_comparable t = let scalar_term_conversion conversion t = let loc = t.term_loc in - let arith_conversion () = conversion ~loc false t (Cil.lzero ~loc ()) in - let ptr_conversion () = - conversion ~loc false t (Logic_const.term ~loc Tnull t.term_type) - in + let arith_conversion t = + conversion ~loc false t (Cil.lzero ~loc ()) in + let real_conversion ?ltyp t = + conversion ~loc false t (Logic_const.treal_zero ~loc ?ltyp ()) in + let ptr_conversion t = + conversion ~loc false t (Logic_const.term ~loc Tnull t.term_type) in + let bool_conversion t = + let ctrue = Logic_env.Logic_ctor_info.find "\\true" in + conversion ~loc true t (term ~loc (TDataCons(ctrue,[])) boolean_type) in match unroll_type t.term_type with - | Ctype (TInt _) -> arith_conversion () - | Ctype (TFloat _) -> - conversion ~loc false t (Logic_const.treal_zero ~loc ~ltyp:t.term_type ()) - | Ctype (TPtr _) -> ptr_conversion () - | Ctype (TArray _) -> ptr_conversion () + | Ctype (TInt _) -> arith_conversion t + | Ctype (TFloat _) as ltyp -> real_conversion ~ltyp t + | Ctype (TPtr _) -> ptr_conversion t + | Ctype (TArray _) -> ptr_conversion t (* Could be transformed to \true: an array is never \null *) - | Ctype (TFun _) -> ptr_conversion () + | Ctype (TFun _) -> ptr_conversion t (* decay as pointer *) - | Linteger -> arith_conversion () - | Lreal -> conversion ~loc false t (Logic_const.treal_zero ~loc ()) + | Linteger -> arith_conversion t + | Lreal -> real_conversion t | Ltype ({lt_name = name},[]) when name = Utf8_logic.boolean -> - let ctrue = Logic_env.Logic_ctor_info.find "\\true" in - conversion ~loc true t (term ~loc (TDataCons(ctrue,[])) boolean_type) + bool_conversion t | Ltype _ | Lvar _ | Larrow _ | Ctype (TVoid _ | TNamed _ | TComp _ | TEnum _ | TBuiltin_va_list _) -> Kernel.fatal @@ -386,124 +388,159 @@ let scalar_term_to_boolean = (* --- Expr Conversion --- *) (* -------------------------------------------------------------------------- *) -let rec expr_to_term ~cast e = +let is_boolean_binop op = + let open Cil_types in + match op with + | Lt | Gt | Le | Ge | Eq | Ne | LAnd | LOr -> true + | PlusA | PlusPI | IndexPI | MinusA | MinusPI | MinusPP + | Mult | Div | Mod | Shiftlt | Shiftrt | BAnd | BXor | BOr -> false + +let float_builtin prefix fkind = + let name = match fkind with + | FFloat -> Printf.sprintf "\\%s_float" prefix + | FDouble | FLongDouble -> Printf.sprintf "\\%s_double" prefix + in match Logic_env.find_all_logic_functions name with + | [ lf ] -> Some lf + | _ -> Kernel.fatal "Missing or ambiguous builtin %S" name + +let is_float_binop op typ = + match typ, op with + | TFloat(fkind,_) , PlusA -> float_builtin "add" fkind + | TFloat(fkind,_) , MinusA -> float_builtin "sub" fkind + | TFloat(fkind,_) , Mult -> float_builtin "mul" fkind + | TFloat(fkind,_) , Div -> float_builtin "div" fkind + | _ -> None + +let is_float_unop op typ = + match typ, op with + | TFloat(fkind,_) , Neg -> float_builtin "neg" fkind + | _ -> None + +let rec expr_to_term ?(coerce=false) e = let loc = e.eloc in - let typ = unrollType (Cil.typeOf e) in - let result = match e.enode with - | Const c -> TConst (constant_to_lconstant c) - | SizeOf t -> TSizeOf t - | SizeOfE e -> TSizeOfE (expr_to_term ~cast e) - | SizeOfStr s -> TSizeOfStr s - | StartOf lv -> TStartOf (lval_to_term_lval ~cast lv) - | AddrOf lv -> TAddrOf (lval_to_term_lval ~cast lv) - | CastE (ty,e) -> (mk_cast (unrollType ty) (expr_to_term ~cast e)).term_node - | BinOp (op, l, r, _) -> - let l' = expr_to_term_coerce ~cast l in - let r' = expr_to_term_coerce ~cast r in - (* type of the conversion of e in the logic. Beware that boolean - operators have boolean type. *) - let tcast = - match op, cast with - | ( Cil_types.Lt | Cil_types.Gt | Cil_types.Le | Cil_types.Ge - | Cil_types.Eq | Cil_types.Ne| Cil_types.LAnd | Cil_types.LOr), - _ -> Some Logic_const.boolean_type - | _, true -> Some (typ_to_logic_type typ) - | _, false -> None - in - let tnode = TBinOp (op,l',r') in - (* if [cast], we add a cast. Otherwise, when [op] is an operator - returning a boolean, we need to cast the whole expression as an - integral type, because (1) the recursive subcalls expect an - integer/float/pointer here, and (2) there is no implicit conversion - Boolean -> integer. *) - begin match tcast with - | Some lt -> (mk_cast typ (Logic_const.term tnode lt)).term_node - | None -> tnode + let typ = Cil.unrollType (Cil.typeOf e) in + let ctyp = Ctype typ in + let node,ltyp = + match e.enode with + | Const c -> TConst (constant_to_lconstant c) , coerced typ + | StartOf lv -> TStartOf (lval_to_term_lval lv) , ctyp + | AddrOf lv -> TAddrOf (lval_to_term_lval lv) , ctyp + | BinOp (op, a, b, _) -> + if is_boolean_binop op then + let tc = expr_to_boolean e in + Tif( tc , Cil.lone ~loc () , Cil.lzero ~loc () ), + Linteger + else begin match is_float_binop op typ with + | Some phi -> + let va = expr_to_term a in + let vb = expr_to_term b in + Tapp(phi,[],[va;vb]) , ctyp + | None -> + let va = expr_to_term ~coerce:true a in + let vb = expr_to_term ~coerce:true b in + TBinOp(op,va,vb) , coerced typ end - | UnOp (op, u, _) -> - let u' = expr_to_term_coerce ~cast u in - let u' = - match op with - | Cil_types.LNot -> - (match u'.term_node with - | TCastE(_, t) when is_boolean_type t.term_type -> t - | _ when is_boolean_type u'.term_type -> u' - | _ when is_zero_comparable u' -> - scalar_term_to_boolean u' - | _ -> - Kernel.fatal - "expr_to_term: unexpected argument of ! operator %a, \ - converted to %a" - Cil_printer.pp_exp u Cil_printer.pp_term u') - | _ -> u' - in - (* See comments for binop case above. *) - let tcast = match op, cast with - | Cil_types.LNot, _ -> Some Logic_const.boolean_type - | _, true -> Some (typ_to_logic_type typ) - | _, false -> None - in - let tnode = TUnOp (op, u') in - begin match tcast with - | Some lt -> (mk_cast typ (Logic_const.term tnode lt)).term_node - | None -> tnode + | UnOp (LNot, c, _) -> + let tc = expr_to_boolean c in + Tif( tc , Cil.lzero ~loc () , Cil.lone ~loc () ), + Linteger + | UnOp(op, a, _) -> + begin match is_float_unop op typ with + | Some phi -> + let va = expr_to_term ~coerce:true a in + Tapp(phi,[],[va]) , ctyp + | None -> + let va = expr_to_term ~coerce:true a in + TUnOp(op,va) , coerced typ end - | AlignOfE e -> TAlignOfE (expr_to_term ~cast e) - | AlignOf typ -> TAlignOf typ - | Lval lv -> TLval (lval_to_term_lval ~cast lv) - | Info (e,_) -> (expr_to_term ~cast e).term_node + | SizeOf t -> TSizeOf t, ctyp + | SizeOfE e -> TSizeOf (Cil.typeOf e), ctyp + | SizeOfStr s -> TSizeOfStr s, ctyp + | AlignOf typ -> TAlignOf typ, ctyp + | AlignOfE e -> TAlignOf (Cil.typeOf e), ctyp + | Lval lv -> TLval (lval_to_term_lval lv), ctyp + | CastE (ty,e) -> + let t = mk_cast ~loc ty (expr_to_term ~coerce e) in + t.term_node , t.term_type + | Info (e,_) -> + let t = expr_to_term ~coerce e in + t.term_node , t.term_type in - let tres = Logic_const.term ~loc result (Ctype typ) in - if cast then tres - else - match e.enode with - (* all immediate values keep their C type by default, and are only lifted - to integer/real if needed. *) - | Const _ | Lval _ | CastE _ -> tres - | _ -> numeric_coerce (typ_to_logic_type typ) tres - -and expr_to_term_coerce ~cast e = - let t = expr_to_term ~cast e in - match Logic_const.unroll_ltdef t.term_type with - | Ctype typ when Cil.isIntegralType typ || Cil.isFloatingType typ -> - let ltyp = typ_to_logic_type typ in - numeric_coerce ltyp t - | _ -> t + let v = mk_cast ~loc typ @@ Logic_const.term ~loc node ltyp in + match typ with + | TInt _ when coerce -> numeric_coerce Linteger v + | TFloat _ when coerce -> numeric_coerce Lreal v + | _ -> v -and lval_to_term_lval ~cast (host,offset) = - host_to_term_host ~cast host, offset_to_term_offset ~cast offset +and lval_to_term_lval (host,offset) = + host_to_term_lhost host, offset_to_term_offset offset -and host_to_term_host ~cast = function +and host_to_term_lhost = function | Var s -> TVar (Cil.cvar_to_lvar s) - | Mem e -> TMem (expr_to_term ~cast e) (*no need of numeric coercion - pointer *) + | Mem e -> TMem (expr_to_term e) -and offset_to_term_offset ~cast:cast = function +and offset_to_term_offset = function | NoOffset -> TNoOffset + | Field (fi,off) -> + TField(fi,offset_to_term_offset off) | Index (e,off) -> - TIndex (expr_to_term_coerce ~cast e,offset_to_term_offset ~cast off) - | Field (fi,off) -> TField(fi,offset_to_term_offset ~cast off) + TIndex (expr_to_term ~coerce:true e,offset_to_term_offset off) -and expr_to_predicate ~cast e = +and expr_to_boolean e = let open Cil_types in + let tbool n = Logic_const.term n Logic_const.boolean_type in match e.enode with - | BinOp ((Lt | Gt | Le | Ge | Eq | Ne as op), l, r, _) -> - let tl = expr_to_term ~cast l in - let tr = expr_to_term ~cast r in - let rel = match op with - | Lt -> Rlt | Gt -> Rgt | Le -> Rle | Ge -> Rge | Eq -> Req | Ne -> Rneq - | _ -> assert false - in - let pred = Prel (rel, tl, tr) in - Logic_const.new_predicate (Logic_const.unamed ~loc:e.eloc pred) + | UnOp(BNot, a,_) -> + tbool @@ TUnOp(BNot, expr_to_boolean a) + | BinOp((BAnd|BOr) as op,a,b,_) -> + let va = expr_to_boolean a in + let vb = expr_to_boolean b in + tbool @@ TBinOp(op,va,vb) + | BinOp(op, a, b, _) when is_boolean_binop op -> + let va = expr_to_term ~coerce:true a in + let vb = expr_to_term ~coerce:true b in + tbool @@ TBinOp(op,va,vb) | _ -> - let t = expr_to_term ~cast e in + let t = expr_to_term ~coerce:true e in if is_zero_comparable t then - Logic_const.new_predicate (scalar_term_to_predicate t) + scalar_term_to_boolean t else Kernel.fatal "Cannot convert into predicate the C expression %a" Cil_printer.pp_exp e +and expr_to_predicate e = + let open Cil_types in + let unamed = Logic_const.unamed ~loc:e.eloc in + let prel r a b = + let va = expr_to_term ~coerce:true a in + let vb = expr_to_term ~coerce:true b in + unamed @@ Prel(r,va,vb) + in match e.enode with + | BinOp(Lt, a, b, _) -> prel Rlt a b + | BinOp(Le, a, b, _) -> prel Rle a b + | BinOp(Gt, a, b, _) -> prel Rgt a b + | BinOp(Ge, a, b, _) -> prel Rge a b + | BinOp(Eq, a, b, _) -> prel Req a b + | BinOp(Ne, a, b, _) -> prel Rneq a b + | BinOp(BAnd, a, b, _) -> + unamed @@ Pand(expr_to_predicate a,expr_to_predicate b) + | BinOp(BOr, a, b, _) -> + unamed @@ Por(expr_to_predicate a,expr_to_predicate b) + | UnOp(BNot, a, _) -> + unamed @@ Pnot(expr_to_predicate a) + | _ -> + let t = expr_to_term ~coerce:true e in + if is_zero_comparable t then + scalar_term_to_predicate t + else + Kernel.fatal + "Cannot convert into predicate the C expression %a" + Cil_printer.pp_exp e + +and expr_to_ipredicate e = + Logic_const.new_predicate (expr_to_predicate e) + (* ************************************************************************* *) (** {1 Various utilities} *) (* ************************************************************************* *) @@ -513,8 +550,8 @@ let array_with_range arr size = let arr = Cil.stripCasts arr in let typ_arr = typeOf arr in let no_cast = isAnyCharPtrType typ_arr || isAnyCharArrayType typ_arr in - let char_ptr = typ_to_logic_type Cil.charPtrType in - let arr = expr_to_term ~cast:true arr in + let char_ptr = Ctype Cil.charPtrType in + let arr = expr_to_term arr in let arr = if no_cast then arr else mk_cast ~loc Cil.charPtrType arr diff --git a/src/kernel_services/ast_queries/logic_utils.mli b/src/kernel_services/ast_queries/logic_utils.mli index 3853a02c250..25dff3363f4 100644 --- a/src/kernel_services/ast_queries/logic_utils.mli +++ b/src/kernel_services/ast_queries/logic_utils.mli @@ -86,7 +86,7 @@ val logicCType : logic_type -> typ val array_to_ptr : logic_type -> logic_type (** C type to logic type, with implicit conversion for arithmetic types. *) -val typ_to_logic_type : typ -> logic_type +val coerced : typ -> logic_type (** {2 Predicates} *) @@ -157,36 +157,62 @@ val pointer_comparable: ?loc:location -> term -> term -> predicate (** \pointer_comparable @since Fluorine-20130401 *) -(** {2 Conversion from exp to term} - - translates a C expression into an "equivalent" logical term. - [cast] specifies how C arithmetic operators are translated. - When [cast] is [true], the translation returns a logic [term] having the - same semantics of the C [expr] by introducing casts (i.e. the C expr [a+b] - can be translated as [(char)(((char)a)+(char)b)] to preserve the modulo - feature of the C addition). - Otherwise, no such casts are introduced and the C arithmetic operators are - translated into perfect mathematical operators (i.e. a floating point - addition is translated into an addition of [real] numbers). - @plugin development guide *) -val expr_to_term : cast:bool -> exp -> term +(** {2 Conversion from exp to term} *) -(** same as {!expr_to_term}, except that if the new term has an arithmetic - type, it is automatically coerced into real (or integer for integral types). +val expr_to_term : ?coerce:bool -> exp -> term +(** Returns a logic term that has exactly the same semantics than the + original C-expression. The type of the resulting term is determined + by the [~coerce] flag as follows: + - when [~coerce:false] is given (the default) the term has the same + c-type than the original expression. + - when [~coerce:true] is given, if the original expression has an int or + float type, then the returned term is coerced into the integer or real + logic type, respectively. - @since Magnesium-20151001 + Remark: when the original expression is a comparison, it is evaluated as + a [_Bool] or [integer] depending on the [~coerce] flag. + To obtain a boolean or predicate, use [expr_to_boolean] or + [expr_to_predicate] instead. + + @modify Frama-C+dev +*) + +val expr_to_predicate: exp -> predicate +(** Returns a predicate semantically equivalent to the condition + of the original C-expression. + + This is different than [expr_to_term e |> scalar_term_to_predicate] + since it directly translate C-relations into logic ones. + + @raise Fatal error if the expression is not a comparison and cannot be + compared to zero. + @since Sulfur-20171101 + @modify Frama-C+dev *) -val expr_to_term_coerce: cast:bool -> exp -> term -val expr_to_predicate: cast:bool -> exp -> identified_predicate -(** same as {expr_to_term}, but the result is a predicate. Expressions starting - with relational operators ([==], [<=], etc) are translated directly. - Otherwise, the result of [expr_to_predicate e] is the predicate - [e <> 0]. +val expr_to_ipredicate: exp -> identified_predicate +(** Returns a predicate semantically equivalent to the condition + of the original C-expression. + + Identical to [expr_to_predicate e |> Logic_const.new_predicate]. + + @raise Fatal error if the expression is not a comparison and cannot be + compared to zero. + @since Sulfur-20171101 + @modify Frama-C+dev +*) + +val expr_to_boolean: exp -> term +(** Returns a boolean term semantically equivalent to the condition + of the original C-expression. + + This is different than [expr_to_term e |> scalar_term_to_predicate] + since it directly translate C-relations into logic ones. @raise Fatal error if the expression is not a comparison and cannot be compared to zero. @since Sulfur-20171101 + @modify Frama-C+dev *) val is_zero_comparable: term -> bool @@ -212,10 +238,9 @@ val scalar_term_to_predicate: term -> predicate @since Sulfur-20171101 *) -val lval_to_term_lval : cast:bool -> lval -> term_lval -val host_to_term_host : cast:bool -> lhost -> term_lhost -val offset_to_term_offset : - cast:bool -> offset -> term_offset +val lval_to_term_lval : lval -> term_lval +val host_to_term_lhost : lhost -> term_lhost +val offset_to_term_offset : offset -> term_offset val constant_to_lconstant: constant -> logic_constant val lconstant_to_constant: logic_constant-> constant diff --git a/src/kernel_services/ast_transformations/inline.ml b/src/kernel_services/ast_transformations/inline.ml index 5cdbfc0f1e2..c078078909a 100644 --- a/src/kernel_services/ast_transformations/inline.ml +++ b/src/kernel_services/ast_transformations/inline.ml @@ -96,7 +96,7 @@ let inline_call loc caller callee return args = method! vterm_lval (host,offset) = match host, return with | TResult _, Some lv -> - let tlv = Logic_utils.lval_to_term_lval ~cast:false lv in + let tlv = Logic_utils.lval_to_term_lval lv in let offset = Visitor.visitFramacTermOffset self offset in Cil.ChangeToPost (Logic_const.addTermOffsetLval offset tlv, Extlib.id) diff --git a/src/plugins/aorai/aorai_dataflow.ml b/src/plugins/aorai/aorai_dataflow.ml index e869e3dd345..554af1f3639 100644 --- a/src/plugins/aorai/aorai_dataflow.ml +++ b/src/plugins/aorai/aorai_dataflow.ml @@ -449,7 +449,7 @@ module Computer(I: Init) = struct "too few arguments in call to %a" Printer.pp_varinfo f | p::prms, a::args -> let lv = Logic_const.tvar (Cil.cvar_to_lvar p) in - let la = Logic_utils.expr_to_term ~cast:false a in + let la = Logic_utils.expr_to_term a in let value = Cil_datatype.Term.Map.add la (Fixed 0) Cil_datatype.Term.Map.empty diff --git a/src/plugins/aorai/aorai_utils.ml b/src/plugins/aorai/aorai_utils.ml index ff3c2f3a3fe..c4fb25191c1 100644 --- a/src/plugins/aorai/aorai_utils.ml +++ b/src/plugins/aorai/aorai_utils.ml @@ -138,7 +138,7 @@ let isCrossableAtInit tr func = let rec aux t = match t.term_node with | TConst (LEnum ei) -> - aux (Logic_utils.expr_to_term ~cast:false ei.eival) + aux (Logic_utils.expr_to_term ei.eival) | TLval lv -> (match aux_lv lv with | Some t -> t @@ -241,7 +241,7 @@ let isCrossableAtInit tr func = and aux_init off initinfo = match off, initinfo with | TNoOffset, SingleInit e -> - Some (aux (Logic_utils.expr_to_term ~cast:false e)) + Some (aux (Logic_utils.expr_to_term e)) | TIndex(t,oth), CompoundInit (ct,initl) -> (match (aux t).term_node with | TConst(Integer(i1,_)) -> @@ -653,7 +653,7 @@ let one_term () = Cil.lconstant Integer.one (** Returns a term representing the variable associated to the given varinfo *) let mk_term_from_vi vi = Logic_const.term - (TLval((Logic_utils.lval_to_term_lval ~cast:true (Cil.var vi)))) + (TLval((Logic_utils.lval_to_term_lval (Cil.var vi)))) (Ctype Cil.intType) (** Given an lval term 'host' and an integer value 'off', it returns a lval term host[off]. *) @@ -681,8 +681,7 @@ let mk_offseted_array_states_as_enum host off = (Ctype Cil.intType) (** Returns a lval term associated to the curState generated variable. *) -let host_state_term() = - lval_to_term_lval ~cast:true (state_lval()) +let host_state_term() = lval_to_term_lval (state_lval()) (* (** Returns a lval term associated to the curStateOld generated variable. *) let host_stateOld_term () = diff --git a/src/plugins/instantiate/basic_blocks.ml b/src/plugins/instantiate/basic_blocks.ml index 660db8c83c0..744917afbad 100644 --- a/src/plugins/instantiate/basic_blocks.ml +++ b/src/plugins/instantiate/basic_blocks.ml @@ -131,7 +131,7 @@ let rec tunref_range ?loc ptr len = and tunref_range_unfold ?loc lval typ = match typ with | Ctype(TArray(typ, Some e, _, _)) -> - let len = Logic_utils.expr_to_term ~cast:false e in + let len = Logic_utils.expr_to_term ~coerce:true e in let last = tminus ?loc len (tinteger ?loc 1) in let range = trange ?loc (Some (tinteger ?loc 0), Some last) in let lval = addTermOffsetLval (TIndex(range, TNoOffset)) lval in @@ -218,7 +218,7 @@ and pall_elems_eq ?loc depth t1 t2 len = and peq_unfold ?loc depth t1 t2 = match Logic_utils.unroll_type t1.term_type with | Ctype(TArray(_, Some len, _, _)) -> - let len = Logic_utils.expr_to_term ~cast:false len in + let len = Logic_utils.expr_to_term ~coerce:true len in pall_elems_eq ?loc depth t1 t2 len | _ -> prel ?loc (Req, t1, t2) @@ -236,7 +236,7 @@ and punfold_pred ?loc ?(dyn_len = None) depth t1 pred = | Ctype(TArray(_, opt_len, _, _)) -> let len = match opt_len, dyn_len with - | Some len, None -> Logic_utils.expr_to_term ~cast:false len + | Some len, None -> Logic_utils.expr_to_term ~coerce:true len | _ , Some len -> len | None, None -> Options.fatal "Unfolding array: cannot find a length" diff --git a/src/plugins/occurrence/register_gui.ml b/src/plugins/occurrence/register_gui.ml index aafb865f349..d7b8da68dfc 100644 --- a/src/plugins/occurrence/register_gui.ml +++ b/src/plugins/occurrence/register_gui.ml @@ -127,7 +127,7 @@ let occurrence_highlighter buffer loc ~start ~stop = | PTermLval (_,ki,_,term_lval) -> let same_tlval (_kf, k, l) = Logic_utils.is_same_tlval - (Logic_utils.lval_to_term_lval ~cast:true l) + (Logic_utils.lval_to_term_lval l) term_lval && Kinstr.equal k ki in diff --git a/src/plugins/studia/studia_gui.ml b/src/plugins/studia/studia_gui.ml index a235a6f490b..65638eed878 100644 --- a/src/plugins/studia/studia_gui.ml +++ b/src/plugins/studia/studia_gui.ml @@ -54,7 +54,7 @@ let get_lval_opt main_ui kf localizable = match localizable with | Pretty_source.PLval (Some _kf, (Kstmt _stmt), lv) -> let lv_txt = Pretty_utils.to_string Printer.pp_lval lv in - let tlv = Logic_utils.lval_to_term_lval ~cast:false lv in + let tlv = Logic_utils.lval_to_term_lval lv in Some (lv_txt, tlv) | Pretty_source.PTermLval (Some _kf, (Kstmt _stmt), _, tlv) -> let tlv_txt = Pretty_utils.to_string Printer.pp_term_lval tlv in diff --git a/src/plugins/value/domains/traces_domain.ml b/src/plugins/value/domains/traces_domain.ml index 1761500f38f..72492be5df5 100644 --- a/src/plugins/value/domains/traces_domain.ml +++ b/src/plugins/value/domains/traces_domain.ml @@ -1080,10 +1080,12 @@ let rec stmts_of_cfg cfg current var_map locals return_exp acc = | Assume (_, exp,b) -> let exp = subst_in_exp var_map exp in - let predicate = (Logic_utils.expr_to_predicate ~cast:true exp).Cil_types.ip_content in + let predicate = Logic_utils.expr_to_predicate exp in let predicate = if b then predicate else Logic_const.pnot predicate in - let code_annot = Logic_const.new_code_annotation(Cil_types.AAssert([],Assert,predicate)) in - let stmt = Cil.mkStmtOneInstr ~valid_sid (Cil_types.Code_annot(code_annot,dummy_loc)) in + let code_node = Cil_types.AAssert([],Assert,predicate) in + let code_annot = Logic_const.new_code_annotation code_node in + let stmt_kind = Cil_types.Code_annot(code_annot,exp.eloc) in + let stmt = Cil.mkStmtOneInstr ~valid_sid stmt_kind in stmts_of_cfg cfg n var_map locals return_exp (stmt::acc) | EnterScope (_, vs) -> diff --git a/src/plugins/wp/LogicSemantics.ml b/src/plugins/wp/LogicSemantics.ml index 2a90684fe56..b15809c85bb 100644 --- a/src/plugins/wp/LogicSemantics.ml +++ b/src/plugins/wp/LogicSemantics.ml @@ -1027,7 +1027,7 @@ struct (* -------------------------------------------------------------------------- *) let assigned_of_lval env ~unfold (lv : Cil_types.lval) = - assignable_lval env ~unfold (Logic_utils.lval_to_term_lval ~cast:false lv) + assignable_lval env ~unfold (Logic_utils.lval_to_term_lval lv) let assigned_of_froms env ~unfold froms = List.concat diff --git a/tests/spec/expr_to_term.ml b/tests/spec/expr_to_term.ml index 17478ac46f1..e6fb35a7376 100644 --- a/tests/spec/expr_to_term.ml +++ b/tests/spec/expr_to_term.ml @@ -14,7 +14,7 @@ let check_expr_term check fct s e = | (_, { ip_content = { pred_content = Papp(_,_,[l;_]) } }) -> l | _ -> Kernel.fatal "Unexpected ensures %a" Printer.pp_post_cond e in - let term' = Logic_utils.expr_to_term ~cast:false exp in + let term' = Logic_utils.expr_to_term ~coerce:true exp in let term' = Logic_utils.mk_cast Cil.intType term' in if check && not (Cil_datatype.Term.equal term term') then Kernel.fatal @@ -29,7 +29,7 @@ let treat_fct check fct = let stmts = (Kernel_function.get_definition fct).sbody.bstmts in let stmts = List.filter - (function + (function { skind = Instr (Set (lv,_,_)) } -> (match lv with (Var v,_) -> v.vglob | _ -> true) | { skind = If _ } -> true @@ -41,7 +41,7 @@ let treat_fct check fct = (* A bit fragile, but should do the trick as long as the test itself does not get too complicated (regarding the C code at least). *) if not (List.length stmts = List.length ensures) then - Kernel.fatal + Kernel.fatal "Stmts:@\n%a@\nPreds:@\n%a@\n" (Pretty_utils.pp_list ~sep:"@\n@\n" Printer.pp_stmt) stmts (Pretty_utils.pp_list ~sep:"@\n@\n" Printer.pp_post_cond) ensures; -- GitLab