From f4ce4b745cf2d0abb91f60c21579bc67cf6a29b2 Mon Sep 17 00:00:00 2001 From: "Claude (SVF sync)" Date: Mon, 4 May 2026 14:50:44 +1000 Subject: [PATCH 1/2] Drop def/use site bindings moved out of AbstractInterpretation Upstream PR #1812 (sparse-AE refactor) and the follow-up SVFG-API commit moved getUseSitesOf{Obj,Val}Var and getDefSiteOf{Val,Obj}Var from AbstractInterpretation onto the FullSparseAbstractInterpretation subclass. The dense base class no longer exposes them, so pybind/AE.cpp fails to compile on master with "is not a member of SVF::AbstractInterpretation". Drop the four bindings (and the matching pyi stubs). Equivalent def/use-site queries live on SVFG and are still bound there; pysvf does not currently expose FullSparseAbstractInterpretation, so there is no replacement to wire up here. Co-Authored-By: Claude Opus 4.7 (1M context) --- pybind/AE.cpp | 14 ++++++-------- pysvf/pysvf.pyi | 5 ----- 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/pybind/AE.cpp b/pybind/AE.cpp index 5fabd52..5b23f33 100644 --- a/pybind/AE.cpp +++ b/pybind/AE.cpp @@ -734,14 +734,12 @@ void bind_abstract_state(py::module& m) { return self.getTrace().count(node) > 0; }, py::arg("node")) - // Def/Use site queries. - .def("getUseSitesOfObjVar", &AbstractInterpretation::getUseSitesOfObjVar, - py::arg("obj"), py::arg("node")) - .def("getUseSitesOfValVar", &AbstractInterpretation::getUseSitesOfValVar, py::arg("var")) - .def("getDefSiteOfValVar", &AbstractInterpretation::getDefSiteOfValVar, - py::arg("var"), py::return_value_policy::reference) - .def("getDefSiteOfObjVar", &AbstractInterpretation::getDefSiteOfObjVar, - py::arg("obj"), py::arg("node"), py::return_value_policy::reference) + // Def/Use site queries used to live on AbstractInterpretation but + // moved to FullSparseAbstractInterpretation in upstream PR #1812 + // (sparse-AE refactor). They aren't part of the dense base class + // public API any more, and pysvf has no FullSparseAbstractInterpretation + // binding yet, so they're dropped here. Equivalent SVFG-based + // queries are available on the SVFG class directly. // Top-level driver methods. .def("analyse", &AbstractInterpretation::analyse) diff --git a/pysvf/pysvf.pyi b/pysvf/pysvf.pyi index a9d58fd..71e6fe3 100644 --- a/pysvf/pysvf.pyi +++ b/pysvf/pysvf.pyi @@ -2022,11 +2022,6 @@ class AbstractInterpretation: def __setitem__(self, node: 'ICFGNode', state: AbstractState) -> None: ... def __contains__(self, node: 'ICFGNode') -> bool: ... - def getUseSitesOfObjVar(self, obj: 'ObjVar', node: 'ICFGNode') -> set: ... - def getUseSitesOfValVar(self, var: 'ValVar') -> set: ... - def getDefSiteOfValVar(self, var: 'ValVar') -> 'ICFGNode': ... - def getDefSiteOfObjVar(self, obj: 'ObjVar', node: 'ICFGNode') -> 'ICFGNode': ... - def analyse(self) -> None: ... def analyzeFromAllProgEntries(self) -> None: ... def runOnModule(self) -> None: ... From 8fb7aba7e5d10ef961c0c98d383675b1f299d646 Mon Sep 17 00:00:00 2001 From: "Claude (SVF sync)" Date: Mon, 4 May 2026 15:04:37 +1000 Subject: [PATCH 2/2] Update SVFG def/use-site bindings to new SVFGNode-typed signatures Upstream commit e4e02013 ("add/update SVFG APIs for sparseAE") retyped SVFG::getDefSiteOf{Val,Obj}Var and getUseSitesOf{Val,Obj}Var to return SVFGNode (sets of SVFGNode) and to take SVFGNode* in place of ICFGNode*. pybind11 fails to compile against svf-lib >= 1.0.2558: cannot convert 'const SVF::ICFGNode*' to 'const SVF::SVFGNode*' Update pybind/Graphs.cpp to use the new signatures, return std::vector, and adjust pysvf.pyi to match. Callers that need the ICFG node can map back via SVFGNode::getICFGNode(). Co-Authored-By: Claude Opus 4.7 (1M context) --- pybind/Graphs.cpp | 26 +++++++++++++++++--------- pysvf/pysvf.pyi | 16 ++++++++-------- 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/pybind/Graphs.cpp b/pybind/Graphs.cpp index 7e924e8..03aa54f 100644 --- a/pybind/Graphs.cpp +++ b/pybind/Graphs.cpp @@ -942,18 +942,26 @@ void bind_svfg(py::module& m) { .def("hasFormalINSVFGNodes", [](SVFG& svfg, const FunObjVar* fun) { return svfg.hasFormalINSVFGNodes(fun); }, py::arg("fun"), "Check if there are FormalIN SVFG nodes for a given function") .def("getSVFGNode", [](SVFG& svfg, NodeID id) -> SVFGNode* { return svfg.getSVFGNode(id); }, py::arg("id"), py::return_value_policy::reference, "Get an SVFG node by ID") .def("hasSVFGNode", [](SVFG& svfg, NodeID id) { return svfg.hasSVFGNode(id); }, py::arg("id"), "Check if an SVFG node exists") - .def("getDefSiteOfValVar", [](SVFG& svfg, const ValVar* var) { return svfg.getDefSiteOfValVar(var); }, py::arg("var"), py::return_value_policy::reference, "Get the definition site of a value variable") - .def("getDefSiteOfObjVar", [](SVFG& svfg, const ObjVar* obj, const ICFGNode* node) { return svfg.getDefSiteOfObjVar(obj, node); }, py::arg("obj"), py::arg("node"), py::return_value_policy::reference, "Get the definition site of an object variable") + // Upstream PR #1812 follow-up retyped these from ICFGNode to SVFGNode. + // The SVFGNode is the SVFG-internal representation of a def/use site; + // callers can map back to ICFGNode via SVFGNode::getICFGNode() if + // they need ICFG-side information. + .def("getDefSiteOfValVar", [](SVFG& svfg, const ValVar* var) { return svfg.getDefSiteOfValVar(var); }, py::arg("var"), py::return_value_policy::reference, "Get the SVFG definition site of a value variable") + .def("getDefSiteOfObjVar", [](SVFG& svfg, const ObjVar* obj, const SVFGNode* node) { + Set sites = svfg.getDefSiteOfObjVar(obj, node); + std::vector result(sites.begin(), sites.end()); + return result; + }, py::arg("obj"), py::arg("node"), py::return_value_policy::reference, "Get the SVFG definition sites of an object variable reaching this SVFG node") .def("getUseSitesOfValVar", [](SVFG& svfg, const ValVar* var) { - Set sites = svfg.getUseSitesOfValVar(var); - std::vector result(sites.begin(), sites.end()); + Set sites = svfg.getUseSitesOfValVar(var); + std::vector result(sites.begin(), sites.end()); return result; - }, py::arg("var"), py::return_value_policy::reference, "Get the use sites of a value variable") - .def("getUseSitesOfObjVar", [](SVFG& svfg, const ObjVar* obj, const ICFGNode* node) { - Set sites = svfg.getUseSitesOfObjVar(obj, node); - std::vector result(sites.begin(), sites.end()); + }, py::arg("var"), py::return_value_policy::reference, "Get the SVFG use sites of a value variable") + .def("getUseSitesOfObjVar", [](SVFG& svfg, const ObjVar* obj, const SVFGNode* node) { + Set sites = svfg.getUseSitesOfObjVar(obj, node); + std::vector result(sites.begin(), sites.end()); return result; - }, py::arg("obj"), py::arg("node"), py::return_value_policy::reference, "Get the use sites of an object variable") + }, py::arg("obj"), py::arg("node"), py::return_value_policy::reference, "Get the SVFG use sites of an object variable starting from this SVFG def-site node") .def("isFunEntrySVFGNode", [](SVFG& svfg, const SVFGNode* node) { return svfg.isFunEntrySVFGNode(node); }, py::arg("node"), py::return_value_policy::reference, "Check if the SVFG node is a function entry node, returns the function or nullptr") .def("isCallSiteRetSVFGNode", [](SVFG& svfg, const SVFGNode* node) { return svfg.isCallSiteRetSVFGNode(node); }, py::arg("node"), py::return_value_policy::reference, "Check if the SVFG node is a call site return node, returns the call site or nullptr"); } diff --git a/pysvf/pysvf.pyi b/pysvf/pysvf.pyi index 71e6fe3..fb40d22 100644 --- a/pysvf/pysvf.pyi +++ b/pysvf/pysvf.pyi @@ -1719,14 +1719,14 @@ class SVFG(VFG): """Get an SVFG node by ID""" def hasSVFGNode(self, id: int) -> bool: ... """Check if an SVFG node exists""" - def getDefSiteOfValVar(self, var: ValVar) -> ICFGNode: ... - """Get the definition site of a value variable""" - def getDefSiteOfObjVar(self, obj: ObjVar, node: ICFGNode) -> ICFGNode: ... - """Get the definition site of an object variable""" - def getUseSitesOfValVar(self, var: ValVar) -> List[ICFGNode]: ... - """Get the use sites of a value variable""" - def getUseSitesOfObjVar(self, obj: ObjVar, node: ICFGNode) -> List[ICFGNode]: ... - """Get the use sites of an object variable""" + def getDefSiteOfValVar(self, var: ValVar) -> "VFGNode": ... + """Get the SVFG definition site of a value variable""" + def getDefSiteOfObjVar(self, obj: ObjVar, node: "VFGNode") -> List["VFGNode"]: ... + """Get the SVFG definition sites of an object variable reaching this SVFG node""" + def getUseSitesOfValVar(self, var: ValVar) -> List["VFGNode"]: ... + """Get the SVFG use sites of a value variable""" + def getUseSitesOfObjVar(self, obj: ObjVar, node: "VFGNode") -> List["VFGNode"]: ... + """Get the SVFG use sites of an object variable starting from this SVFG def-site node""" def isFunEntrySVFGNode(self, node: VFGNode) -> Optional[FunObjVar]: ... """Check if the SVFG node is a function entry node, returns the function or nullptr""" def isCallSiteRetSVFGNode(self, node: VFGNode) -> Optional[CallICFGNode]: ...