commit 07a1d9684dbe5ac17fa5fad4239bd3cab49dcd69
Author: David Malcolm <dmalcolm(a)redhat.com>
Date: Tue Aug 30 19:34:39 2011 -0400
cpychecker: implement PyErr_Format
libcpychecker/refcounts.py | 15 ++++++
.../refcounts/PyErr_Format/correct/input.c | 49 ++++++++++++++++++++
.../refcounts/PyErr_Format/correct/script.py | 22 +++++++++
.../refcounts/PyErr_Format/correct/stdout.txt | 19 ++++++++
4 files changed, 105 insertions(+), 0 deletions(-)
---
diff --git a/libcpychecker/refcounts.py b/libcpychecker/refcounts.py
index 3c7454a..b850b6a 100644
--- a/libcpychecker/refcounts.py
+++ b/libcpychecker/refcounts.py
@@ -591,6 +591,21 @@ class MyState(State):
########################################################################
# PyErr_*
########################################################################
+ def impl_PyErr_Format(self, stmt):
+ # Declared in pyerrors.h:
+ # PyAPI_FUNC(void) PyErr_SetString(PyObject *, const char *);
+ # Defined in Python/errors.c
+ #
+ args = self.eval_stmt_args(stmt)
+ v_exc = args[0]
+ v_fmt = args[1]
+ # It always returns NULL:
+ t_next = self.mktrans_assignment(stmt.lhs,
+ make_null_pyobject_ptr(stmt),
+ 'PyErr_Format()')
+ t_next.dest.exception_rvalue = v_exc
+ return [t_next]
+
def impl_PyErr_Print(self, stmt):
# Declared in pythonrun.h:
# PyAPI_FUNC(void) PyErr_Print(void);
diff --git a/tests/cpychecker/refcounts/PyErr_Format/correct/input.c
b/tests/cpychecker/refcounts/PyErr_Format/correct/input.c
new file mode 100644
index 0000000..2251a7a
--- /dev/null
+++ b/tests/cpychecker/refcounts/PyErr_Format/correct/input.c
@@ -0,0 +1,49 @@
+/*
+ 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 usage of PyErr_Format
+*/
+
+PyObject *
+test(PyObject *self, PyObject *args)
+{
+ /*
+ It's more idiomatic to do a "return PyErr_Format".
+ However, this approach exercises this case, and verifies that the
+ checker doesn't erroneously think that it returns an object:
+ */
+ PyErr_Format(PyExc_RuntimeError,
+ "This test method always fails");
+ return NULL;
+}
+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/PyErr_Format/correct/script.py
b/tests/cpychecker/refcounts/PyErr_Format/correct/script.py
new file mode 100644
index 0000000..fdd5ba3
--- /dev/null
+++ b/tests/cpychecker/refcounts/PyErr_Format/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/PyErr_Format/correct/stdout.txt
b/tests/cpychecker/refcounts/PyErr_Format/correct/stdout.txt
new file mode 100644
index 0000000..dade485
--- /dev/null
+++ b/tests/cpychecker/refcounts/PyErr_Format/correct/stdout.txt
@@ -0,0 +1,19 @@
+Trace 0:
+ Transitions:
+ 'PyErr_Format()'
+ 'returning'
+ Return value:
+ repr(): ConcreteValue(gcctype='struct PyObject *',
loc=gcc.Location(file='tests/cpychecker/refcounts/PyErr_Format/correct/input.c',
line=36), value=0)
+ str(): (struct PyObject *)0 from
tests/cpychecker/refcounts/PyErr_Format/correct/input.c:36
+ 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/PyErr_Format/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/PyErr_Format/correct/input.c',
line=27), region=Region("region-for-type-of-arg-gcc.ParmDecl('args')"))
+ Exception:
+ unknown struct PyObject * from /usr/include/python2.7/pyerrors.h:140