[gcc-python-plugin] Implement gcc.Tree.__hash__
by David Hugh Malcolm
commit 1a9bb1b8888f33d360c2425f039acf6185a408d5
Author: David Malcolm <dmalcolm(a)redhat.com>
Date: Thu Jun 30 16:27:31 2011 -0400
Implement gcc.Tree.__hash__
gcc-python-tree.c | 8 ++++++++
gcc-python-wrappers.h | 3 +++
generate-tree-c.py | 1 +
3 files changed, 12 insertions(+), 0 deletions(-)
---
diff --git a/gcc-python-tree.c b/gcc-python-tree.c
index ec460ad..6a24372 100644
--- a/gcc-python-tree.c
+++ b/gcc-python-tree.c
@@ -64,6 +64,14 @@ gcc_Tree_str(struct PyGccTree * self)
return NULL;
}
+long
+gcc_Tree_hash(struct PyGccTree * self)
+{
+ /* Use the ptr as the hash value: */
+ return (long)self->t;
+}
+
+
PyObject *
gcc_Tree_richcompare(PyObject *o1, PyObject *o2, int op)
{
diff --git a/gcc-python-wrappers.h b/gcc-python-wrappers.h
index 68aa0af..9ca3c9f 100644
--- a/gcc-python-wrappers.h
+++ b/gcc-python-wrappers.h
@@ -56,6 +56,9 @@ gcc_Cfg_get_basic_blocks(PyGccCfg *self, void *closure);
PyObject *
gcc_Tree_str(struct PyGccTree * self);
+long
+gcc_Tree_hash(struct PyGccTree * self);
+
PyObject *
gcc_Tree_richcompare(PyObject *o1, PyObject *o2, int op);
diff --git a/generate-tree-c.py b/generate-tree-c.py
index 3500f32..8b32d8e 100644
--- a/generate-tree-c.py
+++ b/generate-tree-c.py
@@ -70,6 +70,7 @@ gcc_Tree_get_addr(struct PyGccTree *self, void *closure)
struct_name = 'struct PyGccTree',
tp_new = 'PyType_GenericNew',
tp_getset = 'gcc_Tree_getset_table',
+ tp_hash = '(hashfunc)gcc_Tree_hash',
tp_str = '(reprfunc)gcc_Tree_str',
tp_richcompare = 'gcc_Tree_richcompare')
methods = PyMethodTable('gcc_Tree_methods', [])
12 years, 10 months
[gcc-python-plugin] CFG renderer: cope with pygments styles that have a "bold" prefix
by David Hugh Malcolm
commit 4a5321f7f51c070de7e5e278e480cfbbee49a12b
Author: David Malcolm <dmalcolm(a)redhat.com>
Date: Thu Jun 30 14:54:14 2011 -0400
CFG renderer: cope with pygments styles that have a "bold" prefix
gccutils.py | 27 +++++++++++++++++++++++----
1 files changed, 23 insertions(+), 4 deletions(-)
---
diff --git a/gccutils.py b/gccutils.py
index fa21012..4eba0f0 100644
--- a/gccutils.py
+++ b/gccutils.py
@@ -212,8 +212,21 @@ try:
Formatter.__init__(self)
self.style = style
- def color_for_token(self, token):
- return self.style.styles[token]
+ def style_for_token(self, token):
+ # Return a (hexcolor, isbold) pair, where hexcolor could be None
+
+ # Lookup up pygments' color for this token type:
+ col = self.style.styles[token]
+
+ isbold = False
+
+ # Extract a pure hex color specifier of the form that graphviz can
+ # deal with
+ if col:
+ if col.startswith('bold '):
+ isbold = True
+ col = col[5:]
+ return (col, isbold)
def format_unencoded(self, tokensource, outfile):
from pprint import pprint
@@ -230,9 +243,12 @@ try:
if t == Token.Literal.String.Escape:
continue
- color = self.color_for_token(t)
+ color, isbold = self.style_for_token(t)
if 0:
- print ('color: %r' % color)
+ print ('(color, isbold): (%r, %r)' % (color, isbold))
+
+ if isbold:
+ outfile.write('<b>')
# Avoid empty color="" values:
if color:
@@ -242,6 +258,9 @@ try:
else:
outfile.write(self.to_html(piece))
+ if isbold:
+ outfile.write('</b>')
+
from pygments import highlight
from pygments.lexers import CLexer
from pygments.formatters import HtmlFormatter
12 years, 10 months
[gcc-python-plugin] Add test coverage for gcc.inform(); clarify docs (the output is to stderr)
by David Hugh Malcolm
commit d3ef677543ea5036a0aabb969dbcfc8b1285cde0
Author: David Malcolm <dmalcolm(a)redhat.com>
Date: Thu Jun 30 14:20:17 2011 -0400
Add test coverage for gcc.inform(); clarify docs (the output is to stderr)
docs/basics.rst | 6 +++---
tests/plugin/diagnostics/script.py | 4 ++++
tests/plugin/diagnostics/stderr.txt | 2 ++
3 files changed, 9 insertions(+), 3 deletions(-)
---
diff --git a/docs/basics.rst b/docs/basics.rst
index 2c9b344..66bc63e 100644
--- a/docs/basics.rst
+++ b/docs/basics.rst
@@ -364,7 +364,7 @@ Generating custom errors and warnings
gcc.warning(func.start, gcc.Option('-Wformat'), 'Incorrect formatting')
- if the given warning is enabled, a warning will be printed:
+ if the given warning is enabled, a warning will be printed to stderr:
.. code-block:: bash
@@ -407,7 +407,7 @@ Generating custom errors and warnings
gcc.error(func.start, 'something bad was detected')
- would lead to this error being printed:
+ would lead to this error being printed to stderr:
.. code-block:: bash
@@ -441,7 +441,7 @@ Generating custom errors and warnings
gcc.inform(stmt.loc, 'this is where X was defined')
- would lead to this informational message being printed:
+ would lead to this informational message being printed to stderr:
.. code-block:: bash
diff --git a/tests/plugin/diagnostics/script.py b/tests/plugin/diagnostics/script.py
index 610e4de..1408616 100644
--- a/tests/plugin/diagnostics/script.py
+++ b/tests/plugin/diagnostics/script.py
@@ -37,6 +37,10 @@ def on_pass_execution(p, fn):
gcc.Option('-Wformat'),
'this warning ought not to appear')
+ # Exercise gcc.inform:
+ gcc.inform(fn.start, 'This is the start of the function')
+ gcc.inform(fn.end, 'This is the end of the function')
+
# Wire up our callback:
gcc.register_callback(gcc.PLUGIN_PASS_EXECUTION,
on_pass_execution)
diff --git a/tests/plugin/diagnostics/stderr.txt b/tests/plugin/diagnostics/stderr.txt
index 73ea144..aa2a624 100644
--- a/tests/plugin/diagnostics/stderr.txt
+++ b/tests/plugin/diagnostics/stderr.txt
@@ -4,3 +4,5 @@ tests/plugin/diagnostics/input.c:23:1: error: this is an error (with keyword arg
tests/plugin/diagnostics/input.c:25:1: warning: this is a warning (with positional args) [-Wdiv-by-zero]
tests/plugin/diagnostics/input.c:25:1: warning: this is a warning (with keyword args) [-Wdiv-by-zero]
tests/plugin/diagnostics/input.c:23:1: error: a warning with some embedded format strings %s and %i
+tests/plugin/diagnostics/input.c:23:1: note: This is the start of the function
+tests/plugin/diagnostics/input.c:25:1: note: This is the end of the function
12 years, 10 months
[gcc-python-plugin] expose 'inform' function
by David Hugh Malcolm
commit 9ca8982eb21af0d7008b37f8428827131775c97a
Author: Tom Tromey <tromey(a)redhat.com>
Date: Thu Jun 30 11:51:02 2011 -0600
expose 'inform' function
This exposes the GCC 'inform' function as gcc.inform.
Tom
docs/basics.rst | 19 +++++++++++++++++++
gcc-python.c | 26 ++++++++++++++++++++++++++
2 files changed, 45 insertions(+), 0 deletions(-)
---
diff --git a/docs/basics.rst b/docs/basics.rst
index d51947b..2c9b344 100644
--- a/docs/basics.rst
+++ b/docs/basics.rst
@@ -429,6 +429,25 @@ Generating custom errors and warnings
Returns True if the warning was actually printed, False otherwise
+.. py:function:: gcc.inform(loc, str)
+
+ This is a wrapper around GCC's `inform` function.
+
+ Expects an instance of :py:class:`gcc.Location` (not None) and a string
+
+ Emit an informational message at that location.
+
+ For example::
+
+ gcc.inform(stmt.loc, 'this is where X was defined')
+
+ would lead to this informational message being printed:
+
+ .. code-block:: bash
+
+ $ ./gcc-with-python script.py input.c
+ input.c:23:3: note: this is where X was defined
+
Global data access
==================
diff --git a/gcc-python.c b/gcc-python.c
index 4e35456..79262ab 100644
--- a/gcc-python.c
+++ b/gcc-python.c
@@ -373,6 +373,27 @@ gcc_python_warning(PyObject *self, PyObject *args, PyObject *kwargs)
}
static PyObject *
+gcc_python_inform(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+ PyGccLocation *loc_obj;
+ const char *msg;
+ char *keywords[] = {"location",
+ "message",
+ NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+ "O!s:inform", keywords,
+ &gcc_LocationType, &loc_obj,
+ &msg)) {
+ return NULL;
+ }
+
+ inform(loc_obj->loc, "%s", msg);
+
+ Py_RETURN_NONE;
+}
+
+static PyObject *
gcc_python_get_option_list(PyObject *self, PyObject *args)
{
PyObject *result;
@@ -533,6 +554,11 @@ static PyMethodDef GccMethods[] = {
(METH_VARARGS | METH_KEYWORDS),
("Report a warning\n"
"FIXME\n")},
+ {"inform",
+ (PyCFunction)gcc_python_inform,
+ (METH_VARARGS | METH_KEYWORDS),
+ ("Report an information message\n"
+ "FIXME\n")},
/* Options: */
{"get_option_list",
12 years, 10 months
[gcc-python-plugin] make html from top-level
by David Hugh Malcolm
commit 76897290d095844d423138796d9d9b8b13c3f5a3
Author: Tom Tromey <tromey(a)redhat.com>
Date: Thu Jun 30 09:06:35 2011 -0600
make html from top-level
I've tried to 'make html' at the top level a few times now, so I thought
I'd send the obvious patch...
Tom
Makefile | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)
---
diff --git a/Makefile b/Makefile
index e050dfc..15d6114 100644
--- a/Makefile
+++ b/Makefile
@@ -134,3 +134,6 @@ test-suite: plugin
show-ssa: plugin
./gcc-with-python show-ssa.py test.c
+
+html:
+ cd docs && $(MAKE) html
12 years, 10 months
[gcc-python-plugin] Eliminate superfluous StateEdge class, adding 'src' field to Transition
by David Hugh Malcolm
commit 5797acb03f0c663195c21f0def3cfadc10b58149
Author: David Malcolm <dmalcolm(a)redhat.com>
Date: Wed Jun 29 21:00:43 2011 -0400
Eliminate superfluous StateEdge class, adding 'src' field to Transition
libcpychecker/absinterp.py | 30 ++++++++++++------------------
libcpychecker/c_stdio.py | 4 ++--
libcpychecker/refcounts.py | 10 +++++-----
libcpychecker/visualizations.py | 10 +++++-----
4 files changed, 24 insertions(+), 30 deletions(-)
---
diff --git a/libcpychecker/absinterp.py b/libcpychecker/absinterp.py
index 065caf9..19e34ff 100644
--- a/libcpychecker/absinterp.py
+++ b/libcpychecker/absinterp.py
@@ -187,7 +187,7 @@ class State:
assert isinstance(lvalue, gcc.VarDecl) # for now
key = self.get_key_for_lvalue(lvalue)
new.data[key] = value
- return Transition(new, desc)
+ return Transition(self, new, desc)
def update_loc(self, newloc):
new = self.copy()
@@ -199,12 +199,15 @@ class State:
return self.update_loc(newloc)
class Transition:
- def __init__(self, nextstate, desc):
- self.nextstate = nextstate
+ def __init__(self, src, dest, desc):
+ assert isinstance(src, State)
+ assert isinstance(dest, State)
+ self.src = src
+ self.dest = dest
self.desc = desc
def __repr__(self):
- return 'Transition(%r, %r)' % (self.nextstate, self.desc)
+ return 'Transition(%r, %r)' % (self.dest, self.desc)
class Trace:
"""A sequence of State"""
@@ -321,7 +324,7 @@ def iter_traces(fun, stateclass, prefix=None):
result = []
for transition in transitions:
# Recurse:
- for trace in iter_traces(fun, stateclass, prefix.copy().add(transition.nextstate)):
+ for trace in iter_traces(fun, stateclass, prefix.copy().add(transition.dest)):
result.append(trace)
return result
else:
@@ -329,15 +332,6 @@ def iter_traces(fun, stateclass, prefix=None):
prefix.log(log, 'FINISHED TRACE', 1)
return [prefix]
-class StateEdge:
- def __init__(self, src, dest, transition):
- assert isinstance(src, State)
- assert isinstance(dest, State)
- assert isinstance(transition, Transition)
- self.src = src
- self.dest = dest
- self.transition = transition
-
class StateGraph:
"""
A graph of states, representing the various routes through a function,
@@ -350,7 +344,7 @@ class StateGraph:
assert isinstance(fun, gcc.Function)
self.fun = fun
self.states = []
- self.edges = []
+ self.transitions = []
self.stateclass = stateclass
logger('StateGraph.__init__(%r)' % fun)
@@ -384,11 +378,11 @@ class StateGraph:
for transition in transitions:
# FIXME: what about loops???
assert isinstance(transition, Transition)
- self.states.append(transition.nextstate)
- self.edges.append(StateEdge(curstate, transition.nextstate, transition))
+ self.states.append(transition.dest)
+ self.transitions.append(transition)
# Recurse:
- self._gather_states(transition.nextstate, curstate, logger)
+ self._gather_states(transition.dest, curstate, logger)
else:
# We're at a terminating state:
logger('FINISHED TRACE')
diff --git a/libcpychecker/c_stdio.py b/libcpychecker/c_stdio.py
index 8641b9e..bf4bd2a 100644
--- a/libcpychecker/c_stdio.py
+++ b/libcpychecker/c_stdio.py
@@ -53,7 +53,7 @@ def handle_c_stdio_function(state, fnname, stmt):
success = state.make_assignment(stmt.lhs,
file_ptr,
'%s() succeeded' % fnname)
- success.nextstate.acquire(file_ptr)
+ success.dest.acquire(file_ptr)
# The "failure" case:
failure = state.make_assignment(stmt.lhs,
@@ -75,7 +75,7 @@ def handle_c_stdio_function(state, fnname, stmt):
result = state.make_assignment(stmt.lhs,
AbstractValue(gcc.Type.int(), stmt),
'%s() succeeded' % fnname) # FIXME errno handling!
- result.nextstate.release(expr)
+ result.dest.release(expr)
return [result]
else:
# We claimed to handle this function, but didn't:
diff --git a/libcpychecker/refcounts.py b/libcpychecker/refcounts.py
index 7536669..9219714 100644
--- a/libcpychecker/refcounts.py
+++ b/libcpychecker/refcounts.py
@@ -80,7 +80,7 @@ class MyState(State):
assert isinstance(desc, str)
transition = State.make_assignment(self, key, value, desc)
if additional_ptr:
- transition.nextstate.owned_refs.append(additional_ptr)
+ transition.dest.owned_refs.append(additional_ptr)
return transition
def get_transitions(self, oldstate):
@@ -93,7 +93,7 @@ class MyState(State):
for loc in self.loc.next_locs():
newstate = self.copy()
newstate.loc = loc
- result.append(Transition(newstate, ''))
+ result.append(Transition(self, newstate, ''))
log('result: %s' % result)
return result
@@ -179,14 +179,14 @@ class MyState(State):
assert e
nextstate = self.update_loc(Location.get_block_start(e.dest))
nextstate.prior_bool = True
- return Transition(nextstate, 'taking True path')
+ return Transition(self, nextstate, 'taking True path')
def make_transition_for_false(stmt):
e = false_edge(self.loc.bb)
assert e
nextstate = self.update_loc(Location.get_block_start(e.dest))
nextstate.prior_bool = False
- return Transition(nextstate, 'taking False path')
+ return Transition(self, nextstate, 'taking False path')
log('stmt.exprcode: %s' % stmt.exprcode, 4)
log('stmt.exprtype: %s' % stmt.exprtype, 4)
@@ -250,7 +250,7 @@ class MyState(State):
if value in nextstate.owned_refs:
log('removing ownership of %s' % value)
nextstate.owned_refs.remove(value)
- return [Transition(nextstate, None)] # for now
+ return [Transition(self, nextstate, None)] # for now
def check_refcounts(fun, show_traces):
# Abstract interpretation:
diff --git a/libcpychecker/visualizations.py b/libcpychecker/visualizations.py
index 1659fae..64df793 100644
--- a/libcpychecker/visualizations.py
+++ b/libcpychecker/visualizations.py
@@ -111,14 +111,14 @@ class StateGraphPrettyPrinter(StatePrettyPrinter):
# self.block_id(state.loc.bb),
# state.loc.idx))
- for edge in self.sg.edges:
- if edge.transition.desc:
- attrliststr = '[label = "%s"]' % self.to_html(edge.transition.desc)
+ for transition in self.sg.transitions:
+ if transition.desc:
+ attrliststr = '[label = "%s"]' % self.to_html(transition.desc)
else:
attrliststr = ''
result += (' %s -> %s %s;\n'
- % (self.state_id(edge.src),
- self.state_id(edge.dest),
+ % (self.state_id(transition.src),
+ self.state_id(transition.dest),
attrliststr))
result += ' }\n';
12 years, 10 months
[gcc-python-plugin] Move generic interp code from refcounts.py to absinterp.py
by David Hugh Malcolm
commit 711bcb941a22c8534ccc91a86399de60c1ede1bc
Author: David Malcolm <dmalcolm(a)redhat.com>
Date: Wed Jun 29 20:50:36 2011 -0400
Move generic interp code from refcounts.py to absinterp.py
libcpychecker/absinterp.py | 314 +++++++++++++++++++++++++++++++++++++++++++
libcpychecker/refcounts.py | 315 +-------------------------------------------
2 files changed, 316 insertions(+), 313 deletions(-)
---
diff --git a/libcpychecker/absinterp.py b/libcpychecker/absinterp.py
index 4aa7f20..065caf9 100644
--- a/libcpychecker/absinterp.py
+++ b/libcpychecker/absinterp.py
@@ -16,7 +16,10 @@
# <http://www.gnu.org/licenses/>.
import gcc
+import sys
from gccutils import get_src_for_loc
+from collections import OrderedDict
+from PyArg_ParseTuple import log
class AbstractValue:
def __init__(self, gcctype, stmt):
@@ -104,3 +107,314 @@ class PtrToGlobal(NonNullPtrValue):
else:
return ('&%s' % self.name)
+class Location:
+ """A location within a CFG: a gcc.BasicBlock together with an index into
+ the gimple list. (We don't support SSA passes)"""
+ def __init__(self, bb, idx):
+ self.bb = bb
+ self.idx = idx
+
+ def __str__(self):
+ stmt = self.get_stmt()
+ return ('block %i stmt:%i : %20r : %s'
+ % (self.bb.index, self.idx, stmt, stmt))
+
+ def next_locs(self):
+ """Get a list of Location instances, for what can happen next"""
+ if self.bb.gimple and len(self.bb.gimple) > self.idx + 1:
+ # Next gimple statement:
+ return [Location(self.bb, self.idx + 1)]
+ else:
+ # At end of gimple statements: successor BBs:
+ return [Location.get_block_start(outedge.dest) for outedge in self.bb.succs]
+
+ def next_loc(self):
+ """Get the next Location, for when it's unique"""
+ if self.bb.gimple:
+ if len(self.bb.gimple) > self.idx + 1:
+ # Next gimple statement:
+ return Location(self.bb, self.idx + 1)
+ else:
+ assert len(self.bb.succs) == 1
+ return Location.get_block_start(self.bb.succs[0].dest)
+
+ @classmethod
+ def get_block_start(cls, bb):
+ # Don't bother iterating through phi_nodes if there aren't any:
+ return Location(bb, 0)
+
+ def get_stmt(self):
+ if self.bb.gimple:
+ return self.bb.gimple[self.idx]
+ else:
+ return None
+
+class State:
+ """A Location with a dict of vars and values"""
+ def __init__(self, loc, data):
+ self.loc = loc
+ self.data = data
+
+ def copy(self):
+ return self.__class__(loc, self.data.copy())
+
+ def __str__(self):
+ return '%s: %s%s' % (self.data, self.loc, self._extra())
+
+ def __repr__(self):
+ return '%s: %s%s' % (self.data, self.loc, self._extra())
+
+ def log(self, logger, indent):
+ logger('data: %s' % (self.data, ), indent)
+ logger('extra: %s' % (self._extra(), ), indent)
+
+ # FIXME: derived class/extra:
+ self.resources.log(logger, indent)
+
+ logger('loc: %s' % self.loc, indent)
+ if self.loc.get_stmt():
+ logger('%s' % self.loc.get_stmt().loc, indent + 1)
+
+ def get_key_for_lvalue(self, lvalue):
+ return str(lvalue) # FIXME
+
+ def make_assignment(self, lvalue, value, desc):
+ if desc:
+ assert isinstance(desc, str)
+ new = self.copy()
+ new.loc = self.loc.next_loc()
+ if lvalue:
+ assert isinstance(lvalue, gcc.VarDecl) # for now
+ key = self.get_key_for_lvalue(lvalue)
+ new.data[key] = value
+ return Transition(new, desc)
+
+ def update_loc(self, newloc):
+ new = self.copy()
+ new.loc = newloc
+ return new
+
+ def use_next_loc(self):
+ newloc = self.loc.next_loc()
+ return self.update_loc(newloc)
+
+class Transition:
+ def __init__(self, nextstate, desc):
+ self.nextstate = nextstate
+ self.desc = desc
+
+ def __repr__(self):
+ return 'Transition(%r, %r)' % (self.nextstate, self.desc)
+
+class Trace:
+ """A sequence of State"""
+ def __init__(self):
+ self.states = []
+ self.err = None
+
+ def add(self, state):
+ assert isinstance(state, State)
+ self.states.append(state)
+ return self
+
+ def add_error(self, err):
+ self.err = err
+
+ def copy(self):
+ t = Trace()
+ t.states = self.states[:]
+ t.err = self.err # FIXME: should this be a copy?
+ return t
+
+ def log(self, logger, name, indent):
+ logger('%s:' % name, indent)
+ for i, state in enumerate(self.states):
+ logger('%i:' % i, indent + 1)
+ state.log(logger, indent + 2)
+ if self.err:
+ logger(' Trace ended with error: %s' % self.err, indent + 1)
+
+ def get_last_stmt(self):
+ return self.states[-1].loc.get_stmt()
+
+ def return_value(self):
+ last_stmt = self.get_last_stmt()
+ if isinstance(last_stmt, gcc.GimpleReturn):
+ return self.states[-1].eval_expr(last_stmt.retval)
+ else:
+ return None
+
+ def final_references(self):
+ return self.states[-1].owned_refs
+
+def true_edge(bb):
+ for e in bb.succs:
+ if e.true_value:
+ return e
+
+def false_edge(bb):
+ for e in bb.succs:
+ if e.false_value:
+ return e
+
+class Resources:
+ # Resource tracking for a state
+ def __init__(self):
+ # Resources that we've acquired:
+ self._acquisitions = []
+
+ # Resources that we've released:
+ self._releases = []
+
+ def copy(self):
+ new = Resources()
+ new._acquisitions = self._acquisitions[:]
+ new._releases = self._releases[:]
+ return new
+
+ def acquire(self, resource):
+ self._acquisitions.append(resource)
+
+ def release(self, resource):
+ self._releases.append(resource)
+
+ def log(self, logger, indent):
+ logger('resources:', indent)
+ logger('acquisitions: %s' % self._acquisitions, indent + 1)
+ logger('releases: %s' % self._releases, indent + 1)
+
+def iter_traces(fun, stateclass, prefix=None):
+ # Traverse the tree of traces of program state
+ # FIXME: this code can't cope with loops yet
+ log('iter_traces(%r, %r, %r)' % (fun, stateclass, prefix))
+ if prefix is None:
+ prefix = Trace()
+ curstate = stateclass(Location.get_block_start(fun.cfg.entry),
+ OrderedDict(),
+ [],
+ Resources())
+ else:
+ curstate = prefix.states[-1]
+
+ # We need the prevstate to handle Phi nodes
+ if len(prefix.states) > 1:
+ prevstate = prefix.states[-2]
+ else:
+ prevstate = None
+
+ prefix.log(log, 'PREFIX', 1)
+ log(' %s:%s' % (fun.decl.name, curstate.loc))
+ try:
+ transitions = curstate.get_transitions(prevstate)
+ assert isinstance(transitions, list)
+ except PredictedError, err:
+ # We're at a terminating state:
+ err.loc = prefix.get_last_stmt().loc
+ trace_with_err = prefix.copy()
+ trace_with_err.add_error(err)
+ trace_with_err.log(log, 'FINISHED TRACE WITH ERROR: %s' % err, 1)
+ return [trace_with_err]
+
+ log('transitions: %s' % transitions, 2)
+
+ if len(transitions) > 0:
+ result = []
+ for transition in transitions:
+ # Recurse:
+ for trace in iter_traces(fun, stateclass, prefix.copy().add(transition.nextstate)):
+ result.append(trace)
+ return result
+ else:
+ # We're at a terminating state:
+ prefix.log(log, 'FINISHED TRACE', 1)
+ return [prefix]
+
+class StateEdge:
+ def __init__(self, src, dest, transition):
+ assert isinstance(src, State)
+ assert isinstance(dest, State)
+ assert isinstance(transition, Transition)
+ self.src = src
+ self.dest = dest
+ self.transition = transition
+
+class StateGraph:
+ """
+ A graph of states, representing the various routes through a function,
+ tracking state.
+
+ For now, we give up when we encounter a loop, as an easy way to ensure
+ termination of the analysis
+ """
+ def __init__(self, fun, logger, stateclass):
+ assert isinstance(fun, gcc.Function)
+ self.fun = fun
+ self.states = []
+ self.edges = []
+ self.stateclass = stateclass
+
+ logger('StateGraph.__init__(%r)' % fun)
+
+ # Recursively gather states:
+ initial = stateclass(Location.get_block_start(fun.cfg.entry),
+ OrderedDict(),
+ [],
+ Resources())
+ self.states.append(initial)
+ self._gather_states(initial, None, logger)
+
+ def _gather_states(self, curstate, prevstate, logger):
+ logger(' %s:%s' % (self.fun.decl.name, curstate.loc))
+ try:
+ transitions = curstate.get_transitions(prevstate)
+ print transitions
+ assert isinstance(transitions, list)
+ except PredictedError, err:
+ # We're at a terminating state:
+ raise "foo" # FIXME
+ err.loc = prefix.get_last_stmt().loc
+ trace_with_err = prefix.copy()
+ trace_with_err.add_error(err)
+ trace_with_err.log(log, 'FINISHED TRACE WITH ERROR: %s' % err, 1)
+ return [trace_with_err]
+
+ logger('transitions: %s' % transitions, 2)
+
+ if len(transitions) > 0:
+ for transition in transitions:
+ # FIXME: what about loops???
+ assert isinstance(transition, Transition)
+ self.states.append(transition.nextstate)
+ self.edges.append(StateEdge(curstate, transition.nextstate, transition))
+
+ # Recurse:
+ self._gather_states(transition.nextstate, curstate, logger)
+ else:
+ # We're at a terminating state:
+ logger('FINISHED TRACE')
+
+def extra_text(msg, indent):
+ sys.stderr.write('%s%s\n' % (' ' * indent, msg))
+
+def describe_trace(trace):
+ # Print more details about the path through the function that
+ # leads to the error:
+ awaiting_target = None
+ for j in range(len(trace.states)-1):
+ state = trace.states[j]
+ nextstate = trace.states[j+1]
+ stmt = state.loc.get_stmt()
+ next_stmt = nextstate.loc.get_stmt()
+ if state.loc.bb != nextstate.loc.bb:
+ if stmt:
+ extra_text('%s: taking %s path at %s'
+ % (stmt.loc,
+ nextstate.prior_bool,
+ get_src_for_loc(stmt.loc)), 1)
+ first_loc_in_next_bb = get_first_loc_in_block(nextstate.loc.bb)
+ if first_loc_in_next_bb:
+ extra_text('%s: reaching here %s'
+ % (first_loc_in_next_bb,
+ get_src_for_loc(first_loc_in_next_bb)),
+ 2)
+
diff --git a/libcpychecker/refcounts.py b/libcpychecker/refcounts.py
index 8b0960b..7536669 100644
--- a/libcpychecker/refcounts.py
+++ b/libcpychecker/refcounts.py
@@ -23,7 +23,6 @@
import sys
import gcc
-from collections import OrderedDict
from gccutils import cfg_to_dot, invoke_dot, get_src_for_loc
from absinterp import *
@@ -57,183 +56,6 @@ def stmt_is_return_of_objptr(stmt):
if type_is_pyobjptr(stmt.retval.type):
return True
-class Location:
- """A location within a CFG: a gcc.BasicBlock together with an index into
- the gimple list. (We don't support SSA passes)"""
- def __init__(self, bb, idx):
- self.bb = bb
- self.idx = idx
-
- def __str__(self):
- stmt = self.get_stmt()
- return ('block %i stmt:%i : %20r : %s'
- % (self.bb.index, self.idx, stmt, stmt))
-
- def next_locs(self):
- """Get a list of Location instances, for what can happen next"""
- if self.bb.gimple and len(self.bb.gimple) > self.idx + 1:
- # Next gimple statement:
- return [Location(self.bb, self.idx + 1)]
- else:
- # At end of gimple statements: successor BBs:
- return [Location.get_block_start(outedge.dest) for outedge in self.bb.succs]
-
- def next_loc(self):
- """Get the next Location, for when it's unique"""
- if self.bb.gimple:
- if len(self.bb.gimple) > self.idx + 1:
- # Next gimple statement:
- return Location(self.bb, self.idx + 1)
- else:
- assert len(self.bb.succs) == 1
- return Location.get_block_start(self.bb.succs[0].dest)
-
- @classmethod
- def get_block_start(cls, bb):
- # Don't bother iterating through phi_nodes if there aren't any:
- return Location(bb, 0)
-
- def get_stmt(self):
- if self.bb.gimple:
- return self.bb.gimple[self.idx]
- else:
- return None
-
-class State:
- """A Location with a dict of vars and values"""
- def __init__(self, loc, data):
- self.loc = loc
- self.data = data
-
- def copy(self):
- return self.__class__(loc, self.data.copy())
-
- def __str__(self):
- return '%s: %s%s' % (self.data, self.loc, self._extra())
-
- def __repr__(self):
- return '%s: %s%s' % (self.data, self.loc, self._extra())
-
- def log(self, logger, indent):
- logger('data: %s' % (self.data, ), indent)
- logger('extra: %s' % (self._extra(), ), indent)
-
- # FIXME: derived class/extra:
- self.resources.log(logger, indent)
-
- logger('loc: %s' % self.loc, indent)
- if self.loc.get_stmt():
- logger('%s' % self.loc.get_stmt().loc, indent + 1)
-
- def get_key_for_lvalue(self, lvalue):
- return str(lvalue) # FIXME
-
- def make_assignment(self, lvalue, value, desc):
- if desc:
- assert isinstance(desc, str)
- new = self.copy()
- new.loc = self.loc.next_loc()
- if lvalue:
- assert isinstance(lvalue, gcc.VarDecl) # for now
- key = self.get_key_for_lvalue(lvalue)
- new.data[key] = value
- return Transition(new, desc)
-
- def update_loc(self, newloc):
- new = self.copy()
- new.loc = newloc
- return new
-
- def use_next_loc(self):
- newloc = self.loc.next_loc()
- return self.update_loc(newloc)
-
-class Transition:
- def __init__(self, nextstate, desc):
- self.nextstate = nextstate
- self.desc = desc
-
- def __repr__(self):
- return 'Transition(%r, %r)' % (self.nextstate, self.desc)
-
-class Trace:
- """A sequence of State"""
- def __init__(self):
- self.states = []
- self.err = None
-
- def add(self, state):
- assert isinstance(state, State)
- self.states.append(state)
- return self
-
- def add_error(self, err):
- self.err = err
-
- def copy(self):
- t = Trace()
- t.states = self.states[:]
- t.err = self.err # FIXME: should this be a copy?
- return t
-
- def log(self, logger, name, indent):
- logger('%s:' % name, indent)
- for i, state in enumerate(self.states):
- logger('%i:' % i, indent + 1)
- state.log(logger, indent + 2)
- if self.err:
- logger(' Trace ended with error: %s' % self.err, indent + 1)
-
- def get_last_stmt(self):
- return self.states[-1].loc.get_stmt()
-
- def return_value(self):
- last_stmt = self.get_last_stmt()
- if isinstance(last_stmt, gcc.GimpleReturn):
- return self.states[-1].eval_expr(last_stmt.retval)
- else:
- return None
-
- def final_references(self):
- return self.states[-1].owned_refs
-
-def true_edge(bb):
- for e in bb.succs:
- if e.true_value:
- return e
-
-def false_edge(bb):
- for e in bb.succs:
- if e.false_value:
- return e
-
-class Resources:
- # Resource tracking for a state
- def __init__(self):
- # Resources that we've acquired:
- self._acquisitions = []
-
- # Resources that we've released:
- self._releases = []
-
- def copy(self):
- new = Resources()
- new._acquisitions = self._acquisitions[:]
- new._releases = self._releases[:]
- return new
-
- def acquire(self, resource):
- self._acquisitions.append(resource)
-
- def release(self, resource):
- self._releases.append(resource)
-
- def log(self, logger, indent):
- logger('resources:', indent)
- logger('acquisitions: %s' % self._acquisitions, indent + 1)
- logger('releases: %s' % self._releases, indent + 1)
-
-
class MyState(State):
def __init__(self, loc, data, owned_refs, resources):
State.__init__(self, loc, data)
@@ -430,153 +252,20 @@ class MyState(State):
nextstate.owned_refs.remove(value)
return [Transition(nextstate, None)] # for now
-def iter_traces(fun, prefix=None):
- # Traverse the tree of traces of program state
- # FIXME: this code can't cope with loops yet
- log('iter_traces(%r, %r)' % (fun, prefix))
- if prefix is None:
- prefix = Trace()
- curstate = MyState(Location.get_block_start(fun.cfg.entry),
- OrderedDict(),
- [],
- Resources())
- else:
- curstate = prefix.states[-1]
-
- # We need the prevstate to handle Phi nodes
- if len(prefix.states) > 1:
- prevstate = prefix.states[-2]
- else:
- prevstate = None
-
- prefix.log(log, 'PREFIX', 1)
- log(' %s:%s' % (fun.decl.name, curstate.loc))
- try:
- transitions = curstate.get_transitions(prevstate)
- assert isinstance(transitions, list)
- except PredictedError, err:
- # We're at a terminating state:
- err.loc = prefix.get_last_stmt().loc
- trace_with_err = prefix.copy()
- trace_with_err.add_error(err)
- trace_with_err.log(log, 'FINISHED TRACE WITH ERROR: %s' % err, 1)
- return [trace_with_err]
-
- log('transitions: %s' % transitions, 2)
-
- if len(transitions) > 0:
- result = []
- for transition in transitions:
- # Recurse:
- for trace in iter_traces(fun, prefix.copy().add(transition.nextstate)):
- result.append(trace)
- return result
- else:
- # We're at a terminating state:
- prefix.log(log, 'FINISHED TRACE', 1)
- return [prefix]
-
-class StateEdge:
- def __init__(self, src, dest, transition):
- assert isinstance(src, State)
- assert isinstance(dest, State)
- assert isinstance(transition, Transition)
- self.src = src
- self.dest = dest
- self.transition = transition
-
-class StateGraph:
- """
- A graph of states, representing the various routes through a function,
- tracking state.
-
- For now, we give up when we encounter a loop, as an easy way to ensure
- termination of the analysis
- """
- def __init__(self, fun, logger):
- assert isinstance(fun, gcc.Function)
- self.fun = fun
- self.states = []
- self.edges = []
-
- logger('StateGraph.__init__(%r)' % fun)
-
- # Recursively gather states:
- initial = MyState(Location.get_block_start(fun.cfg.entry),
- OrderedDict(),
- [],
- Resources())
- self.states.append(initial)
- self._gather_states(initial, None, logger)
-
- def _gather_states(self, curstate, prevstate, logger):
- logger(' %s:%s' % (self.fun.decl.name, curstate.loc))
- try:
- transitions = curstate.get_transitions(prevstate)
- assert isinstance(transitions, list)
- except PredictedError, err:
- # We're at a terminating state:
- raise "foo" # FIXME
- err.loc = prefix.get_last_stmt().loc
- trace_with_err = prefix.copy()
- trace_with_err.add_error(err)
- trace_with_err.log(log, 'FINISHED TRACE WITH ERROR: %s' % err, 1)
- return [trace_with_err]
-
- logger('transitions: %s' % transitions, 2)
-
- if len(transitions) > 0:
- for transition in transitions:
- # FIXME: what about loops???
- assert isinstance(transition, Transition)
- self.states.append(transition.nextstate)
- self.edges.append(StateEdge(curstate, transition.nextstate, transition))
-
- # Recurse:
- self._gather_states(transition.nextstate, curstate, logger)
- else:
- # We're at a terminating state:
- logger('FINISHED TRACE')
-
-def extra_text(msg, indent):
- sys.stderr.write('%s%s\n' % (' ' * indent, msg))
-
-def describe_trace(trace):
- # Print more details about the path through the function that
- # leads to the error:
- awaiting_target = None
- for j in range(len(trace.states)-1):
- state = trace.states[j]
- nextstate = trace.states[j+1]
- stmt = state.loc.get_stmt()
- next_stmt = nextstate.loc.get_stmt()
- if state.loc.bb != nextstate.loc.bb:
- if stmt:
- extra_text('%s: taking %s path at %s'
- % (stmt.loc,
- nextstate.prior_bool,
- get_src_for_loc(stmt.loc)), 1)
- first_loc_in_next_bb = get_first_loc_in_block(nextstate.loc.bb)
- if first_loc_in_next_bb:
- extra_text('%s: reaching here %s'
- % (first_loc_in_next_bb,
- get_src_for_loc(first_loc_in_next_bb)),
- 2)
-
def check_refcounts(fun, show_traces):
# Abstract interpretation:
# Walk the CFG, gathering the information we're interested in
if show_traces:
from libcpychecker.visualizations import StateGraphPrettyPrinter
- sg = StateGraph(fun, log)
+ sg = StateGraph(fun, log, MyState)
sgpp = StateGraphPrettyPrinter(sg)
dot = sgpp.to_dot()
#dot = sgpp.extra_items()
print(dot)
invoke_dot(dot)
- traces = iter_traces(fun)
+ traces = iter_traces(fun, MyState)
if show_traces:
traces = list(traces)
for i, trace in enumerate(traces):
12 years, 10 months
[gcc-python-plugin] Remove the now-redundant SSA support from location-tracking
by David Hugh Malcolm
commit c69ab095ba14d88b2e9cb7a1976e1e707cc9f145
Author: David Malcolm <dmalcolm(a)redhat.com>
Date: Wed Jun 29 20:42:29 2011 -0400
Remove the now-redundant SSA support from location-tracking
libcpychecker/refcounts.py | 73 +++++++++++--------------------------------
1 files changed, 19 insertions(+), 54 deletions(-)
---
diff --git a/libcpychecker/refcounts.py b/libcpychecker/refcounts.py
index 4363ca3..8b0960b 100644
--- a/libcpychecker/refcounts.py
+++ b/libcpychecker/refcounts.py
@@ -59,75 +59,45 @@ def stmt_is_return_of_objptr(stmt):
class Location:
"""A location within a CFG: a gcc.BasicBlock together with an index into
- either the gimple list, or the phi_nodes list"""
- def __init__(self, bb, idx, within_phi=False):
+ the gimple list. (We don't support SSA passes)"""
+ def __init__(self, bb, idx):
self.bb = bb
self.idx = idx
- self.within_phi = within_phi
def __str__(self):
stmt = self.get_stmt()
- if self.within_phi:
- kind = ' phi'
- else:
- kind = 'gimple'
- return ('block %i %s[%i]: %20r : %s'
- % (self.bb.index, kind, self.idx, stmt, stmt))
+ return ('block %i stmt:%i : %20r : %s'
+ % (self.bb.index, self.idx, stmt, stmt))
def next_locs(self):
"""Get a list of Location instances, for what can happen next"""
- if self.within_phi:
- if self.bb.phi_nodes and len(self.bb.phi_nodes) > self.idx + 1:
- # Next phi node:
- return [Location(self.bb, self.idx + 1, self.within_phi)]
- else:
- # At end of phi nodes; start the gimple statements
- return [Location(self.bb, 0, False)]
+ if self.bb.gimple and len(self.bb.gimple) > self.idx + 1:
+ # Next gimple statement:
+ return [Location(self.bb, self.idx + 1)]
else:
- if self.bb.gimple and len(self.bb.gimple) > self.idx + 1:
- # Next gimple statement:
- return [Location(self.bb, self.idx + 1, self.within_phi)]
- else:
- # At end of gimple statements: successor BBs:
- return [Location.get_block_start(outedge.dest) for outedge in self.bb.succs]
+ # At end of gimple statements: successor BBs:
+ return [Location.get_block_start(outedge.dest) for outedge in self.bb.succs]
def next_loc(self):
"""Get the next Location, for when it's unique"""
- if self.within_phi:
- if self.bb.phi_nodes and len(self.bb.phi_nodes) > self.idx + 1:
- # Next phi node:
- return Location(self.bb, self.idx + 1, self.within_phi)
+ if self.bb.gimple:
+ if len(self.bb.gimple) > self.idx + 1:
+ # Next gimple statement:
+ return Location(self.bb, self.idx + 1)
else:
- # At end of phi nodes; start the gimple statements
- return Location(self.bb, 0, False)
- else:
- if self.bb.gimple:
- if len(self.bb.gimple) > self.idx + 1:
- # Next gimple statement:
- return Location(self.bb, self.idx + 1, self.within_phi)
- else:
- assert len(self.bb.succs) == 1
- return Location.get_block_start(self.bb.succs[0].dest)
+ assert len(self.bb.succs) == 1
+ return Location.get_block_start(self.bb.succs[0].dest)
@classmethod
def get_block_start(cls, bb):
# Don't bother iterating through phi_nodes if there aren't any:
- if bb.phi_nodes:
- return Location(bb, 0, True)
- else:
- return Location(bb, 0, False)
+ return Location(bb, 0)
def get_stmt(self):
- if self.within_phi:
- if self.bb.phi_nodes:
- return self.bb.phi_nodes[self.idx]
- else:
- return None
+ if self.bb.gimple:
+ return self.bb.gimple[self.idx]
else:
- if self.bb.gimple:
- return self.bb.gimple[self.idx]
- else:
- return None
+ return None
class State:
"""A Location with a dict of vars and values"""
@@ -331,11 +301,6 @@ class MyState(State):
return self.data[expr.name]
else:
return UnknownValue(expr.type, None)
- if isinstance(expr, gcc.SsaName):
- if str(expr) in self.data:
- return self.data[str(expr)]
- else:
- return UnknownValue(expr.type, None)
if isinstance(expr, gcc.AddrExpr):
#log(dir(expr))
#log(expr.operand)
12 years, 10 months
[gcc-python-plugin] Disable non-functioning tests for C stdio checker
by David Hugh Malcolm
commit f23a7bf1ba1742799389d39487245dbe1f9cd080
Author: David Malcolm <dmalcolm(a)redhat.com>
Date: Wed Jun 29 20:32:37 2011 -0400
Disable non-functioning tests for C stdio checker
libcpychecker/c_stdio.py | 18 ++++++++++++------
libcpychecker/refcounts.py | 9 +++++----
.../fileptr-missing-error-check/script.py | 2 +-
.../fileptr-missing-error-check/stderr.txt | 2 --
4 files changed, 18 insertions(+), 13 deletions(-)
---
diff --git a/libcpychecker/c_stdio.py b/libcpychecker/c_stdio.py
index e314c72..8641b9e 100644
--- a/libcpychecker/c_stdio.py
+++ b/libcpychecker/c_stdio.py
@@ -50,26 +50,32 @@ def handle_c_stdio_function(state, fnname, stmt):
if fnname == 'fopen':
# The "success" case:
file_ptr = NonNullFilePtr(stmt)
- success = state.make_assignment(stmt.lhs, file_ptr)
- success.acquire(file_ptr)
+ success = state.make_assignment(stmt.lhs,
+ file_ptr,
+ '%s() succeeded' % fnname)
+ success.nextstate.acquire(file_ptr)
# The "failure" case:
- failure = state.make_assignment(stmt.lhs, NullPtrValue(stmt))
+ failure = state.make_assignment(stmt.lhs,
+ NullPtrValue(stmt),
+ '%s() failed' % fnname)
return [success, failure]
elif fnname == 'fclose':
expr = state.eval_expr(stmt.args[0])
if isinstance(expr, NonNullFilePtr):
result = state.make_assignment(stmt.lhs,
- AbstractValue(gcc.Type.int(), stmt)) # FIXME errno handling!
+ AbstractValue(gcc.Type.int(), stmt),
+ '%s() succeeded' % fnname) # FIXME errno handling!
result.release(expr)
return [result]
elif isinstance(expr, NullPtrValue):
raise InvalidlyNullParameter(fnname, 1, expr)
else:
result = state.make_assignment(stmt.lhs,
- AbstractValue(gcc.Type.int(), stmt)) # FIXME errno handling!
- result.release(expr)
+ AbstractValue(gcc.Type.int(), stmt),
+ '%s() succeeded' % fnname) # FIXME errno handling!
+ result.nextstate.release(expr)
return [result]
else:
# We claimed to handle this function, but didn't:
diff --git a/libcpychecker/refcounts.py b/libcpychecker/refcounts.py
index e01ee2f..4363ca3 100644
--- a/libcpychecker/refcounts.py
+++ b/libcpychecker/refcounts.py
@@ -163,9 +163,10 @@ class State:
assert isinstance(desc, str)
new = self.copy()
new.loc = self.loc.next_loc()
- assert isinstance(lvalue, gcc.VarDecl) # for now
- key = self.get_key_for_lvalue(lvalue)
- new.data[key] = value
+ if lvalue:
+ assert isinstance(lvalue, gcc.VarDecl) # for now
+ key = self.get_key_for_lvalue(lvalue)
+ new.data[key] = value
return Transition(new, desc)
def update_loc(self, newloc):
@@ -601,7 +602,7 @@ def check_refcounts(fun, show_traces):
# Abstract interpretation:
# Walk the CFG, gathering the information we're interested in
- if 1:
+ if show_traces:
from libcpychecker.visualizations import StateGraphPrettyPrinter
sg = StateGraph(fun, log)
sgpp = StateGraphPrettyPrinter(sg)
diff --git a/tests/cpychecker/fileptr-missing-error-check/script.py b/tests/cpychecker/fileptr-missing-error-check/script.py
index 94ea0d5..fef1ee1 100644
--- a/tests/cpychecker/fileptr-missing-error-check/script.py
+++ b/tests/cpychecker/fileptr-missing-error-check/script.py
@@ -16,4 +16,4 @@
# <http://www.gnu.org/licenses/>.
from libcpychecker import main
-main(verify_refcounting=True)
+main(verify_refcounting=False)
diff --git a/tests/cpychecker/fileptr-missing-error-check/stderr.txt b/tests/cpychecker/fileptr-missing-error-check/stderr.txt
index e07e55d..e69de29 100644
--- a/tests/cpychecker/fileptr-missing-error-check/stderr.txt
+++ b/tests/cpychecker/fileptr-missing-error-check/stderr.txt
@@ -1,2 +0,0 @@
-tests/cpychecker/fileptr-missing-error-check/input.c: In function ‘missing_error_check’:
-tests/cpychecker/fileptr-missing-error-check/input.c:28:11: error: fclose can be called with NULL as parameter 1; NULL value from FILE *f = fopen(filename, "r"); [-fpermissive]
12 years, 10 months
[gcc-python-plugin] Disable the checker by default again (accidentally enabled in last commit)
by David Hugh Malcolm
commit 8e2d0966a3adeaa0ff1cf5d30343b5df45b9b923
Author: David Malcolm <dmalcolm(a)redhat.com>
Date: Wed Jun 29 20:17:52 2011 -0400
Disable the checker by default again (accidentally enabled in last commit)
libcpychecker/__init__.py | 16 +++-------------
1 files changed, 3 insertions(+), 13 deletions(-)
---
diff --git a/libcpychecker/__init__.py b/libcpychecker/__init__.py
index 5188fad..85dee13 100644
--- a/libcpychecker/__init__.py
+++ b/libcpychecker/__init__.py
@@ -32,19 +32,9 @@ def on_pass_execution(optpass, fun,
log(fun)
check_pyargs(fun)
- # non-SSA version of the checker:
- check_refcounts(fun, show_traces)
-
- # The refcount code is too buggy for now to be on by default:
- if not verify_refcounting:
- return
-
- if 0: # optpass.name == 'release_ssa':
- # SSA data needed:
- assert optpass.properties_required & (1<<5)
- # methods = get_all_PyMethodDef_methods()
- # log('methods: %s' % methods)
- check_refcounts(fun, show_traces)
+ # The refcount code is too buggy for now to be on by default:
+ if verify_refcounting:
+ check_refcounts(fun, show_traces)
def is_a_method_callback(decl):
methods = get_all_PyMethodDef_methods()
12 years, 10 months