[pypy-commit] cffi default: Add some more context in the error messages "cannot generate 'struct $1'

arigo noreply at buildbot.pypy.org
Thu Aug 23 15:15:47 CEST 2012


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r878:889d00534a6b
Date: 2012-08-23 15:15 +0200
http://bitbucket.org/cffi/cffi/changeset/889d00534a6b/

Log:	Add some more context in the error messages "cannot generate 'struct
	$1' in C file".

diff --git a/cffi/model.py b/cffi/model.py
--- a/cffi/model.py
+++ b/cffi/model.py
@@ -2,13 +2,13 @@
 
 class BaseType(object):
 
-    def get_c_name(self, replace_with=''):
+    def get_c_name(self, replace_with='', context='a C file'):
         result = self._get_c_name(replace_with)
         if '$' in result:
             from .ffiplatform import VerificationError
             raise VerificationError(
-                "cannot generate '%s' in a C file: unknown type name"
-                % (result,))
+                "cannot generate '%s' in %s: unknown type name"
+                % (self._get_c_name(''), context))
         return result
 
     def has_c_name(self):
diff --git a/cffi/vengine_cpy.py b/cffi/vengine_cpy.py
--- a/cffi/vengine_cpy.py
+++ b/cffi/vengine_cpy.py
@@ -272,11 +272,13 @@
         prnt('_cffi_f_%s(PyObject *self, PyObject *%s)' % (name, argname))
         prnt('{')
         #
+        context = 'argument of %s' % name
         for i, type in enumerate(tp.args):
-            prnt('  %s;' % type.get_c_name(' x%d' % i))
+            prnt('  %s;' % type.get_c_name(' x%d' % i, context))
         if not isinstance(tp.result, model.VoidType):
             result_code = 'result = '
-            prnt('  %s;' % tp.result.get_c_name(' result'))
+            context = 'result of %s' % name
+            prnt('  %s;' % tp.result.get_c_name(' result', context))
         else:
             result_code = ''
         #
@@ -372,8 +374,11 @@
                 # only accept exactly the type declared.  Note the parentheses
                 # around the '*tmp' below.  In most cases they are not needed
                 # but don't hurt --- except test_struct_array_field.
-                prnt('  { %s = &p->%s; (void)tmp; }' % (
-                    ftype.get_c_name('(*tmp)'), fname))
+                try:
+                    prnt('  { %s = &p->%s; (void)tmp; }' % (
+                        ftype.get_c_name('(*tmp)', 'field %r'%fname), fname))
+                except ffiplatform.VerificationError, e:
+                    prnt('  /* %s */' % str(e))   # cannot verify it, ignore
         prnt('}')
         prnt('static PyObject *')
         prnt('%s(PyObject *self, PyObject *noarg)' % (layoutfuncname,))
@@ -492,7 +497,7 @@
         prnt('  PyObject *o;')
         prnt('  int res;')
         if not is_int:
-            prnt('  %s;' % (vartp or tp).get_c_name(' i'))
+            prnt('  %s;' % (vartp or tp).get_c_name(' i', name))
         else:
             assert category == 'const'
         #
diff --git a/cffi/vengine_gen.py b/cffi/vengine_gen.py
--- a/cffi/vengine_gen.py
+++ b/cffi/vengine_gen.py
@@ -108,13 +108,15 @@
             if isinstance(type, model.StructOrUnion):
                 indirection = '*'
             argnames.append('%sx%d' % (indirection, i))
-        arglist = [type.get_c_name(' %s' % arg)
+        context = 'argument of %s' % name
+        arglist = [type.get_c_name(' %s' % arg, context)
                    for type, arg in zip(tp.args, argnames)]
         arglist = ', '.join(arglist) or 'void'
         wrappername = '_cffi_f_%s' % name
         self.export_symbols.append(wrappername)
         funcdecl = ' %s(%s)' % (wrappername, arglist)
-        prnt(tp.result.get_c_name(funcdecl))
+        context = 'result of %s' % name
+        prnt(tp.result.get_c_name(funcdecl, context))
         prnt('{')
         #
         if not isinstance(tp.result, model.VoidType):
@@ -192,8 +194,11 @@
                 # only accept exactly the type declared.  Note the parentheses
                 # around the '*tmp' below.  In most cases they are not needed
                 # but don't hurt --- except test_struct_array_field.
-                prnt('  { %s = &p->%s; (void)tmp; }' % (
-                    ftype.get_c_name('(*tmp)'), fname))
+                try:
+                    prnt('  { %s = &p->%s; (void)tmp; }' % (
+                        ftype.get_c_name('(*tmp)', 'field %r'%fname), fname))
+                except ffiplatform.VerificationError, e:
+                    prnt('  /* %s */' % str(e))   # cannot verify it, ignore
         prnt('}')
         self.export_symbols.append(layoutfuncname)
         prnt('ssize_t %s(ssize_t i)' % (layoutfuncname,))
@@ -309,7 +314,7 @@
             prnt('}')
         else:
             assert tp is not None
-            prnt(tp.get_c_name(' %s(void)' % funcname),)
+            prnt(tp.get_c_name(' %s(void)' % funcname, name),)
             prnt('{')
             if category == 'var':
                 ampersand = '&'
@@ -336,7 +341,7 @@
             if value < 0 and not negative:
                 value += (1 << (8*self.ffi.sizeof("long long")))
         else:
-            BFunc = self.ffi.typeof(tp.get_c_name('(*)(void)'))
+            BFunc = self.ffi.typeof(tp.get_c_name('(*)(void)', name))
             function = module.load_function(BFunc, funcname)
             value = function()
         return value
@@ -436,7 +441,7 @@
         # remove ptr=<cdata 'int *'> from the library instance, and replace
         # it by a property on the class, which reads/writes into ptr[0].
         funcname = '_cffi_var_%s' % name
-        BFunc = self.ffi.typeof(tp.get_c_name('*(*)(void)'))
+        BFunc = self.ffi.typeof(tp.get_c_name('*(*)(void)', name))
         function = module.load_function(BFunc, funcname)
         ptr = function()
         def getter(library):
diff --git a/testing/test_verify.py b/testing/test_verify.py
--- a/testing/test_verify.py
+++ b/testing/test_verify.py
@@ -882,3 +882,16 @@
     """)
     h = lib.foo()
     assert ffi.sizeof(h) == ffi.sizeof("short")
+
+def test_cannot_name_struct_type():
+    ffi = FFI()
+    ffi.cdef("typedef struct { int x; } *sp; void foo(sp);")
+    e = py.test.raises(VerificationError, ffi.verify,
+                       "typedef struct { int x; } *sp; void foo(sp);")
+    assert 'in argument of foo: unknown type name' in str(e.value)
+
+def test_dont_check_unnamable_fields():
+    ffi = FFI()
+    ffi.cdef("struct foo_s { struct { int x; } someone; };")
+    ffi.verify("struct foo_s { struct { int x; } someone; };")
+    # assert did not crash


More information about the pypy-commit mailing list