[pypy-commit] creflect default: typedefs of function pointers: check more precisely the type if needed
arigo
noreply at buildbot.pypy.org
Tue Nov 18 18:32:09 CET 2014
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r79:b06d3f4392e6
Date: 2014-11-18 18:32 +0100
http://bitbucket.org/cffi/creflect/changeset/b06d3f4392e6/
Log: typedefs of function pointers: check more precisely the type if
needed
diff --git a/creflect/model.py b/creflect/model.py
--- a/creflect/model.py
+++ b/creflect/model.py
@@ -204,13 +204,22 @@
def inspect_type(self, block, inspect):
# this class overrides inspect_type() instead of
# inspect_nonconst_type(), to avoid the extra call to get_const_type()
- inspect.flush()
+
+ # this variable is set if we support slightly misdeclared function
+ # args or return value; this is the case only for typedefs that
+ # declare a pointer to a function without ellipsis.
+ common_case = (not self.ellipsis and isinstance(inspect, TypeInspector)
+ and inspect.started and inspect.levels == ['*'])
+ if common_case:
+ inspect.flush()
+ else:
+ inspect.flush('(%s)' % self.get_c_name('(*)'),
+ "a function pointer type with exactly the given signature")
if self.ellipsis:
return self.inspect_type_ellipsis(block, inspect)
- if (isinstance(inspect, TypeInspector) and inspect.started and
- inspect.levels == ['*']): # common case
+ if common_case:
decl = '%s f' % inspect.typename
else:
decl = self.get_c_name('(*f)')
@@ -409,7 +418,7 @@
class MissingInspector(object):
- def flush(self):
+ def flush(self, cast=None, comment=None):
pass
@@ -418,7 +427,7 @@
self.block = block
self.varname = varname
- def flush(self):
+ def flush(self, cast=None, comment=None):
pass
@@ -445,9 +454,9 @@
self.at_end = []
self.assign_target = None
- def flush(self):
+ def flush(self, cast=None, comment=None):
if self.started:
- self.assign_to_p1('0')
+ self.assign_to_p1('0', cast, comment)
def get_comment_type(self, levels_delta, ignore_array, minlevel=0):
end = len(self.levels)
@@ -488,23 +497,26 @@
star_p1 = '%sp1->%s' % ('*' * len(self.levels), self.structfield)
return star_p1
- def assign_to_p1(self, expr):
+ def assign_to_p1(self, expr, cast=None, comment=None):
+ cast = cast or '(void *)'
+ comment = comment or "a pointer type"
if self.assign_target is None:
length = len(self.levels)
while length > 0 and self.levels[length - 1] == '[]':
length -= 1
- comment = self.get_comment(-1, True, "a pointer type")
+ comment = self.get_comment(-1, True, comment)
spaces = comment and (' ' * (3 - len(expr)))
self.assign_target = '%sp1' % ('*' * length,)
else:
spaces = comment = ''
if self.structfield is None:
- line = '%s = (void *)%s;%s%s' % (self.assign_target, expr, spaces,
- comment)
+ line = '%s = %s%s;%s%s' % (self.assign_target, cast, expr, spaces,
+ comment)
else:
if length > 0:
- line = '%sp1->%s = (void *)%s;%s%s' % (
- '*' * (length - 1), self.structfield, expr, spaces, comment)
+ line = '%sp1->%s = %s%s;%s%s' % (
+ '*' * (length - 1), self.structfield, cast, expr, spaces,
+ comment)
else:
line = 'p1 = (void *)(((char *)%s) - o);' % (expr,)
self.assign_target = None
diff --git a/test/codegen/func-003b.c b/test/codegen/func-003b.c
--- a/test/codegen/func-003b.c
+++ b/test/codegen/func-003b.c
@@ -9,7 +9,7 @@
func_t *p1;
char *p2;
p1 = (void *)&p2;
- *p1 = (void *)0; /* check that 'func_t' is a pointer type */
+ *p1 = (int (*)(long, ...))0; /* check that 'func_t' is a function pointer type with exactly the given signature */
t1 = cb->get_signed_type(cb, sizeof(int), "int");
t2 = cb->get_signed_type(cb, sizeof(long), "long");
a3[0] = t2;
diff --git a/test/codegen/func-004.c b/test/codegen/func-004.c
new file mode 100644
--- /dev/null
+++ b/test/codegen/func-004.c
@@ -0,0 +1,30 @@
+typedef int(**func_t)(long, int);
+
+# ____________________________________________________________
+
+static void testfunc_004__f1(void *func, void *args[], void *result) {
+ int (*f)(long, int) = func;
+ *(int *)result = f(*(long *)args[0], *(int *)args[1]);
+}
+
+void testfunc_004(crx_builder_t *cb)
+{
+ crx_type_t *t1, *t2, *a3[2], *t4, *t5, *t6;
+ {
+ func_t *p1;
+ char *p2;
+ char *p3;
+ p1 = (void *)&p2;
+ *p1 = (void *)&p3; /* check that 'func_t' is a pointer type */
+ **p1 = (int (*)(long, int))0; /* check that '*func_t' is a function pointer type with exactly the given signature */
+ t1 = cb->get_signed_type(cb, sizeof(int), "int");
+ t2 = cb->get_signed_type(cb, sizeof(long), "long");
+ a3[0] = t2;
+ a3[1] = t1;
+ t4 = cb->get_function_type(cb, t1, a3, 2, &testfunc_004__f1);
+ t5 = cb->get_pointer_type(cb, t4);
+ t6 = cb->get_pointer_type(cb, t5);
+ cb->define_type(cb, "func_t", t6);
+#expect TYPEDEF func_t = PTR PTR FUNC( long -> int -> int )
+ }
+}
More information about the pypy-commit
mailing list