123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209(**************************************************************************)(* *)(* This file is part of Frama-C. *)(* *)(* Copyright (C) 2007-2023 *)(* 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 licenses/LGPLv2.1). *)(* *)(**************************************************************************)openCil_typesopenDesignletall_alarms()=letall_red_statuses=Red_statuses.get_all()inletall=List.map(fun(kinstr,ap,number)->letkf_name=matchkinstrwith|Kstmtstmt->Kernel_function.(get_name(find_englobing_kfstmt))|Kglobal->matchapwith|Red_statuses.Alarm_->"<global>"|Red_statuses.Propp->matchProperty.get_kfpwith|Somekf->Kernel_function.get_namekf|None->"<global>"in(kf_name,kinstr,ap,number))all_red_statusesinletkf_name_comparekfname=String.uncapitalize_asciikfnamein(* Sort by function names, then stmt, then alarms *)letcmp(k1,ki1,ap1,_)(k2,ki2,ap2,_)=letn=String.(compare(kf_name_comparek1)(kf_name_comparek2))inifn<>0thennelseletn=Cil_datatype.Kinstr.compareki1ki2inifn<>0thennelseRed_statuses.AlarmOrProp.compareap1ap2inList.sortcmpalltypered_alarm={function_name:string;kind:string;acsl:string;ip:Property.t;callstacks:int;(* Number of callstacks in which the red alarm occured. *)}letget_predicateca=matchca.annot_contentwith|AAssert(_,p)->{pwithtp_statement={p.tp_statementwithpred_name=[]}}|_->assertfalseletmake_red_alarmfunction_namekialarmcallstacks=letkf,stmt=matchkiwith|Kstmts->Kernel_function.find_englobing_kfs,s|Kglobal->(* Bug in initializer. Do the same thing as the kernel. *)letmain=fst(Globals.entry_point())inletfirst_stmt=Kernel_function.find_first_stmtmaininmain,first_stmtinletca,_=Alarms.to_annot(Kstmtstmt)alarminletip=Property.ip_of_code_annot_singlekfstmtcainletkind=String.capitalize_ascii(Alarms.get_namealarm)inletp=get_predicatecainletacsl=Format.asprintf"@[<hov>%a@]"Cil_datatype.Toplevel_predicate.prettypin{function_name;ip;kind;acsl;callstacks}letmake_red_propfunction_nameipcallstacks=letkind="property"(* TODO *)inletacsl=Format.asprintf"@[<hov>%a@]"Property.prettyipin{function_name;ip;kind;acsl;callstacks}(* Semi generic-code for the model of Gtk list of red alarms *)typerow=red_alarmtypet={widget:(int*row)Wtable.columns;append:row->unit;clear:unit->unit;}moduleData=Indexer.Make(structtypet=int*rowletcompare(x,_)(y,_)=Stdlib.comparexyend)letappendtmessage=t.appendmessageletcleart=t.clear()letinformation="This panel lists the properties which were invalid in at least one state \
of the Eva analysis. The consolidated status of these properties for \
all states may not be Invalid, but these properties should often be \
investigated first — either as potential true alarms, or to make the \
analysis more precise. \n\
It should be noted that this list depends on the state partitioning \
performed during the analysis."letbuild_list()=letmodel=object(self)valmutablem=Data.emptyvalmutableage=0methoddata=mmethodsize=Data.sizemmethodindexi=Data.indeximmethodgeti=Data.getimmethodaddi=age<-age+1;m<-Data.add(age,i)m;age,imethodreload=age<-0;m<-Data.emptymethodcoerce=(self:>(int*row)Wtable.listmodel)endinletw=newWtable.list~headers:true~rules:truemodel#coerceinletc=w#add_column_empty(* for alignment *)in(* Sets an help icon with an explanatory tooltip to the right of the last
column header. *)lethelp=GMisc.image~stock:`HELP()inhelp#misc#set_tooltip_textinformation;c#set_alignment1.;c#set_widget(Somehelp#coerce);letappende=w#insert_row(model#adde)inletclear()=(* Post a reload request before clearing.
The current model is used to know how many rows
must be deleted. *)w#reload;inletr={widget=w;append;clear}in(* End of generic code *)letprops=[`YALIGN0.0]inlet_=w#add_column_text~title:"Function"props(function(_,{function_name})->[`TEXTfunction_name])inlet_=w#add_column_text~title:"Kind"props(function(_,{kind})->[`TEXTkind])inlet_=w#add_column_text~title:"Alarm"props(function(_,{acsl})->[`TEXTacsl])inlet_=w#add_column_text~title:"Nb contexts"props(function(_,{callstacks})->[`TEXT(string_of_intcallstacks)])inr(* Fill the table of red alarms from scratch *)letfillt=cleart;letalarms=all_alarms()inletaux(kf_name,ki,ap,cs)=matchapwith|Red_statuses.Alarma->appendt(make_red_alarmkf_namekiacs)|Red_statuses.Propip->appendt(make_red_propkf_nameipcs)inList.iterauxalarmsletmake_panel(main_ui:main_window_extension_points)=letw=build_list()inw.widget#on_click(fun(_,{ip})_col->(* Same code is found in Design, in the callback for the
warning_manager *)ignore(main_ui#scroll(Printer_tag.PIPip));main_ui#view_original(Property.locationip));lettab_label=(GMisc.label~text:"Red Alarms"())#coercein(* This panel is automatically refreshed *)Design.register_reset_extension(fun_->fillw);(* Fill the table when it is created. We are probably missing a call to
'reset' once the saved state is loaded through -load... *)let(_:GtkSignal.id)=w.widget#coerce#misc#connect#after#realize~callback:(fun()->fillw)in(* Insert the page in the notebook, then return *)letn=main_ui#lower_notebook#append_page~tab_labelw.widget#coerceinmain_ui#lower_notebook#get_nth_pagen(*
Local Variables:
compile-command: "make -C ../../.."
End:
*)