123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212(**************************************************************************)(* *)(* This file is part of the Frama-C's Lannotate plug-in. *)(* *)(* Copyright (C) 2012-2025 *)(* CEA (Commissariat à l'énergie atomique et aux énergies *)(* alternatives) *)(* *)(* you can redistribute it and/or modify it under the terms of the GNU *)(* Lesser General Public License as published by the Free Software *)(* Foundation, version 2.1. *)(* *)(* It is distributed in the hope that it will be useful, *)(* but WITHOUT ANY WARRANTY; without even the implied warranty of *)(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *)(* GNU Lesser General Public License for more details. *)(* *)(* See the GNU Lesser General Public License version 2.1 *)(* for more details (enclosed in the file LICENSE) *)(* *)(**************************************************************************)openCil_typesopenAst_constletprint_std_includesfmtglobs=ifnot(Kernel.PrintLibc.get())thenbeginletextract_fileacc=function|AStrs->Datatype.String.Set.addsacc|_->Kernel.warning"Unexpected attribute parameter for fc_stdlib";accinletadd_fileaccg=letattrs=Cil_datatype.Global.attrginList.fold_leftextract_fileacc(Ast_attributes.find_params"fc_stdlib"attrs)inletincludes=List.fold_leftadd_fileDatatype.String.Set.emptyglobsinletprint_one_includes=Format.fprintffmt"#include \"%s\"@."sinDatatype.String.Set.iterprint_one_includeincludesendmodulePrinter=Printer_builder.Make(structclassprinter()=object(self)inheritPrinter.extensible_printer()method!filefmtfile=Format.fprintffmt"@[/* Generated by Frama-C LTest */\n\n";print_std_includesfmtfile.globals;Format.fprintffmt"\n#ifndef pc_label\n#define pc_label(...) do{}while(0)\n\
#endif@\n\
#ifndef pc_label_bindings\n#define pc_label_bindings(...) do{}while(0)\n\
#endif@\n\n";ifOptions.Annotators.mem"RCC"thenbeginFormat.fprintffmt"\
#define MAX_MUTATION %d\n\
unsigned int cpt_mutation = 0;\n\n\
/*%@ assigns cpt_mutation, \\result;\n\
\ behavior can_mutate:\n\
\ assumes cpt_mutation < MAX_MUTATION;\n\
\ ensures \\result <==> cpt_mutation == \\at(cpt_mutation, Pre) + 1;\n\
\ ensures !\\result <==> cpt_mutation == \\at(cpt_mutation, Pre);\n\n\
\ behavior cant_mutate:\n\
\ assumes cpt_mutation >= MAX_MUTATION;\n\
\ ensures !\\result;\n\
\ ensures cpt_mutation == \\at(cpt_mutation, Pre);\n\n\
\ complete behaviors;\n\
\ disjoint behaviors;\n\
*/\n\
int mutated(void);\n"(Options.MaxMutation.get());end;Cil.iterGlobalsfile(fung->self#globalfmtg);Format.fprintffmt"@]@."endend)(** Extracts global variables from an AST *)letextract_global_varsfile=letmoduleS=Cil_datatype.Varinfo.Setinletfaccglobal=matchglobalwith|GVar(vi,_,_)->ifAst_types.is_funvi.vtypethenaccelseS.addviacc|GVarDecl(vi,_)->ifAst_types.is_funvi.vtypethenaccelseS.addviacc|_->accinletglobals=Cil.foldGlobalsfilefS.emptyinS.elementsglobalsletprint_file_pathorigine_loc=Filepath.to_string_rel(fstorigine_loc).Filepath.pos_pathletmk_call?(loc=Cil_datatype.Location.unknown)?resultfvinfoargs=letvinfo_exp=Exp_builder.var~loc(Option.getfvinfo)inStmt_builder.mk(Instr(Call(result,vinfo_exp,args,loc)))(** Indicates whether an instruction is a label. *)letis_labelinstr=matchinstrwith|Call(_,{enode=Lval(Var{vname=name},NoOffset)},_,_)->letregexp=Str.regexp_string"pc_label"inStr.string_matchregexpname0|_->false(**
Indicates whether an expression is boolean in itself.
Used to detect boolean expression outside conditional statement
*)letis_booleane=Options.debug~level:3"is boolean? @[%a@]@."Cil_printer.pp_expe;matche.enodewith(* C99 _Bool type *)|BinOp(_,_,_,{tnode=TIntIBool})|UnOp(_,_,{tnode=TIntIBool})(* Use of logical operators or relational operators *)|BinOp((LAnd|LOr|Lt|Gt|Le|Ge|Eq|Ne),_,_,_)|UnOp(LNot,_,_)->true|_->false(**
Get atomic conditions from a boolean expression.
*)letatomic_conditions=letrecauxaccexp=matchexp.enodewith|BinOp((Ne|Eq),a,b,_)->(* Cil adds !=0 when && or || are present in normal expression (don't do that for !)*)ifCil.isZerob&&is_booleanathenauxaccaelseifCil.isZeroa&&is_booleanbthenauxaccbelseexp::acc|BinOp((LAnd|LOr),e1,e2,_)->aux(auxacce1)e2|UnOp(LNot,e,_)->auxacce|_->exp::accinfunexp->List.rev(aux[]exp)letrev_combine:int->'alist->'alistlist=letreccomb_auxrev_startswithaccnl=matchn,lwith|0,_->(List.revrev_startswith)::acc|_,[]->acc|_,head::tail->letacc=comb_aux(head::rev_startswith)acc(n-1)tailincomb_auxrev_startswithaccntailinfunnl->comb_aux[][]nl(*Needed to keep polymorphism, wtf!?*)(** [combine n l] computes the combinations of [n] elements from the list [l].
Returns the combination in the order of the list [l].
For instance, [combine 2 [1;2;3]] returns [[1;2];[1;3];[2;3]].
*)letcombinen(l:'alist):'alistlist=List.rev(rev_combinenl)(**
[sign_combine pos neg l] computes all sign combinations of a list of elements [l], given two sign functions [pos] and [neg].
Preserves the original order of the list, i.e. each sublist is in the same order.
For instance, [sign_combine (fun x ->"+"^x) (fun x -> "-"^x) ["1";"2"]] returns [["+1";"+2"];["+1";"-2"];["-1";"+2"];["-1";"-2"]].
*)letrev_sign_combine~(pos:'a->'b)~(neg:'a->'b):'alist->'blistlist=letrecauxaccrevprefl=matchlwith|[]->(List.revrevpref)::acc|head::tail->letacc=auxacc(poshead::revpref)tailinauxacc(neghead::revpref)tailinaux[][]letsign_combine~pos~negl=List.rev(rev_sign_combine~pos~negl)letwith_deltaopvaluekind=letdelta=Options.LimitDelta.get()inletop'=matchop,deltawith|_,0->Eq|MinusA,_->Ge|PlusA,_->Le|_->assertfalseinifdelta=0thenop',Exp_builder.kinteger64kindvalueelseop',Exp_builder.binopop(Exp_builder.kinteger64kindvalue)(Exp_builder.integerdelta)letget_boundskind:(binop*exp)list=ifkind=IBoolthen[(Eq,Exp_builder.zero());(Eq,Exp_builder.one())]elseletsize=Cil.bitsSizeOfIntkindinifCil.isSignedkindthen[with_deltaPlusA(Cil.min_signed_numbersize)kind;with_deltaMinusA(Cil.max_signed_numbersize)kind]else[with_deltaPlusAInteger.zerokind;with_deltaMinusA(Cil.max_unsigned_numbersize)kind]letis_bound_kind_i=false(* let size = Cil.bitsSizeOfInt kind in
if Cil.isSigned kind then
i>= (Cil.max_signed_number size)
else
i = Integer.of_int 0 || i >= Cil.max_signed_number size *)