[gcc-python-plugin] cpychecker: fix exception when leaking a reference in a function with "void" return type
by David Hugh Malcolm
commit 55a46ceec2f971a4cfd6d7a61d3cf563206c9d60
Author: David Malcolm <dmalcolm(a)redhat.com>
Date: Mon Aug 29 14:00:10 2011 -0400
cpychecker: fix exception when leaking a reference in a function with "void" return type
libcpychecker/refcounts.py | 9 +++++----
1 files changed, 5 insertions(+), 4 deletions(-)
---
diff --git a/libcpychecker/refcounts.py b/libcpychecker/refcounts.py
index 04583be..eaebbde 100644
--- a/libcpychecker/refcounts.py
+++ b/libcpychecker/refcounts.py
@@ -1353,10 +1353,11 @@ def check_refcounts(fun, dump_traces=False, show_traces=False):
err = emit_refcount_error('ob_refcnt of %s is %i too low'
% (desc, exp_refcnt - ob_refcnt.relvalue))
# Special-case hint for when None has too low a refcount:
- if isinstance(return_value.region, RegionForGlobal):
- if return_value.region.vardecl.name == '_Py_NoneStruct':
- err.add_note(endstate.get_gcc_loc(fun),
- 'consider using "Py_RETURN_NONE;"')
+ if return_value:
+ if isinstance(return_value.region, RegionForGlobal):
+ if return_value.region.vardecl.name == '_Py_NoneStruct':
+ err.add_note(endstate.get_gcc_loc(fun),
+ 'consider using "Py_RETURN_NONE;"')
# Detect returning a deallocated object:
if return_value:
12 years, 9 months
[gcc-python-plugin] cpychecker: fix handling of writes through unknown pointer values
by David Hugh Malcolm
commit 03a51c0cb19b3022af26d6311f7d9bef638d29e4
Author: David Malcolm <dmalcolm(a)redhat.com>
Date: Mon Aug 29 13:54:12 2011 -0400
cpychecker: fix handling of writes through unknown pointer values
libcpychecker/absinterp.py | 4 ++
.../absinterp/write-through-arg-unchecked/input.c | 38 ++++++++++++++++++++
.../write-through-arg-unchecked/script.py | 22 +++++++++++
.../write-through-arg-unchecked/stderr.txt | 4 ++
.../write-through-arg-unchecked/stdout.txt | 14 +++++++
5 files changed, 82 insertions(+), 0 deletions(-)
---
diff --git a/libcpychecker/absinterp.py b/libcpychecker/absinterp.py
index d339bd8..70f5320 100644
--- a/libcpychecker/absinterp.py
+++ b/libcpychecker/absinterp.py
@@ -462,6 +462,10 @@ class State:
# Write through a pointer:
dest_ptr = self.eval_rvalue(expr.operand, loc)
log('dest_ptr: %r', dest_ptr)
+ self.raise_any_null_ptr_deref(expr, dest_ptr)
+ if isinstance(dest_ptr, UnknownValue):
+ # Split into null/non-null pointers:
+ self.raise_split_value(dest_ptr)
check_isinstance(dest_ptr, PointerToRegion)
dest_region = dest_ptr.region
log('dest_region: %r', dest_region)
diff --git a/tests/cpychecker/absinterp/write-through-arg-unchecked/input.c b/tests/cpychecker/absinterp/write-through-arg-unchecked/input.c
new file mode 100644
index 0000000..d75d1fe
--- /dev/null
+++ b/tests/cpychecker/absinterp/write-through-arg-unchecked/input.c
@@ -0,0 +1,38 @@
+/*
+ Copyright 2011 David Malcolm <dmalcolm(a)redhat.com>
+ Copyright 2011 Red Hat, Inc.
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see
+ <http://www.gnu.org/licenses/>.
+*/
+
+#include <Python.h>
+
+/*
+ Test of writing through a pointer as an array:
+*/
+
+void
+test(char *out)
+{
+ out[0] = '\0';
+}
+
+/*
+ PEP-7
+Local variables:
+c-basic-offset: 4
+indent-tabs-mode: nil
+End:
+*/
diff --git a/tests/cpychecker/absinterp/write-through-arg-unchecked/script.py b/tests/cpychecker/absinterp/write-through-arg-unchecked/script.py
new file mode 100644
index 0000000..fdd5ba3
--- /dev/null
+++ b/tests/cpychecker/absinterp/write-through-arg-unchecked/script.py
@@ -0,0 +1,22 @@
+# -*- coding: utf-8 -*-
+# Copyright 2011 David Malcolm <dmalcolm(a)redhat.com>
+# Copyright 2011 Red Hat, Inc.
+#
+# This is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program 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
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see
+# <http://www.gnu.org/licenses/>.
+
+from libcpychecker import main
+main(verify_refcounting=True,
+ dump_traces=True,
+ show_traces=False)
diff --git a/tests/cpychecker/absinterp/write-through-arg-unchecked/stderr.txt b/tests/cpychecker/absinterp/write-through-arg-unchecked/stderr.txt
new file mode 100644
index 0000000..47f0202
--- /dev/null
+++ b/tests/cpychecker/absinterp/write-through-arg-unchecked/stderr.txt
@@ -0,0 +1,4 @@
+tests/cpychecker/absinterp/write-through-arg-unchecked/input.c: In function 'test':
+tests/cpychecker/absinterp/write-through-arg-unchecked/input.c:29:12: error: possibly dereferencing NULL (*out) at tests/cpychecker/absinterp/write-through-arg-unchecked/input.c:30
+tests/cpychecker/absinterp/write-through-arg-unchecked/input.c:29:12: note: when treating unknown char * from tests/cpychecker/absinterp/write-through-arg-unchecked/input.c:27 as (char *)0 at: out[0] = '\0';
+tests/cpychecker/absinterp/write-through-arg-unchecked/input.c:28:1: note: graphical error report for function 'test' written out to 'tests/cpychecker/absinterp/write-through-arg-unchecked/input.c.test-refcount-errors.html'
diff --git a/tests/cpychecker/absinterp/write-through-arg-unchecked/stdout.txt b/tests/cpychecker/absinterp/write-through-arg-unchecked/stdout.txt
new file mode 100644
index 0000000..87e2704
--- /dev/null
+++ b/tests/cpychecker/absinterp/write-through-arg-unchecked/stdout.txt
@@ -0,0 +1,14 @@
+Trace 0:
+ Transitions:
+ "treating unknown char * from tests/cpychecker/absinterp/write-through-arg-unchecked/input.c:27 as (char *)&Region('heap-region-0')"
+ 'returning'
+ Exception:
+ (struct PyObject *)0 from tests/cpychecker/absinterp/write-through-arg-unchecked/input.c:28
+
+Trace 1:
+ Transitions:
+ 'treating unknown char * from tests/cpychecker/absinterp/write-through-arg-unchecked/input.c:27 as (char *)0'
+ error: NullPtrDereference()
+ error: possibly dereferencing NULL (*out) at tests/cpychecker/absinterp/write-through-arg-unchecked/input.c:30
+ Exception:
+ (struct PyObject *)0 from tests/cpychecker/absinterp/write-through-arg-unchecked/input.c:28
12 years, 9 months
[gcc-python-plugin] cpychecker: implement _PyObject_New
by David Hugh Malcolm
commit e121921d86c35e201931a122274ff5b02fe5971e
Author: David Malcolm <dmalcolm(a)redhat.com>
Date: Mon Aug 29 13:36:02 2011 -0400
cpychecker: implement _PyObject_New
libcpychecker/refcounts.py | 51 +++++++++++++++++
.../refcounts/_PyObject_New/correct/input.c | 60 ++++++++++++++++++++
.../refcounts/_PyObject_New/correct/script.py | 22 +++++++
.../refcounts/_PyObject_New/correct/stdout.txt | 43 ++++++++++++++
4 files changed, 176 insertions(+), 0 deletions(-)
---
diff --git a/libcpychecker/refcounts.py b/libcpychecker/refcounts.py
index cb920ae..04583be 100644
--- a/libcpychecker/refcounts.py
+++ b/libcpychecker/refcounts.py
@@ -384,6 +384,26 @@ class MyState(State):
self.value_for_region[ob_refcnt] = RefcountValue(value.relvalue - 1,
value.min_external + 1)
+ def make_new_ref(self, stmt, name):
+ """
+ Make a new State, in which a new ref to some object has been
+ assigned to the statement's LHS.
+
+ Returns a pair: (newstate, RegionOnHeap for the new object)
+ """
+ newstate = self.copy()
+ newstate.loc = self.loc.next_loc()
+
+ nonnull = newstate.make_heap_region(name, stmt)
+ ob_refcnt = newstate.make_field_region(nonnull, 'ob_refcnt') # FIXME: this should be a memref and fieldref
+ newstate.value_for_region[ob_refcnt] = RefcountValue.new_ref()
+ newstate.assign(stmt.lhs,
+ PointerToRegion(stmt.lhs.type,
+ stmt.loc,
+ nonnull),
+ stmt.loc)
+ return newstate, nonnull
+
def make_borrowed_ref(self, stmt, name):
"""Make a new state, giving a borrowed ref to some object"""
newstate = self.copy()
@@ -613,6 +633,37 @@ class MyState(State):
failure = self.make_exception(stmt, 'Py_InitModule4')
return self.make_transitions_for_fncall(stmt, success, failure)
+ def impl__PyObject_New(self, stmt):
+ # Declaration in objimpl.h:
+ # PyAPI_FUNC(PyObject *) _PyObject_New(PyTypeObject *);
+ #
+ # For use via this macro:
+ # #define PyObject_New(type, typeobj) \
+ # ( (type *) _PyObject_New(typeobj) )
+ #
+ # Definition is in Objects/object.c
+ #
+ # Return value: New reference.
+ assert isinstance(stmt, gcc.GimpleCall)
+ assert isinstance(stmt.fn.operand, gcc.FunctionDecl)
+
+ tp_rvalue = self.eval_rvalue(stmt.args[0], stmt.loc)
+
+ # Success case: allocation and assignment:
+ success, nonnull = self.make_new_ref(stmt, '_PyObject_New')
+ # ...and set up ob_type on the result object:
+ ob_type = success.make_field_region(nonnull, 'ob_type')
+ success.value_for_region[ob_type] = tp_rvalue
+ success = Transition(self,
+ success,
+ '_PyObject_New() succeeds')
+ # Failure case:
+ failure = self.make_assignment(stmt.lhs,
+ ConcreteValue(stmt.lhs.type, stmt.loc, 0),
+ '_PyObject_New() fails')
+ failure.dest.set_exception('PyExc_MemoryError')
+ return [success, failure]
+
def _get_transitions_for_GimpleCall(self, stmt):
log('stmt.lhs: %s %r', stmt.lhs, stmt.lhs)
log('stmt.fn: %s %r', stmt.fn, stmt.fn)
diff --git a/tests/cpychecker/refcounts/_PyObject_New/correct/input.c b/tests/cpychecker/refcounts/_PyObject_New/correct/input.c
new file mode 100644
index 0000000..d92acc2
--- /dev/null
+++ b/tests/cpychecker/refcounts/_PyObject_New/correct/input.c
@@ -0,0 +1,60 @@
+/*
+ Copyright 2011 David Malcolm <dmalcolm(a)redhat.com>
+ Copyright 2011 Red Hat, Inc.
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see
+ <http://www.gnu.org/licenses/>.
+*/
+
+#include <Python.h>
+
+/*
+ Test of a correct call to _PyObject_New
+*/
+
+struct FooObject {
+ PyObject_HEAD
+ int x;
+ int y;
+ int z;
+};
+
+extern PyTypeObject FooType;
+
+PyObject *
+test(PyObject *self, PyObject *args)
+{
+ struct FooObject *obj;
+
+ obj = PyObject_New(struct FooObject, &FooType);
+ if (!obj) {
+ return NULL;
+ }
+ obj->x = 0;
+ obj->y = 0;
+ obj->z = 0;
+ return (PyObject*)obj;
+}
+static PyMethodDef test_methods[] = {
+ {"test_method", test, METH_VARARGS, NULL},
+ {NULL, NULL, 0, NULL} /* Sentinel */
+};
+
+/*
+ PEP-7
+Local variables:
+c-basic-offset: 4
+indent-tabs-mode: nil
+End:
+*/
diff --git a/tests/cpychecker/refcounts/_PyObject_New/correct/script.py b/tests/cpychecker/refcounts/_PyObject_New/correct/script.py
new file mode 100644
index 0000000..fdd5ba3
--- /dev/null
+++ b/tests/cpychecker/refcounts/_PyObject_New/correct/script.py
@@ -0,0 +1,22 @@
+# -*- coding: utf-8 -*-
+# Copyright 2011 David Malcolm <dmalcolm(a)redhat.com>
+# Copyright 2011 Red Hat, Inc.
+#
+# This is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program 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
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see
+# <http://www.gnu.org/licenses/>.
+
+from libcpychecker import main
+main(verify_refcounting=True,
+ dump_traces=True,
+ show_traces=False)
diff --git a/tests/cpychecker/refcounts/_PyObject_New/correct/stdout.txt b/tests/cpychecker/refcounts/_PyObject_New/correct/stdout.txt
new file mode 100644
index 0000000..05f702f
--- /dev/null
+++ b/tests/cpychecker/refcounts/_PyObject_New/correct/stdout.txt
@@ -0,0 +1,43 @@
+Trace 0:
+ Transitions:
+ '_PyObject_New() succeeds'
+ 'taking False path'
+ 'returning'
+ Return value:
+ repr(): PointerToRegion(gcctype='struct FooObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/_PyObject_New/correct/input.c', line=40), region=RegionOnHeap('_PyObject_New', gcc.Location(file='tests/cpychecker/refcounts/_PyObject_New/correct/input.c', line=40)))
+ str(): (struct FooObject *)&RegionOnHeap('_PyObject_New', gcc.Location(file='tests/cpychecker/refcounts/_PyObject_New/correct/input.c', line=40)) from tests/cpychecker/refcounts/_PyObject_New/correct/input.c:40
+ r->ob_refcnt: refs: 1 + N where N >= 0
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/_PyObject_New/correct/input.c', line=40), region=RegionForGlobal(gcc.VarDecl('FooType')))
+ Region("region-for-arg-gcc.ParmDecl('self')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('self')")
+ str(): Region("region-for-arg-gcc.ParmDecl('self')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/_PyObject_New/correct/input.c', line=36), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
+ Region("region-for-arg-gcc.ParmDecl('args')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('args')")
+ str(): Region("region-for-arg-gcc.ParmDecl('args')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/_PyObject_New/correct/input.c', line=36), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
+ Exception:
+ (struct PyObject *)0 from tests/cpychecker/refcounts/_PyObject_New/correct/input.c:37
+
+Trace 1:
+ Transitions:
+ '_PyObject_New() fails'
+ 'taking True path'
+ 'returning'
+ Return value:
+ repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/_PyObject_New/correct/input.c', line=42), value=0)
+ str(): (struct PyObject *)0 from tests/cpychecker/refcounts/_PyObject_New/correct/input.c:42
+ Region("region-for-arg-gcc.ParmDecl('self')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('self')")
+ str(): Region("region-for-arg-gcc.ParmDecl('self')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/_PyObject_New/correct/input.c', line=36), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
+ Region("region-for-arg-gcc.ParmDecl('args')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('args')")
+ str(): Region("region-for-arg-gcc.ParmDecl('args')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/_PyObject_New/correct/input.c', line=36), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
+ Exception:
+ RegionForGlobal(gcc.VarDecl('PyExc_MemoryError'))
12 years, 9 months
[gcc-python-plugin] Add HTML debug dump files to .gitignore
by David Hugh Malcolm
commit c7a6532cfd6d8ab00969744fa2fc819a60716168
Author: David Malcolm <dmalcolm(a)redhat.com>
Date: Sun Aug 28 22:57:11 2011 -0400
Add HTML debug dump files to .gitignore
.gitignore | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index 8c2d6be..35409a5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,4 +14,5 @@ docs/_build
# Logfiles generated during the selftest suite:
*.c.cpychecker-log.txt
*.c.*-refcount-errors.html
+*.c.*-refcount-traces.html
tests/plugin/dumpfiles/input.c.*t.test-pass
12 years, 9 months
[gcc-python-plugin] cpychecker: implement PyList_Append
by David Hugh Malcolm
commit 9367bcbe3bee31f248f980294dc3acfed93033f8
Author: David Malcolm <dmalcolm(a)redhat.com>
Date: Sun Aug 28 17:54:04 2011 -0400
cpychecker: implement PyList_Append
libcpychecker/refcounts.py | 44 ++++
.../refcounts/PyList_Append/correct/input.c | 71 ++++++
.../refcounts/PyList_Append/correct/script.py | 22 ++
.../refcounts/PyList_Append/correct/stdout.txt | 264 ++++++++++++++++++++
.../refcounts/PyList_Append/incorrect/input.c | 66 +++++
.../refcounts/PyList_Append/incorrect/script.py | 22 ++
.../refcounts/PyList_Append/incorrect/stderr.txt | 20 ++
.../refcounts/PyList_Append/incorrect/stdout.txt | 263 +++++++++++++++++++
8 files changed, 772 insertions(+), 0 deletions(-)
---
diff --git a/libcpychecker/refcounts.py b/libcpychecker/refcounts.py
index a7c7ee8..cb920ae 100644
--- a/libcpychecker/refcounts.py
+++ b/libcpychecker/refcounts.py
@@ -275,6 +275,20 @@ class MyState(State):
raise NotImplementedError("Don't know how to cope with %r (%s) at %s"
% (stmt, stmt, stmt.loc))
+ def add_ref(self, pyobjectptr, loc):
+ assert isinstance(pyobjectptr, AbstractValue)
+ assert isinstance(pyobjectptr, PointerToRegion)
+ ob_refcnt = self.make_field_region(pyobjectptr.region, 'ob_refcnt')
+ assert isinstance(ob_refcnt, Region)
+ oldvalue = self.get_store(ob_refcnt, None, loc) # FIXME: gcctype
+ assert isinstance(oldvalue, AbstractValue)
+ log('oldvalue: %r' % oldvalue)
+ #if isinstance(oldvalue, UnknownValue):
+ # self.raise_split_value(oldvalue, loc)
+ assert isinstance(oldvalue, RefcountValue)
+ newvalue = RefcountValue(oldvalue.relvalue + 1, oldvalue.min_external)
+ self.value_for_region[ob_refcnt] = newvalue
+
def set_exception(self, exc_name):
"""
Given the name of a (PyObject*) global for an exception class, such as
@@ -497,6 +511,36 @@ class MyState(State):
'PyLongObject', 'PyLong_Type')
return [success, failure]
+ def impl_PyList_Append(self, stmt):
+ # Declared in listobject.h as:
+ # PyAPI_FUNC(int) PyList_Append(PyObject *, PyObject *);
+ #
+ # Defined in listobject.c
+ #
+ # http://docs.python.org/c-api/list.html#PyList_Append
+ #
+ # If it succeeds, it adds a reference on the item
+ #
+ op, newitem = self.eval_stmt_args(stmt)
+
+ # On success, adds a ref on input:
+ success = self.make_concrete_return_of(stmt, 0)
+ success.add_ref(newitem, stmt.loc)
+ #...and set the pointer value within ob_item array, so that we can
+ # discount that refcount:
+ ob_item_region = self.make_field_region(op.region, 'ob_item')
+ ob_size_region = self.make_field_region(op.region, 'ob_size')
+ check_isinstance(success.value_for_region[ob_size_region], ConcreteValue) # for now
+ index = success.value_for_region[ob_size_region].value
+ array_region = success._array_region(ob_item_region, index)
+ success.value_for_region[array_region] = newitem
+
+ # Can fail with memory error, overflow error:
+ failure = self.make_concrete_return_of(stmt, -1)
+ failure.set_exception('PyExc_MemoryError')
+
+ return self.make_transitions_for_fncall(stmt, success, failure)
+
def impl_PyList_SetItem(self, stmt):
# Decl:
# int PyList_SetItem(PyObject *list, Py_ssize_t index, PyObject *item)
diff --git a/tests/cpychecker/refcounts/PyList_Append/correct/input.c b/tests/cpychecker/refcounts/PyList_Append/correct/input.c
new file mode 100644
index 0000000..0e0a091
--- /dev/null
+++ b/tests/cpychecker/refcounts/PyList_Append/correct/input.c
@@ -0,0 +1,71 @@
+/*
+ Copyright 2011 David Malcolm <dmalcolm(a)redhat.com>
+ Copyright 2011 Red Hat, Inc.
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see
+ <http://www.gnu.org/licenses/>.
+*/
+
+#include <Python.h>
+
+/*
+ Test of correct reference-handling in a call to PyList_Append
+*/
+
+PyObject *
+test(PyObject *self, PyObject *args)
+{
+ PyObject *list;
+ PyObject *item;
+
+ list = PyList_New(0);
+ if (!list) {
+ return NULL;
+ }
+ item = PyLong_FromLong(42);
+ if (!item) {
+ Py_DECREF(list);
+ return NULL;
+ }
+
+ if (-1 == PyList_Append(list, item)) {
+ Py_DECREF(list);
+ Py_DECREF(item);
+ return NULL;
+ }
+
+ /* FIXME: perhaps append it multiple times? */
+
+ /* PyList_Append adds a ref to item, reflecting its reference
+ within the list's ob_item array */
+
+ /* "item" is going out of scope, so we must DECREF our reference: */
+ Py_DECREF(item);
+
+ /* "item" should now have an ob_refcnt of 1 */
+
+ return list;
+}
+static PyMethodDef test_methods[] = {
+ {"test_method", test, METH_VARARGS, NULL},
+ {NULL, NULL, 0, NULL} /* Sentinel */
+};
+
+/*
+ PEP-7
+Local variables:
+c-basic-offset: 4
+indent-tabs-mode: nil
+End:
+*/
diff --git a/tests/cpychecker/refcounts/PyList_Append/correct/script.py b/tests/cpychecker/refcounts/PyList_Append/correct/script.py
new file mode 100644
index 0000000..fdd5ba3
--- /dev/null
+++ b/tests/cpychecker/refcounts/PyList_Append/correct/script.py
@@ -0,0 +1,22 @@
+# -*- coding: utf-8 -*-
+# Copyright 2011 David Malcolm <dmalcolm(a)redhat.com>
+# Copyright 2011 Red Hat, Inc.
+#
+# This is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program 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
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see
+# <http://www.gnu.org/licenses/>.
+
+from libcpychecker import main
+main(verify_refcounting=True,
+ dump_traces=True,
+ show_traces=False)
diff --git a/tests/cpychecker/refcounts/PyList_Append/correct/stdout.txt b/tests/cpychecker/refcounts/PyList_Append/correct/stdout.txt
new file mode 100644
index 0000000..3d0a4c1
--- /dev/null
+++ b/tests/cpychecker/refcounts/PyList_Append/correct/stdout.txt
@@ -0,0 +1,264 @@
+Trace 0:
+ Transitions:
+ 'PyList_New() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() succeeds'
+ 'taking False path'
+ 'PyList_Append() succeeds'
+ 'taking False path'
+ 'taking True path'
+ 'returning'
+ Return value:
+ repr(): PointerToRegion(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/correct/input.c', line=32), region=RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/correct/input.c', line=32)))
+ str(): (struct PyObject *)&RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/correct/input.c', line=32)) from tests/cpychecker/refcounts/PyList_Append/correct/input.c:32
+ r->ob_refcnt: refs: 1 + N where N >= 0
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/correct/input.c', line=32), region=RegionForGlobal(gcc.VarDecl('PyList_Type')))
+ Region("region-for-arg-gcc.ParmDecl('self')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('self')")
+ str(): Region("region-for-arg-gcc.ParmDecl('self')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/correct/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
+ Region("region-for-arg-gcc.ParmDecl('args')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('args')")
+ str(): Region("region-for-arg-gcc.ParmDecl('args')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/correct/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
+ PyLongObject allocated at tests/cpychecker/refcounts/PyList_Append/correct/input.c:36:
+ repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/correct/input.c', line=36))
+ str(): PyLongObject allocated at tests/cpychecker/refcounts/PyList_Append/correct/input.c:36
+ r->ob_refcnt: refs: 1 + N where N >= 0
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/correct/input.c', line=36), region=RegionForGlobal(gcc.VarDecl('PyLong_Type')))
+ Exception:
+ (struct PyObject *)0 from tests/cpychecker/refcounts/PyList_Append/correct/input.c:28
+
+Trace 1:
+ Transitions:
+ 'PyList_New() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() succeeds'
+ 'taking False path'
+ 'PyList_Append() fails'
+ 'taking True path'
+ 'taking True path'
+ 'taking True path'
+ 'returning'
+ Return value:
+ repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/correct/input.c', line=45), value=0)
+ str(): (struct PyObject *)0 from tests/cpychecker/refcounts/PyList_Append/correct/input.c:45
+ Region("region-for-arg-gcc.ParmDecl('self')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('self')")
+ str(): Region("region-for-arg-gcc.ParmDecl('self')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/correct/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
+ Region("region-for-arg-gcc.ParmDecl('args')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('args')")
+ str(): Region("region-for-arg-gcc.ParmDecl('args')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/correct/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
+ PyListObject allocated at tests/cpychecker/refcounts/PyList_Append/correct/input.c:32:
+ repr(): RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/correct/input.c', line=32))
+ str(): PyListObject allocated at tests/cpychecker/refcounts/PyList_Append/correct/input.c:32
+ r->ob_refcnt: refs: 0 + N where N >= 0
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/correct/input.c', line=32), region=RegionForGlobal(gcc.VarDecl('PyList_Type')))
+ PyLongObject allocated at tests/cpychecker/refcounts/PyList_Append/correct/input.c:36:
+ repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/correct/input.c', line=36))
+ str(): PyLongObject allocated at tests/cpychecker/refcounts/PyList_Append/correct/input.c:36
+ r->ob_refcnt: refs: 0 + N where N >= 0
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/correct/input.c', line=36), region=RegionForGlobal(gcc.VarDecl('PyLong_Type')))
+ Exception:
+ RegionForGlobal(gcc.VarDecl('PyExc_MemoryError'))
+
+Trace 2:
+ Transitions:
+ 'PyList_New() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() succeeds'
+ 'taking False path'
+ 'PyList_Append() fails'
+ 'taking True path'
+ 'taking True path'
+ 'taking False path'
+ 'calling tp_dealloc on PyLongObject allocated at tests/cpychecker/refcounts/PyList_Append/correct/input.c:36'
+ 'returning'
+ Return value:
+ repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/correct/input.c', line=45), value=0)
+ str(): (struct PyObject *)0 from tests/cpychecker/refcounts/PyList_Append/correct/input.c:45
+ Region("region-for-arg-gcc.ParmDecl('self')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('self')")
+ str(): Region("region-for-arg-gcc.ParmDecl('self')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/correct/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
+ Region("region-for-arg-gcc.ParmDecl('args')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('args')")
+ str(): Region("region-for-arg-gcc.ParmDecl('args')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/correct/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
+ PyListObject allocated at tests/cpychecker/refcounts/PyList_Append/correct/input.c:32:
+ repr(): RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/correct/input.c', line=32))
+ str(): PyListObject allocated at tests/cpychecker/refcounts/PyList_Append/correct/input.c:32
+ r->ob_refcnt: refs: 0 + N where N >= 0
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/correct/input.c', line=32), region=RegionForGlobal(gcc.VarDecl('PyList_Type')))
+ PyLongObject allocated at tests/cpychecker/refcounts/PyList_Append/correct/input.c:36:
+ repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/correct/input.c', line=36))
+ str(): PyLongObject allocated at tests/cpychecker/refcounts/PyList_Append/correct/input.c:36
+ r->ob_refcnt: None
+ r->ob_type: None
+ Exception:
+ RegionForGlobal(gcc.VarDecl('PyExc_MemoryError'))
+
+Trace 3:
+ Transitions:
+ 'PyList_New() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() succeeds'
+ 'taking False path'
+ 'PyList_Append() fails'
+ 'taking True path'
+ 'taking False path'
+ 'calling tp_dealloc on PyListObject allocated at tests/cpychecker/refcounts/PyList_Append/correct/input.c:32'
+ 'taking True path'
+ 'returning'
+ Return value:
+ repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/correct/input.c', line=45), value=0)
+ str(): (struct PyObject *)0 from tests/cpychecker/refcounts/PyList_Append/correct/input.c:45
+ Region("region-for-arg-gcc.ParmDecl('self')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('self')")
+ str(): Region("region-for-arg-gcc.ParmDecl('self')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/correct/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
+ Region("region-for-arg-gcc.ParmDecl('args')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('args')")
+ str(): Region("region-for-arg-gcc.ParmDecl('args')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/correct/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
+ PyListObject allocated at tests/cpychecker/refcounts/PyList_Append/correct/input.c:32:
+ repr(): RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/correct/input.c', line=32))
+ str(): PyListObject allocated at tests/cpychecker/refcounts/PyList_Append/correct/input.c:32
+ r->ob_refcnt: None
+ r->ob_type: None
+ PyLongObject allocated at tests/cpychecker/refcounts/PyList_Append/correct/input.c:36:
+ repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/correct/input.c', line=36))
+ str(): PyLongObject allocated at tests/cpychecker/refcounts/PyList_Append/correct/input.c:36
+ r->ob_refcnt: refs: 0 + N where N >= 0
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/correct/input.c', line=36), region=RegionForGlobal(gcc.VarDecl('PyLong_Type')))
+ Exception:
+ RegionForGlobal(gcc.VarDecl('PyExc_MemoryError'))
+
+Trace 4:
+ Transitions:
+ 'PyList_New() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() succeeds'
+ 'taking False path'
+ 'PyList_Append() fails'
+ 'taking True path'
+ 'taking False path'
+ 'calling tp_dealloc on PyListObject allocated at tests/cpychecker/refcounts/PyList_Append/correct/input.c:32'
+ 'taking False path'
+ 'calling tp_dealloc on PyLongObject allocated at tests/cpychecker/refcounts/PyList_Append/correct/input.c:36'
+ 'returning'
+ Return value:
+ repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/correct/input.c', line=45), value=0)
+ str(): (struct PyObject *)0 from tests/cpychecker/refcounts/PyList_Append/correct/input.c:45
+ Region("region-for-arg-gcc.ParmDecl('self')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('self')")
+ str(): Region("region-for-arg-gcc.ParmDecl('self')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/correct/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
+ Region("region-for-arg-gcc.ParmDecl('args')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('args')")
+ str(): Region("region-for-arg-gcc.ParmDecl('args')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/correct/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
+ PyListObject allocated at tests/cpychecker/refcounts/PyList_Append/correct/input.c:32:
+ repr(): RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/correct/input.c', line=32))
+ str(): PyListObject allocated at tests/cpychecker/refcounts/PyList_Append/correct/input.c:32
+ r->ob_refcnt: None
+ r->ob_type: None
+ PyLongObject allocated at tests/cpychecker/refcounts/PyList_Append/correct/input.c:36:
+ repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/correct/input.c', line=36))
+ str(): PyLongObject allocated at tests/cpychecker/refcounts/PyList_Append/correct/input.c:36
+ r->ob_refcnt: None
+ r->ob_type: None
+ Exception:
+ RegionForGlobal(gcc.VarDecl('PyExc_MemoryError'))
+
+Trace 5:
+ Transitions:
+ 'PyList_New() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() fails'
+ 'taking True path'
+ 'taking True path'
+ 'returning'
+ Return value:
+ repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/correct/input.c', line=39), value=0)
+ str(): (struct PyObject *)0 from tests/cpychecker/refcounts/PyList_Append/correct/input.c:39
+ Region("region-for-arg-gcc.ParmDecl('self')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('self')")
+ str(): Region("region-for-arg-gcc.ParmDecl('self')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/correct/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
+ Region("region-for-arg-gcc.ParmDecl('args')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('args')")
+ str(): Region("region-for-arg-gcc.ParmDecl('args')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/correct/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
+ PyListObject allocated at tests/cpychecker/refcounts/PyList_Append/correct/input.c:32:
+ repr(): RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/correct/input.c', line=32))
+ str(): PyListObject allocated at tests/cpychecker/refcounts/PyList_Append/correct/input.c:32
+ r->ob_refcnt: refs: 0 + N where N >= 0
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/correct/input.c', line=32), region=RegionForGlobal(gcc.VarDecl('PyList_Type')))
+ Exception:
+ RegionForGlobal(gcc.VarDecl('PyExc_MemoryError'))
+
+Trace 6:
+ Transitions:
+ 'PyList_New() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() fails'
+ 'taking True path'
+ 'taking False path'
+ 'calling tp_dealloc on PyListObject allocated at tests/cpychecker/refcounts/PyList_Append/correct/input.c:32'
+ 'returning'
+ Return value:
+ repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/correct/input.c', line=39), value=0)
+ str(): (struct PyObject *)0 from tests/cpychecker/refcounts/PyList_Append/correct/input.c:39
+ Region("region-for-arg-gcc.ParmDecl('self')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('self')")
+ str(): Region("region-for-arg-gcc.ParmDecl('self')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/correct/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
+ Region("region-for-arg-gcc.ParmDecl('args')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('args')")
+ str(): Region("region-for-arg-gcc.ParmDecl('args')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/correct/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
+ PyListObject allocated at tests/cpychecker/refcounts/PyList_Append/correct/input.c:32:
+ repr(): RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/correct/input.c', line=32))
+ str(): PyListObject allocated at tests/cpychecker/refcounts/PyList_Append/correct/input.c:32
+ r->ob_refcnt: None
+ r->ob_type: None
+ Exception:
+ RegionForGlobal(gcc.VarDecl('PyExc_MemoryError'))
+
+Trace 7:
+ Transitions:
+ 'PyList_New() fails'
+ 'taking True path'
+ 'returning'
+ Return value:
+ repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/correct/input.c', line=34), value=0)
+ str(): (struct PyObject *)0 from tests/cpychecker/refcounts/PyList_Append/correct/input.c:34
+ Region("region-for-arg-gcc.ParmDecl('self')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('self')")
+ str(): Region("region-for-arg-gcc.ParmDecl('self')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/correct/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
+ Region("region-for-arg-gcc.ParmDecl('args')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('args')")
+ str(): Region("region-for-arg-gcc.ParmDecl('args')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/correct/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
+ Exception:
+ RegionForGlobal(gcc.VarDecl('PyExc_MemoryError'))
diff --git a/tests/cpychecker/refcounts/PyList_Append/incorrect/input.c b/tests/cpychecker/refcounts/PyList_Append/incorrect/input.c
new file mode 100644
index 0000000..c1d36ab
--- /dev/null
+++ b/tests/cpychecker/refcounts/PyList_Append/incorrect/input.c
@@ -0,0 +1,66 @@
+/*
+ Copyright 2011 David Malcolm <dmalcolm(a)redhat.com>
+ Copyright 2011 Red Hat, Inc.
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see
+ <http://www.gnu.org/licenses/>.
+*/
+
+#include <Python.h>
+
+/*
+ Test of incorrect reference-handling in a call to PyList_Append
+*/
+
+PyObject *
+test(PyObject *self, PyObject *args)
+{
+ PyObject *list;
+ PyObject *item;
+
+ list = PyList_New(0);
+ if (!list) {
+ return NULL;
+ }
+ item = PyLong_FromLong(42);
+ if (!item) {
+ Py_DECREF(list);
+ return NULL;
+ }
+
+ if (-1 == PyList_Append(list, item)) {
+ Py_DECREF(list);
+ Py_DECREF(item);
+ return NULL;
+ }
+
+ /*
+ PyList_Append adds a ref to the item, but we still own a reference to
+ it, so this path through the function leaks the reference.
+ */
+
+ return list;
+}
+static PyMethodDef test_methods[] = {
+ {"test_method", test, METH_VARARGS, NULL},
+ {NULL, NULL, 0, NULL} /* Sentinel */
+};
+
+/*
+ PEP-7
+Local variables:
+c-basic-offset: 4
+indent-tabs-mode: nil
+End:
+*/
diff --git a/tests/cpychecker/refcounts/PyList_Append/incorrect/script.py b/tests/cpychecker/refcounts/PyList_Append/incorrect/script.py
new file mode 100644
index 0000000..fdd5ba3
--- /dev/null
+++ b/tests/cpychecker/refcounts/PyList_Append/incorrect/script.py
@@ -0,0 +1,22 @@
+# -*- coding: utf-8 -*-
+# Copyright 2011 David Malcolm <dmalcolm(a)redhat.com>
+# Copyright 2011 Red Hat, Inc.
+#
+# This is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program 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
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see
+# <http://www.gnu.org/licenses/>.
+
+from libcpychecker import main
+main(verify_refcounting=True,
+ dump_traces=True,
+ show_traces=False)
diff --git a/tests/cpychecker/refcounts/PyList_Append/incorrect/stderr.txt b/tests/cpychecker/refcounts/PyList_Append/incorrect/stderr.txt
new file mode 100644
index 0000000..e612c50
--- /dev/null
+++ b/tests/cpychecker/refcounts/PyList_Append/incorrect/stderr.txt
@@ -0,0 +1,20 @@
+tests/cpychecker/refcounts/PyList_Append/incorrect/input.c: In function 'test':
+tests/cpychecker/refcounts/PyList_Append/incorrect/input.c:54:1: error: ob_refcnt of PyLongObject is 1 too high
+tests/cpychecker/refcounts/PyList_Append/incorrect/input.c:54:1: note: was expecting final ob_refcnt to be N + 1 (for some unknown N)
+tests/cpychecker/refcounts/PyList_Append/incorrect/input.c:54:1: note: due to object being referenced by: PyListObject.ob_item[0]
+tests/cpychecker/refcounts/PyList_Append/incorrect/input.c:54:1: note: but final ob_refcnt is N + 2
+tests/cpychecker/refcounts/PyList_Append/incorrect/input.c:36:10: note: PyLongObject allocated at: item = PyLong_FromLong(42);
+tests/cpychecker/refcounts/PyList_Append/incorrect/input.c:32:10: note: when PyList_New() succeeds at: list = PyList_New(0);
+tests/cpychecker/refcounts/PyList_Append/incorrect/input.c:33:8: note: when taking False path at: if (!list) {
+tests/cpychecker/refcounts/PyList_Append/incorrect/input.c:36:10: note: reaching: item = PyLong_FromLong(42);
+tests/cpychecker/refcounts/PyList_Append/incorrect/input.c:36:10: note: when PyLong_FromLong() succeeds at: item = PyLong_FromLong(42);
+tests/cpychecker/refcounts/PyList_Append/incorrect/input.c:36:10: note: ob_refcnt is now refs: 1 + N where N >= 0
+tests/cpychecker/refcounts/PyList_Append/incorrect/input.c:37:8: note: when taking False path at: if (!item) {
+tests/cpychecker/refcounts/PyList_Append/incorrect/input.c:42:28: note: reaching: if (-1 == PyList_Append(list, item)) {
+tests/cpychecker/refcounts/PyList_Append/incorrect/input.c:42:28: note: when PyList_Append() succeeds at: if (-1 == PyList_Append(list, item)) {
+tests/cpychecker/refcounts/PyList_Append/incorrect/input.c:42:28: note: ob_refcnt is now refs: 2 + N where N >= 0
+tests/cpychecker/refcounts/PyList_Append/incorrect/input.c:42:28: note: PyLongObject is now referenced by 1 non-stack value(s): PyListObject.ob_item[0]
+tests/cpychecker/refcounts/PyList_Append/incorrect/input.c:42:8: note: when taking False path at: if (-1 == PyList_Append(list, item)) {
+tests/cpychecker/refcounts/PyList_Append/incorrect/input.c:53:5: note: reaching: return list;
+tests/cpychecker/refcounts/PyList_Append/incorrect/input.c:54:1: note: when returning
+tests/cpychecker/refcounts/PyList_Append/incorrect/input.c:28:1: note: graphical error report for function 'test' written out to 'tests/cpychecker/refcounts/PyList_Append/incorrect/input.c.test-refcount-errors.html'
diff --git a/tests/cpychecker/refcounts/PyList_Append/incorrect/stdout.txt b/tests/cpychecker/refcounts/PyList_Append/incorrect/stdout.txt
new file mode 100644
index 0000000..55d66f3
--- /dev/null
+++ b/tests/cpychecker/refcounts/PyList_Append/incorrect/stdout.txt
@@ -0,0 +1,263 @@
+Trace 0:
+ Transitions:
+ 'PyList_New() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() succeeds'
+ 'taking False path'
+ 'PyList_Append() succeeds'
+ 'taking False path'
+ 'returning'
+ Return value:
+ repr(): PointerToRegion(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/incorrect/input.c', line=32), region=RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/incorrect/input.c', line=32)))
+ str(): (struct PyObject *)&RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/incorrect/input.c', line=32)) from tests/cpychecker/refcounts/PyList_Append/incorrect/input.c:32
+ r->ob_refcnt: refs: 1 + N where N >= 0
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/incorrect/input.c', line=32), region=RegionForGlobal(gcc.VarDecl('PyList_Type')))
+ Region("region-for-arg-gcc.ParmDecl('self')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('self')")
+ str(): Region("region-for-arg-gcc.ParmDecl('self')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/incorrect/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
+ Region("region-for-arg-gcc.ParmDecl('args')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('args')")
+ str(): Region("region-for-arg-gcc.ParmDecl('args')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/incorrect/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
+ PyLongObject allocated at tests/cpychecker/refcounts/PyList_Append/incorrect/input.c:36:
+ repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/incorrect/input.c', line=36))
+ str(): PyLongObject allocated at tests/cpychecker/refcounts/PyList_Append/incorrect/input.c:36
+ r->ob_refcnt: refs: 2 + N where N >= 0
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/incorrect/input.c', line=36), region=RegionForGlobal(gcc.VarDecl('PyLong_Type')))
+ Exception:
+ (struct PyObject *)0 from tests/cpychecker/refcounts/PyList_Append/incorrect/input.c:28
+
+Trace 1:
+ Transitions:
+ 'PyList_New() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() succeeds'
+ 'taking False path'
+ 'PyList_Append() fails'
+ 'taking True path'
+ 'taking True path'
+ 'taking True path'
+ 'returning'
+ Return value:
+ repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/incorrect/input.c', line=45), value=0)
+ str(): (struct PyObject *)0 from tests/cpychecker/refcounts/PyList_Append/incorrect/input.c:45
+ Region("region-for-arg-gcc.ParmDecl('self')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('self')")
+ str(): Region("region-for-arg-gcc.ParmDecl('self')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/incorrect/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
+ Region("region-for-arg-gcc.ParmDecl('args')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('args')")
+ str(): Region("region-for-arg-gcc.ParmDecl('args')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/incorrect/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
+ PyListObject allocated at tests/cpychecker/refcounts/PyList_Append/incorrect/input.c:32:
+ repr(): RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/incorrect/input.c', line=32))
+ str(): PyListObject allocated at tests/cpychecker/refcounts/PyList_Append/incorrect/input.c:32
+ r->ob_refcnt: refs: 0 + N where N >= 0
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/incorrect/input.c', line=32), region=RegionForGlobal(gcc.VarDecl('PyList_Type')))
+ PyLongObject allocated at tests/cpychecker/refcounts/PyList_Append/incorrect/input.c:36:
+ repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/incorrect/input.c', line=36))
+ str(): PyLongObject allocated at tests/cpychecker/refcounts/PyList_Append/incorrect/input.c:36
+ r->ob_refcnt: refs: 0 + N where N >= 0
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/incorrect/input.c', line=36), region=RegionForGlobal(gcc.VarDecl('PyLong_Type')))
+ Exception:
+ RegionForGlobal(gcc.VarDecl('PyExc_MemoryError'))
+
+Trace 2:
+ Transitions:
+ 'PyList_New() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() succeeds'
+ 'taking False path'
+ 'PyList_Append() fails'
+ 'taking True path'
+ 'taking True path'
+ 'taking False path'
+ 'calling tp_dealloc on PyLongObject allocated at tests/cpychecker/refcounts/PyList_Append/incorrect/input.c:36'
+ 'returning'
+ Return value:
+ repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/incorrect/input.c', line=45), value=0)
+ str(): (struct PyObject *)0 from tests/cpychecker/refcounts/PyList_Append/incorrect/input.c:45
+ Region("region-for-arg-gcc.ParmDecl('self')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('self')")
+ str(): Region("region-for-arg-gcc.ParmDecl('self')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/incorrect/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
+ Region("region-for-arg-gcc.ParmDecl('args')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('args')")
+ str(): Region("region-for-arg-gcc.ParmDecl('args')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/incorrect/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
+ PyListObject allocated at tests/cpychecker/refcounts/PyList_Append/incorrect/input.c:32:
+ repr(): RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/incorrect/input.c', line=32))
+ str(): PyListObject allocated at tests/cpychecker/refcounts/PyList_Append/incorrect/input.c:32
+ r->ob_refcnt: refs: 0 + N where N >= 0
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/incorrect/input.c', line=32), region=RegionForGlobal(gcc.VarDecl('PyList_Type')))
+ PyLongObject allocated at tests/cpychecker/refcounts/PyList_Append/incorrect/input.c:36:
+ repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/incorrect/input.c', line=36))
+ str(): PyLongObject allocated at tests/cpychecker/refcounts/PyList_Append/incorrect/input.c:36
+ r->ob_refcnt: None
+ r->ob_type: None
+ Exception:
+ RegionForGlobal(gcc.VarDecl('PyExc_MemoryError'))
+
+Trace 3:
+ Transitions:
+ 'PyList_New() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() succeeds'
+ 'taking False path'
+ 'PyList_Append() fails'
+ 'taking True path'
+ 'taking False path'
+ 'calling tp_dealloc on PyListObject allocated at tests/cpychecker/refcounts/PyList_Append/incorrect/input.c:32'
+ 'taking True path'
+ 'returning'
+ Return value:
+ repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/incorrect/input.c', line=45), value=0)
+ str(): (struct PyObject *)0 from tests/cpychecker/refcounts/PyList_Append/incorrect/input.c:45
+ Region("region-for-arg-gcc.ParmDecl('self')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('self')")
+ str(): Region("region-for-arg-gcc.ParmDecl('self')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/incorrect/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
+ Region("region-for-arg-gcc.ParmDecl('args')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('args')")
+ str(): Region("region-for-arg-gcc.ParmDecl('args')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/incorrect/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
+ PyListObject allocated at tests/cpychecker/refcounts/PyList_Append/incorrect/input.c:32:
+ repr(): RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/incorrect/input.c', line=32))
+ str(): PyListObject allocated at tests/cpychecker/refcounts/PyList_Append/incorrect/input.c:32
+ r->ob_refcnt: None
+ r->ob_type: None
+ PyLongObject allocated at tests/cpychecker/refcounts/PyList_Append/incorrect/input.c:36:
+ repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/incorrect/input.c', line=36))
+ str(): PyLongObject allocated at tests/cpychecker/refcounts/PyList_Append/incorrect/input.c:36
+ r->ob_refcnt: refs: 0 + N where N >= 0
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/incorrect/input.c', line=36), region=RegionForGlobal(gcc.VarDecl('PyLong_Type')))
+ Exception:
+ RegionForGlobal(gcc.VarDecl('PyExc_MemoryError'))
+
+Trace 4:
+ Transitions:
+ 'PyList_New() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() succeeds'
+ 'taking False path'
+ 'PyList_Append() fails'
+ 'taking True path'
+ 'taking False path'
+ 'calling tp_dealloc on PyListObject allocated at tests/cpychecker/refcounts/PyList_Append/incorrect/input.c:32'
+ 'taking False path'
+ 'calling tp_dealloc on PyLongObject allocated at tests/cpychecker/refcounts/PyList_Append/incorrect/input.c:36'
+ 'returning'
+ Return value:
+ repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/incorrect/input.c', line=45), value=0)
+ str(): (struct PyObject *)0 from tests/cpychecker/refcounts/PyList_Append/incorrect/input.c:45
+ Region("region-for-arg-gcc.ParmDecl('self')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('self')")
+ str(): Region("region-for-arg-gcc.ParmDecl('self')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/incorrect/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
+ Region("region-for-arg-gcc.ParmDecl('args')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('args')")
+ str(): Region("region-for-arg-gcc.ParmDecl('args')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/incorrect/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
+ PyListObject allocated at tests/cpychecker/refcounts/PyList_Append/incorrect/input.c:32:
+ repr(): RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/incorrect/input.c', line=32))
+ str(): PyListObject allocated at tests/cpychecker/refcounts/PyList_Append/incorrect/input.c:32
+ r->ob_refcnt: None
+ r->ob_type: None
+ PyLongObject allocated at tests/cpychecker/refcounts/PyList_Append/incorrect/input.c:36:
+ repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/incorrect/input.c', line=36))
+ str(): PyLongObject allocated at tests/cpychecker/refcounts/PyList_Append/incorrect/input.c:36
+ r->ob_refcnt: None
+ r->ob_type: None
+ Exception:
+ RegionForGlobal(gcc.VarDecl('PyExc_MemoryError'))
+
+Trace 5:
+ Transitions:
+ 'PyList_New() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() fails'
+ 'taking True path'
+ 'taking True path'
+ 'returning'
+ Return value:
+ repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/incorrect/input.c', line=39), value=0)
+ str(): (struct PyObject *)0 from tests/cpychecker/refcounts/PyList_Append/incorrect/input.c:39
+ Region("region-for-arg-gcc.ParmDecl('self')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('self')")
+ str(): Region("region-for-arg-gcc.ParmDecl('self')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/incorrect/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
+ Region("region-for-arg-gcc.ParmDecl('args')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('args')")
+ str(): Region("region-for-arg-gcc.ParmDecl('args')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/incorrect/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
+ PyListObject allocated at tests/cpychecker/refcounts/PyList_Append/incorrect/input.c:32:
+ repr(): RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/incorrect/input.c', line=32))
+ str(): PyListObject allocated at tests/cpychecker/refcounts/PyList_Append/incorrect/input.c:32
+ r->ob_refcnt: refs: 0 + N where N >= 0
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/incorrect/input.c', line=32), region=RegionForGlobal(gcc.VarDecl('PyList_Type')))
+ Exception:
+ RegionForGlobal(gcc.VarDecl('PyExc_MemoryError'))
+
+Trace 6:
+ Transitions:
+ 'PyList_New() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() fails'
+ 'taking True path'
+ 'taking False path'
+ 'calling tp_dealloc on PyListObject allocated at tests/cpychecker/refcounts/PyList_Append/incorrect/input.c:32'
+ 'returning'
+ Return value:
+ repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/incorrect/input.c', line=39), value=0)
+ str(): (struct PyObject *)0 from tests/cpychecker/refcounts/PyList_Append/incorrect/input.c:39
+ Region("region-for-arg-gcc.ParmDecl('self')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('self')")
+ str(): Region("region-for-arg-gcc.ParmDecl('self')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/incorrect/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
+ Region("region-for-arg-gcc.ParmDecl('args')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('args')")
+ str(): Region("region-for-arg-gcc.ParmDecl('args')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/incorrect/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
+ PyListObject allocated at tests/cpychecker/refcounts/PyList_Append/incorrect/input.c:32:
+ repr(): RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/incorrect/input.c', line=32))
+ str(): PyListObject allocated at tests/cpychecker/refcounts/PyList_Append/incorrect/input.c:32
+ r->ob_refcnt: None
+ r->ob_type: None
+ Exception:
+ RegionForGlobal(gcc.VarDecl('PyExc_MemoryError'))
+
+Trace 7:
+ Transitions:
+ 'PyList_New() fails'
+ 'taking True path'
+ 'returning'
+ Return value:
+ repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/incorrect/input.c', line=34), value=0)
+ str(): (struct PyObject *)0 from tests/cpychecker/refcounts/PyList_Append/incorrect/input.c:34
+ Region("region-for-arg-gcc.ParmDecl('self')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('self')")
+ str(): Region("region-for-arg-gcc.ParmDecl('self')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/incorrect/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
+ Region("region-for-arg-gcc.ParmDecl('args')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('args')")
+ str(): Region("region-for-arg-gcc.ParmDecl('args')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/PyList_Append/incorrect/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
+ Exception:
+ RegionForGlobal(gcc.VarDecl('PyExc_MemoryError'))
12 years, 9 months
[gcc-python-plugin] cpychecker: add hook for rendering detailed debug dump of all traces in HTML form
by David Hugh Malcolm
commit a6fb96c2307112cf84ee54f144955923b60d931a
Author: David Malcolm <dmalcolm(a)redhat.com>
Date: Sun Aug 28 17:49:58 2011 -0400
cpychecker: add hook for rendering detailed debug dump of all traces in HTML form
libcpychecker/diagnostics.py | 12 ++++++++-
libcpychecker/refcounts.py | 54 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 65 insertions(+), 1 deletions(-)
---
diff --git a/libcpychecker/diagnostics.py b/libcpychecker/diagnostics.py
index 8904036..18d8a1b 100644
--- a/libcpychecker/diagnostics.py
+++ b/libcpychecker/diagnostics.py
@@ -94,18 +94,28 @@ class Reporter:
"""
def __init__(self):
self.reports = []
+ self._got_errors = False
def make_error(self, fun, loc, msg):
assert isinstance(fun, gcc.Function)
assert isinstance(loc, gcc.Location)
gcc.error(loc, msg)
+ self._got_errors = True
+
err = Report(fun, loc, msg)
self.reports.append(err)
return err
+ def make_debug_dump(self, fun, loc, msg):
+ assert isinstance(fun, gcc.Function)
+ assert isinstance(loc, gcc.Location)
+ r = Report(fun, loc, msg)
+ self.reports.append(r)
+ return r
+
def got_errors(self):
- return self.reports != []
+ return self._got_errors
def to_html(self, fun):
# (FIXME: eliminate self.fun from HtmlRenderer and the above arg)
diff --git a/libcpychecker/refcounts.py b/libcpychecker/refcounts.py
index 8c17676..a7c7ee8 100644
--- a/libcpychecker/refcounts.py
+++ b/libcpychecker/refcounts.py
@@ -1005,6 +1005,44 @@ def dump_traces_to_stdout(traces):
if i + 1 < len(traces):
sys.stdout.write('\n')
+class DebugAnnotator(Annotator):
+ """
+ Annotate a trace with copious debug information
+ """
+ def get_notes(self, transition):
+ loc = transition.src.get_gcc_loc_or_none()
+ if loc is None:
+ # (we can't add a note without a valid location)
+ return []
+
+ result = []
+
+ # Add refcount information on all PyObject*
+ for k in transition.dest.region_for_var:
+ region = transition.dest.region_for_var[k]
+ check_isinstance(region, Region)
+ if 'ob_refcnt' not in region.fields:
+ continue
+ ra = RefcountAnnotator(region)
+ result += ra.get_notes(transition)
+
+ # Show all new/changing regions:
+ for region in transition.dest.value_for_region:
+ dest_value = transition.dest.value_for_region[region]
+ if region in transition.src.value_for_region:
+ src_value = transition.src.value_for_region[region]
+ if dest_value != src_value:
+ result.append(Note(loc,
+ ('%s now has value: %s'
+ % (region, dest_value))))
+ else:
+ result.append(Note(loc,
+ ('%s has initial value: %s'
+ % (region, dest_value))))
+
+ return result
+
+
class RefcountAnnotator(Annotator):
"""
Annotate a trace with information on the reference count of a particular
@@ -1091,6 +1129,22 @@ def check_refcounts(fun, dump_traces=False, show_traces=False):
traces = list(traces)
dump_traces_to_stdout(traces)
+ # Debug dump of all traces in HTML form:
+ if 0:
+ filename = ('%s.%s-refcount-traces.html'
+ % (gcc.get_dump_base_name(), fun.decl.name))
+ rep = Reporter()
+ for i, trace in enumerate(traces):
+ endstate = trace.states[-1]
+ r = rep.make_debug_dump(fun,
+ endstate.get_gcc_loc(fun),
+ 'Debug dump of trace %i' % i)
+ r.add_trace(trace, DebugAnnotator())
+ rep.dump_html(fun, filename)
+ gcc.inform(fun.start,
+ ('graphical debug report for function %r written out to %r'
+ % (fun.decl.name, filename)))
+
rep = Reporter()
for i, trace in enumerate(traces):
12 years, 9 months
[gcc-python-plugin] cpychecker: improve handling of conditionals; add testcase support functions
by David Hugh Malcolm
commit 6b12536d7b50713c6727d29f0abbdc2056de17b1
Author: David Malcolm <dmalcolm(a)redhat.com>
Date: Fri Aug 26 17:56:38 2011 -0400
cpychecker: improve handling of conditionals; add testcase support functions
Special-case handling for calls to certain functions to help with debugging
and selftests:
__cpychecker_log()
Log the given string constant within the trace
__cpychecker_dump()
Log the given r-value within the trace
__cpychecker_assert_equal()
Compare two r-values and raise an AssertionError if they are non-equal
Implement non-equality checking for ConcreteValue to help with the above
assertion checks
Refactor State.eval_condition() so that it's usable both for GimpleCond
statements and for eval_rhs (boolean expressions).
Extend it from supporting just == and != to add <, <=, >, >=
Add test cases for the conditional support (using the new __cpychecker
functions).
libcpychecker/absinterp.py | 5 +
libcpychecker/refcounts.py | 166 ++++++++++++++++++--
.../absinterp/comparisons/conditionals/input.c | 113 +++++++++++++
.../absinterp/comparisons/conditionals/script.py | 22 +++
.../absinterp/comparisons/conditionals/stdout.txt | 26 +++
.../absinterp/comparisons/expressions/input.c | 75 +++++++++
.../absinterp/comparisons/expressions/script.py | 22 +++
.../absinterp/comparisons/expressions/stdout.txt | 26 +++
8 files changed, 439 insertions(+), 16 deletions(-)
---
diff --git a/libcpychecker/absinterp.py b/libcpychecker/absinterp.py
index 9169394..d339bd8 100644
--- a/libcpychecker/absinterp.py
+++ b/libcpychecker/absinterp.py
@@ -86,6 +86,11 @@ class ConcreteValue(AbstractValue):
self.loc = loc
self.value = value
+ def __ne__(self, other):
+ if isinstance(other, ConcreteValue):
+ return self.value != other.value
+ return NotImplemented
+
def __str__(self):
if self.loc:
return '(%s)%r from %s' % (self.gcctype, self.value, self.loc)
diff --git a/libcpychecker/refcounts.py b/libcpychecker/refcounts.py
index 643ff88..8c17676 100644
--- a/libcpychecker/refcounts.py
+++ b/libcpychecker/refcounts.py
@@ -124,6 +124,9 @@ class RefcountValue(AbstractValue):
return RefcountValue(relvalue=0,
min_external=1)
+ def get_min_value(self):
+ return self.relvalue + self.min_external
+
def __str__(self):
return 'refs: %i + N where N >= %i' % (self.relvalue, self.min_external)
@@ -405,6 +408,61 @@ class MyState(State):
return [Transition(self, success, '%s() succeeds' % fnname),
Transition(self, failure, '%s() fails' % fnname)]
+ def eval_stmt_args(self, stmt):
+ assert isinstance(stmt, gcc.GimpleCall)
+ return [self.eval_rvalue(arg, stmt.loc)
+ for arg in stmt.args]
+
+ # Treat calls to various function prefixed with __cpychecker as special,
+ # to help with debugging, and when writing selftests:
+
+ def impl___cpychecker_log(self, stmt):
+ """
+ Assuming a C function with this declaration:
+ extern void __cpychecker_log(const char *);
+ and that it is called with a string constant, log the message
+ within the trace.
+ """
+ returntype = stmt.fn.type.dereference.type
+ args = self.eval_stmt_args(stmt)
+ desc = None
+ if isinstance(args[0], PointerToRegion):
+ if isinstance(args[0].region, RegionForStringConstant):
+ desc = args[0].region.text
+ return [self.make_assignment(stmt.lhs,
+ UnknownValue(returntype, stmt.loc),
+ desc)]
+
+ def impl___cpychecker_dump(self, stmt):
+ returntype = stmt.fn.type.dereference.type
+ # Give the transition a description that embeds the argument values
+ # This will show up in selftests (and in error reports that embed
+ # traces)
+ args = self.eval_stmt_args(stmt)
+ desc = '__dump(%s)' % (','.join([str(arg) for arg in args]))
+ return [self.make_assignment(stmt.lhs,
+ UnknownValue(returntype, stmt.loc),
+ desc)]
+
+ def impl___cpychecker_assert_equal(self, stmt):
+ """
+ Assuming a C function with this declaration:
+ extern void __cpychecker_assert_equal(T, T);
+ for some type T, raise an exception within the checker if the two
+ arguments are non-equal (for use in writing selftests).
+ """
+ returntype = stmt.fn.type.dereference.type
+ # Give the transition a description that embeds the argument values
+ # This will show up in selftests (and in error reports that embed
+ # traces)
+ args = self.eval_stmt_args(stmt)
+ if args[0] != args[1]:
+ raise AssertionError('%s != %s' % (args[0], args[1]))
+ desc = '__cpychecker_assert_equal(%s)' % (','.join([str(arg) for arg in args]))
+ return [self.make_assignment(stmt.lhs,
+ UnknownValue(returntype, stmt.loc),
+ desc)]
+
# Specific Python API function implementations:
def impl_PyList_New(self, stmt):
# Decl:
@@ -581,9 +639,7 @@ class MyState(State):
log('stmt.exprtype: %s', stmt.exprtype)
log('stmt.lhs: %r %s', stmt.lhs, stmt.lhs)
log('stmt.rhs: %r %s', stmt.rhs, stmt.rhs)
- log('dir(stmt.lhs): %s', dir(stmt.lhs))
- log('dir(stmt.rhs): %s', dir(stmt.rhs))
- boolval = self.eval_condition(stmt)
+ boolval = self.eval_condition(stmt, stmt.lhs, stmt.exprcode, stmt.rhs)
if boolval is True:
log('taking True edge')
nextstate = make_transition_for_true(stmt)
@@ -598,7 +654,20 @@ class MyState(State):
return [make_transition_for_true(stmt),
make_transition_for_false(stmt)]
- def eval_condition(self, stmt):
+ def eval_condition(self, stmt, expr_lhs, exprcode, expr_rhs):
+ """
+ Evaluate a comparison, returning one of True, False, or None
+ """
+ log('eval_condition: %s %s %s ', expr_lhs, exprcode, expr_rhs)
+ check_isinstance(expr_lhs, gcc.Tree)
+ check_isinstance(exprcode, type) # it's a type, rather than an instance
+ check_isinstance(expr_rhs, gcc.Tree)
+
+ lhs = self.eval_rvalue(expr_lhs, stmt.loc)
+ rhs = self.eval_rvalue(expr_rhs, stmt.loc)
+ check_isinstance(lhs, AbstractValue)
+ check_isinstance(rhs, AbstractValue)
+
def is_equal(lhs, rhs):
check_isinstance(lhs, AbstractValue)
check_isinstance(rhs, AbstractValue)
@@ -622,32 +691,84 @@ class MyState(State):
# We don't know:
return None
- log('eval_condition: %s', stmt)
- lhs = self.eval_rvalue(stmt.lhs, stmt.loc)
- rhs = self.eval_rvalue(stmt.rhs, stmt.loc)
- log('eval of lhs: %r', lhs)
- log('eval of rhs: %r', rhs)
- log('stmt.exprcode: %r', stmt.exprcode)
- if stmt.exprcode == gcc.EqExpr:
+ def is_lt(lhs, rhs):
+ # "less-than"
+ check_isinstance(lhs, AbstractValue)
+ check_isinstance(rhs, AbstractValue)
+ if isinstance(rhs, ConcreteValue):
+ if isinstance(lhs, ConcreteValue):
+ log('comparing concrete values: %s %s', lhs, rhs)
+ return lhs.value < rhs.value
+ if isinstance(lhs, RefcountValue):
+ log('comparing refcount value %s with concrete value: %s', lhs, rhs)
+ if lhs.get_min_value() >= rhs.value:
+ return False
+ # We don't know:
+ return None
+
+ def is_le(lhs, rhs):
+ # "less-than-or-equal"
+ # Implement using is_equal and is_lt:
+ # First try "less-than":
+ lt_result = is_lt(lhs, rhs)
+ if lt_result is not None:
+ if lt_result:
+ return True
+ # Either not less than, or we don't know
+ # Try equality:
+ eq_result = is_equal(lhs, rhs)
+ if eq_result is not None:
+ if eq_result:
+ # Definitely equal:
+ return eq_result
+ else:
+ # Definitely not equal
+ # If we have a definite result for less-than, use it:
+ if lt_result is not None:
+ return lt_result
+ # We don't know:
+ return None
+
+ if exprcode == gcc.EqExpr:
result = is_equal(lhs, rhs)
if result is not None:
return result
- elif stmt.exprcode == gcc.NeExpr:
+ elif exprcode == gcc.NeExpr:
result = is_equal(lhs, rhs)
if result is not None:
return not result
+ elif exprcode == gcc.LtExpr:
+ result = is_lt(lhs, rhs)
+ if result is not None:
+ return result
+ elif exprcode == gcc.LeExpr:
+ result = is_le(lhs, rhs)
+ if result is not None:
+ return result
+ elif exprcode == gcc.GeExpr:
+ # Implement "A >= B" as "not(A < B)":
+ result = is_lt(lhs, rhs)
+ if result is not None:
+ return not result
+ elif exprcode == gcc.GtExpr:
+ # Implement "A > B " as "not(A <= B)":
+ result = is_le(lhs, rhs)
+ if result is not None:
+ return not result
# Specialcasing: comparison of unknown ptr with NULL:
- if (isinstance(stmt.lhs, gcc.VarDecl)
- and isinstance(stmt.rhs, gcc.IntegerCst)
- and isinstance(stmt.lhs.type, gcc.PointerType)):
+ if (isinstance(expr_lhs, gcc.VarDecl)
+ and isinstance(expr_rhs, gcc.IntegerCst)
+ and isinstance(expr_lhs.type, gcc.PointerType)):
# Split the ptr variable immediately into NULL and non-NULL
# versions, so that we can evaluate the true and false branch with
# explicitly data
- log('splitting %s into non-NULL/NULL pointers', stmt.lhs)
+ log('splitting %s into non-NULL/NULL pointers', expr_lhs)
self.raise_split_value(lhs, stmt.loc)
log('unable to compare %r with %r', lhs, rhs)
+ #raise NotImplementedError("Don't know how to do %s comparison of %s with %s"
+ # % (exprcode, lhs, rhs))
return UnknownValue(stmt.lhs.type, stmt.loc)
def eval_rhs(self, stmt):
@@ -658,6 +779,8 @@ class MyState(State):
b = self.eval_rvalue(rhs[1], stmt.loc)
log('a: %r', a)
log('b: %r', b)
+ if isinstance(a, UnknownValue) or isinstance(b, UnknownValue):
+ return UnknownValue(stmt.lhs.type, stmt.loc)
if isinstance(a, ConcreteValue) and isinstance(b, ConcreteValue):
return ConcreteValue(stmt.lhs.type, stmt.loc, a.value + b.value)
if isinstance(a, RefcountValue) and isinstance(b, ConcreteValue):
@@ -672,6 +795,8 @@ class MyState(State):
b = self.eval_rvalue(rhs[1], stmt.loc)
log('a: %r', a)
log('b: %r', b)
+ if isinstance(a, UnknownValue) or isinstance(b, UnknownValue):
+ return UnknownValue(stmt.lhs.type, stmt.loc)
if isinstance(a, RefcountValue) and isinstance(b, ConcreteValue):
return RefcountValue(a.relvalue - b.value, a.min_external)
raise NotImplementedError("Don't know how to cope with subtraction of\n %r\nand\n %rat %s"
@@ -695,6 +820,15 @@ class MyState(State):
elif stmt.exprcode == gcc.PointerPlusExpr:
region = self.pointer_plus_region(stmt)
return PointerToRegion(stmt.lhs.type, stmt.loc, region)
+ elif stmt.exprcode in (gcc.EqExpr, gcc.NeExpr, gcc.LtExpr,
+ gcc.LeExpr, gcc.GeExpr, gcc.GtExpr):
+ # Comparisons
+ result = self.eval_condition(stmt, rhs[0], stmt.exprcode, rhs[1])
+ if result is not None:
+ return ConcreteValue(stmt.lhs.type, stmt.loc,
+ 1 if result else 0)
+ else:
+ return UnknownValue(stmt.lhs.type, stmt.loc)
else:
raise NotImplementedError("Don't know how to cope with exprcode: %r (%s) at %s"
% (stmt.exprcode, stmt.exprcode, stmt.loc))
diff --git a/tests/cpychecker/absinterp/comparisons/conditionals/input.c b/tests/cpychecker/absinterp/comparisons/conditionals/input.c
new file mode 100644
index 0000000..1b01d96
--- /dev/null
+++ b/tests/cpychecker/absinterp/comparisons/conditionals/input.c
@@ -0,0 +1,113 @@
+/*
+ Copyright 2011 David Malcolm <dmalcolm(a)redhat.com>
+ Copyright 2011 Red Hat, Inc.
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see
+ <http://www.gnu.org/licenses/>.
+*/
+
+#include <Python.h>
+
+/*
+ Test that we can cope with various kinds of comparisons
+*/
+
+extern void __cpychecker_log(const char *);
+
+int test_conditionals(void)
+{
+ /*
+ Force the absinterp code to run various comparisons
+
+ All of these comparisons should be fully deterministic, and thus
+ there should be just a single trace through the function, with
+ a particular pattern of "true" and "false" branches taken
+ */
+ int one;
+ int other_one;
+ int two;
+
+ one = 1;
+ /* we need a second copy to stop GCC optimizing away some comparisons: */
+ other_one = 1;
+ two = 2;
+
+ __cpychecker_log("Comparing 1 with 1");
+ if (one < other_one) {
+ should_not_be_reached();
+ }
+ if (one <= other_one) {
+ should_be_reached();
+ }
+ if (one == other_one) {
+ should_be_reached();
+ }
+ if (one != other_one) {
+ should_not_be_reached();
+ }
+ if (one >= other_one) {
+ should_be_reached();
+ }
+ if (one > other_one) {
+ should_not_be_reached();
+ }
+
+ __cpychecker_log("Comparing 1 with 2");
+ if (one < two) {
+ should_be_reached();
+ }
+ if (one <= two) {
+ should_be_reached();
+ }
+ if (one == two) {
+ should_not_be_reached();
+ }
+ if (one != two) {
+ should_be_reached();
+ }
+ if (one >= two) {
+ should_be_reached();
+ }
+ if (one > two) {
+ should_not_be_reached();
+ }
+
+ __cpychecker_log("Comparing 2 with 1");
+ if (two < one) {
+ should_not_be_reached();
+ }
+ if (two <= one) {
+ should_not_be_reached();
+ }
+ if (two == one) {
+ should_not_be_reached();
+ }
+ if (two != one) {
+ should_be_reached();
+ }
+ if (two >= one) {
+ should_be_reached();
+ }
+ if (two > one) {
+ should_be_reached();
+ }
+}
+
+/*
+ PEP-7
+Local variables:
+c-basic-offset: 4
+indent-tabs-mode: nil
+End:
+*/
diff --git a/tests/cpychecker/absinterp/comparisons/conditionals/script.py b/tests/cpychecker/absinterp/comparisons/conditionals/script.py
new file mode 100644
index 0000000..6bb62fd
--- /dev/null
+++ b/tests/cpychecker/absinterp/comparisons/conditionals/script.py
@@ -0,0 +1,22 @@
+# -*- coding: utf-8 -*-
+# Copyright 2011 David Malcolm <dmalcolm(a)redhat.com>
+# Copyright 2011 Red Hat, Inc.
+#
+# This is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program 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
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see
+# <http://www.gnu.org/licenses/>.
+
+from libcpychecker import main
+
+main(verify_refcounting=True,
+ dump_traces=True)
diff --git a/tests/cpychecker/absinterp/comparisons/conditionals/stdout.txt b/tests/cpychecker/absinterp/comparisons/conditionals/stdout.txt
new file mode 100644
index 0000000..a305545
--- /dev/null
+++ b/tests/cpychecker/absinterp/comparisons/conditionals/stdout.txt
@@ -0,0 +1,26 @@
+Trace 0:
+ Transitions:
+ 'Comparing 1 with 1'
+ 'taking False path'
+ 'taking True path'
+ 'taking True path'
+ 'taking False path'
+ 'taking True path'
+ 'taking False path'
+ 'Comparing 1 with 2'
+ 'taking True path'
+ 'taking True path'
+ 'taking False path'
+ 'taking True path'
+ 'taking False path'
+ 'taking False path'
+ 'Comparing 2 with 1'
+ 'taking False path'
+ 'taking False path'
+ 'taking False path'
+ 'taking True path'
+ 'taking True path'
+ 'taking True path'
+ 'returning'
+ Exception:
+ (struct PyObject *)0 from tests/cpychecker/absinterp/comparisons/conditionals/input.c:29
diff --git a/tests/cpychecker/absinterp/comparisons/expressions/input.c b/tests/cpychecker/absinterp/comparisons/expressions/input.c
new file mode 100644
index 0000000..a893fbb
--- /dev/null
+++ b/tests/cpychecker/absinterp/comparisons/expressions/input.c
@@ -0,0 +1,75 @@
+/*
+ Copyright 2011 David Malcolm <dmalcolm(a)redhat.com>
+ Copyright 2011 Red Hat, Inc.
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see
+ <http://www.gnu.org/licenses/>.
+*/
+
+#include <Python.h>
+
+/*
+ Test that we can cope with various kinds of comparisons
+*/
+
+extern void __cpychecker_log(const char *);
+extern void __cpychecker_assert_equal(int, int);
+
+int test_comparison_expressions(void)
+{
+ /*
+ Force the absinterp code to evaluate various boolean expressions,
+ checking the results
+ */
+ int one;
+ int other_one;
+ int two;
+
+ one = 1;
+ /* we need a second copy to stop GCC optimizing away some comparisons: */
+ other_one = 1;
+ two = 2;
+
+ __cpychecker_log("Comparing 1 with 1");
+ __cpychecker_assert_equal(one < other_one, 0);
+ __cpychecker_assert_equal(one <= other_one, 1);
+ __cpychecker_assert_equal(one == other_one, 1);
+ __cpychecker_assert_equal(one != other_one, 0);
+ __cpychecker_assert_equal(one >= other_one, 1);
+ __cpychecker_assert_equal(one > other_one, 0);
+
+ __cpychecker_log("Comparing 1 with 2");
+ __cpychecker_assert_equal(one < two, 1);
+ __cpychecker_assert_equal(one <= two, 1);
+ __cpychecker_assert_equal(one == two, 0);
+ __cpychecker_assert_equal(one != two, 1);
+ __cpychecker_assert_equal(one >= two, 0);
+ __cpychecker_assert_equal(one > two, 0);
+
+ __cpychecker_log("Comparing 2 with 1");
+ __cpychecker_assert_equal(two < one, 0);
+ __cpychecker_assert_equal(two <= one, 0);
+ __cpychecker_assert_equal(two == one, 0);
+ __cpychecker_assert_equal(two != one, 1);
+ __cpychecker_assert_equal(two >= one, 1);
+ __cpychecker_assert_equal(two > one, 1);
+}
+
+/*
+ PEP-7
+Local variables:
+c-basic-offset: 4
+indent-tabs-mode: nil
+End:
+*/
diff --git a/tests/cpychecker/absinterp/comparisons/expressions/script.py b/tests/cpychecker/absinterp/comparisons/expressions/script.py
new file mode 100644
index 0000000..6bb62fd
--- /dev/null
+++ b/tests/cpychecker/absinterp/comparisons/expressions/script.py
@@ -0,0 +1,22 @@
+# -*- coding: utf-8 -*-
+# Copyright 2011 David Malcolm <dmalcolm(a)redhat.com>
+# Copyright 2011 Red Hat, Inc.
+#
+# This is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program 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
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see
+# <http://www.gnu.org/licenses/>.
+
+from libcpychecker import main
+
+main(verify_refcounting=True,
+ dump_traces=True)
diff --git a/tests/cpychecker/absinterp/comparisons/expressions/stdout.txt b/tests/cpychecker/absinterp/comparisons/expressions/stdout.txt
new file mode 100644
index 0000000..371982b
--- /dev/null
+++ b/tests/cpychecker/absinterp/comparisons/expressions/stdout.txt
@@ -0,0 +1,26 @@
+Trace 0:
+ Transitions:
+ 'Comparing 1 with 1'
+ '__cpychecker_assert_equal((int)0 from tests/cpychecker/absinterp/comparisons/expressions/input.c:45,(int)0 from tests/cpychecker/absinterp/comparisons/expressions/input.c:45)'
+ '__cpychecker_assert_equal((int)1 from tests/cpychecker/absinterp/comparisons/expressions/input.c:46,(int)1 from tests/cpychecker/absinterp/comparisons/expressions/input.c:46)'
+ '__cpychecker_assert_equal((int)1 from tests/cpychecker/absinterp/comparisons/expressions/input.c:47,(int)1 from tests/cpychecker/absinterp/comparisons/expressions/input.c:47)'
+ '__cpychecker_assert_equal((int)0 from tests/cpychecker/absinterp/comparisons/expressions/input.c:48,(int)0 from tests/cpychecker/absinterp/comparisons/expressions/input.c:48)'
+ '__cpychecker_assert_equal((int)1 from tests/cpychecker/absinterp/comparisons/expressions/input.c:49,(int)1 from tests/cpychecker/absinterp/comparisons/expressions/input.c:49)'
+ '__cpychecker_assert_equal((int)0 from tests/cpychecker/absinterp/comparisons/expressions/input.c:50,(int)0 from tests/cpychecker/absinterp/comparisons/expressions/input.c:50)'
+ 'Comparing 1 with 2'
+ '__cpychecker_assert_equal((int)1 from tests/cpychecker/absinterp/comparisons/expressions/input.c:53,(int)1 from tests/cpychecker/absinterp/comparisons/expressions/input.c:53)'
+ '__cpychecker_assert_equal((int)1 from tests/cpychecker/absinterp/comparisons/expressions/input.c:54,(int)1 from tests/cpychecker/absinterp/comparisons/expressions/input.c:54)'
+ '__cpychecker_assert_equal((int)0 from tests/cpychecker/absinterp/comparisons/expressions/input.c:55,(int)0 from tests/cpychecker/absinterp/comparisons/expressions/input.c:55)'
+ '__cpychecker_assert_equal((int)1 from tests/cpychecker/absinterp/comparisons/expressions/input.c:56,(int)1 from tests/cpychecker/absinterp/comparisons/expressions/input.c:56)'
+ '__cpychecker_assert_equal((int)0 from tests/cpychecker/absinterp/comparisons/expressions/input.c:57,(int)0 from tests/cpychecker/absinterp/comparisons/expressions/input.c:57)'
+ '__cpychecker_assert_equal((int)0 from tests/cpychecker/absinterp/comparisons/expressions/input.c:58,(int)0 from tests/cpychecker/absinterp/comparisons/expressions/input.c:58)'
+ 'Comparing 2 with 1'
+ '__cpychecker_assert_equal((int)0 from tests/cpychecker/absinterp/comparisons/expressions/input.c:61,(int)0 from tests/cpychecker/absinterp/comparisons/expressions/input.c:61)'
+ '__cpychecker_assert_equal((int)0 from tests/cpychecker/absinterp/comparisons/expressions/input.c:62,(int)0 from tests/cpychecker/absinterp/comparisons/expressions/input.c:62)'
+ '__cpychecker_assert_equal((int)0 from tests/cpychecker/absinterp/comparisons/expressions/input.c:63,(int)0 from tests/cpychecker/absinterp/comparisons/expressions/input.c:63)'
+ '__cpychecker_assert_equal((int)1 from tests/cpychecker/absinterp/comparisons/expressions/input.c:64,(int)1 from tests/cpychecker/absinterp/comparisons/expressions/input.c:64)'
+ '__cpychecker_assert_equal((int)1 from tests/cpychecker/absinterp/comparisons/expressions/input.c:65,(int)1 from tests/cpychecker/absinterp/comparisons/expressions/input.c:65)'
+ '__cpychecker_assert_equal((int)1 from tests/cpychecker/absinterp/comparisons/expressions/input.c:66,(int)1 from tests/cpychecker/absinterp/comparisons/expressions/input.c:66)'
+ 'returning'
+ Exception:
+ (struct PyObject *)0 from tests/cpychecker/absinterp/comparisons/expressions/input.c:30
12 years, 9 months
[gcc-python-plugin] cpychecker: in log() calls, only expand the message arguments when logging is enabled
by David Hugh Malcolm
commit 15858320e4f08153768e973a519dcf9e44013b24
Author: David Malcolm <dmalcolm(a)redhat.com>
Date: Fri Aug 26 13:36:06 2011 -0400
cpychecker: in log() calls, only expand the message arguments when logging is enabled
The most complex selftest:
tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple
was taking ~15 seconds/1-2GB to run.
On moving string expansion to within logging, it's now near instantaneous (and
with no visible memory hump).
The expense appears to have been largely due to State.log()'s generation
of tabular representations of its internal state. This is now guarded by
a "logging_enabled" check.
libcpychecker/PyArg_ParseTuple.py | 24 +++---
libcpychecker/__init__.py | 12 ++--
libcpychecker/absinterp.py | 147 ++++++++++++++++++-------------------
libcpychecker/diagnostics.py | 2 +-
libcpychecker/refcounts.py | 140 ++++++++++++++++++------------------
libcpychecker/utils.py | 25 ++++--
6 files changed, 179 insertions(+), 171 deletions(-)
---
diff --git a/libcpychecker/PyArg_ParseTuple.py b/libcpychecker/PyArg_ParseTuple.py
index 853f7ee..6c7817e 100644
--- a/libcpychecker/PyArg_ParseTuple.py
+++ b/libcpychecker/PyArg_ParseTuple.py
@@ -311,7 +311,7 @@ class ConverterCallbackType(AwkwardType):
return False
# Write back to the ConverterResultType with the second arg:
- log('2nd argument of converter should be of type %s' % signature.argument_types[1])
+ log('2nd argument of converter should be of type %s', signature.argument_types[1])
self.conv.result.type = signature.argument_types[1]
self.actual_type = actual_type
@@ -589,9 +589,9 @@ class MismatchingType(ParsedFormatStringError):
% (self.funcname, self.fmt.fmt_string))
def compatible_type(exp_type, actual_type, actualarg=None):
- log('comparing exp_type: %s (%r) with actual_type: %s (%r)' % (exp_type, exp_type, actual_type, actual_type))
- log('type(exp_type): %r %s' % (type(exp_type), type(exp_type)))
- log('actualarg: %s (%r)' % (actualarg, actualarg))
+ log('comparing exp_type: %s (%r) with actual_type: %s (%r)', exp_type, exp_type, actual_type, actual_type)
+ log('type(exp_type): %r %s', type(exp_type), type(exp_type))
+ log('actualarg: %s (%r)', actualarg, actualarg)
# Support exp_type being actually a tuple of expected types (we need this
# for "S" and "U"):
@@ -705,12 +705,12 @@ def check_pyargs(fun):
i = i + 1
def check_callsite(stmt, funcname, format_idx, varargs_idx, with_size_t):
- log('got call at %s' % stmt.loc)
+ log('got call at %s', stmt.loc)
log(get_src_for_loc(stmt.loc))
- # log('stmt: %r %s' % (stmt, stmt))
- # log('args: %r' % stmt.args)
+ # log('stmt: %r %s', (stmt, stmt))
+ # log('args: %r', stmt.args)
# for arg in stmt.args:
- # # log(' arg: %s %r' % (arg, arg))
+ # # log(' arg: %s %r', (arg, arg))
# We expect the following args:
@@ -721,7 +721,7 @@ def check_pyargs(fun):
if len(stmt.args) > 1:
fmt_string = get_format_string(stmt, format_idx)
if fmt_string:
- log('fmt_string: %r' % fmt_string)
+ log('fmt_string: %r', fmt_string)
loc = stmt.loc
@@ -732,14 +732,14 @@ def check_pyargs(fun):
exc = sys.exc_info()[1]
gcc.permerror(stmt.loc, str(exc))
return
- log('fmt: %r' % fmt.args)
+ log('fmt: %r', fmt.args)
exp_types = list(fmt.iter_exp_types())
- log('exp_types: %r' % exp_types)
+ log('exp_types: %r', exp_types)
# ...then compare them against the actual types:
varargs = stmt.args[varargs_idx:]
- # log('varargs: %r' % varargs)
+ # log('varargs: %r', varargs)
if len(varargs) < len(exp_types):
gcc.permerror(loc, str(NotEnoughVars(funcname, fmt, varargs)))
return
diff --git a/libcpychecker/__init__.py b/libcpychecker/__init__.py
index 91b9753..65afa31 100644
--- a/libcpychecker/__init__.py
+++ b/libcpychecker/__init__.py
@@ -35,7 +35,7 @@ class CpyChecker(gcc.GimplePass):
def execute(self, fun):
if fun:
- log(fun)
+ log('%s', fun)
check_pyargs(fun)
# The refcount code is too buggy for now to be on by default:
@@ -44,7 +44,7 @@ class CpyChecker(gcc.GimplePass):
def is_a_method_callback(decl):
methods = get_all_PyMethodDef_methods()
- log('methods: %s' % methods)
+ log('methods: %s', methods)
# FIXME
@@ -59,10 +59,10 @@ def get_all_PyMethodDef_methods():
if isinstance(idx2, gcc.Declaration):
if idx2.name == 'ml_meth':
if isinstance(value2, gcc.AddrExpr):
- log(' GOT A PyMethodDef.ml_meth initializer declaration: %s' % value2)
- log(' value2.operand: %r' % value2.operand) # gcc.Declaration
- log(' value2.operand: %s' % value2.operand)
- log(' value2.operand.function: %s' % value2.operand.function)
+ log(' GOT A PyMethodDef.ml_meth initializer declaration: %s', value2)
+ log(' value2.operand: %r', value2.operand) # gcc.Declaration
+ log(' value2.operand: %s', value2.operand)
+ log(' value2.operand.function: %s', value2.operand.function)
return (value2.operand, value2.location)
result = []
vars = gcc.get_variables()
diff --git a/libcpychecker/absinterp.py b/libcpychecker/absinterp.py
index 498551e..9169394 100644
--- a/libcpychecker/absinterp.py
+++ b/libcpychecker/absinterp.py
@@ -21,7 +21,7 @@ import sys
from six import StringIO
from gccutils import get_src_for_loc, get_nonnull_arguments, check_isinstance
from collections import OrderedDict
-from libcpychecker.utils import log
+from libcpychecker.utils import log, logging_enabled
from libcpychecker.types import *
class AbstractValue:
@@ -330,10 +330,10 @@ class SplitValue(Exception):
'\n'.join([repr(alt) for alt in self.altvalues])))
def split(self, state):
- log('creating states for split of %s into %s' % (self.value, self.altvalues))
+ log('creating states for split of %s into %s', self.value, self.altvalues)
result = []
for altvalue in self.altvalues:
- log(' creating state for split where %s is %s' % (self.value, altvalue))
+ log(' creating state for split where %s is %s', self.value, altvalue)
altvalue.fromsplit = True
newstate = state.copy()
@@ -341,7 +341,7 @@ class SplitValue(Exception):
for r in newstate.value_for_region:
# Replace instances of the value itself:
if newstate.value_for_region[r] is self.value:
- log(' replacing value for region %s with %s' % (r, altvalue))
+ log(' replacing value for region %s with %s', r, altvalue)
newstate.value_for_region[r] = altvalue
result.append(Transition(state,
newstate,
@@ -387,9 +387,9 @@ class State:
self.value_for_region,
self._extra()))
- def log(self, logger, indent):
- #logger(str(self.region_for_var), indent + 1)
- #logger(str(self.value_for_region), indent + 1)
+ def log(self, logger):
+ if not logging_enabled:
+ return
# Display data in tabular form:
from gccutils import Table
t = Table(['Expression', 'Region', 'Value'])
@@ -399,17 +399,16 @@ class State:
t.add_row((k, region, value),)
s = StringIO()
t.write(s)
- for line in s.getvalue().splitlines():
- logger(line, indent + 1)
+ logger('%s', s.getvalue())
#logger('extra: %s' % (self._extra(), ), indent)
# FIXME: derived class/extra:
#self.resources.log(logger, indent)
- logger('loc: %s' % self.loc, indent)
+ logger('loc: %s', self.loc)
if self.loc.get_stmt():
- logger('%s' % self.loc.get_stmt().loc, indent + 1)
+ logger('%s', self.loc.get_stmt().loc)
def copy(self):
c = self.__class__(loc,
@@ -436,7 +435,7 @@ class State:
"""
Return the Region for the given expression
"""
- log('eval_lvalue: %r %s' % (expr, expr))
+ log('eval_lvalue: %r %s', expr, expr)
if loc:
check_isinstance(loc, gcc.Location)
if isinstance(expr, (gcc.VarDecl, gcc.ParmDecl)):
@@ -457,10 +456,10 @@ class State:
elif isinstance(expr, gcc.MemRef):
# Write through a pointer:
dest_ptr = self.eval_rvalue(expr.operand, loc)
- log('dest_ptr: %r' % dest_ptr)
+ log('dest_ptr: %r', dest_ptr)
check_isinstance(dest_ptr, PointerToRegion)
dest_region = dest_ptr.region
- log('dest_region: %r' % dest_region)
+ log('dest_region: %r', dest_region)
return dest_region
raise NotImplementedError('eval_lvalue: %r %s' % (expr, expr))
@@ -469,7 +468,7 @@ class State:
Return the value for the given expression, as an AbstractValue
FIXME: also as a Region?
"""
- log('eval_rvalue: %r %s' % (expr, expr))
+ log('eval_rvalue: %r %s', expr, expr)
if loc:
check_isinstance(loc, gcc.Location)
@@ -490,33 +489,33 @@ class State:
#check_isinstance(expr.field, gcc.FieldDecl)
region = self.get_field_region(expr, loc)#.target, expr.field.name)
check_isinstance(region, Region)
- log('got field region for %s: %r' % (expr, region))
+ log('got field region for %s: %r', expr, region)
try:
value = self.get_store(region, expr.type, loc)
- log('got value: %r' % value)
+ log('got value: %r', value)
except MissingValue:
value = UnknownValue(expr.type, loc)
- log('no value; using: %r' % value)
+ log('no value; using: %r', value)
check_isinstance(value, AbstractValue)
return value
if isinstance(expr, gcc.AddrExpr):
- log('expr.operand: %r' % expr.operand)
+ log('expr.operand: %r', expr.operand)
lvalue = self.eval_lvalue(expr.operand, loc)
check_isinstance(lvalue, Region)
return PointerToRegion(expr.type, loc, lvalue)
if isinstance(expr, gcc.ArrayRef):
- log('expr.array: %r' % expr.array)
- log('expr.index: %r' % expr.index)
+ log('expr.array: %r', expr.array)
+ log('expr.index: %r', expr.index)
lvalue = self.eval_lvalue(expr, loc)
check_isinstance(lvalue, Region)
rvalue = self.get_store(lvalue, expr.type, loc)
check_isinstance(rvalue, AbstractValue)
return rvalue
if isinstance(expr, gcc.MemRef):
- log('expr.operand: %r' % expr.operand)
+ log('expr.operand: %r', expr.operand)
opvalue = self.eval_rvalue(expr.operand, loc)
check_isinstance(opvalue, AbstractValue)
- log('opvalue: %r' % opvalue)
+ log('opvalue: %r', opvalue)
self.raise_any_null_ptr_deref(expr, opvalue)
if isinstance(opvalue, UnknownValue):
# Split into null/non-null pointers:
@@ -529,14 +528,14 @@ class State:
return UnknownValue(expr.type, loc) # FIXME
def assign(self, lhs, rhs, loc):
- log('assign(%r, %r)' % (lhs, rhs))
- log('assign(%s, %s)' % (lhs, rhs))
+ log('assign(%r, %r)', lhs, rhs)
+ log('assign(%s, %s)', lhs, rhs)
if loc:
check_isinstance(loc, gcc.Location)
dest_region = self.eval_lvalue(lhs, loc)
- log('dest_region: %s %r' % (dest_region, dest_region))
+ log('dest_region: %s %r', dest_region, dest_region)
value = self.eval_rvalue(rhs, loc)
- log('value: %s %r' % (value, value))
+ log('value: %s %r', value, value)
check_isinstance(value, AbstractValue)
check_isinstance(dest_region, Region)
self.value_for_region[dest_region] = value
@@ -545,7 +544,7 @@ class State:
check_isinstance(var, (gcc.VarDecl, gcc.ParmDecl))
if var not in self.region_for_var:
# Presumably a reference to a global variable:
- log('adding region for global var: %r' % var)
+ log('adding region for global var: %r', var)
region = RegionForGlobal(var)
# it is its own region:
self.region_for_var[var] = region
@@ -559,19 +558,19 @@ class State:
return self.region_for_var[var]
def element_region(self, ar, loc):
- log('element_region: %s' % ar)
+ log('element_region: %s', ar)
check_isinstance(ar, gcc.ArrayRef)
if loc:
check_isinstance(loc, gcc.Location)
- log(' ar.array: %r' % ar.array)
- log(' ar.index: %r' % ar.index)
+ log(' ar.array: %r', ar.array)
+ log(' ar.index: %r', ar.index)
parent = self.eval_lvalue(ar.array, loc)
check_isinstance(parent, Region)
- log(' parent: %r' % parent)
+ log(' parent: %r', parent)
index = self.eval_rvalue(ar.index, loc)
check_isinstance(index, AbstractValue)
- log(' index: %r' % index)
+ log(' index: %r', index)
if isinstance(index, ConcreteValue):
index = index.value
return self._array_region(parent, index)
@@ -584,14 +583,14 @@ class State:
rhs = stmt.rhs
a = self.eval_rvalue(rhs[0], stmt.loc)
b = self.eval_rvalue(rhs[1], stmt.loc)
- log('a: %r' % a)
- log('b: %r' % b)
+ log('a: %r', a)
+ log('b: %r', b)
if isinstance(a, PointerToRegion) and isinstance(b, ConcreteValue):
parent = a.region
- log(rhs[0].type)
- log(rhs[0].type.dereference)
+ log('%s', rhs[0].type)
+ log('%s', rhs[0].type.dereference)
sizeof = rhs[0].type.dereference.sizeof
- log(sizeof)
+ log('%s', sizeof)
index = b.value / sizeof
return self._array_region(parent, index)
else:
@@ -617,39 +616,39 @@ class State:
if loc:
check_isinstance(loc, gcc.Location)
#cr.debug()
- log('target: %r %s ' % (cr.target, cr.target))
- log('field: %r' % cr.field)
+ log('target: %r %s ', cr.target, cr.target)
+ log('field: %r', cr.field)
#fr = FIXME #self.make_field_region(target, field)
if 1: # fr not in self.region_for_var:
if 1: # cr.target not in self.region_for_var:
log('foo')
if isinstance(cr.target, gcc.MemRef):
ptr = self.eval_rvalue(cr.target.operand, loc) # FIXME
- log('ptr: %r' % ptr)
+ log('ptr: %r', ptr)
self.raise_any_null_ptr_deref(cr, ptr)
if isinstance(ptr, UnknownValue):
# It could be NULL; it could be non-NULL
# Split the analysis
# Non-NULL pointer:
- log('splitting %s into non-NULL/NULL pointers' % cr)
+ log('splitting %s into non-NULL/NULL pointers', cr)
self.raise_split_value(ptr)
check_isinstance(ptr, PointerToRegion)
return self.make_field_region(ptr.region, cr.field.name)
elif isinstance(cr.target, gcc.VarDecl):
log('bar')
vr = self.var_region(cr.target)
- log(vr)
+ log('%s', vr)
return self.make_field_region(vr, cr.field.name)
elif isinstance(cr.target, gcc.ComponentRef):
# nested field:
vr = self.get_field_region(cr.target, loc)
- log(vr)
+ log('%s', vr)
return self.make_field_region(vr, cr.field.name)
- log('cr: %r %s' % (cr, cr))
+ log('cr: %r %s', cr, cr)
return self.region_for_var[cr]
def string_constant_region(self, expr, loc):
- log('string_constant_region: %s' % expr)
+ log('string_constant_region: %s', expr)
check_isinstance(expr, gcc.StringCst)
if loc:
check_isinstance(loc, gcc.Location)
@@ -669,7 +668,7 @@ class State:
# "unknown" value:
if isinstance(region, RegionForGlobal):
newval = UnknownValue(region.vardecl.type, region.vardecl.location)
- log('setting up %s for %s' % (newval, region.vardecl))
+ log('setting up %s for %s', newval, region.vardecl)
self.value_for_region[region] = newval
return newval
@@ -678,7 +677,7 @@ class State:
def _get_store_recursive(self, region, gcctype, loc):
check_isinstance(region, Region)
- # self.log(log, 0)
+ # self.log(log)
if region in self.value_for_region:
return self.value_for_region[region]
@@ -700,7 +699,7 @@ class State:
def make_field_region(self, target, field):
check_isinstance(target, Region)
check_isinstance(field, str)
- log('make_field_region(%r, %r)' % (target, field))
+ log('make_field_region(%r, %r)', target, field)
if field in target.fields:
log('reusing')
return target.fields[field]
@@ -715,7 +714,7 @@ class State:
def get_value_of_field_by_varname(self, varname, field):
# Lookup varname.field
# For use in writing selftests
- log('get_value_of_field_by_varname(%r, %r)' % (varname, field), 0)
+ log('get_value_of_field_by_varname(%r, %r)', varname, field)
check_isinstance(varname, str)
check_isinstance(field, str)
for k in self.region_for_var:
@@ -729,7 +728,7 @@ class State:
def get_value_of_field_by_region(self, region, field):
# Lookup region->field
# For use in writing selftests
- log('get_value_of_field_by_region(%r, %r)' % (region, field), 0)
+ log('get_value_of_field_by_region(%r, %r)', region, field)
check_isinstance(region, Region)
check_isinstance(field, str)
if field in region.fields:
@@ -738,7 +737,7 @@ class State:
return None
def init_for_function(self, fun):
- log('State.init_for_function(%r)' % fun)
+ log('State.init_for_function(%r)', fun)
self.fun = fun
root_region = Region('root', None)
stack = RegionOnStack('stack for %s' % fun.decl.name, root_region)
@@ -761,7 +760,7 @@ class State:
self.verify()
def make_assignment(self, lhs, rhs, desc):
- log('make_assignment(%r, %r, %r)' % (lhs, rhs, desc))
+ log('make_assignment(%r, %r, %r)', lhs, rhs, desc)
if desc:
check_isinstance(desc, str)
new = self.copy()
@@ -790,9 +789,9 @@ class State:
# Some statements have None for their location, but gcc.error() etc
# don't allow this. Use the end of the function for this case.
stmt = self.loc.get_stmt()
- log('%s %r' % (stmt, stmt))
+ log('%s %r', stmt, stmt)
if stmt:
- log(self.loc.get_stmt().loc)
+ log('%s' % self.loc.get_stmt().loc)
# grrr... not all statements have a non-NULL location
gccloc = self.loc.get_stmt().loc
if gccloc is None:
@@ -845,10 +844,10 @@ class Transition:
def __repr__(self):
return 'Transition(%r, %r)' % (self.dest, self.desc)
- def log(self, logger, indent):
- logger('desc: %r' % self.desc, indent)
- logger('dest:', indent)
- self.dest.log(logger, indent + 1)
+ def log(self, logger):
+ logger('desc: %r' % self.desc)
+ logger('dest:')
+ self.dest.log(logger)
class Trace:
"""A sequence of States and Transitions"""
@@ -873,13 +872,13 @@ class Trace:
t.err = self.err # FIXME: should this be a copy?
return t
- def log(self, logger, name, indent):
- logger('%s:' % name, indent)
+ def log(self, logger, name):
+ logger('%s:' % name)
for i, state in enumerate(self.states):
- logger('%i:' % i, indent + 1)
- state.log(logger, indent + 2)
+ logger('%i:' % i)
+ state.log(logger)
if self.err:
- logger(' Trace ended with error: %s' % self.err, indent + 1)
+ logger(' Trace ended with error: %s' % self.err)
def get_last_stmt(self):
return self.states[-1].loc.get_stmt()
@@ -939,10 +938,10 @@ class Resources:
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 log(self, logger):
+ logger('resources:')
+ logger('acquisitions: %s' % self._acquisitions)
+ logger('releases: %s' % self._releases)
def iter_traces(fun, stateclass, prefix=None):
"""
@@ -952,7 +951,7 @@ def iter_traces(fun, stateclass, prefix=None):
For now, don't include any traces that contain loops, as a primitive
way of ensuring termination of the analysis
"""
- log('iter_traces(%r, %r, %r)' % (fun, stateclass, prefix))
+ log('iter_traces(%r, %r, %r)', fun, stateclass, prefix)
if prefix is None:
prefix = Trace()
curstate = stateclass(Location.get_block_start(fun.cfg.entry),
@@ -986,8 +985,8 @@ def iter_traces(fun, stateclass, prefix=None):
else:
prevstate = None
- prefix.log(log, 'PREFIX', 1)
- log(' %s:%s' % (fun.decl.name, curstate.loc))
+ prefix.log(log, 'PREFIX')
+ log(' %s:%s', fun.decl.name, curstate.loc)
try:
transitions = curstate.get_transitions()
check_isinstance(transitions, list)
@@ -997,7 +996,7 @@ def iter_traces(fun, stateclass, prefix=None):
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)
+ trace_with_err.log(log, 'FINISHED TRACE WITH ERROR: %s' % err)
return [trace_with_err]
except SplitValue:
# Split the state up, splitting into parallel worlds with different
@@ -1007,7 +1006,7 @@ def iter_traces(fun, stateclass, prefix=None):
transitions = err.split(curstate)
check_isinstance(transitions, list)
- log('transitions: %s' % transitions, 2)
+ log('transitions: %s', transitions)
if len(transitions) > 0:
result = []
@@ -1021,7 +1020,7 @@ def iter_traces(fun, stateclass, prefix=None):
return result
else:
# We're at a terminating state:
- prefix.log(log, 'FINISHED TRACE', 1)
+ prefix.log(log, 'FINISHED TRACE')
return [prefix]
class StateGraph:
diff --git a/libcpychecker/diagnostics.py b/libcpychecker/diagnostics.py
index 9394a06..8904036 100644
--- a/libcpychecker/diagnostics.py
+++ b/libcpychecker/diagnostics.py
@@ -63,7 +63,7 @@ def describe_trace(trace, fun, annotator):
"""
awaiting_target = None
for t in trace.transitions:
- log('transition: %s' % t)
+ log('transition: %s', t)
srcloc = t.src.get_gcc_loc_or_none()
if t.desc:
if srcloc:
diff --git a/libcpychecker/refcounts.py b/libcpychecker/refcounts.py
index 1c8d7c7..643ff88 100644
--- a/libcpychecker/refcounts.py
+++ b/libcpychecker/refcounts.py
@@ -145,7 +145,7 @@ class GenericTpDealloc(AbstractValue):
check_isinstance(value, PointerToRegion)
region = value.region
check_isinstance(region, Region)
- log('generic tp_dealloc called for %s' % region)
+ log('generic tp_dealloc called for %s', region)
# Get the description of the region before trashing it:
desc = 'calling tp_dealloc on %s' % region
@@ -198,7 +198,7 @@ class MyState(State):
self.resources.release(resource)
def init_for_function(self, fun):
- log('MyState.init_for_function(%r)' % fun)
+ log('MyState.init_for_function(%r)', fun)
State.init_for_function(self, fun)
# Initialize PyObject* arguments to sane values
@@ -208,7 +208,7 @@ class MyState(State):
region = self.eval_lvalue(parm, None)
if type_is_pyobjptr_subclass(parm.type):
# We have a PyObject* (or a derived class)
- log('got python obj arg: %r' % region)
+ log('got python obj arg: %r', region)
# Assume it's a non-NULL ptr:
objregion = Region('region-for-arg-%s' % parm, None)
self.region_for_var[objregion] = objregion
@@ -246,12 +246,12 @@ class MyState(State):
newstate = self.copy()
newstate.loc = loc
result.append(Transition(self, newstate, ''))
- log('result: %s' % result)
+ log('result: %s', result)
return result
def _get_transitions_for_stmt(self, stmt):
- log('_get_transitions_for_stmt: %r %s' % (stmt, stmt), 2)
- log('dir(stmt): %s' % dir(stmt), 3)
+ log('_get_transitions_for_stmt: %r %s', stmt, stmt)
+ log('dir(stmt): %s', dir(stmt))
if stmt.loc:
gcc.set_location(stmt.loc)
if isinstance(stmt, gcc.GimpleCall):
@@ -355,7 +355,7 @@ class MyState(State):
return newstate
def steal_reference(self, region):
- log('steal_reference(%r)' % region)
+ log('steal_reference(%r)', region)
check_isinstance(region, Region)
ob_refcnt = self.make_field_region(region, 'ob_refcnt')
value = self.value_for_region[ob_refcnt]
@@ -512,13 +512,13 @@ class MyState(State):
return self.make_transitions_for_fncall(stmt, success, failure)
def _get_transitions_for_GimpleCall(self, stmt):
- log('stmt.lhs: %s %r' % (stmt.lhs, stmt.lhs), 3)
- log('stmt.fn: %s %r' % (stmt.fn, stmt.fn), 3)
- log('dir(stmt.fn): %s' % dir(stmt.fn), 4)
+ log('stmt.lhs: %s %r', stmt.lhs, stmt.lhs)
+ log('stmt.fn: %s %r', stmt.fn, stmt.fn)
+ log('dir(stmt.fn): %s', dir(stmt.fn))
if hasattr(stmt.fn, 'operand'):
- log('stmt.fn.operand: %s' % stmt.fn.operand, 4)
+ log('stmt.fn.operand: %s', stmt.fn.operand)
returntype = stmt.fn.type.dereference.type
- log('returntype: %s' % returntype)
+ log('returntype: %s', returntype)
if stmt.noreturn:
# The function being called does not return e.g. "exit(0);"
@@ -532,13 +532,13 @@ class MyState(State):
if isinstance(stmt.fn, gcc.VarDecl):
# Calling through a function pointer:
val = self.eval_rvalue(stmt.fn, stmt.loc)
- log('val: %s' % val)
+ log('val: %s', val)
check_isinstance(val, AbstractValue)
return val.get_transitions_for_function_call(self, stmt)
if isinstance(stmt.fn.operand, gcc.FunctionDecl):
- log('dir(stmt.fn.operand): %s' % dir(stmt.fn.operand), 4)
- log('stmt.fn.operand.name: %r' % stmt.fn.operand.name, 4)
+ log('dir(stmt.fn.operand): %s', dir(stmt.fn.operand))
+ log('stmt.fn.operand.name: %r', stmt.fn.operand.name)
fnname = stmt.fn.operand.name
# Hand off to impl_* methods, where these exist:
@@ -553,14 +553,14 @@ class MyState(State):
# return handle_c_stdio_function(self, fnname, stmt)
# Unknown function:
- log('Invocation of unknown function: %r' % fnname)
+ log('Invocation of unknown function: %r', fnname)
return [self.make_assignment(stmt.lhs,
UnknownValue(returntype, stmt.loc),
None)]
- log('stmt.args: %s %r' % (stmt.args, stmt.args), 3)
+ log('stmt.args: %s %r', stmt.args, stmt.args)
for i, arg in enumerate(stmt.args):
- log('args[%i]: %s %r' % (i, arg, arg), 4)
+ log('args[%i]: %s %r', i, arg, arg)
def _get_transitions_for_GimpleCond(self, stmt):
def make_transition_for_true(stmt):
@@ -577,19 +577,19 @@ class MyState(State):
nextstate.prior_bool = False
return Transition(self, nextstate, 'taking False path')
- log('stmt.exprcode: %s' % stmt.exprcode, 4)
- log('stmt.exprtype: %s' % stmt.exprtype, 4)
- log('stmt.lhs: %r %s' % (stmt.lhs, stmt.lhs), 4)
- log('stmt.rhs: %r %s' % (stmt.rhs, stmt.rhs), 4)
- log('dir(stmt.lhs): %s' % dir(stmt.lhs), 5)
- log('dir(stmt.rhs): %s' % dir(stmt.rhs), 5)
+ log('stmt.exprcode: %s', stmt.exprcode)
+ log('stmt.exprtype: %s', stmt.exprtype)
+ log('stmt.lhs: %r %s', stmt.lhs, stmt.lhs)
+ log('stmt.rhs: %r %s', stmt.rhs, stmt.rhs)
+ log('dir(stmt.lhs): %s', dir(stmt.lhs))
+ log('dir(stmt.rhs): %s', dir(stmt.rhs))
boolval = self.eval_condition(stmt)
if boolval is True:
- log('taking True edge', 2)
+ log('taking True edge')
nextstate = make_transition_for_true(stmt)
return [nextstate]
elif boolval is False:
- log('taking False edge', 2)
+ log('taking False edge')
nextstate = make_transition_for_false(stmt)
return [nextstate]
else:
@@ -604,30 +604,30 @@ class MyState(State):
check_isinstance(rhs, AbstractValue)
if isinstance(rhs, ConcreteValue):
if isinstance(lhs, PointerToRegion) and rhs.value == 0:
- log('ptr to region vs 0: %s is definitely not equal to %s' % (lhs, rhs))
+ log('ptr to region vs 0: %s is definitely not equal to %s', lhs, rhs)
return False
if isinstance(lhs, ConcreteValue):
- log('comparing concrete values: %s %s' % (lhs, rhs))
+ log('comparing concrete values: %s %s', lhs, rhs)
return lhs.value == rhs.value
if isinstance(lhs, RefcountValue):
- log('comparing refcount value %s with concrete value: %s' % (lhs, rhs))
+ log('comparing refcount value %s with concrete value: %s', lhs, rhs)
# The actual value of ob_refcnt >= lhs.relvalue
if lhs.relvalue > rhs.value:
# (Equality is thus not possible for this case)
return False
if isinstance(rhs, PointerToRegion):
if isinstance(lhs, PointerToRegion):
- log('comparing regions: %s %s' % (lhs, rhs))
+ log('comparing regions: %s %s', lhs, rhs)
return lhs.region == rhs.region
# We don't know:
return None
- log('eval_condition: %s' % stmt)
+ log('eval_condition: %s', stmt)
lhs = self.eval_rvalue(stmt.lhs, stmt.loc)
rhs = self.eval_rvalue(stmt.rhs, stmt.loc)
- log('eval of lhs: %r' % lhs)
- log('eval of rhs: %r' % rhs)
- log('stmt.exprcode: %r' % stmt.exprcode)
+ log('eval of lhs: %r', lhs)
+ log('eval of rhs: %r', rhs)
+ log('stmt.exprcode: %r', stmt.exprcode)
if stmt.exprcode == gcc.EqExpr:
result = is_equal(lhs, rhs)
if result is not None:
@@ -644,20 +644,20 @@ class MyState(State):
# Split the ptr variable immediately into NULL and non-NULL
# versions, so that we can evaluate the true and false branch with
# explicitly data
- log('splitting %s into non-NULL/NULL pointers' % stmt.lhs)
+ log('splitting %s into non-NULL/NULL pointers', stmt.lhs)
self.raise_split_value(lhs, stmt.loc)
- log('unable to compare %r with %r' % (lhs, rhs))
+ log('unable to compare %r with %r', lhs, rhs)
return UnknownValue(stmt.lhs.type, stmt.loc)
def eval_rhs(self, stmt):
- log('eval_rhs(%s): %s' % (stmt, stmt.rhs))
+ log('eval_rhs(%s): %s', stmt, stmt.rhs)
rhs = stmt.rhs
if stmt.exprcode == gcc.PlusExpr:
a = self.eval_rvalue(rhs[0], stmt.loc)
b = self.eval_rvalue(rhs[1], stmt.loc)
- log('a: %r' % a)
- log('b: %r' % b)
+ log('a: %r', a)
+ log('b: %r', b)
if isinstance(a, ConcreteValue) and isinstance(b, ConcreteValue):
return ConcreteValue(stmt.lhs.type, stmt.loc, a.value + b.value)
if isinstance(a, RefcountValue) and isinstance(b, ConcreteValue):
@@ -670,8 +670,8 @@ class MyState(State):
elif stmt.exprcode == gcc.MinusExpr:
a = self.eval_rvalue(rhs[0], stmt.loc)
b = self.eval_rvalue(rhs[1], stmt.loc)
- log('a: %r' % a)
- log('b: %r' % b)
+ log('a: %r', a)
+ log('b: %r', b)
if isinstance(a, RefcountValue) and isinstance(b, ConcreteValue):
return RefcountValue(a.relvalue - b.value, a.min_external)
raise NotImplementedError("Don't know how to cope with subtraction of\n %r\nand\n %rat %s"
@@ -700,13 +700,13 @@ class MyState(State):
% (stmt.exprcode, stmt.exprcode, stmt.loc))
def _get_transitions_for_GimpleAssign(self, stmt):
- log('stmt.lhs: %r %s' % (stmt.lhs, stmt.lhs))
- log('stmt.rhs: %r %s' % (stmt.rhs, stmt.rhs))
- log('stmt: %r %s' % (stmt, stmt))
- log('stmt.exprcode: %r' % stmt.exprcode)
+ log('stmt.lhs: %r %s', stmt.lhs, stmt.lhs)
+ log('stmt.rhs: %r %s', stmt.rhs, stmt.rhs)
+ log('stmt: %r %s', stmt, stmt)
+ log('stmt.exprcode: %r', stmt.exprcode)
value = self.eval_rhs(stmt)
- log('value from eval_rhs: %r' % value)
+ log('value from eval_rhs: %r', value)
check_isinstance(value, AbstractValue)
if isinstance(value, DeallocatedMemory):
@@ -715,11 +715,11 @@ class MyState(State):
nextstate = self.use_next_loc()
"""
if isinstance(stmt.lhs, gcc.MemRef):
- log('value: %s %r' % (value, value))
+ log('value: %s %r', value, value)
# We're writing a value to memory; if it's a PyObject*
# then we're surrending a reference on it:
if value in nextstate.owned_refs:
- log('removing ownership of %s' % value)
+ log('removing ownership of %s', value)
nextstate.owned_refs.remove(value)
"""
return [self.make_assignment(stmt.lhs,
@@ -727,16 +727,16 @@ class MyState(State):
None)]
def _get_transitions_for_GimpleReturn(self, stmt):
- #log('stmt.lhs: %r %s' % (stmt.lhs, stmt.lhs))
- #log('stmt.rhs: %r %s' % (stmt.rhs, stmt.rhs))
- log('stmt: %r %s' % (stmt, stmt))
- log('stmt.retval: %r' % stmt.retval)
+ #log('stmt.lhs: %r %s', stmt.lhs, stmt.lhs)
+ #log('stmt.rhs: %r %s', stmt.rhs, stmt.rhs)
+ log('stmt: %r %s', stmt, stmt)
+ log('stmt.retval: %r', stmt.retval)
nextstate = self.copy()
if stmt.retval:
rvalue = self.eval_rvalue(stmt.retval, stmt.loc)
- log('rvalue from eval_rvalue: %r' % rvalue)
+ log('rvalue from eval_rvalue: %r', rvalue)
nextstate.return_rvalue = rvalue
nextstate.has_returned = True
return [Transition(self, nextstate, 'returning')]
@@ -749,12 +749,12 @@ class MyState(State):
# FIXME: for now, treat all labels as possible:
result.append(label)
return result
- log('stmt.indexvar: %r' % stmt.indexvar)
- log('stmt.labels: %r' % (stmt.labels,))
+ log('stmt.indexvar: %r', stmt.indexvar)
+ log('stmt.labels: %r', stmt.labels)
indexval = self.eval_rvalue(stmt.indexvar, stmt.loc)
- log('indexval: %r' % indexval)
+ log('indexval: %r', indexval)
labels = get_labels_for_rvalue(self, stmt, indexval)
- log('labels: %r' % labels)
+ log('labels: %r', labels)
result = []
for label in labels:
newstate = self.copy()
@@ -898,8 +898,8 @@ class RefcountAnnotator(Annotator):
dest_refcnt = transition.dest.get_value_of_field_by_region(self.region,
'ob_refcnt')
if src_refcnt != dest_refcnt:
- log('src_refcnt: %r' % src_refcnt, 0)
- log('dest_refcnt: %r' % dest_refcnt, 0)
+ log('src_refcnt: %r', src_refcnt)
+ log('dest_refcnt: %r', dest_refcnt)
result.append(Note(loc,
('ob_refcnt is now %s' % dest_refcnt)))
@@ -939,7 +939,7 @@ def check_refcounts(fun, dump_traces=False, show_traces=False):
# Abstract interpretation:
# Walk the CFG, gathering the information we're interested in
- log('check_refcounts(%r, %r, %r)' % (fun, dump_traces, show_traces))
+ log('check_refcounts(%r, %r, %r)', fun, dump_traces, show_traces)
check_isinstance(fun, gcc.Function)
@@ -960,18 +960,18 @@ def check_refcounts(fun, dump_traces=False, show_traces=False):
rep = Reporter()
for i, trace in enumerate(traces):
- trace.log(log, 'TRACE %i' % i, 0)
+ trace.log(log, 'TRACE %i' % i)
if trace.err:
# This trace bails early with a fatal error; it probably doesn't
# have a return value
- log('trace.err: %s %r' % (trace.err, trace.err))
+ log('trace.err: %s %r', trace.err, trace.err)
err = rep.make_error(fun, trace.err.loc, str(trace.err))
err.add_trace(trace)
# FIXME: in our example this ought to mention where the values came from
continue
# Otherwise, the trace proceeds normally
return_value = trace.return_value()
- log('trace.return_value(): %s' % trace.return_value())
+ log('trace.return_value(): %s', trace.return_value())
# Ideally, we should "own" exactly one reference, and it should be
# the return value. Anything else is an error (and there are other
@@ -979,10 +979,10 @@ def check_refcounts(fun, dump_traces=False, show_traces=False):
# Locate all PyObject that we touched
endstate = trace.states[-1]
- endstate.log(log, 0)
- log('return_value: %r' % return_value, 0)
- log('endstate.region_for_var: %r' % endstate.region_for_var, 0)
- log('endstate.value_for_region: %r' % endstate.value_for_region, 0)
+ endstate.log(log)
+ log('return_value: %r', return_value)
+ log('endstate.region_for_var: %r', endstate.region_for_var)
+ log('endstate.value_for_region: %r', endstate.value_for_region)
# Consider all regions of memory we know about:
for k in endstate.region_for_var:
@@ -990,7 +990,7 @@ def check_refcounts(fun, dump_traces=False, show_traces=False):
continue
region = endstate.region_for_var[k]
- log('considering ob_refcnt of %r' % region)
+ log('considering ob_refcnt of %r', region)
check_isinstance(region, Region)
# Consider those for which we know something about an "ob_refcnt"
@@ -1000,7 +1000,7 @@ def check_refcounts(fun, dump_traces=False, show_traces=False):
ob_refcnt = endstate.get_value_of_field_by_region(region,
'ob_refcnt')
- log('ob_refcnt: %r' % ob_refcnt, 0)
+ log('ob_refcnt: %r', ob_refcnt)
# If it's the return value, it should have a net refcnt delta of
# 1; all other PyObject should have a net delta of 0:
@@ -1019,7 +1019,7 @@ def check_refcounts(fun, dump_traces=False, show_traces=False):
exp_refs += [ref.name
for ref in endstate.get_persistent_refs_for_region(region)]
exp_refcnt = len(exp_refs)
- log('exp_refs: %r' % exp_refs, 0)
+ log('exp_refs: %r', exp_refs)
# Helper function for when ob_refcnt is wrong:
def emit_refcount_error(msg):
diff --git a/libcpychecker/utils.py b/libcpychecker/utils.py
index 882b401..de3b2da 100644
--- a/libcpychecker/utils.py
+++ b/libcpychecker/utils.py
@@ -16,16 +16,25 @@
# <http://www.gnu.org/licenses/>.
# Logging
+import sys
import gcc
logfile = None
-def log(msg, indent=0):
- if 0:
- global logfile
- if not logfile:
- logfile = open(gcc.get_dump_base_name() + '.cpychecker-log.txt', 'w')
- logfile.write('%s%s\n' % (' ' * indent, msg))
- if 0:
- sys.stderr.write('%s%s\n' % (' ' * indent, msg))
+logging_enabled = False
+
+def log(msg, *args):
+ if logging_enabled:
+ # Only do the work of expanding the message if logging is enabled:
+ expanded_msg = msg % args
+ if 1:
+ global logfile
+ if not logfile:
+ filename = gcc.get_dump_base_name() + '.cpychecker-log.txt'
+ logfile = open(filename, 'w')
+ logfile.write(expanded_msg)
+ logfile.write('\n')
+ if 0:
+ sys.stderr.write(expanded_msg)
+ sys.stderr.write('\n')
12 years, 9 months
[gcc-python-plugin] make the logging be less verbose
by David Hugh Malcolm
commit 1bf22b18a9e895a206f1750e1402ff44b45c1392
Author: David Malcolm <dmalcolm(a)redhat.com>
Date: Thu Aug 25 20:06:02 2011 -0400
make the logging be less verbose
libcpychecker/absinterp.py | 8 ++++----
1 files changed, 4 insertions(+), 4 deletions(-)
---
diff --git a/libcpychecker/absinterp.py b/libcpychecker/absinterp.py
index f4b2a48..498551e 100644
--- a/libcpychecker/absinterp.py
+++ b/libcpychecker/absinterp.py
@@ -388,8 +388,8 @@ class State:
self._extra()))
def log(self, logger, indent):
- logger(str(self.region_for_var), indent + 1)
- logger(str(self.value_for_region), indent + 1)
+ #logger(str(self.region_for_var), indent + 1)
+ #logger(str(self.value_for_region), indent + 1)
# Display data in tabular form:
from gccutils import Table
t = Table(['Expression', 'Region', 'Value'])
@@ -402,10 +402,10 @@ class State:
for line in s.getvalue().splitlines():
logger(line, indent + 1)
- logger('extra: %s' % (self._extra(), ), indent)
+ #logger('extra: %s' % (self._extra(), ), indent)
# FIXME: derived class/extra:
- self.resources.log(logger, indent)
+ #self.resources.log(logger, indent)
logger('loc: %s' % self.loc, indent)
if self.loc.get_stmt():
12 years, 9 months
[gcc-python-plugin] cpychecker: revamp of reference-count checking
by David Hugh Malcolm
commit ad6ddd61bbfa8bdd4dd5b32ce90ae53771444640
Author: David Malcolm <dmalcolm(a)redhat.com>
Date: Thu Aug 25 19:57:39 2011 -0400
cpychecker: revamp of reference-count checking
Split up the counting within the RefcountValue class to track both those
references that the function "owns" versus those owned by the rest of the
program state. This allows us to know for an object e.g. that the function
doesn't directly own any references, but that the reference count is still > 0
(for a borrowed reference), as compared to the case where the function owns a
reference, but we don't know of any in the rest of the program (typical for a
"new reference" e.g. from a constructor).
Explicitly track which regions are on the stack (by being directly marked as
such, or by being a child of a stack region)
Within impl_PyList_New, create an "ob_item" array in the simulated heap, in
case the code modifies it.
Within the reference-count checker, we now look for memory locations that
store references to objects. If those locations not on the stack, then the
references they store are now assumed to legally count towards the ob_refcnt
that the function "owns". This is needed in order to correctly handle the
PyList_SET_ITEM() macro, which directly writes to the list's ob_item field,
"stealing" a reference: we can detect these references, and count them towards
the ob_refcnt value.
Extend RefcountAnnotator so that it reports on "persistent" reference changes
to the object in question (i.e. within non-stack memory locations)
When reporting on a reference-counting error, report on what we thought the
reference count was, and what we thought it should have been, listing all of
the references we know about (e.g. return value, stored pointers on the heap
or within globals).
Add test cases that use the PyList_SET_ITEM macro, in order to exercise the
above, and update the expected test outputs to reflect the above changes.
[all of the above was motivated by needing to correctly handle
the PyList_SET_ITEM() macro]
libcpychecker/absinterp.py | 24 +-
libcpychecker/diagnostics.py | 7 +
libcpychecker/refcounts.py | 143 ++++-
libcpychecker/visualizations.py | 8 +-
.../correct_PyList_SET_ITEM_macro/input.c | 60 ++
.../correct_PyList_SET_ITEM_macro/script.py | 22 +
.../correct_PyList_SET_ITEM_macro/stdout.txt | 109 ++++
.../correct_PyList_SET_ITEM_macro_multiple/input.c | 83 +++
.../script.py | 22 +
.../stdout.txt | 647 ++++++++++++++++++++
.../cpychecker/refcounts/correct_decref/stdout.txt | 10 +-
.../refcounts/correct_object_ctor/stdout.txt | 2 +-
.../refcounts/correct_py_none/stdout.txt | 6 +-
.../refcounts/fold_conditional/stdout.txt | 10 +-
tests/cpychecker/refcounts/getter/stdout.txt | 2 +-
.../input.c | 88 +++
.../script.py | 22 +
.../stderr.txt | 23 +
.../stdout.txt | 647 ++++++++++++++++++++
.../refcounts/incorrect_py_none/script.py | 2 +-
.../refcounts/incorrect_py_none/stderr.txt | 3 +
.../refcounts/incorrect_py_none/stdout.txt | 2 +-
tests/cpychecker/refcounts/loop_n_times/stdout.txt | 32 +-
.../cpychecker/refcounts/missing_decref/stderr.txt | 4 +-
.../cpychecker/refcounts/missing_decref/stdout.txt | 18 +-
.../refcounts/module_handling/stdout.txt | 2 +-
.../refcounts/not_setting_exception/stdout.txt | 4 +-
tests/cpychecker/refcounts/object_leak/stderr.txt | 4 +-
.../refcounts/returning_dead_object/stderr.txt | 7 +-
.../refcounts/returning_dead_object/stdout.txt | 14 +-
.../refcounts/subclass/handling/stdout.txt | 4 +-
.../refcounts/too_many_increfs/stderr.txt | 7 +-
.../refcounts/too_many_increfs/stdout.txt | 10 +-
.../refcounts/use_after_dealloc/stdout.txt | 14 +-
34 files changed, 1960 insertions(+), 102 deletions(-)
---
diff --git a/libcpychecker/absinterp.py b/libcpychecker/absinterp.py
index f292ba0..f4b2a48 100644
--- a/libcpychecker/absinterp.py
+++ b/libcpychecker/absinterp.py
@@ -249,6 +249,13 @@ class Region:
def __repr__(self):
return '%s(%r)' % (self.__class__.__name__, self.name)
+ def is_on_stack(self):
+ if isinstance(self, RegionOnStack):
+ return True
+ if self.parent:
+ return self.parent.is_on_stack()
+ return False
+
class RegionForGlobal(Region):
"""
Represents the area of memory (e.g. in .data or .bss section)
@@ -262,6 +269,13 @@ class RegionForGlobal(Region):
def __repr__(self):
return 'RegionForGlobal(%r)' % self.vardecl
+class RegionOnStack(Region):
+ def __repr__(self):
+ return 'RegionOnStack(%r)' % self.name
+
+ def __str__(self):
+ return '%s on stack' % self.name
+
class RegionOnHeap(Region):
"""
Represents an area of memory allocated on the heap
@@ -541,7 +555,7 @@ class State:
if str(var.type) == 'struct PyObject':
from libcpychecker.refcounts import RefcountValue
ob_refcnt = self.make_field_region(region, 'ob_refcnt') # FIXME: this should be a memref and fieldref
- self.value_for_region[ob_refcnt] = RefcountValue(0)
+ self.value_for_region[ob_refcnt] = RefcountValue.borrowed_ref()
return self.region_for_var[var]
def element_region(self, ar, loc):
@@ -727,21 +741,21 @@ class State:
log('State.init_for_function(%r)' % fun)
self.fun = fun
root_region = Region('root', None)
- stack = Region('stack for %s' % fun.decl.name, root_region)
+ stack = RegionOnStack('stack for %s' % fun.decl.name, root_region)
nonnull_args = get_nonnull_arguments(fun.decl.type)
for idx, parm in enumerate(fun.decl.arguments):
- region = Region('region for %r' % parm, stack)
+ region = RegionOnStack('region for %r' % parm, stack)
self.region_for_var[parm] = region
if idx in nonnull_args:
# Make a non-NULL ptr:
- other = Region('region-for-arg-%s' % parm, None)
+ other = RegionOnStack('region-for-arg-%s' % parm, None)
self.region_for_var[other] = other
self.value_for_region[region] = PointerToRegion(parm.type, parm.location, other)
else:
self.value_for_region[region] = UnknownValue(parm.type, parm.location)
for local in fun.local_decls:
- region = Region('region for %r' % local, stack)
+ region = RegionOnStack('region for %r' % local, stack)
self.region_for_var[local] = region
self.value_for_region[region] = UninitializedData(local.type, fun.start)
self.verify()
diff --git a/libcpychecker/diagnostics.py b/libcpychecker/diagnostics.py
index 2881990..9394a06 100644
--- a/libcpychecker/diagnostics.py
+++ b/libcpychecker/diagnostics.py
@@ -29,6 +29,9 @@ class Annotator:
"""
A collection of hooks for use when describing a trace (either as text,
or as an HTML report)
+
+ This allows us to add the annotations to the correct place in the textual
+ stream when reporting on flow through a function
"""
def get_notes(self, transition):
"""
@@ -38,6 +41,10 @@ class Annotator:
raise NotImplementedError
class TestAnnotator(Annotator):
+ """
+ A sample annotator that adds information to the trace on movement between
+ gimple statements
+ """
def get_notes(self, transition):
result = []
srcloc = transition.src.get_gcc_loc_or_none()
diff --git a/libcpychecker/refcounts.py b/libcpychecker/refcounts.py
index ae26da4..1c8d7c7 100644
--- a/libcpychecker/refcounts.py
+++ b/libcpychecker/refcounts.py
@@ -96,16 +96,39 @@ class RefcountValue(AbstractValue):
'relvalue' is all of the references owned within this function.
- The actual value of ob_refcnt >= relvalue
+ 'min_external' is a lower bound on all references owned outside the
+ scope of this function.
+
+ The actual value of ob_refcnt >= (relvalue + min_external)
+
+ Examples:
+
+ - an argument passed in a a borrowed ref starts with (0, 1), in that
+ the function doesn't own any refs on it, but it has a refcount of at
+ least 1, due to refs we know nothing about.
+
+ - a newly constructed object gets (1, 0): we own a reference on it,
+ and we don't know if there are any external refs on it.
"""
- def __init__(self, relvalue):
+ def __init__(self, relvalue, min_external):
self.relvalue = relvalue
+ self.min_external = min_external
+
+ @classmethod
+ def new_ref(cls):
+ return RefcountValue(relvalue=1,
+ min_external=0)
+
+ @classmethod
+ def borrowed_ref(cls):
+ return RefcountValue(relvalue=0,
+ min_external=1)
def __str__(self):
- return 'refs: %i' % self.relvalue
+ return 'refs: %i + N where N >= %i' % (self.relvalue, self.min_external)
def __repr__(self):
- return 'RefcountValue(%i)' % self.relvalue
+ return 'RefcountValue(%i, %i)' % (self.relvalue, self.min_external)
class GenericTpDealloc(AbstractValue):
"""
@@ -194,7 +217,7 @@ class MyState(State):
objregion)
# Assume we have a borrowed reference:
ob_refcnt = self.make_field_region(objregion, 'ob_refcnt') # FIXME: this should be a memref and fieldref
- self.value_for_region[ob_refcnt] = RefcountValue(0) # borrowed ref
+ self.value_for_region[ob_refcnt] = RefcountValue.borrowed_ref()
# Assume it has a non-NULL ob_type:
ob_type = self.make_field_region(objregion, 'ob_type')
@@ -299,7 +322,7 @@ class MyState(State):
nonnull = success.make_heap_region(typename, stmt)
ob_refcnt = success.make_field_region(nonnull, 'ob_refcnt') # FIXME: this should be a memref and fieldref
- success.value_for_region[ob_refcnt] = RefcountValue(1)
+ success.value_for_region[ob_refcnt] = RefcountValue.new_ref()
ob_type = success.make_field_region(nonnull, 'ob_type')
success.value_for_region[ob_type] = PointerToRegion(get_PyTypeObject().pointer,
stmt.loc,
@@ -341,7 +364,8 @@ class MyState(State):
# rest of the program. Given that the rest of the program is
# stealing a ref, that is increasing by one, hence our value must
# go down by one:
- self.value_for_region[ob_refcnt] = RefcountValue(value.relvalue - 1)
+ self.value_for_region[ob_refcnt] = RefcountValue(value.relvalue - 1,
+ value.min_external + 1)
def make_borrowed_ref(self, stmt, name):
"""Make a new state, giving a borrowed ref to some object"""
@@ -350,7 +374,7 @@ class MyState(State):
nonnull = newstate.make_heap_region(name, stmt)
ob_refcnt = newstate.make_field_region(nonnull, 'ob_refcnt') # FIXME: this should be a memref and fieldref
- newstate.value_for_region[ob_refcnt] = RefcountValue(0)
+ newstate.value_for_region[ob_refcnt] = RefcountValue.borrowed_ref()
#ob_type = newstate.make_field_region(nonnull, 'ob_type')
#newstate.value_for_region[ob_type] = PointerToRegion(get_PyTypeObject().pointer,
# stmt.loc,
@@ -393,6 +417,21 @@ class MyState(State):
# Set ob_size:
ob_size = success.dest.make_field_region(newobj, 'ob_size')
success.dest.value_for_region[ob_size] = lenarg
+
+ # "Allocate" ob_item, and set it up so that all of the array is
+ # treated as NULL:
+ ob_item_region = success.dest.make_heap_region(
+ 'ob_item array for PyListObject',
+ stmt)
+ success.dest.value_for_region[ob_item_region] = \
+ ConcreteValue(get_PyObjectPtr(),
+ stmt.loc, 0)
+
+ ob_item = success.dest.make_field_region(newobj, 'ob_item')
+ success.dest.value_for_region[ob_item] = PointerToRegion(get_PyObjectPtr().pointer,
+ stmt.loc,
+ ob_item_region)
+
return [success, failure]
def impl_PyLong_FromLong(self, stmt):
@@ -622,7 +661,7 @@ class MyState(State):
if isinstance(a, ConcreteValue) and isinstance(b, ConcreteValue):
return ConcreteValue(stmt.lhs.type, stmt.loc, a.value + b.value)
if isinstance(a, RefcountValue) and isinstance(b, ConcreteValue):
- return RefcountValue(a.relvalue + b.value)
+ return RefcountValue(a.relvalue + b.value, a.min_external)
return UnknownValue(stmt.lhs.type, stmt.loc)
@@ -634,7 +673,7 @@ class MyState(State):
log('a: %r' % a)
log('b: %r' % b)
if isinstance(a, RefcountValue) and isinstance(b, ConcreteValue):
- return RefcountValue(a.relvalue - b.value)
+ return RefcountValue(a.relvalue - b.value, a.min_external)
raise NotImplementedError("Don't know how to cope with subtraction of\n %r\nand\n %rat %s"
% (a, b, stmt.loc))
elif stmt.exprcode == gcc.ComponentRef:
@@ -735,6 +774,28 @@ class MyState(State):
desc))
return result
+ def get_persistent_refs_for_region(self, dst_region):
+ # Locate all regions containing pointers that point at the given region
+ # that are either on the heap or are globals (not locals)
+ check_isinstance(dst_region, Region)
+ result = []
+ for src_region in self.get_all_refs_for_region(dst_region):
+ if src_region.is_on_stack():
+ continue
+ result.append(src_region)
+ return result
+
+ def get_all_refs_for_region(self, dst_region):
+ # Locate all regions containing pointers that point at the given region
+ check_isinstance(dst_region, Region)
+ result = []
+ for src_region in self.value_for_region:
+ v = self.value_for_region[src_region]
+ if isinstance(v, PointerToRegion):
+ if v.region == dst_region:
+ result.append(src_region)
+ return result
+
def get_traces(fun):
return list(iter_traces(fun, MyState))
@@ -751,7 +812,7 @@ def dump_traces_to_stdout(traces):
print(' repr(): %r' % rvalue)
print(' str(): %s' % rvalue)
if isinstance(rvalue, PointerToRegion):
- print(' r->ob_refcnt: %r'
+ print(' r->ob_refcnt: %s'
% endstate.get_value_of_field_by_region(rvalue.region, 'ob_refcnt'))
print(' r->ob_type: %r'
% endstate.get_value_of_field_by_region(rvalue.region, 'ob_type'))
@@ -761,7 +822,7 @@ def dump_traces_to_stdout(traces):
print(' %s:' % title)
print(' repr(): %r' % region)
print(' str(): %s' % region)
- print(' r->ob_refcnt: %r'
+ print(' r->ob_refcnt: %s'
% endstate.get_value_of_field_by_region(region, 'ob_refcnt'))
print(' r->ob_type: %r'
% endstate.get_value_of_field_by_region(region, 'ob_type'))
@@ -816,14 +877,22 @@ class RefcountAnnotator(Annotator):
object
"""
def __init__(self, region):
+ check_isinstance(region, Region)
self.region = region
def get_notes(self, transition):
"""
- Add a note to every transition that changes the reference count of
+ Add a note to every transition that affects reference-counting for
our target object
"""
+ loc = transition.src.get_gcc_loc_or_none()
+ if loc is None:
+ # (we can't add a note without a valid location)
+ return []
+
result = []
+
+ # Add a note when the ob_refcnt of the object changes:
src_refcnt = transition.src.get_value_of_field_by_region(self.region,
'ob_refcnt')
dest_refcnt = transition.dest.get_value_of_field_by_region(self.region,
@@ -831,11 +900,28 @@ class RefcountAnnotator(Annotator):
if src_refcnt != dest_refcnt:
log('src_refcnt: %r' % src_refcnt, 0)
log('dest_refcnt: %r' % dest_refcnt, 0)
- loc = transition.src.get_gcc_loc_or_none()
- if loc:
+ result.append(Note(loc,
+ ('ob_refcnt is now %s' % dest_refcnt)))
+
+ # Add a note when there's a change to the set of persistent storage
+ # locations referencing this object:
+ src_refs = transition.src.get_persistent_refs_for_region(self.region)
+ dest_refs = transition.dest.get_persistent_refs_for_region(self.region)
+ if src_refs != dest_refs:
+ result.append(Note(loc,
+ ('%s is now referenced by %i non-stack value(s): %s'
+ % (self.region.name,
+ len(dest_refs),
+ ', '.join([ref.name for ref in dest_refs])))))
+
+ if 0:
+ # For debugging: show the history of all references to the given
+ # object:
+ src_refs = transition.src.get_all_refs_for_region(self.region)
+ dest_refs = transition.dest.get_all_refs_for_region(self.region)
+ if src_refs != dest_refs:
result.append(Note(loc,
- ('ob_refcnt is now %s' % dest_refcnt)))
-
+ ('all refs: %s' % dest_refs)))
return result
def check_refcounts(fun, dump_traces=False, show_traces=False):
@@ -920,19 +1006,34 @@ def check_refcounts(fun, dump_traces=False, show_traces=False):
# 1; all other PyObject should have a net delta of 0:
if isinstance(return_value, PointerToRegion) and region == return_value.region:
desc = 'return value'
- exp_refcnt = 1
+ exp_refs = ['return value']
else:
desc = 'PyObject'
# We may have a more descriptive name within the region:
if isinstance(region, RegionOnHeap):
desc = region.name
- exp_refcnt = 0
- log('exp_refcnt: %r' % exp_refcnt, 0)
+ exp_refs = []
+
+ # The reference count should also reflect any non-stack pointers
+ # that point at this object:
+ exp_refs += [ref.name
+ for ref in endstate.get_persistent_refs_for_region(region)]
+ exp_refcnt = len(exp_refs)
+ log('exp_refs: %r' % exp_refs, 0)
# Helper function for when ob_refcnt is wrong:
def emit_refcount_error(msg):
err = rep.make_error(fun, endstate.get_gcc_loc(fun), msg)
-
+ err.add_note(endstate.get_gcc_loc(fun),
+ ('was expecting final ob_refcnt to be N + %i (for some unknown N)'
+ % exp_refcnt))
+ if exp_refcnt > 0:
+ err.add_note(endstate.get_gcc_loc(fun),
+ ('due to object being referenced by: %s'
+ % ', '.join(exp_refs)))
+ err.add_note(endstate.get_gcc_loc(fun),
+ ('but final ob_refcnt is N + %i'
+ % ob_refcnt.relvalue))
# For dynamically-allocated objects, indicate where they
# were allocated:
if isinstance(region, RegionOnHeap):
diff --git a/libcpychecker/visualizations.py b/libcpychecker/visualizations.py
index cc09843..45d0c05 100644
--- a/libcpychecker/visualizations.py
+++ b/libcpychecker/visualizations.py
@@ -362,14 +362,14 @@ pre {
# Report the top-level message, if it happens here:
if report.loc.line == linenum:
result += '<span class="error">%s</span>\n' % report.msg
+ # Add notes attached to the report:
+ for note in report.notes:
+ if note.loc and note.loc.line == linenum:
+ result += '<span class="note">%s</span>\n' % note.msg
# Add any notes from the annotator:
for note in notes:
if note.loc and note.loc.line == linenum:
result += '<span class="transition">%s</span>\n' % note.msg
- # Add additional notes attached to the report:
- for note in report.notes:
- if note.loc and note.loc.line == linenum:
- result += '<span class="note">%s</span>\n' % note.msg
result += '\n'
result += '<script type="text/javascript">\n'
diff --git a/tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro/input.c b/tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro/input.c
new file mode 100644
index 0000000..fd14dd5
--- /dev/null
+++ b/tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro/input.c
@@ -0,0 +1,60 @@
+/*
+ Copyright 2011 David Malcolm <dmalcolm(a)redhat.com>
+ Copyright 2011 Red Hat, Inc.
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see
+ <http://www.gnu.org/licenses/>.
+*/
+
+#include <Python.h>
+
+PyObject *
+handle_SET_ITEM_macro(PyObject *self, PyObject *args)
+{
+ PyObject *list;
+ PyObject *item;
+ list = PyList_New(1);
+ if (!list) {
+ return NULL;
+ }
+
+ item = PyLong_FromLong(42);
+ if (!item) {
+ Py_DECREF(list);
+ return NULL;
+ }
+
+ /*
+ Set the item in the list via the PyList_SET_ITEM macro.
+
+ The checker ought to figure out that the macro has stolen the reference
+ to "item", and that this function is thus _not_ leaking a reference to
+ "item".
+ */
+ PyList_SET_ITEM(list, 0, item);
+
+ return list;
+}
+static PyMethodDef test_methods[] = {
+ {"test_method", handle_SET_ITEM_macro, METH_VARARGS, NULL},
+ {NULL, NULL, 0, NULL} /* Sentinel */
+};
+
+/*
+ PEP-7
+Local variables:
+c-basic-offset: 4
+indent-tabs-mode: nil
+End:
+*/
diff --git a/tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro/script.py b/tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro/script.py
new file mode 100644
index 0000000..6bb62fd
--- /dev/null
+++ b/tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro/script.py
@@ -0,0 +1,22 @@
+# -*- coding: utf-8 -*-
+# Copyright 2011 David Malcolm <dmalcolm(a)redhat.com>
+# Copyright 2011 Red Hat, Inc.
+#
+# This is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program 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
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see
+# <http://www.gnu.org/licenses/>.
+
+from libcpychecker import main
+
+main(verify_refcounting=True,
+ dump_traces=True)
diff --git a/tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro/stdout.txt b/tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro/stdout.txt
new file mode 100644
index 0000000..e2d40c8
--- /dev/null
+++ b/tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro/stdout.txt
@@ -0,0 +1,109 @@
+Trace 0:
+ Transitions:
+ 'PyList_New() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() succeeds'
+ 'taking False path'
+ 'returning'
+ Return value:
+ repr(): PointerToRegion(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro/input.c', line=27), region=RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro/input.c', line=27)))
+ str(): (struct PyObject *)&RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro/input.c', line=27)) from tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro/input.c:27
+ r->ob_refcnt: refs: 1 + N where N >= 0
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro/input.c', line=27), region=RegionForGlobal(gcc.VarDecl('PyList_Type')))
+ Region("region-for-arg-gcc.ParmDecl('self')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('self')")
+ str(): Region("region-for-arg-gcc.ParmDecl('self')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
+ Region("region-for-arg-gcc.ParmDecl('args')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('args')")
+ str(): Region("region-for-arg-gcc.ParmDecl('args')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
+ PyLongObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro/input.c:32:
+ repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro/input.c', line=32))
+ str(): PyLongObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro/input.c:32
+ r->ob_refcnt: refs: 1 + N where N >= 0
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro/input.c', line=32), region=RegionForGlobal(gcc.VarDecl('PyLong_Type')))
+ Exception:
+ (struct PyObject *)0 from tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro/input.c:24
+
+Trace 1:
+ Transitions:
+ 'PyList_New() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() fails'
+ 'taking True path'
+ 'taking True path'
+ 'returning'
+ Return value:
+ repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro/input.c', line=35), value=0)
+ str(): (struct PyObject *)0 from tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro/input.c:35
+ Region("region-for-arg-gcc.ParmDecl('self')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('self')")
+ str(): Region("region-for-arg-gcc.ParmDecl('self')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
+ Region("region-for-arg-gcc.ParmDecl('args')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('args')")
+ str(): Region("region-for-arg-gcc.ParmDecl('args')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
+ PyListObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro/input.c:27:
+ repr(): RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro/input.c', line=27))
+ str(): PyListObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro/input.c:27
+ r->ob_refcnt: refs: 0 + N where N >= 0
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro/input.c', line=27), region=RegionForGlobal(gcc.VarDecl('PyList_Type')))
+ Exception:
+ RegionForGlobal(gcc.VarDecl('PyExc_MemoryError'))
+
+Trace 2:
+ Transitions:
+ 'PyList_New() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() fails'
+ 'taking True path'
+ 'taking False path'
+ 'calling tp_dealloc on PyListObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro/input.c:27'
+ 'returning'
+ Return value:
+ repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro/input.c', line=35), value=0)
+ str(): (struct PyObject *)0 from tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro/input.c:35
+ Region("region-for-arg-gcc.ParmDecl('self')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('self')")
+ str(): Region("region-for-arg-gcc.ParmDecl('self')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
+ Region("region-for-arg-gcc.ParmDecl('args')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('args')")
+ str(): Region("region-for-arg-gcc.ParmDecl('args')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
+ PyListObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro/input.c:27:
+ repr(): RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro/input.c', line=27))
+ str(): PyListObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro/input.c:27
+ r->ob_refcnt: None
+ r->ob_type: None
+ Exception:
+ RegionForGlobal(gcc.VarDecl('PyExc_MemoryError'))
+
+Trace 3:
+ Transitions:
+ 'PyList_New() fails'
+ 'taking True path'
+ 'returning'
+ Return value:
+ repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro/input.c', line=29), value=0)
+ str(): (struct PyObject *)0 from tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro/input.c:29
+ Region("region-for-arg-gcc.ParmDecl('self')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('self')")
+ str(): Region("region-for-arg-gcc.ParmDecl('self')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
+ Region("region-for-arg-gcc.ParmDecl('args')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('args')")
+ str(): Region("region-for-arg-gcc.ParmDecl('args')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
+ Exception:
+ RegionForGlobal(gcc.VarDecl('PyExc_MemoryError'))
diff --git a/tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c b/tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c
new file mode 100644
index 0000000..b036238
--- /dev/null
+++ b/tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c
@@ -0,0 +1,83 @@
+/*
+ Copyright 2011 David Malcolm <dmalcolm(a)redhat.com>
+ Copyright 2011 Red Hat, Inc.
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see
+ <http://www.gnu.org/licenses/>.
+*/
+
+#include <Python.h>
+
+PyObject *
+handle_SET_ITEM_macro(PyObject *self, PyObject *args)
+{
+ PyObject *list;
+ /*
+ The checker must not get confused by this temporary array:
+ the borrowed refs that it stores do not persist beyond the
+ lifetime of the function:
+ */
+ PyObject *items[3];
+
+ list = PyList_New(3);
+ if (!list) {
+ return NULL;
+ }
+
+ /* Construct 3 new references: */
+ items[0] = PyLong_FromLong(1000);
+ if (!items[0]) {
+ Py_DECREF(list);
+ return NULL;
+ }
+ items[1] = PyLong_FromLong(2000);
+ if (!items[1]) {
+ Py_DECREF(items[0]);
+ Py_DECREF(list);
+ return NULL;
+ }
+ items[2] = PyLong_FromLong(3000);
+ if (!items[2]) {
+ Py_DECREF(items[1]);
+ Py_DECREF(items[0]);
+ Py_DECREF(list);
+ return NULL;
+ }
+
+ /*
+ Set each item in the list via the PyList_SET_ITEM macro.
+
+ The checker ought to figure out that the macro has stolen the reference
+ to "item", and that this function is thus _not_ leaking a reference to
+ "item".
+ */
+ PyList_SET_ITEM(list, 0, items[0]);
+ PyList_SET_ITEM(list, 1, items[1]);
+ PyList_SET_ITEM(list, 2, items[2]);
+
+ /* This isn't a leak: the 3 new references are owned by the list: */
+ return list;
+}
+static PyMethodDef test_methods[] = {
+ {"test_method", handle_SET_ITEM_macro, METH_VARARGS, NULL},
+ {NULL, NULL, 0, NULL} /* Sentinel */
+};
+
+/*
+ PEP-7
+Local variables:
+c-basic-offset: 4
+indent-tabs-mode: nil
+End:
+*/
diff --git a/tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/script.py b/tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/script.py
new file mode 100644
index 0000000..6bb62fd
--- /dev/null
+++ b/tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/script.py
@@ -0,0 +1,22 @@
+# -*- coding: utf-8 -*-
+# Copyright 2011 David Malcolm <dmalcolm(a)redhat.com>
+# Copyright 2011 Red Hat, Inc.
+#
+# This is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program 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
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see
+# <http://www.gnu.org/licenses/>.
+
+from libcpychecker import main
+
+main(verify_refcounting=True,
+ dump_traces=True)
diff --git a/tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/stdout.txt b/tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/stdout.txt
new file mode 100644
index 0000000..3053363
--- /dev/null
+++ b/tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/stdout.txt
@@ -0,0 +1,647 @@
+Trace 0:
+ Transitions:
+ 'PyList_New() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() succeeds'
+ 'taking False path'
+ 'returning'
+ Return value:
+ repr(): PointerToRegion(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=33), region=RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=33)))
+ str(): (struct PyObject *)&RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=33)) from tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:33
+ r->ob_refcnt: refs: 1 + N where N >= 0
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=33), region=RegionForGlobal(gcc.VarDecl('PyList_Type')))
+ Region("region-for-arg-gcc.ParmDecl('self')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('self')")
+ str(): Region("region-for-arg-gcc.ParmDecl('self')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
+ Region("region-for-arg-gcc.ParmDecl('args')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('args')")
+ str(): Region("region-for-arg-gcc.ParmDecl('args')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
+ PyLongObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:39:
+ repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=39))
+ str(): PyLongObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:39
+ r->ob_refcnt: refs: 1 + N where N >= 0
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=39), region=RegionForGlobal(gcc.VarDecl('PyLong_Type')))
+ PyLongObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:44:
+ repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=44))
+ str(): PyLongObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:44
+ r->ob_refcnt: refs: 1 + N where N >= 0
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=44), region=RegionForGlobal(gcc.VarDecl('PyLong_Type')))
+ PyLongObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:50:
+ repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=50))
+ str(): PyLongObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:50
+ r->ob_refcnt: refs: 1 + N where N >= 0
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=50), region=RegionForGlobal(gcc.VarDecl('PyLong_Type')))
+ Exception:
+ (struct PyObject *)0 from tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:24
+
+Trace 1:
+ Transitions:
+ 'PyList_New() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() fails'
+ 'taking True path'
+ 'taking True path'
+ 'taking True path'
+ 'taking True path'
+ 'returning'
+ Return value:
+ repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=55), value=0)
+ str(): (struct PyObject *)0 from tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:55
+ Region("region-for-arg-gcc.ParmDecl('self')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('self')")
+ str(): Region("region-for-arg-gcc.ParmDecl('self')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
+ Region("region-for-arg-gcc.ParmDecl('args')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('args')")
+ str(): Region("region-for-arg-gcc.ParmDecl('args')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
+ PyListObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:33:
+ repr(): RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=33))
+ str(): PyListObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:33
+ r->ob_refcnt: refs: 0 + N where N >= 0
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=33), region=RegionForGlobal(gcc.VarDecl('PyList_Type')))
+ PyLongObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:39:
+ repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=39))
+ str(): PyLongObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:39
+ r->ob_refcnt: refs: 0 + N where N >= 0
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=39), region=RegionForGlobal(gcc.VarDecl('PyLong_Type')))
+ PyLongObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:44:
+ repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=44))
+ str(): PyLongObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:44
+ r->ob_refcnt: refs: 0 + N where N >= 0
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=44), region=RegionForGlobal(gcc.VarDecl('PyLong_Type')))
+ Exception:
+ RegionForGlobal(gcc.VarDecl('PyExc_MemoryError'))
+
+Trace 2:
+ Transitions:
+ 'PyList_New() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() fails'
+ 'taking True path'
+ 'taking True path'
+ 'taking True path'
+ 'taking False path'
+ 'calling tp_dealloc on PyListObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:33'
+ 'returning'
+ Return value:
+ repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=55), value=0)
+ str(): (struct PyObject *)0 from tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:55
+ Region("region-for-arg-gcc.ParmDecl('self')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('self')")
+ str(): Region("region-for-arg-gcc.ParmDecl('self')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
+ Region("region-for-arg-gcc.ParmDecl('args')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('args')")
+ str(): Region("region-for-arg-gcc.ParmDecl('args')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
+ PyListObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:33:
+ repr(): RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=33))
+ str(): PyListObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:33
+ r->ob_refcnt: None
+ r->ob_type: None
+ PyLongObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:39:
+ repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=39))
+ str(): PyLongObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:39
+ r->ob_refcnt: refs: 0 + N where N >= 0
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=39), region=RegionForGlobal(gcc.VarDecl('PyLong_Type')))
+ PyLongObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:44:
+ repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=44))
+ str(): PyLongObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:44
+ r->ob_refcnt: refs: 0 + N where N >= 0
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=44), region=RegionForGlobal(gcc.VarDecl('PyLong_Type')))
+ Exception:
+ RegionForGlobal(gcc.VarDecl('PyExc_MemoryError'))
+
+Trace 3:
+ Transitions:
+ 'PyList_New() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() fails'
+ 'taking True path'
+ 'taking True path'
+ 'taking False path'
+ 'calling tp_dealloc on PyLongObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:39'
+ 'taking True path'
+ 'returning'
+ Return value:
+ repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=55), value=0)
+ str(): (struct PyObject *)0 from tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:55
+ Region("region-for-arg-gcc.ParmDecl('self')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('self')")
+ str(): Region("region-for-arg-gcc.ParmDecl('self')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
+ Region("region-for-arg-gcc.ParmDecl('args')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('args')")
+ str(): Region("region-for-arg-gcc.ParmDecl('args')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
+ PyListObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:33:
+ repr(): RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=33))
+ str(): PyListObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:33
+ r->ob_refcnt: refs: 0 + N where N >= 0
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=33), region=RegionForGlobal(gcc.VarDecl('PyList_Type')))
+ PyLongObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:39:
+ repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=39))
+ str(): PyLongObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:39
+ r->ob_refcnt: None
+ r->ob_type: None
+ PyLongObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:44:
+ repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=44))
+ str(): PyLongObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:44
+ r->ob_refcnt: refs: 0 + N where N >= 0
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=44), region=RegionForGlobal(gcc.VarDecl('PyLong_Type')))
+ Exception:
+ RegionForGlobal(gcc.VarDecl('PyExc_MemoryError'))
+
+Trace 4:
+ Transitions:
+ 'PyList_New() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() fails'
+ 'taking True path'
+ 'taking True path'
+ 'taking False path'
+ 'calling tp_dealloc on PyLongObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:39'
+ 'taking False path'
+ 'calling tp_dealloc on PyListObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:33'
+ 'returning'
+ Return value:
+ repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=55), value=0)
+ str(): (struct PyObject *)0 from tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:55
+ Region("region-for-arg-gcc.ParmDecl('self')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('self')")
+ str(): Region("region-for-arg-gcc.ParmDecl('self')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
+ Region("region-for-arg-gcc.ParmDecl('args')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('args')")
+ str(): Region("region-for-arg-gcc.ParmDecl('args')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
+ PyListObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:33:
+ repr(): RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=33))
+ str(): PyListObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:33
+ r->ob_refcnt: None
+ r->ob_type: None
+ PyLongObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:39:
+ repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=39))
+ str(): PyLongObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:39
+ r->ob_refcnt: None
+ r->ob_type: None
+ PyLongObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:44:
+ repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=44))
+ str(): PyLongObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:44
+ r->ob_refcnt: refs: 0 + N where N >= 0
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=44), region=RegionForGlobal(gcc.VarDecl('PyLong_Type')))
+ Exception:
+ RegionForGlobal(gcc.VarDecl('PyExc_MemoryError'))
+
+Trace 5:
+ Transitions:
+ 'PyList_New() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() fails'
+ 'taking True path'
+ 'taking False path'
+ 'calling tp_dealloc on PyLongObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:44'
+ 'taking True path'
+ 'taking True path'
+ 'returning'
+ Return value:
+ repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=55), value=0)
+ str(): (struct PyObject *)0 from tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:55
+ Region("region-for-arg-gcc.ParmDecl('self')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('self')")
+ str(): Region("region-for-arg-gcc.ParmDecl('self')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
+ Region("region-for-arg-gcc.ParmDecl('args')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('args')")
+ str(): Region("region-for-arg-gcc.ParmDecl('args')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
+ PyListObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:33:
+ repr(): RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=33))
+ str(): PyListObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:33
+ r->ob_refcnt: refs: 0 + N where N >= 0
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=33), region=RegionForGlobal(gcc.VarDecl('PyList_Type')))
+ PyLongObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:39:
+ repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=39))
+ str(): PyLongObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:39
+ r->ob_refcnt: refs: 0 + N where N >= 0
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=39), region=RegionForGlobal(gcc.VarDecl('PyLong_Type')))
+ PyLongObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:44:
+ repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=44))
+ str(): PyLongObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:44
+ r->ob_refcnt: None
+ r->ob_type: None
+ Exception:
+ RegionForGlobal(gcc.VarDecl('PyExc_MemoryError'))
+
+Trace 6:
+ Transitions:
+ 'PyList_New() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() fails'
+ 'taking True path'
+ 'taking False path'
+ 'calling tp_dealloc on PyLongObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:44'
+ 'taking True path'
+ 'taking False path'
+ 'calling tp_dealloc on PyListObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:33'
+ 'returning'
+ Return value:
+ repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=55), value=0)
+ str(): (struct PyObject *)0 from tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:55
+ Region("region-for-arg-gcc.ParmDecl('self')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('self')")
+ str(): Region("region-for-arg-gcc.ParmDecl('self')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
+ Region("region-for-arg-gcc.ParmDecl('args')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('args')")
+ str(): Region("region-for-arg-gcc.ParmDecl('args')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
+ PyListObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:33:
+ repr(): RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=33))
+ str(): PyListObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:33
+ r->ob_refcnt: None
+ r->ob_type: None
+ PyLongObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:39:
+ repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=39))
+ str(): PyLongObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:39
+ r->ob_refcnt: refs: 0 + N where N >= 0
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=39), region=RegionForGlobal(gcc.VarDecl('PyLong_Type')))
+ PyLongObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:44:
+ repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=44))
+ str(): PyLongObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:44
+ r->ob_refcnt: None
+ r->ob_type: None
+ Exception:
+ RegionForGlobal(gcc.VarDecl('PyExc_MemoryError'))
+
+Trace 7:
+ Transitions:
+ 'PyList_New() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() fails'
+ 'taking True path'
+ 'taking False path'
+ 'calling tp_dealloc on PyLongObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:44'
+ 'taking False path'
+ 'calling tp_dealloc on PyLongObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:39'
+ 'taking True path'
+ 'returning'
+ Return value:
+ repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=55), value=0)
+ str(): (struct PyObject *)0 from tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:55
+ Region("region-for-arg-gcc.ParmDecl('self')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('self')")
+ str(): Region("region-for-arg-gcc.ParmDecl('self')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
+ Region("region-for-arg-gcc.ParmDecl('args')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('args')")
+ str(): Region("region-for-arg-gcc.ParmDecl('args')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
+ PyListObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:33:
+ repr(): RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=33))
+ str(): PyListObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:33
+ r->ob_refcnt: refs: 0 + N where N >= 0
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=33), region=RegionForGlobal(gcc.VarDecl('PyList_Type')))
+ PyLongObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:39:
+ repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=39))
+ str(): PyLongObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:39
+ r->ob_refcnt: None
+ r->ob_type: None
+ PyLongObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:44:
+ repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=44))
+ str(): PyLongObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:44
+ r->ob_refcnt: None
+ r->ob_type: None
+ Exception:
+ RegionForGlobal(gcc.VarDecl('PyExc_MemoryError'))
+
+Trace 8:
+ Transitions:
+ 'PyList_New() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() fails'
+ 'taking True path'
+ 'taking False path'
+ 'calling tp_dealloc on PyLongObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:44'
+ 'taking False path'
+ 'calling tp_dealloc on PyLongObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:39'
+ 'taking False path'
+ 'calling tp_dealloc on PyListObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:33'
+ 'returning'
+ Return value:
+ repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=55), value=0)
+ str(): (struct PyObject *)0 from tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:55
+ Region("region-for-arg-gcc.ParmDecl('self')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('self')")
+ str(): Region("region-for-arg-gcc.ParmDecl('self')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
+ Region("region-for-arg-gcc.ParmDecl('args')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('args')")
+ str(): Region("region-for-arg-gcc.ParmDecl('args')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
+ PyListObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:33:
+ repr(): RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=33))
+ str(): PyListObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:33
+ r->ob_refcnt: None
+ r->ob_type: None
+ PyLongObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:39:
+ repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=39))
+ str(): PyLongObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:39
+ r->ob_refcnt: None
+ r->ob_type: None
+ PyLongObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:44:
+ repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=44))
+ str(): PyLongObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:44
+ r->ob_refcnt: None
+ r->ob_type: None
+ Exception:
+ RegionForGlobal(gcc.VarDecl('PyExc_MemoryError'))
+
+Trace 9:
+ Transitions:
+ 'PyList_New() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() fails'
+ 'taking True path'
+ 'taking True path'
+ 'taking True path'
+ 'returning'
+ Return value:
+ repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=48), value=0)
+ str(): (struct PyObject *)0 from tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:48
+ Region("region-for-arg-gcc.ParmDecl('self')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('self')")
+ str(): Region("region-for-arg-gcc.ParmDecl('self')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
+ Region("region-for-arg-gcc.ParmDecl('args')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('args')")
+ str(): Region("region-for-arg-gcc.ParmDecl('args')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
+ PyListObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:33:
+ repr(): RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=33))
+ str(): PyListObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:33
+ r->ob_refcnt: refs: 0 + N where N >= 0
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=33), region=RegionForGlobal(gcc.VarDecl('PyList_Type')))
+ PyLongObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:39:
+ repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=39))
+ str(): PyLongObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:39
+ r->ob_refcnt: refs: 0 + N where N >= 0
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=39), region=RegionForGlobal(gcc.VarDecl('PyLong_Type')))
+ Exception:
+ RegionForGlobal(gcc.VarDecl('PyExc_MemoryError'))
+
+Trace 10:
+ Transitions:
+ 'PyList_New() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() fails'
+ 'taking True path'
+ 'taking True path'
+ 'taking False path'
+ 'calling tp_dealloc on PyListObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:33'
+ 'returning'
+ Return value:
+ repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=48), value=0)
+ str(): (struct PyObject *)0 from tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:48
+ Region("region-for-arg-gcc.ParmDecl('self')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('self')")
+ str(): Region("region-for-arg-gcc.ParmDecl('self')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
+ Region("region-for-arg-gcc.ParmDecl('args')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('args')")
+ str(): Region("region-for-arg-gcc.ParmDecl('args')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
+ PyListObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:33:
+ repr(): RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=33))
+ str(): PyListObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:33
+ r->ob_refcnt: None
+ r->ob_type: None
+ PyLongObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:39:
+ repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=39))
+ str(): PyLongObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:39
+ r->ob_refcnt: refs: 0 + N where N >= 0
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=39), region=RegionForGlobal(gcc.VarDecl('PyLong_Type')))
+ Exception:
+ RegionForGlobal(gcc.VarDecl('PyExc_MemoryError'))
+
+Trace 11:
+ Transitions:
+ 'PyList_New() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() fails'
+ 'taking True path'
+ 'taking False path'
+ 'calling tp_dealloc on PyLongObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:39'
+ 'taking True path'
+ 'returning'
+ Return value:
+ repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=48), value=0)
+ str(): (struct PyObject *)0 from tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:48
+ Region("region-for-arg-gcc.ParmDecl('self')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('self')")
+ str(): Region("region-for-arg-gcc.ParmDecl('self')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
+ Region("region-for-arg-gcc.ParmDecl('args')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('args')")
+ str(): Region("region-for-arg-gcc.ParmDecl('args')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
+ PyListObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:33:
+ repr(): RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=33))
+ str(): PyListObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:33
+ r->ob_refcnt: refs: 0 + N where N >= 0
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=33), region=RegionForGlobal(gcc.VarDecl('PyList_Type')))
+ PyLongObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:39:
+ repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=39))
+ str(): PyLongObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:39
+ r->ob_refcnt: None
+ r->ob_type: None
+ Exception:
+ RegionForGlobal(gcc.VarDecl('PyExc_MemoryError'))
+
+Trace 12:
+ Transitions:
+ 'PyList_New() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() fails'
+ 'taking True path'
+ 'taking False path'
+ 'calling tp_dealloc on PyLongObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:39'
+ 'taking False path'
+ 'calling tp_dealloc on PyListObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:33'
+ 'returning'
+ Return value:
+ repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=48), value=0)
+ str(): (struct PyObject *)0 from tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:48
+ Region("region-for-arg-gcc.ParmDecl('self')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('self')")
+ str(): Region("region-for-arg-gcc.ParmDecl('self')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
+ Region("region-for-arg-gcc.ParmDecl('args')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('args')")
+ str(): Region("region-for-arg-gcc.ParmDecl('args')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
+ PyListObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:33:
+ repr(): RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=33))
+ str(): PyListObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:33
+ r->ob_refcnt: None
+ r->ob_type: None
+ PyLongObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:39:
+ repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=39))
+ str(): PyLongObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:39
+ r->ob_refcnt: None
+ r->ob_type: None
+ Exception:
+ RegionForGlobal(gcc.VarDecl('PyExc_MemoryError'))
+
+Trace 13:
+ Transitions:
+ 'PyList_New() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() fails'
+ 'taking True path'
+ 'taking True path'
+ 'returning'
+ Return value:
+ repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=42), value=0)
+ str(): (struct PyObject *)0 from tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:42
+ Region("region-for-arg-gcc.ParmDecl('self')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('self')")
+ str(): Region("region-for-arg-gcc.ParmDecl('self')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
+ Region("region-for-arg-gcc.ParmDecl('args')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('args')")
+ str(): Region("region-for-arg-gcc.ParmDecl('args')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
+ PyListObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:33:
+ repr(): RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=33))
+ str(): PyListObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:33
+ r->ob_refcnt: refs: 0 + N where N >= 0
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=33), region=RegionForGlobal(gcc.VarDecl('PyList_Type')))
+ Exception:
+ RegionForGlobal(gcc.VarDecl('PyExc_MemoryError'))
+
+Trace 14:
+ Transitions:
+ 'PyList_New() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() fails'
+ 'taking True path'
+ 'taking False path'
+ 'calling tp_dealloc on PyListObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:33'
+ 'returning'
+ Return value:
+ repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=42), value=0)
+ str(): (struct PyObject *)0 from tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:42
+ Region("region-for-arg-gcc.ParmDecl('self')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('self')")
+ str(): Region("region-for-arg-gcc.ParmDecl('self')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
+ Region("region-for-arg-gcc.ParmDecl('args')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('args')")
+ str(): Region("region-for-arg-gcc.ParmDecl('args')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
+ PyListObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:33:
+ repr(): RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=33))
+ str(): PyListObject allocated at tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:33
+ r->ob_refcnt: None
+ r->ob_type: None
+ Exception:
+ RegionForGlobal(gcc.VarDecl('PyExc_MemoryError'))
+
+Trace 15:
+ Transitions:
+ 'PyList_New() fails'
+ 'taking True path'
+ 'returning'
+ Return value:
+ repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=35), value=0)
+ str(): (struct PyObject *)0 from tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c:35
+ Region("region-for-arg-gcc.ParmDecl('self')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('self')")
+ str(): Region("region-for-arg-gcc.ParmDecl('self')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
+ Region("region-for-arg-gcc.ParmDecl('args')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('args')")
+ str(): Region("region-for-arg-gcc.ParmDecl('args')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_PyList_SET_ITEM_macro_multiple/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
+ Exception:
+ RegionForGlobal(gcc.VarDecl('PyExc_MemoryError'))
diff --git a/tests/cpychecker/refcounts/correct_decref/stdout.txt b/tests/cpychecker/refcounts/correct_decref/stdout.txt
index eddd96c..d6ade9a 100644
--- a/tests/cpychecker/refcounts/correct_decref/stdout.txt
+++ b/tests/cpychecker/refcounts/correct_decref/stdout.txt
@@ -7,17 +7,17 @@ Trace 0:
Return value:
repr(): PointerToRegion(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_decref/input.c', line=30), region=RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/correct_decref/input.c', line=30)))
str(): (struct PyObject *)&RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/correct_decref/input.c', line=30)) from tests/cpychecker/refcounts/correct_decref/input.c:30
- r->ob_refcnt: RefcountValue(1)
+ r->ob_refcnt: refs: 1 + N where N >= 0
r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_decref/input.c', line=30), region=RegionForGlobal(gcc.VarDecl('PyLong_Type')))
Region("region-for-arg-gcc.ParmDecl('self')"):
repr(): Region("region-for-arg-gcc.ParmDecl('self')")
str(): Region("region-for-arg-gcc.ParmDecl('self')")
- r->ob_refcnt: RefcountValue(0)
+ r->ob_refcnt: refs: 0 + N where N >= 1
r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_decref/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
Region("region-for-arg-gcc.ParmDecl('args')"):
repr(): Region("region-for-arg-gcc.ParmDecl('args')")
str(): Region("region-for-arg-gcc.ParmDecl('args')")
- r->ob_refcnt: RefcountValue(0)
+ r->ob_refcnt: refs: 0 + N where N >= 1
r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_decref/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
Exception:
(struct PyObject *)0 from tests/cpychecker/refcounts/correct_decref/input.c:28
@@ -33,12 +33,12 @@ Trace 1:
Region("region-for-arg-gcc.ParmDecl('self')"):
repr(): Region("region-for-arg-gcc.ParmDecl('self')")
str(): Region("region-for-arg-gcc.ParmDecl('self')")
- r->ob_refcnt: RefcountValue(0)
+ r->ob_refcnt: refs: 0 + N where N >= 1
r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_decref/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
Region("region-for-arg-gcc.ParmDecl('args')"):
repr(): Region("region-for-arg-gcc.ParmDecl('args')")
str(): Region("region-for-arg-gcc.ParmDecl('args')")
- r->ob_refcnt: RefcountValue(0)
+ r->ob_refcnt: refs: 0 + N where N >= 1
r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_decref/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
Exception:
RegionForGlobal(gcc.VarDecl('PyExc_MemoryError'))
diff --git a/tests/cpychecker/refcounts/correct_object_ctor/stdout.txt b/tests/cpychecker/refcounts/correct_object_ctor/stdout.txt
index 78a5e4f..b18bf5e 100644
--- a/tests/cpychecker/refcounts/correct_object_ctor/stdout.txt
+++ b/tests/cpychecker/refcounts/correct_object_ctor/stdout.txt
@@ -1,5 +1,5 @@
Trace 0:
returned: PointerToRegion(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_object_ctor/input.c', line=30), region=RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/correct_object_ctor/input.c', line=30)))
- r->ob_refcnt: RefcountValue(1)
+ r->ob_refcnt: RefcountValue(1, 0)
Trace 1:
returned: ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_object_ctor/input.c', line=30), value=0)
diff --git a/tests/cpychecker/refcounts/correct_py_none/stdout.txt b/tests/cpychecker/refcounts/correct_py_none/stdout.txt
index 72eaaf9..cb011f5 100644
--- a/tests/cpychecker/refcounts/correct_py_none/stdout.txt
+++ b/tests/cpychecker/refcounts/correct_py_none/stdout.txt
@@ -4,17 +4,17 @@ Trace 0:
Return value:
repr(): PointerToRegion(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_py_none/input.c', line=25), region=RegionForGlobal(gcc.VarDecl('_Py_NoneStruct')))
str(): (struct PyObject *)&RegionForGlobal(gcc.VarDecl('_Py_NoneStruct')) from tests/cpychecker/refcounts/correct_py_none/input.c:25
- r->ob_refcnt: RefcountValue(1)
+ r->ob_refcnt: refs: 1 + N where N >= 1
r->ob_type: None
Region("region-for-arg-gcc.ParmDecl('self')"):
repr(): Region("region-for-arg-gcc.ParmDecl('self')")
str(): Region("region-for-arg-gcc.ParmDecl('self')")
- r->ob_refcnt: RefcountValue(0)
+ r->ob_refcnt: refs: 0 + N where N >= 1
r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_py_none/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
Region("region-for-arg-gcc.ParmDecl('args')"):
repr(): Region("region-for-arg-gcc.ParmDecl('args')")
str(): Region("region-for-arg-gcc.ParmDecl('args')")
- r->ob_refcnt: RefcountValue(0)
+ r->ob_refcnt: refs: 0 + N where N >= 1
r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/correct_py_none/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
Exception:
(struct PyObject *)0 from tests/cpychecker/refcounts/correct_py_none/input.c:24
diff --git a/tests/cpychecker/refcounts/fold_conditional/stdout.txt b/tests/cpychecker/refcounts/fold_conditional/stdout.txt
index a18a8a0..36c55a4 100644
--- a/tests/cpychecker/refcounts/fold_conditional/stdout.txt
+++ b/tests/cpychecker/refcounts/fold_conditional/stdout.txt
@@ -8,17 +8,17 @@ Trace 0:
Return value:
repr(): PointerToRegion(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/fold_conditional/input.c', line=26), region=RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/fold_conditional/input.c', line=26)))
str(): (struct PyObject *)&RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/fold_conditional/input.c', line=26)) from tests/cpychecker/refcounts/fold_conditional/input.c:26
- r->ob_refcnt: RefcountValue(1)
+ r->ob_refcnt: refs: 1 + N where N >= 0
r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/fold_conditional/input.c', line=26), region=RegionForGlobal(gcc.VarDecl('PyList_Type')))
Region("region-for-arg-gcc.ParmDecl('self')"):
repr(): Region("region-for-arg-gcc.ParmDecl('self')")
str(): Region("region-for-arg-gcc.ParmDecl('self')")
- r->ob_refcnt: RefcountValue(0)
+ r->ob_refcnt: refs: 0 + N where N >= 1
r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/fold_conditional/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
Region("region-for-arg-gcc.ParmDecl('args')"):
repr(): Region("region-for-arg-gcc.ParmDecl('args')")
str(): Region("region-for-arg-gcc.ParmDecl('args')")
- r->ob_refcnt: RefcountValue(0)
+ r->ob_refcnt: refs: 0 + N where N >= 1
r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/fold_conditional/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
Exception:
(struct PyObject *)0 from tests/cpychecker/refcounts/fold_conditional/input.c:24
@@ -34,12 +34,12 @@ Trace 1:
Region("region-for-arg-gcc.ParmDecl('self')"):
repr(): Region("region-for-arg-gcc.ParmDecl('self')")
str(): Region("region-for-arg-gcc.ParmDecl('self')")
- r->ob_refcnt: RefcountValue(0)
+ r->ob_refcnt: refs: 0 + N where N >= 1
r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/fold_conditional/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
Region("region-for-arg-gcc.ParmDecl('args')"):
repr(): Region("region-for-arg-gcc.ParmDecl('args')")
str(): Region("region-for-arg-gcc.ParmDecl('args')")
- r->ob_refcnt: RefcountValue(0)
+ r->ob_refcnt: refs: 0 + N where N >= 1
r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/fold_conditional/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
Exception:
RegionForGlobal(gcc.VarDecl('PyExc_MemoryError'))
diff --git a/tests/cpychecker/refcounts/getter/stdout.txt b/tests/cpychecker/refcounts/getter/stdout.txt
index 581721c..161415c 100644
--- a/tests/cpychecker/refcounts/getter/stdout.txt
+++ b/tests/cpychecker/refcounts/getter/stdout.txt
@@ -7,7 +7,7 @@ Trace 0:
Region("region-for-arg-gcc.ParmDecl('self')"):
repr(): Region("region-for-arg-gcc.ParmDecl('self')")
str(): Region("region-for-arg-gcc.ParmDecl('self')")
- r->ob_refcnt: RefcountValue(0)
+ r->ob_refcnt: refs: 0 + N where N >= 1
r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/getter/input.c', line=35), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
Exception:
(struct PyObject *)0 from tests/cpychecker/refcounts/getter/input.c:36
diff --git a/tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c b/tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c
new file mode 100644
index 0000000..2312468
--- /dev/null
+++ b/tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c
@@ -0,0 +1,88 @@
+/*
+ Copyright 2011 David Malcolm <dmalcolm(a)redhat.com>
+ Copyright 2011 Red Hat, Inc.
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see
+ <http://www.gnu.org/licenses/>.
+*/
+
+#include <Python.h>
+
+PyObject *
+handle_SET_ITEM_macro(PyObject *self, PyObject *args)
+{
+ PyObject *list;
+ /*
+ The checker must not get confused by this temporary array:
+ the borrowed refs that it stores do not persist beyond the
+ lifetime of the function:
+ */
+ PyObject *items[3];
+
+ list = PyList_New(3);
+ if (!list) {
+ return NULL;
+ }
+
+ /* Construct 3 new references: */
+ items[0] = PyLong_FromLong(1000);
+ if (!items[0]) {
+ Py_DECREF(list);
+ return NULL;
+ }
+ items[1] = PyLong_FromLong(2000);
+ if (!items[1]) {
+ Py_DECREF(items[0]);
+ Py_DECREF(list);
+ return NULL;
+ }
+ items[2] = PyLong_FromLong(3000);
+ if (!items[2]) {
+ Py_DECREF(items[1]);
+ Py_DECREF(items[0]);
+ Py_DECREF(list);
+ return NULL;
+ }
+
+ /*
+ Set each item in the list via the PyList_SET_ITEM macro.
+
+ These are stolen references, so at this point the reference counts for
+ the PyLongObjects are balanced.
+ */
+ PyList_SET_ITEM(list, 0, items[0]);
+ PyList_SET_ITEM(list, 1, items[1]);
+ PyList_SET_ITEM(list, 2, items[2]);
+
+ /*
+ Now erroneously increment the reference count on one of them:
+ */
+ Py_INCREF(items[2]);
+
+ /* This is a leak of items[2]: the 3 new references are owned by the list
+ but the extra incref above is a leak: */
+ return list;
+}
+static PyMethodDef test_methods[] = {
+ {"test_method", handle_SET_ITEM_macro, METH_VARARGS, NULL},
+ {NULL, NULL, 0, NULL} /* Sentinel */
+};
+
+/*
+ PEP-7
+Local variables:
+c-basic-offset: 4
+indent-tabs-mode: nil
+End:
+*/
diff --git a/tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/script.py b/tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/script.py
new file mode 100644
index 0000000..6bb62fd
--- /dev/null
+++ b/tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/script.py
@@ -0,0 +1,22 @@
+# -*- coding: utf-8 -*-
+# Copyright 2011 David Malcolm <dmalcolm(a)redhat.com>
+# Copyright 2011 Red Hat, Inc.
+#
+# This is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program 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
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see
+# <http://www.gnu.org/licenses/>.
+
+from libcpychecker import main
+
+main(verify_refcounting=True,
+ dump_traces=True)
diff --git a/tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/stderr.txt b/tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/stderr.txt
new file mode 100644
index 0000000..08fafe0
--- /dev/null
+++ b/tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/stderr.txt
@@ -0,0 +1,23 @@
+tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c: In function 'handle_SET_ITEM_macro':
+tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:76:1: error: ob_refcnt of PyLongObject is 1 too high
+tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:76:1: note: was expecting final ob_refcnt to be N + 1 (for some unknown N)
+tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:76:1: note: due to object being referenced by: ob_item array for PyListObject[2]
+tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:76:1: note: but final ob_refcnt is N + 2
+tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:50:31: note: PyLongObject allocated at: items[2] = PyLong_FromLong(3000);
+tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:33:10: note: when PyList_New() succeeds at: list = PyList_New(3);
+tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:34:8: note: when taking False path at: if (!list) {
+tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:39:31: note: reaching: items[0] = PyLong_FromLong(1000);
+tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:39:31: note: when PyLong_FromLong() succeeds at: items[0] = PyLong_FromLong(1000);
+tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:40:8: note: when taking False path at: if (!items[0]) {
+tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:44:31: note: reaching: items[1] = PyLong_FromLong(2000);
+tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:44:31: note: when PyLong_FromLong() succeeds at: items[1] = PyLong_FromLong(2000);
+tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:45:8: note: when taking False path at: if (!items[1]) {
+tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:50:31: note: reaching: items[2] = PyLong_FromLong(3000);
+tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:50:31: note: when PyLong_FromLong() succeeds at: items[2] = PyLong_FromLong(3000);
+tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:50:31: note: ob_refcnt is now refs: 1 + N where N >= 0
+tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:51:8: note: when taking False path at: if (!items[2]) {
+tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:64:5: note: reaching: PyList_SET_ITEM(list, 0, items[0]);
+tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:66:5: note: PyLongObject is now referenced by 1 non-stack value(s): ob_item array for PyListObject[2]
+tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:71:5: note: ob_refcnt is now refs: 2 + N where N >= 0
+tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:76:1: note: when returning
+tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:24:1: note: graphical error report for function 'handle_SET_ITEM_macro' written out to 'tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c.handle_SET_ITEM_macro-refcount-errors.html'
diff --git a/tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/stdout.txt b/tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/stdout.txt
new file mode 100644
index 0000000..5f175a7
--- /dev/null
+++ b/tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/stdout.txt
@@ -0,0 +1,647 @@
+Trace 0:
+ Transitions:
+ 'PyList_New() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() succeeds'
+ 'taking False path'
+ 'returning'
+ Return value:
+ repr(): PointerToRegion(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=33), region=RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=33)))
+ str(): (struct PyObject *)&RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=33)) from tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:33
+ r->ob_refcnt: refs: 1 + N where N >= 0
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=33), region=RegionForGlobal(gcc.VarDecl('PyList_Type')))
+ Region("region-for-arg-gcc.ParmDecl('self')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('self')")
+ str(): Region("region-for-arg-gcc.ParmDecl('self')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
+ Region("region-for-arg-gcc.ParmDecl('args')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('args')")
+ str(): Region("region-for-arg-gcc.ParmDecl('args')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
+ PyLongObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:39:
+ repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=39))
+ str(): PyLongObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:39
+ r->ob_refcnt: refs: 1 + N where N >= 0
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=39), region=RegionForGlobal(gcc.VarDecl('PyLong_Type')))
+ PyLongObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:44:
+ repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=44))
+ str(): PyLongObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:44
+ r->ob_refcnt: refs: 1 + N where N >= 0
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=44), region=RegionForGlobal(gcc.VarDecl('PyLong_Type')))
+ PyLongObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:50:
+ repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=50))
+ str(): PyLongObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:50
+ r->ob_refcnt: refs: 2 + N where N >= 0
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=50), region=RegionForGlobal(gcc.VarDecl('PyLong_Type')))
+ Exception:
+ (struct PyObject *)0 from tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:24
+
+Trace 1:
+ Transitions:
+ 'PyList_New() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() fails'
+ 'taking True path'
+ 'taking True path'
+ 'taking True path'
+ 'taking True path'
+ 'returning'
+ Return value:
+ repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=55), value=0)
+ str(): (struct PyObject *)0 from tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:55
+ Region("region-for-arg-gcc.ParmDecl('self')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('self')")
+ str(): Region("region-for-arg-gcc.ParmDecl('self')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
+ Region("region-for-arg-gcc.ParmDecl('args')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('args')")
+ str(): Region("region-for-arg-gcc.ParmDecl('args')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
+ PyListObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:33:
+ repr(): RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=33))
+ str(): PyListObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:33
+ r->ob_refcnt: refs: 0 + N where N >= 0
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=33), region=RegionForGlobal(gcc.VarDecl('PyList_Type')))
+ PyLongObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:39:
+ repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=39))
+ str(): PyLongObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:39
+ r->ob_refcnt: refs: 0 + N where N >= 0
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=39), region=RegionForGlobal(gcc.VarDecl('PyLong_Type')))
+ PyLongObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:44:
+ repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=44))
+ str(): PyLongObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:44
+ r->ob_refcnt: refs: 0 + N where N >= 0
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=44), region=RegionForGlobal(gcc.VarDecl('PyLong_Type')))
+ Exception:
+ RegionForGlobal(gcc.VarDecl('PyExc_MemoryError'))
+
+Trace 2:
+ Transitions:
+ 'PyList_New() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() fails'
+ 'taking True path'
+ 'taking True path'
+ 'taking True path'
+ 'taking False path'
+ 'calling tp_dealloc on PyListObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:33'
+ 'returning'
+ Return value:
+ repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=55), value=0)
+ str(): (struct PyObject *)0 from tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:55
+ Region("region-for-arg-gcc.ParmDecl('self')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('self')")
+ str(): Region("region-for-arg-gcc.ParmDecl('self')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
+ Region("region-for-arg-gcc.ParmDecl('args')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('args')")
+ str(): Region("region-for-arg-gcc.ParmDecl('args')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
+ PyListObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:33:
+ repr(): RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=33))
+ str(): PyListObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:33
+ r->ob_refcnt: None
+ r->ob_type: None
+ PyLongObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:39:
+ repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=39))
+ str(): PyLongObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:39
+ r->ob_refcnt: refs: 0 + N where N >= 0
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=39), region=RegionForGlobal(gcc.VarDecl('PyLong_Type')))
+ PyLongObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:44:
+ repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=44))
+ str(): PyLongObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:44
+ r->ob_refcnt: refs: 0 + N where N >= 0
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=44), region=RegionForGlobal(gcc.VarDecl('PyLong_Type')))
+ Exception:
+ RegionForGlobal(gcc.VarDecl('PyExc_MemoryError'))
+
+Trace 3:
+ Transitions:
+ 'PyList_New() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() fails'
+ 'taking True path'
+ 'taking True path'
+ 'taking False path'
+ 'calling tp_dealloc on PyLongObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:39'
+ 'taking True path'
+ 'returning'
+ Return value:
+ repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=55), value=0)
+ str(): (struct PyObject *)0 from tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:55
+ Region("region-for-arg-gcc.ParmDecl('self')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('self')")
+ str(): Region("region-for-arg-gcc.ParmDecl('self')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
+ Region("region-for-arg-gcc.ParmDecl('args')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('args')")
+ str(): Region("region-for-arg-gcc.ParmDecl('args')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
+ PyListObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:33:
+ repr(): RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=33))
+ str(): PyListObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:33
+ r->ob_refcnt: refs: 0 + N where N >= 0
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=33), region=RegionForGlobal(gcc.VarDecl('PyList_Type')))
+ PyLongObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:39:
+ repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=39))
+ str(): PyLongObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:39
+ r->ob_refcnt: None
+ r->ob_type: None
+ PyLongObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:44:
+ repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=44))
+ str(): PyLongObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:44
+ r->ob_refcnt: refs: 0 + N where N >= 0
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=44), region=RegionForGlobal(gcc.VarDecl('PyLong_Type')))
+ Exception:
+ RegionForGlobal(gcc.VarDecl('PyExc_MemoryError'))
+
+Trace 4:
+ Transitions:
+ 'PyList_New() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() fails'
+ 'taking True path'
+ 'taking True path'
+ 'taking False path'
+ 'calling tp_dealloc on PyLongObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:39'
+ 'taking False path'
+ 'calling tp_dealloc on PyListObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:33'
+ 'returning'
+ Return value:
+ repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=55), value=0)
+ str(): (struct PyObject *)0 from tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:55
+ Region("region-for-arg-gcc.ParmDecl('self')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('self')")
+ str(): Region("region-for-arg-gcc.ParmDecl('self')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
+ Region("region-for-arg-gcc.ParmDecl('args')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('args')")
+ str(): Region("region-for-arg-gcc.ParmDecl('args')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
+ PyListObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:33:
+ repr(): RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=33))
+ str(): PyListObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:33
+ r->ob_refcnt: None
+ r->ob_type: None
+ PyLongObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:39:
+ repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=39))
+ str(): PyLongObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:39
+ r->ob_refcnt: None
+ r->ob_type: None
+ PyLongObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:44:
+ repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=44))
+ str(): PyLongObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:44
+ r->ob_refcnt: refs: 0 + N where N >= 0
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=44), region=RegionForGlobal(gcc.VarDecl('PyLong_Type')))
+ Exception:
+ RegionForGlobal(gcc.VarDecl('PyExc_MemoryError'))
+
+Trace 5:
+ Transitions:
+ 'PyList_New() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() fails'
+ 'taking True path'
+ 'taking False path'
+ 'calling tp_dealloc on PyLongObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:44'
+ 'taking True path'
+ 'taking True path'
+ 'returning'
+ Return value:
+ repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=55), value=0)
+ str(): (struct PyObject *)0 from tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:55
+ Region("region-for-arg-gcc.ParmDecl('self')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('self')")
+ str(): Region("region-for-arg-gcc.ParmDecl('self')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
+ Region("region-for-arg-gcc.ParmDecl('args')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('args')")
+ str(): Region("region-for-arg-gcc.ParmDecl('args')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
+ PyListObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:33:
+ repr(): RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=33))
+ str(): PyListObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:33
+ r->ob_refcnt: refs: 0 + N where N >= 0
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=33), region=RegionForGlobal(gcc.VarDecl('PyList_Type')))
+ PyLongObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:39:
+ repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=39))
+ str(): PyLongObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:39
+ r->ob_refcnt: refs: 0 + N where N >= 0
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=39), region=RegionForGlobal(gcc.VarDecl('PyLong_Type')))
+ PyLongObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:44:
+ repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=44))
+ str(): PyLongObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:44
+ r->ob_refcnt: None
+ r->ob_type: None
+ Exception:
+ RegionForGlobal(gcc.VarDecl('PyExc_MemoryError'))
+
+Trace 6:
+ Transitions:
+ 'PyList_New() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() fails'
+ 'taking True path'
+ 'taking False path'
+ 'calling tp_dealloc on PyLongObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:44'
+ 'taking True path'
+ 'taking False path'
+ 'calling tp_dealloc on PyListObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:33'
+ 'returning'
+ Return value:
+ repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=55), value=0)
+ str(): (struct PyObject *)0 from tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:55
+ Region("region-for-arg-gcc.ParmDecl('self')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('self')")
+ str(): Region("region-for-arg-gcc.ParmDecl('self')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
+ Region("region-for-arg-gcc.ParmDecl('args')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('args')")
+ str(): Region("region-for-arg-gcc.ParmDecl('args')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
+ PyListObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:33:
+ repr(): RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=33))
+ str(): PyListObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:33
+ r->ob_refcnt: None
+ r->ob_type: None
+ PyLongObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:39:
+ repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=39))
+ str(): PyLongObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:39
+ r->ob_refcnt: refs: 0 + N where N >= 0
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=39), region=RegionForGlobal(gcc.VarDecl('PyLong_Type')))
+ PyLongObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:44:
+ repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=44))
+ str(): PyLongObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:44
+ r->ob_refcnt: None
+ r->ob_type: None
+ Exception:
+ RegionForGlobal(gcc.VarDecl('PyExc_MemoryError'))
+
+Trace 7:
+ Transitions:
+ 'PyList_New() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() fails'
+ 'taking True path'
+ 'taking False path'
+ 'calling tp_dealloc on PyLongObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:44'
+ 'taking False path'
+ 'calling tp_dealloc on PyLongObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:39'
+ 'taking True path'
+ 'returning'
+ Return value:
+ repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=55), value=0)
+ str(): (struct PyObject *)0 from tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:55
+ Region("region-for-arg-gcc.ParmDecl('self')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('self')")
+ str(): Region("region-for-arg-gcc.ParmDecl('self')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
+ Region("region-for-arg-gcc.ParmDecl('args')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('args')")
+ str(): Region("region-for-arg-gcc.ParmDecl('args')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
+ PyListObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:33:
+ repr(): RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=33))
+ str(): PyListObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:33
+ r->ob_refcnt: refs: 0 + N where N >= 0
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=33), region=RegionForGlobal(gcc.VarDecl('PyList_Type')))
+ PyLongObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:39:
+ repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=39))
+ str(): PyLongObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:39
+ r->ob_refcnt: None
+ r->ob_type: None
+ PyLongObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:44:
+ repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=44))
+ str(): PyLongObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:44
+ r->ob_refcnt: None
+ r->ob_type: None
+ Exception:
+ RegionForGlobal(gcc.VarDecl('PyExc_MemoryError'))
+
+Trace 8:
+ Transitions:
+ 'PyList_New() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() fails'
+ 'taking True path'
+ 'taking False path'
+ 'calling tp_dealloc on PyLongObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:44'
+ 'taking False path'
+ 'calling tp_dealloc on PyLongObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:39'
+ 'taking False path'
+ 'calling tp_dealloc on PyListObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:33'
+ 'returning'
+ Return value:
+ repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=55), value=0)
+ str(): (struct PyObject *)0 from tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:55
+ Region("region-for-arg-gcc.ParmDecl('self')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('self')")
+ str(): Region("region-for-arg-gcc.ParmDecl('self')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
+ Region("region-for-arg-gcc.ParmDecl('args')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('args')")
+ str(): Region("region-for-arg-gcc.ParmDecl('args')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
+ PyListObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:33:
+ repr(): RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=33))
+ str(): PyListObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:33
+ r->ob_refcnt: None
+ r->ob_type: None
+ PyLongObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:39:
+ repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=39))
+ str(): PyLongObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:39
+ r->ob_refcnt: None
+ r->ob_type: None
+ PyLongObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:44:
+ repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=44))
+ str(): PyLongObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:44
+ r->ob_refcnt: None
+ r->ob_type: None
+ Exception:
+ RegionForGlobal(gcc.VarDecl('PyExc_MemoryError'))
+
+Trace 9:
+ Transitions:
+ 'PyList_New() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() fails'
+ 'taking True path'
+ 'taking True path'
+ 'taking True path'
+ 'returning'
+ Return value:
+ repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=48), value=0)
+ str(): (struct PyObject *)0 from tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:48
+ Region("region-for-arg-gcc.ParmDecl('self')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('self')")
+ str(): Region("region-for-arg-gcc.ParmDecl('self')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
+ Region("region-for-arg-gcc.ParmDecl('args')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('args')")
+ str(): Region("region-for-arg-gcc.ParmDecl('args')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
+ PyListObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:33:
+ repr(): RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=33))
+ str(): PyListObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:33
+ r->ob_refcnt: refs: 0 + N where N >= 0
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=33), region=RegionForGlobal(gcc.VarDecl('PyList_Type')))
+ PyLongObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:39:
+ repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=39))
+ str(): PyLongObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:39
+ r->ob_refcnt: refs: 0 + N where N >= 0
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=39), region=RegionForGlobal(gcc.VarDecl('PyLong_Type')))
+ Exception:
+ RegionForGlobal(gcc.VarDecl('PyExc_MemoryError'))
+
+Trace 10:
+ Transitions:
+ 'PyList_New() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() fails'
+ 'taking True path'
+ 'taking True path'
+ 'taking False path'
+ 'calling tp_dealloc on PyListObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:33'
+ 'returning'
+ Return value:
+ repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=48), value=0)
+ str(): (struct PyObject *)0 from tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:48
+ Region("region-for-arg-gcc.ParmDecl('self')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('self')")
+ str(): Region("region-for-arg-gcc.ParmDecl('self')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
+ Region("region-for-arg-gcc.ParmDecl('args')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('args')")
+ str(): Region("region-for-arg-gcc.ParmDecl('args')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
+ PyListObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:33:
+ repr(): RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=33))
+ str(): PyListObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:33
+ r->ob_refcnt: None
+ r->ob_type: None
+ PyLongObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:39:
+ repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=39))
+ str(): PyLongObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:39
+ r->ob_refcnt: refs: 0 + N where N >= 0
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=39), region=RegionForGlobal(gcc.VarDecl('PyLong_Type')))
+ Exception:
+ RegionForGlobal(gcc.VarDecl('PyExc_MemoryError'))
+
+Trace 11:
+ Transitions:
+ 'PyList_New() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() fails'
+ 'taking True path'
+ 'taking False path'
+ 'calling tp_dealloc on PyLongObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:39'
+ 'taking True path'
+ 'returning'
+ Return value:
+ repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=48), value=0)
+ str(): (struct PyObject *)0 from tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:48
+ Region("region-for-arg-gcc.ParmDecl('self')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('self')")
+ str(): Region("region-for-arg-gcc.ParmDecl('self')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
+ Region("region-for-arg-gcc.ParmDecl('args')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('args')")
+ str(): Region("region-for-arg-gcc.ParmDecl('args')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
+ PyListObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:33:
+ repr(): RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=33))
+ str(): PyListObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:33
+ r->ob_refcnt: refs: 0 + N where N >= 0
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=33), region=RegionForGlobal(gcc.VarDecl('PyList_Type')))
+ PyLongObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:39:
+ repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=39))
+ str(): PyLongObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:39
+ r->ob_refcnt: None
+ r->ob_type: None
+ Exception:
+ RegionForGlobal(gcc.VarDecl('PyExc_MemoryError'))
+
+Trace 12:
+ Transitions:
+ 'PyList_New() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() fails'
+ 'taking True path'
+ 'taking False path'
+ 'calling tp_dealloc on PyLongObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:39'
+ 'taking False path'
+ 'calling tp_dealloc on PyListObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:33'
+ 'returning'
+ Return value:
+ repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=48), value=0)
+ str(): (struct PyObject *)0 from tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:48
+ Region("region-for-arg-gcc.ParmDecl('self')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('self')")
+ str(): Region("region-for-arg-gcc.ParmDecl('self')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
+ Region("region-for-arg-gcc.ParmDecl('args')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('args')")
+ str(): Region("region-for-arg-gcc.ParmDecl('args')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
+ PyListObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:33:
+ repr(): RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=33))
+ str(): PyListObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:33
+ r->ob_refcnt: None
+ r->ob_type: None
+ PyLongObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:39:
+ repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=39))
+ str(): PyLongObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:39
+ r->ob_refcnt: None
+ r->ob_type: None
+ Exception:
+ RegionForGlobal(gcc.VarDecl('PyExc_MemoryError'))
+
+Trace 13:
+ Transitions:
+ 'PyList_New() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() fails'
+ 'taking True path'
+ 'taking True path'
+ 'returning'
+ Return value:
+ repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=42), value=0)
+ str(): (struct PyObject *)0 from tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:42
+ Region("region-for-arg-gcc.ParmDecl('self')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('self')")
+ str(): Region("region-for-arg-gcc.ParmDecl('self')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
+ Region("region-for-arg-gcc.ParmDecl('args')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('args')")
+ str(): Region("region-for-arg-gcc.ParmDecl('args')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
+ PyListObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:33:
+ repr(): RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=33))
+ str(): PyListObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:33
+ r->ob_refcnt: refs: 0 + N where N >= 0
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=33), region=RegionForGlobal(gcc.VarDecl('PyList_Type')))
+ Exception:
+ RegionForGlobal(gcc.VarDecl('PyExc_MemoryError'))
+
+Trace 14:
+ Transitions:
+ 'PyList_New() succeeds'
+ 'taking False path'
+ 'PyLong_FromLong() fails'
+ 'taking True path'
+ 'taking False path'
+ 'calling tp_dealloc on PyListObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:33'
+ 'returning'
+ Return value:
+ repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=42), value=0)
+ str(): (struct PyObject *)0 from tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:42
+ Region("region-for-arg-gcc.ParmDecl('self')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('self')")
+ str(): Region("region-for-arg-gcc.ParmDecl('self')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
+ Region("region-for-arg-gcc.ParmDecl('args')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('args')")
+ str(): Region("region-for-arg-gcc.ParmDecl('args')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
+ PyListObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:33:
+ repr(): RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=33))
+ str(): PyListObject allocated at tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:33
+ r->ob_refcnt: None
+ r->ob_type: None
+ Exception:
+ RegionForGlobal(gcc.VarDecl('PyExc_MemoryError'))
+
+Trace 15:
+ Transitions:
+ 'PyList_New() fails'
+ 'taking True path'
+ 'returning'
+ Return value:
+ repr(): ConcreteValue(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=35), value=0)
+ str(): (struct PyObject *)0 from tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c:35
+ Region("region-for-arg-gcc.ParmDecl('self')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('self')")
+ str(): Region("region-for-arg-gcc.ParmDecl('self')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
+ Region("region-for-arg-gcc.ParmDecl('args')"):
+ repr(): Region("region-for-arg-gcc.ParmDecl('args')")
+ str(): Region("region-for-arg-gcc.ParmDecl('args')")
+ r->ob_refcnt: refs: 0 + N where N >= 1
+ r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_PyList_SET_ITEM_macro_multiple/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
+ Exception:
+ RegionForGlobal(gcc.VarDecl('PyExc_MemoryError'))
diff --git a/tests/cpychecker/refcounts/incorrect_py_none/script.py b/tests/cpychecker/refcounts/incorrect_py_none/script.py
index c31bb6e..7fb78e8 100644
--- a/tests/cpychecker/refcounts/incorrect_py_none/script.py
+++ b/tests/cpychecker/refcounts/incorrect_py_none/script.py
@@ -29,7 +29,7 @@ def verify_traces(optpass, fun):
#print('traces: %r' % traces)
assert len(traces) == 1
state = traces[0].states[-1]
- print('_Py_NoneStruct.ob_refcnt: %r'
+ print('_Py_NoneStruct.ob_refcnt: %s'
% state.get_value_of_field_by_varname('_Py_NoneStruct', 'ob_refcnt'))
print('state.return_rvalue: %r' % state.return_rvalue)
diff --git a/tests/cpychecker/refcounts/incorrect_py_none/stderr.txt b/tests/cpychecker/refcounts/incorrect_py_none/stderr.txt
index b7c6866..447d183 100644
--- a/tests/cpychecker/refcounts/incorrect_py_none/stderr.txt
+++ b/tests/cpychecker/refcounts/incorrect_py_none/stderr.txt
@@ -1,5 +1,8 @@
tests/cpychecker/refcounts/incorrect_py_none/input.c: In function 'losing_refcnt_of_none':
tests/cpychecker/refcounts/incorrect_py_none/input.c:26:5: error: ob_refcnt of return value is 1 too low
+tests/cpychecker/refcounts/incorrect_py_none/input.c:26:5: note: was expecting final ob_refcnt to be N + 1 (for some unknown N)
+tests/cpychecker/refcounts/incorrect_py_none/input.c:26:5: note: due to object being referenced by: return value
+tests/cpychecker/refcounts/incorrect_py_none/input.c:26:5: note: but final ob_refcnt is N + 0
tests/cpychecker/refcounts/incorrect_py_none/input.c:26:5: note: when returning at: return Py_None;
tests/cpychecker/refcounts/incorrect_py_none/input.c:26:5: note: consider using "Py_RETURN_NONE;"
tests/cpychecker/refcounts/incorrect_py_none/input.c:24:1: note: graphical error report for function 'losing_refcnt_of_none' written out to 'tests/cpychecker/refcounts/incorrect_py_none/input.c.losing_refcnt_of_none-refcount-errors.html'
diff --git a/tests/cpychecker/refcounts/incorrect_py_none/stdout.txt b/tests/cpychecker/refcounts/incorrect_py_none/stdout.txt
index 763afff..b288c56 100644
--- a/tests/cpychecker/refcounts/incorrect_py_none/stdout.txt
+++ b/tests/cpychecker/refcounts/incorrect_py_none/stdout.txt
@@ -1,2 +1,2 @@
-_Py_NoneStruct.ob_refcnt: RefcountValue(0)
+_Py_NoneStruct.ob_refcnt: refs: 0 + N where N >= 1
state.return_rvalue: PointerToRegion(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/incorrect_py_none/input.c', line=26), region=RegionForGlobal(gcc.VarDecl('_Py_NoneStruct')))
diff --git a/tests/cpychecker/refcounts/loop_n_times/stdout.txt b/tests/cpychecker/refcounts/loop_n_times/stdout.txt
index c8bb07c..258b313 100644
--- a/tests/cpychecker/refcounts/loop_n_times/stdout.txt
+++ b/tests/cpychecker/refcounts/loop_n_times/stdout.txt
@@ -12,22 +12,22 @@ Trace 0:
Return value:
repr(): PointerToRegion(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/loop_n_times/input.c', line=38), region=RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/loop_n_times/input.c', line=38)))
str(): (struct PyObject *)&RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/loop_n_times/input.c', line=38)) from tests/cpychecker/refcounts/loop_n_times/input.c:38
- r->ob_refcnt: RefcountValue(1)
+ r->ob_refcnt: refs: 1 + N where N >= 0
r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/loop_n_times/input.c', line=38), region=RegionForGlobal(gcc.VarDecl('PyList_Type')))
Region("region-for-arg-gcc.ParmDecl('self')"):
repr(): Region("region-for-arg-gcc.ParmDecl('self')")
str(): Region("region-for-arg-gcc.ParmDecl('self')")
- r->ob_refcnt: RefcountValue(0)
+ r->ob_refcnt: refs: 0 + N where N >= 1
r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/loop_n_times/input.c', line=28), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
Region("region-for-arg-gcc.ParmDecl('args')"):
repr(): Region("region-for-arg-gcc.ParmDecl('args')")
str(): Region("region-for-arg-gcc.ParmDecl('args')")
- r->ob_refcnt: RefcountValue(0)
+ r->ob_refcnt: refs: 0 + N where N >= 1
r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/loop_n_times/input.c', line=28), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
PyLongObject allocated at tests/cpychecker/refcounts/loop_n_times/input.c:42:
repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/loop_n_times/input.c', line=42))
str(): PyLongObject allocated at tests/cpychecker/refcounts/loop_n_times/input.c:42
- r->ob_refcnt: RefcountValue(0)
+ r->ob_refcnt: refs: 0 + N where N >= 0
r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/loop_n_times/input.c', line=42), region=RegionForGlobal(gcc.VarDecl('PyLong_Type')))
Exception:
(struct PyObject *)0 from tests/cpychecker/refcounts/loop_n_times/input.c:29
@@ -47,17 +47,17 @@ Trace 1:
Return value:
repr(): PointerToRegion(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/loop_n_times/input.c', line=38), region=RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/loop_n_times/input.c', line=38)))
str(): (struct PyObject *)&RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/loop_n_times/input.c', line=38)) from tests/cpychecker/refcounts/loop_n_times/input.c:38
- r->ob_refcnt: RefcountValue(1)
+ r->ob_refcnt: refs: 1 + N where N >= 0
r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/loop_n_times/input.c', line=38), region=RegionForGlobal(gcc.VarDecl('PyList_Type')))
Region("region-for-arg-gcc.ParmDecl('self')"):
repr(): Region("region-for-arg-gcc.ParmDecl('self')")
str(): Region("region-for-arg-gcc.ParmDecl('self')")
- r->ob_refcnt: RefcountValue(0)
+ r->ob_refcnt: refs: 0 + N where N >= 1
r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/loop_n_times/input.c', line=28), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
Region("region-for-arg-gcc.ParmDecl('args')"):
repr(): Region("region-for-arg-gcc.ParmDecl('args')")
str(): Region("region-for-arg-gcc.ParmDecl('args')")
- r->ob_refcnt: RefcountValue(0)
+ r->ob_refcnt: refs: 0 + N where N >= 1
r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/loop_n_times/input.c', line=28), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
PyLongObject allocated at tests/cpychecker/refcounts/loop_n_times/input.c:42:
repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/loop_n_times/input.c', line=42))
@@ -83,17 +83,17 @@ Trace 2:
Region("region-for-arg-gcc.ParmDecl('self')"):
repr(): Region("region-for-arg-gcc.ParmDecl('self')")
str(): Region("region-for-arg-gcc.ParmDecl('self')")
- r->ob_refcnt: RefcountValue(0)
+ r->ob_refcnt: refs: 0 + N where N >= 1
r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/loop_n_times/input.c', line=28), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
Region("region-for-arg-gcc.ParmDecl('args')"):
repr(): Region("region-for-arg-gcc.ParmDecl('args')")
str(): Region("region-for-arg-gcc.ParmDecl('args')")
- r->ob_refcnt: RefcountValue(0)
+ r->ob_refcnt: refs: 0 + N where N >= 1
r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/loop_n_times/input.c', line=28), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
PyListObject allocated at tests/cpychecker/refcounts/loop_n_times/input.c:38:
repr(): RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/loop_n_times/input.c', line=38))
str(): PyListObject allocated at tests/cpychecker/refcounts/loop_n_times/input.c:38
- r->ob_refcnt: RefcountValue(0)
+ r->ob_refcnt: refs: 0 + N where N >= 0
r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/loop_n_times/input.c', line=38), region=RegionForGlobal(gcc.VarDecl('PyList_Type')))
Exception:
RegionForGlobal(gcc.VarDecl('PyExc_MemoryError'))
@@ -115,12 +115,12 @@ Trace 3:
Region("region-for-arg-gcc.ParmDecl('self')"):
repr(): Region("region-for-arg-gcc.ParmDecl('self')")
str(): Region("region-for-arg-gcc.ParmDecl('self')")
- r->ob_refcnt: RefcountValue(0)
+ r->ob_refcnt: refs: 0 + N where N >= 1
r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/loop_n_times/input.c', line=28), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
Region("region-for-arg-gcc.ParmDecl('args')"):
repr(): Region("region-for-arg-gcc.ParmDecl('args')")
str(): Region("region-for-arg-gcc.ParmDecl('args')")
- r->ob_refcnt: RefcountValue(0)
+ r->ob_refcnt: refs: 0 + N where N >= 1
r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/loop_n_times/input.c', line=28), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
PyListObject allocated at tests/cpychecker/refcounts/loop_n_times/input.c:38:
repr(): RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/loop_n_times/input.c', line=38))
@@ -143,12 +143,12 @@ Trace 4:
Region("region-for-arg-gcc.ParmDecl('self')"):
repr(): Region("region-for-arg-gcc.ParmDecl('self')")
str(): Region("region-for-arg-gcc.ParmDecl('self')")
- r->ob_refcnt: RefcountValue(0)
+ r->ob_refcnt: refs: 0 + N where N >= 1
r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/loop_n_times/input.c', line=28), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
Region("region-for-arg-gcc.ParmDecl('args')"):
repr(): Region("region-for-arg-gcc.ParmDecl('args')")
str(): Region("region-for-arg-gcc.ParmDecl('args')")
- r->ob_refcnt: RefcountValue(0)
+ r->ob_refcnt: refs: 0 + N where N >= 1
r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/loop_n_times/input.c', line=28), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
Exception:
RegionForGlobal(gcc.VarDecl('PyExc_MemoryError'))
@@ -164,12 +164,12 @@ Trace 5:
Region("region-for-arg-gcc.ParmDecl('self')"):
repr(): Region("region-for-arg-gcc.ParmDecl('self')")
str(): Region("region-for-arg-gcc.ParmDecl('self')")
- r->ob_refcnt: RefcountValue(0)
+ r->ob_refcnt: refs: 0 + N where N >= 1
r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/loop_n_times/input.c', line=28), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
Region("region-for-arg-gcc.ParmDecl('args')"):
repr(): Region("region-for-arg-gcc.ParmDecl('args')")
str(): Region("region-for-arg-gcc.ParmDecl('args')")
- r->ob_refcnt: RefcountValue(0)
+ r->ob_refcnt: refs: 0 + N where N >= 1
r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/loop_n_times/input.c', line=28), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
Exception:
RegionForGlobal(gcc.VarDecl('PyExc_TypeError'))
diff --git a/tests/cpychecker/refcounts/missing_decref/stderr.txt b/tests/cpychecker/refcounts/missing_decref/stderr.txt
index 77a9818..ae535d8 100644
--- a/tests/cpychecker/refcounts/missing_decref/stderr.txt
+++ b/tests/cpychecker/refcounts/missing_decref/stderr.txt
@@ -1,8 +1,10 @@
tests/cpychecker/refcounts/missing_decref/input.c: In function 'missing_decref':
tests/cpychecker/refcounts/missing_decref/input.c:38:1: error: ob_refcnt of PyListObject is 1 too high
+tests/cpychecker/refcounts/missing_decref/input.c:38:1: note: was expecting final ob_refcnt to be N + 0 (for some unknown N)
+tests/cpychecker/refcounts/missing_decref/input.c:38:1: note: but final ob_refcnt is N + 1
tests/cpychecker/refcounts/missing_decref/input.c:27:10: note: PyListObject allocated at: list = PyList_New(1);
tests/cpychecker/refcounts/missing_decref/input.c:27:10: note: when PyList_New() succeeds at: list = PyList_New(1);
-tests/cpychecker/refcounts/missing_decref/input.c:27:10: note: ob_refcnt is now refs: 1
+tests/cpychecker/refcounts/missing_decref/input.c:27:10: note: ob_refcnt is now refs: 1 + N where N >= 0
tests/cpychecker/refcounts/missing_decref/input.c:28:8: note: when taking False path at: if (!list)
tests/cpychecker/refcounts/missing_decref/input.c:30:10: note: reaching: item = PyLong_FromLong(42);
tests/cpychecker/refcounts/missing_decref/input.c:30:10: note: when PyLong_FromLong() fails at: item = PyLong_FromLong(42);
diff --git a/tests/cpychecker/refcounts/missing_decref/stdout.txt b/tests/cpychecker/refcounts/missing_decref/stdout.txt
index d3526ea..45a9619 100644
--- a/tests/cpychecker/refcounts/missing_decref/stdout.txt
+++ b/tests/cpychecker/refcounts/missing_decref/stdout.txt
@@ -9,22 +9,22 @@ Trace 0:
Return value:
repr(): PointerToRegion(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/missing_decref/input.c', line=27), region=RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/missing_decref/input.c', line=27)))
str(): (struct PyObject *)&RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/missing_decref/input.c', line=27)) from tests/cpychecker/refcounts/missing_decref/input.c:27
- r->ob_refcnt: RefcountValue(1)
+ r->ob_refcnt: refs: 1 + N where N >= 0
r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/missing_decref/input.c', line=27), region=RegionForGlobal(gcc.VarDecl('PyList_Type')))
Region("region-for-arg-gcc.ParmDecl('self')"):
repr(): Region("region-for-arg-gcc.ParmDecl('self')")
str(): Region("region-for-arg-gcc.ParmDecl('self')")
- r->ob_refcnt: RefcountValue(0)
+ r->ob_refcnt: refs: 0 + N where N >= 1
r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/missing_decref/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
Region("region-for-arg-gcc.ParmDecl('args')"):
repr(): Region("region-for-arg-gcc.ParmDecl('args')")
str(): Region("region-for-arg-gcc.ParmDecl('args')")
- r->ob_refcnt: RefcountValue(0)
+ r->ob_refcnt: refs: 0 + N where N >= 1
r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/missing_decref/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
PyLongObject allocated at tests/cpychecker/refcounts/missing_decref/input.c:30:
repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/missing_decref/input.c', line=30))
str(): PyLongObject allocated at tests/cpychecker/refcounts/missing_decref/input.c:30
- r->ob_refcnt: RefcountValue(0)
+ r->ob_refcnt: refs: 0 + N where N >= 1
r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/missing_decref/input.c', line=30), region=RegionForGlobal(gcc.VarDecl('PyLong_Type')))
Exception:
(struct PyObject *)0 from tests/cpychecker/refcounts/missing_decref/input.c:24
@@ -42,17 +42,17 @@ Trace 1:
Region("region-for-arg-gcc.ParmDecl('self')"):
repr(): Region("region-for-arg-gcc.ParmDecl('self')")
str(): Region("region-for-arg-gcc.ParmDecl('self')")
- r->ob_refcnt: RefcountValue(0)
+ r->ob_refcnt: refs: 0 + N where N >= 1
r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/missing_decref/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
Region("region-for-arg-gcc.ParmDecl('args')"):
repr(): Region("region-for-arg-gcc.ParmDecl('args')")
str(): Region("region-for-arg-gcc.ParmDecl('args')")
- r->ob_refcnt: RefcountValue(0)
+ r->ob_refcnt: refs: 0 + N where N >= 1
r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/missing_decref/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
PyListObject allocated at tests/cpychecker/refcounts/missing_decref/input.c:27:
repr(): RegionOnHeap('PyListObject', gcc.Location(file='tests/cpychecker/refcounts/missing_decref/input.c', line=27))
str(): PyListObject allocated at tests/cpychecker/refcounts/missing_decref/input.c:27
- r->ob_refcnt: RefcountValue(1)
+ r->ob_refcnt: refs: 1 + N where N >= 0
r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/missing_decref/input.c', line=27), region=RegionForGlobal(gcc.VarDecl('PyList_Type')))
Exception:
RegionForGlobal(gcc.VarDecl('PyExc_MemoryError'))
@@ -68,12 +68,12 @@ Trace 2:
Region("region-for-arg-gcc.ParmDecl('self')"):
repr(): Region("region-for-arg-gcc.ParmDecl('self')")
str(): Region("region-for-arg-gcc.ParmDecl('self')")
- r->ob_refcnt: RefcountValue(0)
+ r->ob_refcnt: refs: 0 + N where N >= 1
r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/missing_decref/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
Region("region-for-arg-gcc.ParmDecl('args')"):
repr(): Region("region-for-arg-gcc.ParmDecl('args')")
str(): Region("region-for-arg-gcc.ParmDecl('args')")
- r->ob_refcnt: RefcountValue(0)
+ r->ob_refcnt: refs: 0 + N where N >= 1
r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/missing_decref/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
Exception:
RegionForGlobal(gcc.VarDecl('PyExc_MemoryError'))
diff --git a/tests/cpychecker/refcounts/module_handling/stdout.txt b/tests/cpychecker/refcounts/module_handling/stdout.txt
index 00f789e..8f04a7d 100644
--- a/tests/cpychecker/refcounts/module_handling/stdout.txt
+++ b/tests/cpychecker/refcounts/module_handling/stdout.txt
@@ -5,7 +5,7 @@ Trace 0:
output from Py_InitModule4 allocated at tests/cpychecker/refcounts/module_handling/input.c:46:
repr(): RegionOnHeap('output from Py_InitModule4', gcc.Location(file='tests/cpychecker/refcounts/module_handling/input.c', line=46))
str(): output from Py_InitModule4 allocated at tests/cpychecker/refcounts/module_handling/input.c:46
- r->ob_refcnt: RefcountValue(0)
+ r->ob_refcnt: refs: 0 + N where N >= 1
r->ob_type: None
Exception:
(struct PyObject *)0 from tests/cpychecker/refcounts/module_handling/input.c:41
diff --git a/tests/cpychecker/refcounts/not_setting_exception/stdout.txt b/tests/cpychecker/refcounts/not_setting_exception/stdout.txt
index 3521f3d..c6bb61e 100644
--- a/tests/cpychecker/refcounts/not_setting_exception/stdout.txt
+++ b/tests/cpychecker/refcounts/not_setting_exception/stdout.txt
@@ -7,12 +7,12 @@ Trace 0:
Region("region-for-arg-gcc.ParmDecl('self')"):
repr(): Region("region-for-arg-gcc.ParmDecl('self')")
str(): Region("region-for-arg-gcc.ParmDecl('self')")
- r->ob_refcnt: RefcountValue(0)
+ r->ob_refcnt: refs: 0 + N where N >= 1
r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/not_setting_exception/input.c', line=26), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
Region("region-for-arg-gcc.ParmDecl('args')"):
repr(): Region("region-for-arg-gcc.ParmDecl('args')")
str(): Region("region-for-arg-gcc.ParmDecl('args')")
- r->ob_refcnt: RefcountValue(0)
+ r->ob_refcnt: refs: 0 + N where N >= 1
r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/not_setting_exception/input.c', line=26), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
Exception:
(struct PyObject *)0 from tests/cpychecker/refcounts/not_setting_exception/input.c:27
diff --git a/tests/cpychecker/refcounts/object_leak/stderr.txt b/tests/cpychecker/refcounts/object_leak/stderr.txt
index 25f7b4c..9478857 100644
--- a/tests/cpychecker/refcounts/object_leak/stderr.txt
+++ b/tests/cpychecker/refcounts/object_leak/stderr.txt
@@ -1,8 +1,10 @@
tests/cpychecker/refcounts/object_leak/input.c: In function 'object_leak':
tests/cpychecker/refcounts/object_leak/input.c:29:5: error: ob_refcnt of PyLongObject is 1 too high
+tests/cpychecker/refcounts/object_leak/input.c:29:5: note: was expecting final ob_refcnt to be N + 0 (for some unknown N)
+tests/cpychecker/refcounts/object_leak/input.c:29:5: note: but final ob_refcnt is N + 1
tests/cpychecker/refcounts/object_leak/input.c:26:15: note: PyLongObject allocated at: PyObject *tmp = PyLong_FromLong(0x1000);
tests/cpychecker/refcounts/object_leak/input.c:26:15: note: when PyLong_FromLong() succeeds at: PyObject *tmp = PyLong_FromLong(0x1000);
-tests/cpychecker/refcounts/object_leak/input.c:26:15: note: ob_refcnt is now refs: 1
+tests/cpychecker/refcounts/object_leak/input.c:26:15: note: ob_refcnt is now refs: 1 + N where N >= 0
tests/cpychecker/refcounts/object_leak/input.c:29:5: note: when returning at: return NULL;
tests/cpychecker/refcounts/object_leak/input.c:29:5: error: returning (PyObject*)NULL without setting an exception
tests/cpychecker/refcounts/object_leak/input.c:26:15: note: when PyLong_FromLong() succeeds at: PyObject *tmp = PyLong_FromLong(0x1000);
diff --git a/tests/cpychecker/refcounts/returning_dead_object/stderr.txt b/tests/cpychecker/refcounts/returning_dead_object/stderr.txt
index 6bbaf9e..7af9179 100644
--- a/tests/cpychecker/refcounts/returning_dead_object/stderr.txt
+++ b/tests/cpychecker/refcounts/returning_dead_object/stderr.txt
@@ -1,11 +1,14 @@
tests/cpychecker/refcounts/returning_dead_object/input.c: In function 'returning_dead_object':
tests/cpychecker/refcounts/returning_dead_object/input.c:43:1: error: ob_refcnt of return value is 1 too low
+tests/cpychecker/refcounts/returning_dead_object/input.c:43:1: note: was expecting final ob_refcnt to be N + 1 (for some unknown N)
+tests/cpychecker/refcounts/returning_dead_object/input.c:43:1: note: due to object being referenced by: return value
+tests/cpychecker/refcounts/returning_dead_object/input.c:43:1: note: but final ob_refcnt is N + 0
tests/cpychecker/refcounts/returning_dead_object/input.c:29:15: note: PyLongObject allocated at: PyObject *tmp = PyLong_FromLong(0x1000);
tests/cpychecker/refcounts/returning_dead_object/input.c:29:15: note: when PyLong_FromLong() succeeds at: PyObject *tmp = PyLong_FromLong(0x1000);
-tests/cpychecker/refcounts/returning_dead_object/input.c:29:15: note: ob_refcnt is now refs: 1
+tests/cpychecker/refcounts/returning_dead_object/input.c:29:15: note: ob_refcnt is now refs: 1 + N where N >= 0
tests/cpychecker/refcounts/returning_dead_object/input.c:31:8: note: when taking False path at: if (!tmp) {
tests/cpychecker/refcounts/returning_dead_object/input.c:39:5: note: reaching: Py_DECREF(tmp);
-tests/cpychecker/refcounts/returning_dead_object/input.c:39:5: note: ob_refcnt is now refs: 0
+tests/cpychecker/refcounts/returning_dead_object/input.c:39:5: note: ob_refcnt is now refs: 0 + N where N >= 0
tests/cpychecker/refcounts/returning_dead_object/input.c:39:5: note: when taking True path at: Py_DECREF(tmp);
tests/cpychecker/refcounts/returning_dead_object/input.c:42:5: note: reaching: return tmp;
tests/cpychecker/refcounts/returning_dead_object/input.c:43:1: note: when returning
diff --git a/tests/cpychecker/refcounts/returning_dead_object/stdout.txt b/tests/cpychecker/refcounts/returning_dead_object/stdout.txt
index 00091c6..7ec1151 100644
--- a/tests/cpychecker/refcounts/returning_dead_object/stdout.txt
+++ b/tests/cpychecker/refcounts/returning_dead_object/stdout.txt
@@ -7,17 +7,17 @@ Trace 0:
Return value:
repr(): PointerToRegion(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/returning_dead_object/input.c', line=29), region=RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/returning_dead_object/input.c', line=29)))
str(): (struct PyObject *)&RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/returning_dead_object/input.c', line=29)) from tests/cpychecker/refcounts/returning_dead_object/input.c:29
- r->ob_refcnt: RefcountValue(0)
+ r->ob_refcnt: refs: 0 + N where N >= 0
r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/returning_dead_object/input.c', line=29), region=RegionForGlobal(gcc.VarDecl('PyLong_Type')))
Region("region-for-arg-gcc.ParmDecl('self')"):
repr(): Region("region-for-arg-gcc.ParmDecl('self')")
str(): Region("region-for-arg-gcc.ParmDecl('self')")
- r->ob_refcnt: RefcountValue(0)
+ r->ob_refcnt: refs: 0 + N where N >= 1
r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/returning_dead_object/input.c', line=26), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
Region("region-for-arg-gcc.ParmDecl('args')"):
repr(): Region("region-for-arg-gcc.ParmDecl('args')")
str(): Region("region-for-arg-gcc.ParmDecl('args')")
- r->ob_refcnt: RefcountValue(0)
+ r->ob_refcnt: refs: 0 + N where N >= 1
r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/returning_dead_object/input.c', line=26), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
Exception:
(struct PyObject *)0 from tests/cpychecker/refcounts/returning_dead_object/input.c:27
@@ -37,12 +37,12 @@ Trace 1:
Region("region-for-arg-gcc.ParmDecl('self')"):
repr(): Region("region-for-arg-gcc.ParmDecl('self')")
str(): Region("region-for-arg-gcc.ParmDecl('self')")
- r->ob_refcnt: RefcountValue(0)
+ r->ob_refcnt: refs: 0 + N where N >= 1
r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/returning_dead_object/input.c', line=26), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
Region("region-for-arg-gcc.ParmDecl('args')"):
repr(): Region("region-for-arg-gcc.ParmDecl('args')")
str(): Region("region-for-arg-gcc.ParmDecl('args')")
- r->ob_refcnt: RefcountValue(0)
+ r->ob_refcnt: refs: 0 + N where N >= 1
r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/returning_dead_object/input.c', line=26), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
Exception:
(struct PyObject *)0 from tests/cpychecker/refcounts/returning_dead_object/input.c:27
@@ -58,12 +58,12 @@ Trace 2:
Region("region-for-arg-gcc.ParmDecl('self')"):
repr(): Region("region-for-arg-gcc.ParmDecl('self')")
str(): Region("region-for-arg-gcc.ParmDecl('self')")
- r->ob_refcnt: RefcountValue(0)
+ r->ob_refcnt: refs: 0 + N where N >= 1
r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/returning_dead_object/input.c', line=26), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
Region("region-for-arg-gcc.ParmDecl('args')"):
repr(): Region("region-for-arg-gcc.ParmDecl('args')")
str(): Region("region-for-arg-gcc.ParmDecl('args')")
- r->ob_refcnt: RefcountValue(0)
+ r->ob_refcnt: refs: 0 + N where N >= 1
r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/returning_dead_object/input.c', line=26), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
Exception:
RegionForGlobal(gcc.VarDecl('PyExc_MemoryError'))
diff --git a/tests/cpychecker/refcounts/subclass/handling/stdout.txt b/tests/cpychecker/refcounts/subclass/handling/stdout.txt
index ded0138..c4d8cbf 100644
--- a/tests/cpychecker/refcounts/subclass/handling/stdout.txt
+++ b/tests/cpychecker/refcounts/subclass/handling/stdout.txt
@@ -7,12 +7,12 @@ Trace 0:
Region("region-for-arg-gcc.ParmDecl('self')"):
repr(): Region("region-for-arg-gcc.ParmDecl('self')")
str(): Region("region-for-arg-gcc.ParmDecl('self')")
- r->ob_refcnt: RefcountValue(0)
+ r->ob_refcnt: refs: 0 + N where N >= 1
r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/subclass/handling/input.c', line=37), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
Region("region-for-arg-gcc.ParmDecl('args')"):
repr(): Region("region-for-arg-gcc.ParmDecl('args')")
str(): Region("region-for-arg-gcc.ParmDecl('args')")
- r->ob_refcnt: RefcountValue(0)
+ r->ob_refcnt: refs: 0 + N where N >= 1
r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/subclass/handling/input.c', line=37), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
Exception:
(struct PyObject *)0 from tests/cpychecker/refcounts/subclass/handling/input.c:38
diff --git a/tests/cpychecker/refcounts/too_many_increfs/stderr.txt b/tests/cpychecker/refcounts/too_many_increfs/stderr.txt
index bd5df29..71fbccc 100644
--- a/tests/cpychecker/refcounts/too_many_increfs/stderr.txt
+++ b/tests/cpychecker/refcounts/too_many_increfs/stderr.txt
@@ -1,9 +1,12 @@
tests/cpychecker/refcounts/too_many_increfs/input.c: In function 'too_many_increfs':
tests/cpychecker/refcounts/too_many_increfs/input.c:31:5: error: ob_refcnt of return value is 1 too high
+tests/cpychecker/refcounts/too_many_increfs/input.c:31:5: note: was expecting final ob_refcnt to be N + 1 (for some unknown N)
+tests/cpychecker/refcounts/too_many_increfs/input.c:31:5: note: due to object being referenced by: return value
+tests/cpychecker/refcounts/too_many_increfs/input.c:31:5: note: but final ob_refcnt is N + 2
tests/cpychecker/refcounts/too_many_increfs/input.c:26:9: note: PyLongObject allocated at: tmp = PyLong_FromLong(0x1000);
tests/cpychecker/refcounts/too_many_increfs/input.c:26:9: note: when PyLong_FromLong() succeeds at: tmp = PyLong_FromLong(0x1000);
-tests/cpychecker/refcounts/too_many_increfs/input.c:26:9: note: ob_refcnt is now refs: 1
-tests/cpychecker/refcounts/too_many_increfs/input.c:30:5: note: ob_refcnt is now refs: 2
+tests/cpychecker/refcounts/too_many_increfs/input.c:26:9: note: ob_refcnt is now refs: 1 + N where N >= 0
+tests/cpychecker/refcounts/too_many_increfs/input.c:30:5: note: ob_refcnt is now refs: 2 + N where N >= 0
tests/cpychecker/refcounts/too_many_increfs/input.c:31:5: note: when returning at: return tmp;
tests/cpychecker/refcounts/too_many_increfs/input.c:30:5: error: dereferencing NULL (tmp->ob_refcnt) at tests/cpychecker/refcounts/too_many_increfs/input.c:30
tests/cpychecker/refcounts/too_many_increfs/input.c:26:9: note: when PyLong_FromLong() fails at: tmp = PyLong_FromLong(0x1000);
diff --git a/tests/cpychecker/refcounts/too_many_increfs/stdout.txt b/tests/cpychecker/refcounts/too_many_increfs/stdout.txt
index fc26723..a2ed0d7 100644
--- a/tests/cpychecker/refcounts/too_many_increfs/stdout.txt
+++ b/tests/cpychecker/refcounts/too_many_increfs/stdout.txt
@@ -5,17 +5,17 @@ Trace 0:
Return value:
repr(): PointerToRegion(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/too_many_increfs/input.c', line=26), region=RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/too_many_increfs/input.c', line=26)))
str(): (struct PyObject *)&RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/too_many_increfs/input.c', line=26)) from tests/cpychecker/refcounts/too_many_increfs/input.c:26
- r->ob_refcnt: RefcountValue(2)
+ r->ob_refcnt: refs: 2 + N where N >= 0
r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/too_many_increfs/input.c', line=26), region=RegionForGlobal(gcc.VarDecl('PyLong_Type')))
Region("region-for-arg-gcc.ParmDecl('self')"):
repr(): Region("region-for-arg-gcc.ParmDecl('self')")
str(): Region("region-for-arg-gcc.ParmDecl('self')")
- r->ob_refcnt: RefcountValue(0)
+ r->ob_refcnt: refs: 0 + N where N >= 1
r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/too_many_increfs/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
Region("region-for-arg-gcc.ParmDecl('args')"):
repr(): Region("region-for-arg-gcc.ParmDecl('args')")
str(): Region("region-for-arg-gcc.ParmDecl('args')")
- r->ob_refcnt: RefcountValue(0)
+ r->ob_refcnt: refs: 0 + N where N >= 1
r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/too_many_increfs/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
Exception:
(struct PyObject *)0 from tests/cpychecker/refcounts/too_many_increfs/input.c:24
@@ -28,12 +28,12 @@ Trace 1:
Region("region-for-arg-gcc.ParmDecl('self')"):
repr(): Region("region-for-arg-gcc.ParmDecl('self')")
str(): Region("region-for-arg-gcc.ParmDecl('self')")
- r->ob_refcnt: RefcountValue(0)
+ r->ob_refcnt: refs: 0 + N where N >= 1
r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/too_many_increfs/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
Region("region-for-arg-gcc.ParmDecl('args')"):
repr(): Region("region-for-arg-gcc.ParmDecl('args')")
str(): Region("region-for-arg-gcc.ParmDecl('args')")
- r->ob_refcnt: RefcountValue(0)
+ r->ob_refcnt: refs: 0 + N where N >= 1
r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/too_many_increfs/input.c', line=23), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
Exception:
RegionForGlobal(gcc.VarDecl('PyExc_MemoryError'))
diff --git a/tests/cpychecker/refcounts/use_after_dealloc/stdout.txt b/tests/cpychecker/refcounts/use_after_dealloc/stdout.txt
index 96a26ef..6cdd47d 100644
--- a/tests/cpychecker/refcounts/use_after_dealloc/stdout.txt
+++ b/tests/cpychecker/refcounts/use_after_dealloc/stdout.txt
@@ -7,17 +7,17 @@ Trace 0:
Return value:
repr(): PointerToRegion(gcctype='struct PyObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/use_after_dealloc/input.c', line=30), region=RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/use_after_dealloc/input.c', line=30)))
str(): (struct PyObject *)&RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/use_after_dealloc/input.c', line=30)) from tests/cpychecker/refcounts/use_after_dealloc/input.c:30
- r->ob_refcnt: RefcountValue(1)
+ r->ob_refcnt: refs: 1 + N where N >= 0
r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/use_after_dealloc/input.c', line=30), region=RegionForGlobal(gcc.VarDecl('PyLong_Type')))
Region("region-for-arg-gcc.ParmDecl('self')"):
repr(): Region("region-for-arg-gcc.ParmDecl('self')")
str(): Region("region-for-arg-gcc.ParmDecl('self')")
- r->ob_refcnt: RefcountValue(0)
+ r->ob_refcnt: refs: 0 + N where N >= 1
r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/use_after_dealloc/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
Region("region-for-arg-gcc.ParmDecl('args')"):
repr(): Region("region-for-arg-gcc.ParmDecl('args')")
str(): Region("region-for-arg-gcc.ParmDecl('args')")
- r->ob_refcnt: RefcountValue(0)
+ r->ob_refcnt: refs: 0 + N where N >= 1
r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/use_after_dealloc/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
Exception:
(struct PyObject *)0 from tests/cpychecker/refcounts/use_after_dealloc/input.c:28
@@ -33,12 +33,12 @@ Trace 1:
Region("region-for-arg-gcc.ParmDecl('self')"):
repr(): Region("region-for-arg-gcc.ParmDecl('self')")
str(): Region("region-for-arg-gcc.ParmDecl('self')")
- r->ob_refcnt: RefcountValue(0)
+ r->ob_refcnt: refs: 0 + N where N >= 1
r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/use_after_dealloc/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
Region("region-for-arg-gcc.ParmDecl('args')"):
repr(): Region("region-for-arg-gcc.ParmDecl('args')")
str(): Region("region-for-arg-gcc.ParmDecl('args')")
- r->ob_refcnt: RefcountValue(0)
+ r->ob_refcnt: refs: 0 + N where N >= 1
r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/use_after_dealloc/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
PyLongObject allocated at tests/cpychecker/refcounts/use_after_dealloc/input.c:30:
repr(): RegionOnHeap('PyLongObject', gcc.Location(file='tests/cpychecker/refcounts/use_after_dealloc/input.c', line=30))
@@ -59,12 +59,12 @@ Trace 2:
Region("region-for-arg-gcc.ParmDecl('self')"):
repr(): Region("region-for-arg-gcc.ParmDecl('self')")
str(): Region("region-for-arg-gcc.ParmDecl('self')")
- r->ob_refcnt: RefcountValue(0)
+ r->ob_refcnt: refs: 0 + N where N >= 1
r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/use_after_dealloc/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('self')"))
Region("region-for-arg-gcc.ParmDecl('args')"):
repr(): Region("region-for-arg-gcc.ParmDecl('args')")
str(): Region("region-for-arg-gcc.ParmDecl('args')")
- r->ob_refcnt: RefcountValue(0)
+ r->ob_refcnt: refs: 0 + N where N >= 1
r->ob_type: PointerToRegion(gcctype='struct PyTypeObject *', loc=gcc.Location(file='tests/cpychecker/refcounts/use_after_dealloc/input.c', line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
Exception:
RegionForGlobal(gcc.VarDecl('PyExc_MemoryError'))
12 years, 9 months