Skip to content

Commit 32fa1c8

Browse files
committed
APP: add analysis info to function
1 parent 6f97471 commit 32fa1c8

File tree

1 file changed

+102
-0
lines changed

1 file changed

+102
-0
lines changed

chc/app/CFunction.py

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,93 @@
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+
69150
class 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

Comments
 (0)