Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file rpp_extend_checker.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235(**************************************************************************)(* *)(* SPDX-License-Identifier LGPL-2.1 *)(* Copyright (C) *)(* CEA (Commissariat à l'énergie atomique et aux énergies alternatives) *)(* *)(**************************************************************************)openFilecheckopenCil_typesletid_checkeridentifierlocid_hash=matchidentifierwith|FormalLabel(s)->(matchStr.bounded_split(Str.regexp"_")s2with|"Pre"::id::[]|"Post"::id::[]->ifnot(Hashtbl.memid_hashid)thenRpp_options.Self.fatal~source:loc"Unknown label: @ @[%s@] @."s|_->())|_->()let_id_updateidentifierlocid_hash=matchidentifierwith|FormalLabel(s)->(matchStr.bounded_split(Str.regexp"_")s2with|"Pre"::id::[]->let_=try(Hashtbl.findid_hashid)with|Not_found->Rpp_options.Self.fatal~source:loc"Unknown label: @ @[%s@] @."s|_->assertfalseinBuiltinLabel(Pre)|"Post"::id::[]->let_=try(Hashtbl.findid_hashid)with|Not_found->Rpp_options.Self.fatal~source:loc"Unknown label: @ @[%s@] @."s|_->assertfalseinBuiltinLabel(Here)|_->identifier)|_->identifierletcheck_param_typefnameparamformalsloc=matchformalswith|Somel->List.iter2(funx(_,t,_)->matchx.term_typewith|Ctype(ty)->ifCil_datatype.Typ.equalttythen()elseRpp_options.Self.fatal~source:loc"Cast are not supported:@. @[%a and %a are not \
compatible@] for term @[%a@] in callpure of %s @."(Printer.pp_logic_type)x.term_type(Printer.pp_typ)t(Printer.pp_term)x(fname)|Linteger->ifnot(Ast_types.is_integralt)thenRpp_options.Self.fatal~source:loc"Cast are not supported:@. @[%a and %a are not compatible@] \
for term @[%a@] in callpure of %s @."(Printer.pp_logic_type)x.term_type(Printer.pp_typ)tPrinter.pp_termx(fname)|Lreal->ifnot(Ast_types.is_floatt)thenRpp_options.Self.fatal~source:loc"Cast are not supported:@. @[%a and %a are not compatible@] \
for term @[%a@] in callpure of %s @."(Printer.pp_logic_type)x.term_type(Printer.pp_typ)tPrinter.pp_termx(fname)|_->Rpp_options.Self.fatal~source:loc"Function %s is called with a parameter with type \
is not a C type:@. @[%a@] @."(fname)Printer.pp_termx)paraml|None->Rpp_options.Self.fatal~source:loc"Function %s is declared without prototype. Can't use it in a relational property"fnameletrpp_extend_checkercheck=letmoduleOrigin=(valcheck:Extensible_checker)inletmoduleNew_check=structclasscheck?is_normalizedid=object(self)inheritOrigin.check?is_normalizedidassupervalid_hash=Hashtbl.create3method!vtermt=letloc=fstt.term_locinmatcht.term_nodewith|Tapp({l_var_info={lv_name="\\callpure"}},[],terms)->beginmatchtermswith|{term_node=TConst(Integer(_,_))}::q->beginmatchqwith|{term_node=TLval(TVar({lv_origin=Some(x)}),TNoOffset)}::p->ifAst_types.is_funx.vtypethenbeginlet(rt,args,_is_va,_)=Cil.splitFunctionTypex.vtypeincheck_param_typex.vnamepargsloc;ifnot(Cil_datatype.Logic_type.equal(t.term_type)(Ctypert))thenRpp_options.Self.fatal~source:loc"\\callpure type (@[%a@]) is different from result type \
of function @[%a@] (@[%a@]):@.@[%a@]"Printer.pp_logic_typet.term_typePrinter.pp_varinfoxPrinter.pp_typrtPrinter.pp_termtendelseRpp_options.Self.fatal~source:loc"Expected a function as second parameter::@. @[%a@] @."(Printer.pp_term)t;DoChildren|_->Rpp_options.Self.fatal~source:loc"Expected a logical variable as second parameter :@. @[%a@] @."(Printer.pp_term)tend|_->Rpp_options.Self.fatal~source:loc"Expected an integer for first parameter:@. @[%a@] @."(Printer.pp_term)tend|Tapp({l_var_info={lv_name="\\call"}},[],terms)->beginmatchtermswith|{term_node=TConst(LStr(s))}::k->beginmatchHashtbl.findid_hashswith|exceptionNot_found->beginmatchkwith|{term_node=TConst(Integer(_,_))}::q->beginmatchqwith|{term_node=TLval(TVar({lv_origin=Some(x)}),TNoOffset)}::p->ifAst_types.is_funx.vtypethenlet(_,args,_,_)=Cil.splitFunctionTypex.vtypeincheck_param_typex.vnamepargsloc;Hashtbl.addid_hashsx;Cil.DoChildrenelseRpp_options.Self.fatal~source:loc"Expected a function as third parameter:@. @[%a@] @."(Printer.pp_term)t|_->Rpp_options.Self.fatal~source:loc"Expected a logical variable as third parameter:@. @[%a@] @."(Printer.pp_term)tend|_->Rpp_options.Self.fatal~source:loc"Expected an integer for second parameter:@. @[%a@] @."(Printer.pp_term)tend|_->Rpp_options.Self.fatal~source:loc"Multiple use of identifier %s @."send|_->Rpp_options.Self.fatal~source:loc"Expected an string for first parameter (identifier):@. @[%a@] @."(Printer.pp_term)tend|Tapp({l_var_info={lv_name="\\callresult"}},[],terms)->if(List.lengthterms)<>1thenRpp_options.Self.fatal~source:loc"\\callresult contain more then one parameter:@. @[%a@] @."(Printer.pp_term)telseletterm=List.hdtermsinbeginmatchterm.term_nodewith|TConst(LStr(s))->letv=matchHashtbl.find_optid_hashswith|Somev->v|None->Rpp_options.Self.fatal~source:loc"Unknown identifier %s in \\callresult:@. @[%a@] @."s(Printer.pp_term)tinlet(rt,_,_,_)=Cil.splitFunctionTypev.vtypeinif(Cil_datatype.Logic_type.equal(Ctypert)(t.term_type))then()elsebeginRpp_options.Self.fatal~source:loc"\\callresult type (@[%a@]) is different from result type of function @[%a@] \
(@[%a@]) with identifier %s @."Printer.pp_logic_type(t.term_type)Printer.pp_varinfovPrinter.pp_logic_type(Ctypert)send|_->Rpp_options.Self.fatal~source:loc"\\callresult contain no string : @[%a@] @."Printer.pp_termtermend;Cil.SkipChildren|Tapp({l_var_info={lv_name="\\callpure"}},_::_,_)->Rpp_options.Self.fatal~source:loc"Expect no label for built-in \\callpure:@. @[%a@]"Printer.pp_termt|Tapp({l_var_info={lv_name="\\callresult"}},_::_,_)->Rpp_options.Self.fatal~source:loc"Expect no label for built-in \\callresult:@. @[%a@]"Printer.pp_termt|Tapp({l_var_info={lv_name="\\call"}},_::_,_)->Rpp_options.Self.fatal~source:loc"Expect no label for built-in \\callresult:@. @[%a@]"Printer.pp_termt|Tat(v,l)->id_checkerllocid_hash;self#vtermv|_->super#vtermtmethod!vpredicatep=let(loc,_)=p.pred_locinmatchp.pred_contentwith|Papp({l_var_info={lv_name="\\callset"}},[],terms)->Hashtbl.clearid_hash;List.iter(funx->matchx.term_nodewith|Tapp({l_var_info={lv_name="\\call"}},_,_)->let_=self#vtermxin()|_->Rpp_options.Self.fatal~source:loc"\\callset contain no \\call: @. @[%a@] @."Printer.pp_termx)terms;Cil.SkipChildren|Papp(li,labels,params)->List.iter(funl->id_checkerllocid_hash)labels;ignore(super#vlogic_info_useli);List.iter(funt->ignore(Visitor.visitFramacTerm(self:>Visitor.frama_c_visitor)t))params;Cil.SkipChildren|_->super#vpredicatependendin(moduleNew_check:Extensible_checker)let()=extend_checkerrpp_extend_checker