commit 1e226e4d6c76a300bbdded7e056cb463f7a8b011
Author: David Malcolm <dmalcolm(a)redhat.com>
Date: Tue Sep 27 16:24:14 2011 -0400
cpychecker: cope with gimple that uses a gcc.ResultDecl
libcpychecker/absinterp.py | 12 +++-
tests/cpychecker/absinterp/result-decl/input.c | 57 +++++++++++++++++++++
tests/cpychecker/absinterp/result-decl/script.py | 22 ++++++++
tests/cpychecker/absinterp/result-decl/stdout.txt | 8 +++
4 files changed, 96 insertions(+), 3 deletions(-)
---
diff --git a/libcpychecker/absinterp.py b/libcpychecker/absinterp.py
index ec18149..6df46b6 100644
--- a/libcpychecker/absinterp.py
+++ b/libcpychecker/absinterp.py
@@ -688,7 +688,7 @@ class State:
log('eval_lvalue: %r %s', expr, expr)
if loc:
check_isinstance(loc, gcc.Location)
- if isinstance(expr, (gcc.VarDecl, gcc.ParmDecl)):
+ if isinstance(expr, (gcc.VarDecl, gcc.ParmDecl, gcc.ResultDecl)):
region = self.var_region(expr)
check_isinstance(region, Region)
return region
@@ -732,7 +732,7 @@ class State:
return expr
if isinstance(expr, gcc.IntegerCst):
return ConcreteValue(expr.type, loc, expr.constant)
- if isinstance(expr, (gcc.VarDecl, gcc.ParmDecl)):
+ if isinstance(expr, (gcc.VarDecl, gcc.ParmDecl, gcc.ResultDecl)):
region = self.var_region(expr)
check_isinstance(region, Region)
value = self.get_store(region, expr.type, loc)
@@ -795,7 +795,7 @@ class State:
self.value_for_region[dest_region] = value
def var_region(self, var):
- check_isinstance(var, (gcc.VarDecl, gcc.ParmDecl))
+ check_isinstance(var, (gcc.VarDecl, gcc.ParmDecl, gcc.ResultDecl))
if var not in self.region_for_var:
# Presumably a reference to a global variable:
log('adding region for global var: %r', var)
@@ -1000,6 +1000,12 @@ class State:
region = RegionOnStack('region for %r' % local, stack)
self.region_for_var[local] = region
self.value_for_region[region] = UninitializedData(local.type, fun.start)
+ # Region for the gcc.ResultDecl, if any:
+ if fun.decl.result:
+ result = fun.decl.result
+ region = RegionOnStack('region for %s' % result, stack)
+ self.region_for_var[result] = region
+ self.value_for_region[region] = UninitializedData(result.type, fun.start)
self.verify()
def mktrans_assignment(self, lhs, rhs, desc):
diff --git a/tests/cpychecker/absinterp/result-decl/input.c
b/tests/cpychecker/absinterp/result-decl/input.c
new file mode 100644
index 0000000..395a4eb
--- /dev/null
+++ b/tests/cpychecker/absinterp/result-decl/input.c
@@ -0,0 +1,57 @@
+/*
+ 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 returning a struct containing pointers, which seems
+ to gimple containing an assignment to a gcc.ResultDecl;
+ in the pretty-printed gimple it looks like:
+ assign to fields of a tmp value
+ <returnval> = tmp
+ return <returnval>
+ (this seems to only happen if there are 3 or more fields, and at least two
+ are pointers; not sure of exact conditions)
+*/
+
+struct foo {
+ void *x;
+ void *y;
+ int z;
+};
+
+struct foo
+test(void *x, void *y, int z)
+{
+ struct foo result;
+
+ result.x = x;
+ result.y = y;
+ result.z = z;
+
+ return result;
+}
+
+/*
+ PEP-7
+Local variables:
+c-basic-offset: 4
+indent-tabs-mode: nil
+End:
+*/
diff --git a/tests/cpychecker/absinterp/result-decl/script.py
b/tests/cpychecker/absinterp/result-decl/script.py
new file mode 100644
index 0000000..fdd5ba3
--- /dev/null
+++ b/tests/cpychecker/absinterp/result-decl/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/result-decl/stdout.txt
b/tests/cpychecker/absinterp/result-decl/stdout.txt
new file mode 100644
index 0000000..312b5e0
--- /dev/null
+++ b/tests/cpychecker/absinterp/result-decl/stdout.txt
@@ -0,0 +1,8 @@
+Trace 0:
+ Transitions:
+ 'returning'
+ Return value:
+ repr(): UninitializedData(gcctype='struct foo',
loc=gcc.Location(file='tests/cpychecker/absinterp/result-decl/input.c', line=41))
+ str(): uninitialized data at tests/cpychecker/absinterp/result-decl/input.c:41
+ Exception:
+ (struct PyObject *)0 from tests/cpychecker/absinterp/result-decl/input.c:41