6060 from chc .api .CFunctionContract import CFunctionContract
6161 from chc .api .InterfaceDictionary import InterfaceDictionary
6262 from chc .app .CApplication import CApplication
63+ from chc .app .CDictionary import CDictionary
6364 from chc .app .CFile import CFile
6465 from chc .app .CFileDeclarations import CFileDeclarations
66+ from chc .app .COffset import COffset
6567 from chc .app .CTyp import CTyp
6668 from chc .app .CVarInfo import CVarInfo
6769
6870
71+ class CandidateOutputParameter :
72+
73+ def __init__ (
74+ self ,
75+ cfun : "CFunction" ,
76+ cvar : "CVarInfo" ,
77+ offsets : List ["COffset" ]) -> None :
78+ self ._cfun = cfun
79+ self ._cvar = cvar
80+ self ._offsets = offsets
81+
82+ @property
83+ def cfun (self ) -> "CFunction" :
84+ return self ._cfun
85+
86+ @property
87+ def parameter (self ) -> "CVarInfo" :
88+ return self ._cvar
89+
90+ @property
91+ def offsets (self ) -> List ["COffset" ]:
92+ return self ._offsets
93+
94+ def __str__ (self ) -> str :
95+ return (
96+ self .parameter .vname + "[" + ", " .join (str (o ) for o in self .offsets ) + "]" )
97+
98+
99+ class CAnalysisInfo :
100+
101+ def __init__ (self , xnode : Optional [ET .Element ], cfun : "CFunction" ) -> None :
102+ self ._xnode = xnode
103+ self ._cfun = cfun
104+
105+ @property
106+ def cfun (self ) -> "CFunction" :
107+ return self ._cfun
108+
109+ @property
110+ def cdictionary (self ) -> "CDictionary" :
111+ return self .cfun .cdictionary
112+
113+ @property
114+ def cfiledecls (self ) -> "CFileDeclarations" :
115+ return self .cfun .cfiledecls
116+
117+ @property
118+ def analysis (self ) -> str :
119+ if self ._xnode is None :
120+ return "undefined-behavior"
121+ else :
122+ return self ._xnode .get ("name" , "unknown" )
123+
124+ @property
125+ def candidate_parameters (self ) -> List [CandidateOutputParameter ]:
126+ result : List [CandidateOutputParameter ] = []
127+ if self ._xnode is not None :
128+ if self .analysis == "output-parameters" :
129+ xparams = self ._xnode .find ("candidate-parameters" )
130+ if xparams is not None :
131+ xparamlist = xparams .findall ("vinfo" )
132+ for xparam in xparamlist :
133+ xid = int (xparam .get ("xid" , "-1" ))
134+ if xid > 0 :
135+ vinfo = self .cfiledecls .get_varinfo (xid )
136+ xoffsets = xparam .get ("offsets" , "" )
137+ if xoffsets is not None :
138+ offsets = list (
139+ self .cdictionary .get_offset (int (i ))
140+ for i in xoffsets .split ("," ))
141+
142+ result .append (CandidateOutputParameter (
143+ self .cfun , vinfo , offsets ))
144+ return result
145+
146+ def __str__ (self ) -> str :
147+ return ", " .join (str (vinfo ) for vinfo in self .candidate_parameters )
148+
149+
69150class CFunction :
70151 """Function implementation."""
71152
@@ -84,6 +165,7 @@ def __init__(self, cfile: "CFile", xnode: ET.Element, fname: str) -> None:
84165 self ._vard : Optional [CFunVarDictionary ] = None
85166 self ._invd : Optional [CFunInvDictionary ] = None
86167 self ._invarianttable : Optional [CFunInvariantTable ] = None
168+ self ._analysisinfo : Optional [CAnalysisInfo ] = None
87169
88170 def xmsg (self , txt : str ) -> str :
89171 return "Function " + self .name + ": " + txt
@@ -140,6 +222,10 @@ def ftype(self) -> "CTyp":
140222 def cfiledecls (self ) -> "CFileDeclarations" :
141223 return self .cfile .declarations
142224
225+ @property
226+ def cdictionary (self ) -> "CDictionary" :
227+ return self .cfile .dictionary
228+
143229 @property
144230 def interfacedictionary (self ) -> "InterfaceDictionary" :
145231 return self .cfile .interfacedictionary
@@ -315,6 +401,22 @@ def proofs(self) -> CFunctionProofs:
315401 self ._proofs = CFunctionProofs (self , xxpponode , xxsponode )
316402 return self ._proofs
317403
404+ @property
405+ def analysis_info (self ) -> CAnalysisInfo :
406+ if self ._analysisinfo is None :
407+ xpponode = UF .get_ppo_xnode (
408+ self .targetpath ,
409+ self .projectname ,
410+ self .cfilepath ,
411+ self .cfilename ,
412+ self .name )
413+ if xpponode is not None :
414+ self ._analysisinfo = (
415+ CAnalysisInfo (xpponode .find ("analysis-info" ), self ))
416+ else :
417+ self ._analysisinfo = CAnalysisInfo (None , self )
418+ return self ._analysisinfo
419+
318420 def reinitialize_tables (self ) -> None :
319421 self ._api = None
320422 self ._podictionary = None
0 commit comments