commit 8abed6e97c9a35532939d5f0f102aeeb6068cde6 Author: David Malcolm dmalcolm@redhat.com Date: Fri Mar 30 17:15:03 2012 -0400
cpychecker: in C++ code, "this" can't be NULL
docs/tree.rst | 8 ++++ generate-tree-c.py | 19 +++++---- libcpychecker/absinterp.py | 5 ++- tests/cpychecker/refcounts/cplusplus/this/input.cc | 45 ++++++++++++++++++++ .../cpychecker/refcounts/cplusplus/this/script.py | 22 ++++++++++ .../cpychecker/refcounts/cplusplus/this/stdout.txt | 8 ++++ 6 files changed, 98 insertions(+), 9 deletions(-) --- diff --git a/docs/tree.rst b/docs/tree.rst index 5edae87..d54131a 100644 --- a/docs/tree.rst +++ b/docs/tree.rst @@ -217,6 +217,14 @@ Declarations
The :py:class:`gcc.Location` for this declaration
+ .. py:attribute:: is_artifical + + (bool) Is this declaration a compiler-generated entity, rather than + one provided by the user? + + An example of such an "artifical" declaration occurs within the + arguments of C++ methods: the initial `this` argument is a + compiler-generated :py:class:`gcc.ParmDecl`.
.. py:class:: gcc.FieldDecl
diff --git a/generate-tree-c.py b/generate-tree-c.py index 54ffdc6..457b2de 100644 --- a/generate-tree-c.py +++ b/generate-tree-c.py @@ -149,6 +149,14 @@ def generate_intermediate_tree_classes(): tp_getset = getsettable.identifier, tp_methods = methods.identifier)
+ def add_simple_getter(name, c_expression, doc): + getsettable.add_gsdef(name, + cu.add_simple_getter('gcc_%s_get_%s' % (localname, name), + 'PyGccTree', + c_expression), + None, + doc) + if localname == 'Declaration': cu.add_defn(""" PyObject * @@ -175,16 +183,11 @@ gcc_Declaration_get_location(struct PyGccTree *self, void *closure) 'gcc_Declaration_get_location', None, 'The gcc.Location for this declaration') + add_simple_getter('is_artificial', + 'PyBool_FromLong(DECL_ARTIFICIAL(self->t))', + "Is this a compiler-generated entity?") pytype.tp_repr = '(reprfunc)gcc_Declaration_repr'
- def add_simple_getter(name, c_expression, doc): - getsettable.add_gsdef(name, - cu.add_simple_getter('gcc_%s_get_%s' % (localname, name), - 'PyGccTree', - c_expression), - None, - doc) - if localname == 'Type': add_simple_getter('name', 'gcc_python_make_wrapper_tree(TYPE_NAME(self->t))', diff --git a/libcpychecker/absinterp.py b/libcpychecker/absinterp.py index 35c4103..97e5d7f 100644 --- a/libcpychecker/absinterp.py +++ b/libcpychecker/absinterp.py @@ -1916,9 +1916,12 @@ class State(object):
nonnull_args = get_nonnull_arguments(fun.decl.type) for idx, parm in enumerate(fun.decl.arguments): + def parm_is_this(): + if idx == 0 and parm.is_artificial and parm.name == 'this': + return True region = RegionForLocal(parm, stack) self.region_for_var[parm] = region - if idx in nonnull_args: + if idx in nonnull_args or parm_is_this(): # Make a non-NULL ptr: other = Region('region-for-arg-%r' % parm, None) self.region_for_var[other] = other diff --git a/tests/cpychecker/refcounts/cplusplus/this/input.cc b/tests/cpychecker/refcounts/cplusplus/this/input.cc new file mode 100644 index 0000000..788af9f --- /dev/null +++ b/tests/cpychecker/refcounts/cplusplus/this/input.cc @@ -0,0 +1,45 @@ +/* + Copyright 2012 David Malcolm dmalcolm@redhat.com + Copyright 2012 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/. +*/ + + +/* Verify that the checker can handle "this" in C++ code */ +#include <Python.h> + +class Foo +{ + int x; + +public: + int + get_x(); +}; + +int Foo::get_x() +{ + /* the checker should assume that "this" is non-NULL */ + return this->x; +} + +/* + PEP-7 +Local variables: +c-basic-offset: 4 +indent-tabs-mode: nil +End: +*/ diff --git a/tests/cpychecker/refcounts/cplusplus/this/script.py b/tests/cpychecker/refcounts/cplusplus/this/script.py new file mode 100644 index 0000000..fdd5ba3 --- /dev/null +++ b/tests/cpychecker/refcounts/cplusplus/this/script.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2011 David Malcolm dmalcolm@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/cplusplus/this/stdout.txt b/tests/cpychecker/refcounts/cplusplus/this/stdout.txt new file mode 100644 index 0000000..9f488bd --- /dev/null +++ b/tests/cpychecker/refcounts/cplusplus/this/stdout.txt @@ -0,0 +1,8 @@ +Trace 0: + Transitions: + 'returning' + Return value: + repr(): WithinRange(gcctype='int', loc=gcc.Location(file='tests/cpychecker/refcounts/cplusplus/this/input.cc', line=36), minvalue=-0x80000000, maxvalue=0x7fffffff) + str(): (int)val [-0x80000000 <= val <= 0x7fffffff] from tests/cpychecker/refcounts/cplusplus/this/input.cc:36 + Exception: + (struct PyObject *)0 from tests/cpychecker/refcounts/cplusplus/this/input.cc:34
gcc-python-plugin-commits@lists.stg.fedorahosted.org