[pypy-commit] cffi default: Fix/test/expand the error messages we get by using structs/unions as
arigo
pypy.commits at gmail.com
Thu Dec 22 06:06:16 EST 2016
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r2836:6e21f10eead4
Date: 2016-12-22 12:05 +0100
http://bitbucket.org/cffi/cffi/changeset/6e21f10eead4/
Log: Fix/test/expand the error messages we get by using structs/unions as
arguments/return values of functions
diff --git a/c/_cffi_backend.c b/c/_cffi_backend.c
--- a/c/_cffi_backend.c
+++ b/c/_cffi_backend.c
@@ -4629,6 +4629,22 @@
}
}
+#define SUPPORTED_IN_API_MODE \
+ " are only supported as %s if the function is " \
+ "'API mode' and non-variadic (i.e. declared inside ffibuilder" \
+ ".cdef()+ffibuilder.set_source() and not taking a final '...' " \
+ "argument)"
+
+static ffi_type *fb_unsupported(CTypeDescrObject *ct, const char *place,
+ const char *detail)
+{
+ PyErr_Format(PyExc_NotImplementedError,
+ "ctype '%s' not supported as %s. %s. "
+ "Such structs" SUPPORTED_IN_API_MODE,
+ ct->ct_name, place, detail, place);
+ return NULL;
+}
+
static ffi_type *fb_fill_type(struct funcbuilder_s *fb, CTypeDescrObject *ct,
int is_result_type)
{
@@ -4675,11 +4691,10 @@
if (ct->ct_flags & CT_CUSTOM_FIELD_POS) {
/* these NotImplementedErrors may be caught and ignored until
a real call is made to a function of this type */
- PyErr_Format(PyExc_NotImplementedError,
- "ctype '%s' not supported as %s (it is a struct declared "
- "with \"...;\", but the C calling convention may depend "
- "on the missing fields)", ct->ct_name, place);
- return NULL;
+ return fb_unsupported(ct, place,
+ "It can be a struct declared with \"...;\": then the C "
+ "calling convention may depend on the missing fields. "
+ "Or, it can be a struct with nested anonymous structs/unions");
}
n = PyDict_Size(ct->ct_stuff);
@@ -4693,11 +4708,8 @@
CTypeDescrObject *ct1;
assert(cf != NULL);
if (cf->cf_bitshift >= 0) {
- PyErr_Format(PyExc_NotImplementedError,
- "ctype '%s' not supported as %s"
- " (it is a struct with bit fields)",
- ct->ct_name, place);
- return NULL;
+ return fb_unsupported(ct, place,
+ "It is a struct with bit fields");
}
flat = 1;
ct1 = cf->cf_type;
@@ -4706,11 +4718,8 @@
ct1 = ct1->ct_itemdescr;
}
if (flat <= 0) {
- PyErr_Format(PyExc_NotImplementedError,
- "ctype '%s' not supported as %s"
- " (it is a struct with a zero-length array)",
- ct->ct_name, place);
- return NULL;
+ return fb_unsupported(ct, place,
+ "It is a struct with a zero-length array");
}
nflat += flat;
cf = cf->cf_next;
@@ -4751,8 +4760,9 @@
}
else {
PyErr_Format(PyExc_NotImplementedError,
- "ctype '%s' (size %zd) not supported as %s",
- ct->ct_name, ct->ct_size, place);
+ "ctype '%s' (size %zd) not supported as %s. "
+ "Unions" SUPPORTED_IN_API_MODE,
+ ct->ct_name, ct->ct_size, place, place);
return NULL;
}
}
diff --git a/testing/cffi1/test_recompiler.py b/testing/cffi1/test_recompiler.py
--- a/testing/cffi1/test_recompiler.py
+++ b/testing/cffi1/test_recompiler.py
@@ -2012,3 +2012,79 @@
py.test.raises(ffi.error, ffi.sizeof, "vmat_t")
p = ffi.new("vmat_t", 4)
assert ffi.sizeof(p[3]) == 8 * ffi.sizeof("int")
+
+def test_call_with_custom_field_pos():
+ ffi = FFI()
+ ffi.cdef("""
+ struct foo { int x; ...; };
+ struct foo f(void);
+ struct foo g(int, ...);
+ """)
+ lib = verify(ffi, "test_call_with_custom_field_pos", """
+ struct foo { int y, x; };
+ struct foo f(void) {
+ struct foo s = { 40, 200 };
+ return s;
+ }
+ struct foo g(int a, ...) { }
+ """)
+ assert lib.f().x == 200
+ e = py.test.raises(NotImplementedError, lib.g, 0)
+ print str(e.value)
+
+def test_call_with_bitfield():
+ ffi = FFI()
+ ffi.cdef("""
+ struct foo { int x:5; };
+ struct foo f(void);
+ struct foo g(int, ...);
+ """)
+ lib = verify(ffi, "test_call_with_bitfield", """
+ struct foo { int x:5; };
+ struct foo f(void) {
+ struct foo s = { 11 };
+ return s;
+ }
+ struct foo g(int a, ...) { }
+ """)
+ assert lib.f().x == 11
+ e = py.test.raises(NotImplementedError, lib.g, 0)
+ print str(e.value)
+
+def test_call_with_zero_length_field():
+ ffi = FFI()
+ ffi.cdef("""
+ struct foo { int a; int x[0]; };
+ struct foo f(void);
+ struct foo g(int, ...);
+ """)
+ lib = verify(ffi, "test_call_with_zero_length_field", """
+ struct foo { int a; int x[0]; };
+ struct foo f(void) {
+ struct foo s = { 42 };
+ return s;
+ }
+ struct foo g(int a, ...) { }
+ """)
+ assert lib.f().a == 42
+ e = py.test.raises(NotImplementedError, lib.g, 0)
+ print str(e.value)
+
+def test_call_with_union():
+ ffi = FFI()
+ ffi.cdef("""
+ union foo { int a; char b; };
+ union foo f(void);
+ union foo g(int, ...);
+ """)
+ lib = verify(ffi, "test_call_with_union", """
+ union foo { int a; char b; };
+ union foo f(void) {
+ union foo s = { 42 };
+ return s;
+ }
+ union foo g(int a, ...) { }
+ """)
+ assert lib.f().a == 42
+ e = py.test.raises(NotImplementedError, lib.g, 0)
+ print str(e.value)
More information about the pypy-commit
mailing list