[pypy-commit] pypy exc-later: hg merge default

rlamy noreply at buildbot.pypy.org
Sat Nov 21 11:50:31 EST 2015


Author: Ronan Lamy <ronan.lamy at gmail.com>
Branch: exc-later
Changeset: r80820:c61a1f069e26
Date: 2015-11-21 16:50 +0000
http://bitbucket.org/pypy/pypy/changeset/c61a1f069e26/

Log:	hg merge default

diff too long, truncating to 2000 out of 10259 lines

diff --git a/.hgtags b/.hgtags
--- a/.hgtags
+++ b/.hgtags
@@ -17,3 +17,4 @@
 295ee98b69288471b0fcf2e0ede82ce5209eb90b release-2.6.0
 f3ad1e1e1d6215e20d34bb65ab85ff9188c9f559 release-2.6.1
 850edf14b2c75573720f59e95767335fb1affe55 release-4.0.0
+5f8302b8bf9f53056e40426f10c72151564e5b19 release-4.0.1
diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -56,14 +56,15 @@
   Anders Chrigstrom
   Eric van Riet Paap
   Wim Lavrijsen
+  Richard Plangger
   Richard Emslie
   Alexander Schremmer
   Dan Villiom Podlaski Christiansen
   Lukas Diekmann
   Sven Hager
   Anders Lehmann
+  Remi Meier
   Aurelien Campeas
-  Remi Meier
   Niklaus Haldimann
   Camillo Bruni
   Laura Creighton
@@ -87,7 +88,6 @@
   Ludovic Aubry
   Jacob Hallen
   Jason Creighton
-  Richard Plangger
   Alex Martelli
   Michal Bendowski
   stian
@@ -200,9 +200,12 @@
   Alex Perry
   Vincent Legoll
   Alan McIntyre
+  Spenser Bauman
   Alexander Sedov
   Attila Gobi
   Christopher Pope
+  Devin Jeanpierre
+  Vaibhav Sood
   Christian Tismer 
   Marc Abramowitz
   Dan Stromberg
@@ -234,6 +237,7 @@
   Lutz Paelike
   Lucio Torre
   Lars Wassermann
+  Philipp Rustemeuer
   Henrik Vendelbo
   Dan Buch
   Miguel de Val Borro
@@ -244,6 +248,7 @@
   Martin Blais
   Lene Wagner
   Tomo Cocoa
+  Kim Jin Su
   Toni Mattis
   Lucas Stadler
   Julian Berman
@@ -253,6 +258,7 @@
   Anna Katrina Dominguez
   William Leslie
   Bobby Impollonia
+  Faye Zhao
   timo at eistee.fritz.box
   Andrew Thompson
   Yusei Tahara
@@ -283,6 +289,7 @@
   shoma hosaka
   Daniel Neuhäuser
   Ben Mather
+  Niclas Olofsson
   halgari
   Boglarka Vezer
   Chris Pressey
@@ -309,13 +316,16 @@
   Stefan Marr
   jiaaro
   Mads Kiilerich
+  Richard Lancaster
   opassembler.py
   Antony Lee
+  Yaroslav Fedevych
   Jim Hunziker
   Markus Unterwaditzer
   Even Wiik Thomassen
   jbs
   squeaky
+  Zearin
   soareschen
   Kurt Griffiths
   Mike Bayer
@@ -327,6 +337,7 @@
   Anna Ravencroft
   Andrey Churin
   Dan Crosta
+  Tobias Diaz
   Julien Phalip
   Roman Podoliaka
   Dan Loewenherz
diff --git a/lib_pypy/cffi.egg-info/PKG-INFO b/lib_pypy/cffi.egg-info/PKG-INFO
--- a/lib_pypy/cffi.egg-info/PKG-INFO
+++ b/lib_pypy/cffi.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: cffi
-Version: 1.3.0
+Version: 1.3.1
 Summary: Foreign Function Interface for Python calling C code.
 Home-page: http://cffi.readthedocs.org
 Author: Armin Rigo, Maciej Fijalkowski
diff --git a/lib_pypy/cffi/__init__.py b/lib_pypy/cffi/__init__.py
--- a/lib_pypy/cffi/__init__.py
+++ b/lib_pypy/cffi/__init__.py
@@ -4,8 +4,8 @@
 from .api import FFI, CDefError, FFIError
 from .ffiplatform import VerificationError, VerificationMissing
 
-__version__ = "1.3.0"
-__version_info__ = (1, 3, 0)
+__version__ = "1.3.1"
+__version_info__ = (1, 3, 1)
 
 # The verifier module file names are based on the CRC32 of a string that
 # contains the following version number.  It may be older than __version__
diff --git a/lib_pypy/cffi/cffi_opcode.py b/lib_pypy/cffi/cffi_opcode.py
--- a/lib_pypy/cffi/cffi_opcode.py
+++ b/lib_pypy/cffi/cffi_opcode.py
@@ -110,6 +110,8 @@
 _UNKNOWN_FLOAT_PRIM    = -2
 _UNKNOWN_LONG_DOUBLE   = -3
 
+_IO_FILE_STRUCT        = -1
+
 PRIMITIVE_TO_INDEX = {
     'char':               PRIM_CHAR,
     'short':              PRIM_SHORT,
diff --git a/lib_pypy/cffi/commontypes.py b/lib_pypy/cffi/commontypes.py
--- a/lib_pypy/cffi/commontypes.py
+++ b/lib_pypy/cffi/commontypes.py
@@ -2,10 +2,17 @@
 from . import api, model
 
 
-COMMON_TYPES = {
-    'FILE': model.unknown_type('FILE', '_IO_FILE'),
-    'bool': '_Bool',
-    }
+COMMON_TYPES = {}
+
+try:
+    # fetch "bool" and all simple Windows types
+    from _cffi_backend import _get_common_types
+    _get_common_types(COMMON_TYPES)
+except ImportError:
+    pass
+
+COMMON_TYPES['FILE'] = model.unknown_type('FILE', '_IO_FILE')
+COMMON_TYPES['bool'] = '_Bool'    # in case we got ImportError above
 
 for _type in model.PrimitiveType.ALL_PRIMITIVE_TYPES:
     if _type.endswith('_t'):
@@ -14,212 +21,35 @@
 
 _CACHE = {}
 
-def resolve_common_type(commontype):
+def resolve_common_type(parser, commontype):
     try:
         return _CACHE[commontype]
     except KeyError:
-        result = COMMON_TYPES.get(commontype, commontype)
-        if not isinstance(result, str):
-            pass    # result is already a BaseType
-        elif result.endswith(' *'):
-            if result.startswith('const '):
-                result = model.ConstPointerType(
-                    resolve_common_type(result[6:-2]))
-            else:
-                result = model.PointerType(resolve_common_type(result[:-2]))
-        elif result in model.PrimitiveType.ALL_PRIMITIVE_TYPES:
-            result = model.PrimitiveType(result)
-        elif result == 'set-unicode-needed':
+        cdecl = COMMON_TYPES.get(commontype, commontype)
+        if not isinstance(cdecl, str):
+            result, quals = cdecl, 0    # cdecl is already a BaseType
+        elif cdecl in model.PrimitiveType.ALL_PRIMITIVE_TYPES:
+            result, quals = model.PrimitiveType(cdecl), 0
+        elif cdecl == 'set-unicode-needed':
             raise api.FFIError("The Windows type %r is only available after "
                                "you call ffi.set_unicode()" % (commontype,))
         else:
-            if commontype == result:
+            if commontype == cdecl:
                 raise api.FFIError("Unsupported type: %r.  Please file a bug "
                                    "if you think it should be." % (commontype,))
-            result = resolve_common_type(result)   # recursively
+            result, quals = parser.parse_type_and_quals(cdecl)   # recursive
+
         assert isinstance(result, model.BaseTypeByIdentity)
-        _CACHE[commontype] = result
-        return result
+        _CACHE[commontype] = result, quals
+        return result, quals
 
 
 # ____________________________________________________________
-# Windows common types
+# extra types for Windows (most of them are in commontypes.c)
 
 
-def win_common_types(maxsize):
-    result = {}
-    if maxsize < (1<<32):
-        result.update({      # Windows 32-bits
-            'HALF_PTR': 'short',
-            'INT_PTR': 'int',
-            'LONG_PTR': 'long',
-            'UHALF_PTR': 'unsigned short',
-            'UINT_PTR': 'unsigned int',
-            'ULONG_PTR': 'unsigned long',
-            })
-    else:
-        result.update({      # Windows 64-bits
-            'HALF_PTR': 'int',
-            'INT_PTR': 'long long',
-            'LONG_PTR': 'long long',
-            'UHALF_PTR': 'unsigned int',
-            'UINT_PTR': 'unsigned long long',
-            'ULONG_PTR': 'unsigned long long',
-            })
-    result.update({
-        "BYTE": "unsigned char",
-        "BOOL": "int",
-        "CCHAR": "char",
-        "CHAR": "char",
-        "DWORD": "unsigned long",
-        "DWORD32": "unsigned int",
-        "DWORD64": "unsigned long long",
-        "FLOAT": "float",
-        "INT": "int",
-        "INT8": "signed char",
-        "INT16": "short",
-        "INT32": "int",
-        "INT64": "long long",
-        "LONG": "long",
-        "LONGLONG": "long long",
-        "LONG32": "int",
-        "LONG64": "long long",
-        "WORD": "unsigned short",
-        "PVOID": model.voidp_type,
-        "ULONGLONG": "unsigned long long",
-        "WCHAR": "wchar_t",
-        "SHORT": "short",
-        "UCHAR": "unsigned char",
-        "UINT": "unsigned int",
-        "UINT8": "unsigned char",
-        "UINT16": "unsigned short",
-        "UINT32": "unsigned int",
-        "UINT64": "unsigned long long",
-        "ULONG": "unsigned long",
-        "ULONG32": "unsigned int",
-        "ULONG64": "unsigned long long",
-        "USHORT": "unsigned short",
-
-        "SIZE_T": "ULONG_PTR",
-        "SSIZE_T": "LONG_PTR",
-        "ATOM": "WORD",
-        "BOOLEAN": "BYTE",
-        "COLORREF": "DWORD",
-
-        "HANDLE": "PVOID",
-        "DWORDLONG": "ULONGLONG",
-        "DWORD_PTR": "ULONG_PTR",
-        "HACCEL": "HANDLE",
-
-        "HBITMAP": "HANDLE",
-        "HBRUSH": "HANDLE",
-        "HCOLORSPACE": "HANDLE",
-        "HCONV": "HANDLE",
-        "HCONVLIST": "HANDLE",
-        "HDC": "HANDLE",
-        "HDDEDATA": "HANDLE",
-        "HDESK": "HANDLE",
-        "HDROP": "HANDLE",
-        "HDWP": "HANDLE",
-        "HENHMETAFILE": "HANDLE",
-        "HFILE": "int",
-        "HFONT": "HANDLE",
-        "HGDIOBJ": "HANDLE",
-        "HGLOBAL": "HANDLE",
-        "HHOOK": "HANDLE",
-        "HICON": "HANDLE",
-        "HCURSOR": "HICON",
-        "HINSTANCE": "HANDLE",
-        "HKEY": "HANDLE",
-        "HKL": "HANDLE",
-        "HLOCAL": "HANDLE",
-        "HMENU": "HANDLE",
-        "HMETAFILE": "HANDLE",
-        "HMODULE": "HINSTANCE",
-        "HMONITOR": "HANDLE",
-        "HPALETTE": "HANDLE",
-        "HPEN": "HANDLE",
-        "HRESULT": "LONG",
-        "HRGN": "HANDLE",
-        "HRSRC": "HANDLE",
-        "HSZ": "HANDLE",
-        "WINSTA": "HANDLE",
-        "HWND": "HANDLE",
-
-        "LANGID": "WORD",
-        "LCID": "DWORD",
-        "LCTYPE": "DWORD",
-        "LGRPID": "DWORD",
-        "LPARAM": "LONG_PTR",
-        "LPBOOL": "BOOL *",
-        "LPBYTE": "BYTE *",
-        "LPCOLORREF": "DWORD *",
-        "LPCSTR": "const char *",
-
-        "LPCVOID": model.const_voidp_type,
-        "LPCWSTR": "const WCHAR *",
-        "LPDWORD": "DWORD *",
-        "LPHANDLE": "HANDLE *",
-        "LPINT": "int *",
-        "LPLONG": "long *",
-        "LPSTR": "CHAR *",
-        "LPWSTR": "WCHAR *",
-        "LPVOID": model.voidp_type,
-        "LPWORD": "WORD *",
-        "LRESULT": "LONG_PTR",
-        "PBOOL": "BOOL *",
-        "PBOOLEAN": "BOOLEAN *",
-        "PBYTE": "BYTE *",
-        "PCHAR": "CHAR *",
-        "PCSTR": "const CHAR *",
-        "PCWSTR": "const WCHAR *",
-        "PDWORD": "DWORD *",
-        "PDWORDLONG": "DWORDLONG *",
-        "PDWORD_PTR": "DWORD_PTR *",
-        "PDWORD32": "DWORD32 *",
-        "PDWORD64": "DWORD64 *",
-        "PFLOAT": "FLOAT *",
-        "PHALF_PTR": "HALF_PTR *",
-        "PHANDLE": "HANDLE *",
-        "PHKEY": "HKEY *",
-        "PINT": "int *",
-        "PINT_PTR": "INT_PTR *",
-        "PINT8": "INT8 *",
-        "PINT16": "INT16 *",
-        "PINT32": "INT32 *",
-        "PINT64": "INT64 *",
-        "PLCID": "PDWORD",
-        "PLONG": "LONG *",
-        "PLONGLONG": "LONGLONG *",
-        "PLONG_PTR": "LONG_PTR *",
-        "PLONG32": "LONG32 *",
-        "PLONG64": "LONG64 *",
-        "PSHORT": "SHORT *",
-        "PSIZE_T": "SIZE_T *",
-        "PSSIZE_T": "SSIZE_T *",
-        "PSTR": "CHAR *",
-        "PUCHAR": "UCHAR *",
-        "PUHALF_PTR": "UHALF_PTR *",
-        "PUINT": "UINT *",
-        "PUINT_PTR": "UINT_PTR *",
-        "PUINT8": "UINT8 *",
-        "PUINT16": "UINT16 *",
-        "PUINT32": "UINT32 *",
-        "PUINT64": "UINT64 *",
-        "PULONG": "ULONG *",
-        "PULONGLONG": "ULONGLONG *",
-        "PULONG_PTR": "ULONG_PTR *",
-        "PULONG32": "ULONG32 *",
-        "PULONG64": "ULONG64 *",
-        "PUSHORT": "USHORT *",
-        "PWCHAR": "WCHAR *",
-        "PWORD": "WORD *",
-        "PWSTR": "WCHAR *",
-        "QWORD": "unsigned long long",
-        "SC_HANDLE": "HANDLE",
-        "SC_LOCK": "LPVOID",
-        "SERVICE_STATUS_HANDLE": "HANDLE",
-
+def win_common_types():
+    return {
         "UNICODE_STRING": model.StructType(
             "_UNICODE_STRING",
             ["Length",
@@ -232,10 +62,6 @@
         "PUNICODE_STRING": "UNICODE_STRING *",
         "PCUNICODE_STRING": "const UNICODE_STRING *",
 
-        "USN": "LONGLONG",
-        "VOID": model.void_type,
-        "WPARAM": "UINT_PTR",
-
         "TBYTE": "set-unicode-needed",
         "TCHAR": "set-unicode-needed",
         "LPCTSTR": "set-unicode-needed",
@@ -244,9 +70,7 @@
         "PTSTR": "set-unicode-needed",
         "PTBYTE": "set-unicode-needed",
         "PTCHAR": "set-unicode-needed",
-        })
-    return result
-
+        }
 
 if sys.platform == 'win32':
-    COMMON_TYPES.update(win_common_types(sys.maxsize))
+    COMMON_TYPES.update(win_common_types())
diff --git a/lib_pypy/cffi/cparser.py b/lib_pypy/cffi/cparser.py
--- a/lib_pypy/cffi/cparser.py
+++ b/lib_pypy/cffi/cparser.py
@@ -29,6 +29,8 @@
 _r_stdcall1 = re.compile(r"\b(__stdcall|WINAPI)\b")
 _r_stdcall2 = re.compile(r"[(]\s*(__stdcall|WINAPI)\b")
 _r_cdecl = re.compile(r"\b__cdecl\b")
+_r_star_const_space = re.compile(       # matches "* const "
+    r"[*]\s*((const|volatile|restrict)\b\s*)+")
 
 def _get_parser():
     global _parser_cache
@@ -36,6 +38,48 @@
         _parser_cache = pycparser.CParser()
     return _parser_cache
 
+def _workaround_for_old_pycparser(csource):
+    # Workaround for a pycparser issue (fixed between pycparser 2.10 and
+    # 2.14): "char*const***" gives us a wrong syntax tree, the same as
+    # for "char***(*const)".  This means we can't tell the difference
+    # afterwards.  But "char(*const(***))" gives us the right syntax
+    # tree.  The issue only occurs if there are several stars in
+    # sequence with no parenthesis inbetween, just possibly qualifiers.
+    # Attempt to fix it by adding some parentheses in the source: each
+    # time we see "* const" or "* const *", we add an opening
+    # parenthesis before each star---the hard part is figuring out where
+    # to close them.
+    parts = []
+    while True:
+        match = _r_star_const_space.search(csource)
+        if not match:
+            break
+        #print repr(''.join(parts)+csource), '=>',
+        parts.append(csource[:match.start()])
+        parts.append('('); closing = ')'
+        parts.append(match.group())   # e.g. "* const "
+        endpos = match.end()
+        if csource.startswith('*', endpos):
+            parts.append('('); closing += ')'
+        level = 0
+        i = endpos
+        while i < len(csource):
+            c = csource[i]
+            if c == '(':
+                level += 1
+            elif c == ')':
+                if level == 0:
+                    break
+                level -= 1
+            elif c in ',;=':
+                if level == 0:
+                    break
+            i += 1
+        csource = csource[endpos:i] + closing + csource[i:]
+        #print repr(''.join(parts)+csource)
+    parts.append(csource)
+    return ''.join(parts)
+
 def _preprocess(csource):
     # Remove comments.  NOTE: this only work because the cdef() section
     # should not contain any string literal!
@@ -47,6 +91,10 @@
         macrovalue = macrovalue.replace('\\\n', '').strip()
         macros[macroname] = macrovalue
     csource = _r_define.sub('', csource)
+    #
+    if pycparser.__version__ < '2.14':
+        csource = _workaround_for_old_pycparser(csource)
+    #
     # BIG HACK: replace WINAPI or __stdcall with "volatile const".
     # It doesn't make sense for the return type of a function to be
     # "volatile volatile const", so we abuse it to detect __stdcall...
@@ -320,13 +368,15 @@
                     self._declare('variable ' + decl.name, tp, quals=quals)
 
     def parse_type(self, cdecl):
+        return self.parse_type_and_quals(cdecl)[0]
+
+    def parse_type_and_quals(self, cdecl):
         ast, macros = self._parse('void __dummy(\n%s\n);' % cdecl)[:2]
         assert not macros
         exprnode = ast.ext[-1].type.args.params[0]
         if isinstance(exprnode, pycparser.c_ast.ID):
             raise api.CDefError("unknown identifier '%s'" % (exprnode.name,))
-        tp, quals = self._get_type_and_quals(exprnode.type)
-        return tp
+        return self._get_type_and_quals(exprnode.type)
 
     def _declare(self, name, obj, included=False, quals=0):
         if name in self._declarations:
@@ -348,6 +398,8 @@
                              pycparser.c_ast.PtrDecl)):
             if 'const' in type.quals:
                 quals |= model.Q_CONST
+            if 'volatile' in type.quals:
+                quals |= model.Q_VOLATILE
             if 'restrict' in type.quals:
                 quals |= model.Q_RESTRICT
         return quals
@@ -422,7 +474,8 @@
                 if ident == '__dotdotdot__':
                     raise api.FFIError(':%d: bad usage of "..."' %
                             typenode.coord.line)
-                return resolve_common_type(ident), quals
+                tp0, quals0 = resolve_common_type(self, ident)
+                return tp0, (quals | quals0)
             #
             if isinstance(type, pycparser.c_ast.Struct):
                 # 'struct foobar'
@@ -456,6 +509,13 @@
 
     def _parse_function_type(self, typenode, funcname=None):
         params = list(getattr(typenode.args, 'params', []))
+        for i, arg in enumerate(params):
+            if not hasattr(arg, 'type'):
+                raise api.CDefError("%s arg %d: unknown type '%s'"
+                    " (if you meant to use the old C syntax of giving"
+                    " untyped arguments, it is not supported)"
+                    % (funcname or 'in expression', i + 1,
+                       getattr(arg, 'name', '?')))
         ellipsis = (
             len(params) > 0 and
             isinstance(params[-1].type, pycparser.c_ast.TypeDecl) and
diff --git a/lib_pypy/cffi/model.py b/lib_pypy/cffi/model.py
--- a/lib_pypy/cffi/model.py
+++ b/lib_pypy/cffi/model.py
@@ -7,10 +7,13 @@
 # type qualifiers
 Q_CONST    = 0x01
 Q_RESTRICT = 0x02
+Q_VOLATILE = 0x04
 
 def qualify(quals, replace_with):
     if quals & Q_CONST:
         replace_with = ' const ' + replace_with.lstrip()
+    if quals & Q_VOLATILE:
+        replace_with = ' volatile ' + replace_with.lstrip()
     if quals & Q_RESTRICT:
         # It seems that __restrict is supported by gcc and msvc.
         # If you hit some different compiler, add a #define in
@@ -511,12 +514,17 @@
         if self.baseinttype is not None:
             return self.baseinttype.get_cached_btype(ffi, finishlist)
         #
+        from . import api
         if self.enumvalues:
             smallest_value = min(self.enumvalues)
             largest_value = max(self.enumvalues)
         else:
-            smallest_value = 0
-            largest_value = 0
+            import warnings
+            warnings.warn("%r has no values explicitly defined; next version "
+                          "will refuse to guess which integer type it is "
+                          "meant to be (unsigned/signed, int/long)"
+                          % self._get_c_name())
+            smallest_value = largest_value = 0
         if smallest_value < 0:   # needs a signed type
             sign = 1
             candidate1 = PrimitiveType("int")
diff --git a/lib_pypy/cffi/parse_c_type.h b/lib_pypy/cffi/parse_c_type.h
--- a/lib_pypy/cffi/parse_c_type.h
+++ b/lib_pypy/cffi/parse_c_type.h
@@ -83,6 +83,8 @@
 #define _CFFI__UNKNOWN_FLOAT_PRIM     (-2)
 #define _CFFI__UNKNOWN_LONG_DOUBLE    (-3)
 
+#define _CFFI__IO_FILE_STRUCT         (-1)
+
 
 struct _cffi_global_s {
     const char *name;
diff --git a/lib_pypy/greenlet.py b/lib_pypy/greenlet.py
--- a/lib_pypy/greenlet.py
+++ b/lib_pypy/greenlet.py
@@ -88,9 +88,19 @@
         #
         try:
             unbound_method = getattr(_continulet, methodname)
+            _tls.leaving = current
             args, kwds = unbound_method(current, *baseargs, to=target)
-        finally:
             _tls.current = current
+        except:
+            _tls.current = current
+            if hasattr(_tls, 'trace'):
+                _run_trace_callback('throw')
+            _tls.leaving = None
+            raise
+        else:
+            if hasattr(_tls, 'trace'):
+                _run_trace_callback('switch')
+            _tls.leaving = None
         #
         if kwds:
             if args:
@@ -122,6 +132,34 @@
         return f.f_back.f_back.f_back   # go past start(), __switch(), switch()
 
 # ____________________________________________________________
+# Recent additions
+
+GREENLET_USE_GC = True
+GREENLET_USE_TRACING = True
+
+def gettrace():
+    return getattr(_tls, 'trace', None)
+
+def settrace(callback):
+    try:
+        prev = _tls.trace
+        del _tls.trace
+    except AttributeError:
+        prev = None
+    if callback is not None:
+        _tls.trace = callback
+    return prev
+
+def _run_trace_callback(event):
+    try:
+        _tls.trace(event, (_tls.leaving, _tls.current))
+    except:
+        # In case of exceptions trace function is removed
+        if hasattr(_tls, 'trace'):
+            del _tls.trace
+        raise
+
+# ____________________________________________________________
 # Internal stuff
 
 try:
@@ -143,22 +181,32 @@
     _tls.current = gmain
 
 def _greenlet_start(greenlet, args):
-    args, kwds = args
-    _tls.current = greenlet
     try:
-        res = greenlet.run(*args, **kwds)
-    except GreenletExit, e:
-        res = e
+        args, kwds = args
+        _tls.current = greenlet
+        try:
+            if hasattr(_tls, 'trace'):
+                _run_trace_callback('switch')
+            res = greenlet.run(*args, **kwds)
+        except GreenletExit, e:
+            res = e
+        finally:
+            _continuation.permute(greenlet, greenlet.parent)
+        return ((res,), None)
     finally:
-        _continuation.permute(greenlet, greenlet.parent)
-    return ((res,), None)
+        _tls.leaving = greenlet
 
 def _greenlet_throw(greenlet, exc, value, tb):
-    _tls.current = greenlet
     try:
-        raise exc, value, tb
-    except GreenletExit, e:
-        res = e
+        _tls.current = greenlet
+        try:
+            if hasattr(_tls, 'trace'):
+                _run_trace_callback('throw')
+            raise exc, value, tb
+        except GreenletExit, e:
+            res = e
+        finally:
+            _continuation.permute(greenlet, greenlet.parent)
+        return ((res,), None)
     finally:
-        _continuation.permute(greenlet, greenlet.parent)
-    return ((res,), None)
+        _tls.leaving = greenlet
diff --git a/pypy/config/pypyoption.py b/pypy/config/pypyoption.py
--- a/pypy/config/pypyoption.py
+++ b/pypy/config/pypyoption.py
@@ -76,10 +76,10 @@
     if "cppyy" in working_modules:
         working_modules.remove("cppyy")  # depends on ctypes
 
-if sys.platform.startswith("linux"):
-    _mach = os.popen('uname -m', 'r').read().strip()
-    if _mach.startswith('ppc'):
-        working_modules.remove("_continuation")
+#if sys.platform.startswith("linux"):
+#    _mach = os.popen('uname -m', 'r').read().strip()
+#    if _mach.startswith(...):
+#        working_modules.remove("_continuation")
 
 
 module_dependencies = {
diff --git a/pypy/doc/build.rst b/pypy/doc/build.rst
--- a/pypy/doc/build.rst
+++ b/pypy/doc/build.rst
@@ -85,13 +85,16 @@
 _ssl
     libssl
 
+gdbm
+    libgdbm-dev
+
 Make sure to have these libraries (with development headers) installed before
 building PyPy, otherwise the resulting binary will not contain these modules.
 
 On Debian, this is the command to install all build-time dependencies::
 
     apt-get install gcc make libffi-dev pkg-config libz-dev libbz2-dev \
-    libsqlite3-dev libncurses-dev libexpat1-dev libssl-dev
+    libsqlite3-dev libncurses-dev libexpat1-dev libssl-dev libgdbm-dev
 
 For the optional lzma module on PyPy3 you will also need ``liblzma-dev``.
 
diff --git a/pypy/doc/contributor.rst b/pypy/doc/contributor.rst
--- a/pypy/doc/contributor.rst
+++ b/pypy/doc/contributor.rst
@@ -26,15 +26,15 @@
   Anders Chrigstrom
   Eric van Riet Paap
   Wim Lavrijsen
+  Richard Plangger
   Richard Emslie
   Alexander Schremmer
   Dan Villiom Podlaski Christiansen
   Lukas Diekmann
   Sven Hager
   Anders Lehmann
-  Richard Plangger
+  Remi Meier
   Aurelien Campeas
-  Remi Meier
   Niklaus Haldimann
   Camillo Bruni
   Laura Creighton
@@ -170,9 +170,12 @@
   Alex Perry
   Vincent Legoll
   Alan McIntyre
+  Spenser Bauman
   Alexander Sedov
   Attila Gobi
   Christopher Pope
+  Devin Jeanpierre
+  Vaibhav Sood
   Christian Tismer 
   Marc Abramowitz
   Dan Stromberg
@@ -204,6 +207,7 @@
   Lutz Paelike
   Lucio Torre
   Lars Wassermann
+  Philipp Rustemeuer
   Henrik Vendelbo
   Dan Buch
   Miguel de Val Borro
@@ -214,6 +218,7 @@
   Martin Blais
   Lene Wagner
   Tomo Cocoa
+  Kim Jin Su
   Toni Mattis
   Lucas Stadler
   Julian Berman
@@ -223,6 +228,7 @@
   Anna Katrina Dominguez
   William Leslie
   Bobby Impollonia
+  Faye Zhao
   timo at eistee.fritz.box
   Andrew Thompson
   Yusei Tahara
@@ -280,13 +286,16 @@
   Stefan Marr
   jiaaro
   Mads Kiilerich
+  Richard Lancaster
   opassembler.py
   Antony Lee
+  Yaroslav Fedevych
   Jim Hunziker
   Markus Unterwaditzer
   Even Wiik Thomassen
   jbs
   squeaky
+  Zearin
   soareschen
   Kurt Griffiths
   Mike Bayer
@@ -298,6 +307,7 @@
   Anna Ravencroft
   Andrey Churin
   Dan Crosta
+  Tobias Diaz
   Julien Phalip
   Roman Podoliaka
   Dan Loewenherz
diff --git a/pypy/doc/index-of-release-notes.rst b/pypy/doc/index-of-release-notes.rst
--- a/pypy/doc/index-of-release-notes.rst
+++ b/pypy/doc/index-of-release-notes.rst
@@ -6,6 +6,7 @@
 
 .. toctree::
 
+   release-4.0.1.rst
    release-4.0.0.rst
    release-2.6.1.rst
    release-2.6.0.rst
diff --git a/pypy/doc/index-of-whatsnew.rst b/pypy/doc/index-of-whatsnew.rst
--- a/pypy/doc/index-of-whatsnew.rst
+++ b/pypy/doc/index-of-whatsnew.rst
@@ -7,6 +7,7 @@
 .. toctree::
 
    whatsnew-head.rst
+   whatsnew-4.0.1.rst
    whatsnew-4.0.0.rst
    whatsnew-2.6.1.rst
    whatsnew-2.6.0.rst
diff --git a/pypy/doc/release-4.0.1.rst b/pypy/doc/release-4.0.1.rst
new file mode 100644
--- /dev/null
+++ b/pypy/doc/release-4.0.1.rst
@@ -0,0 +1,106 @@
+==========
+PyPy 4.0.1
+==========
+
+We have released PyPy 4.0.1, three weeks after PyPy 4.0.0. We have fixed
+a few critical bugs in the JIT compiled code, reported by users. We therefore
+encourage all users of PyPy to update to this version. There are a few minor
+enhancements in this version as well.
+
+You can download the PyPy 4.0.1 release here:
+
+    http://pypy.org/download.html
+
+We would like to thank our donors for the continued support of the PyPy
+project.
+
+We would also like to thank our contributors and 
+encourage new people to join the project. PyPy has many
+layers and we need help with all of them: `PyPy`_ and `RPython`_ documentation
+improvements, tweaking popular `modules`_ to run on pypy, or general `help`_ 
+with making RPython's JIT even better. 
+
+CFFI
+====
+
+While not applicable only to PyPy, `cffi`_ is arguably our most significant
+contribution to the python ecosystem. PyPy 4.0.1 ships with 
+`cffi-1.3.1`_ with the improvements it brings.
+
+.. _`PyPy`: http://doc.pypy.org 
+.. _`RPython`: https://rpython.readthedocs.org
+.. _`cffi`: https://cffi.readthedocs.org
+.. _`cffi-1.3.1`: http://cffi.readthedocs.org/en/latest/whatsnew.html#v1-3-1
+.. _`modules`: http://doc.pypy.org/en/latest/project-ideas.html#make-more-python-modules-pypy-friendly
+.. _`help`: http://doc.pypy.org/en/latest/project-ideas.html
+.. _`numpy`: https://bitbucket.org/pypy/numpy
+
+What is PyPy?
+=============
+
+PyPy is a very compliant Python interpreter, almost a drop-in replacement for
+CPython 2.7. It's fast (`pypy and cpython 2.7.x`_ performance comparison)
+due to its integrated tracing JIT compiler.
+
+We also welcome developers of other
+`dynamic languages`_ to see what RPython can do for them.
+
+This release supports **x86** machines on most common operating systems
+(Linux 32/64, Mac OS X 64, Windows 32, OpenBSD, freebsd),
+newer **ARM** hardware (ARMv6 or ARMv7, with VFPv3) running Linux, and the
+big- and little-endian variants of **ppc64** running Linux.
+
+.. _`pypy and cpython 2.7.x`: http://speed.pypy.org
+.. _`dynamic languages`: http://pypyjs.org
+
+Other Highlights (since 4.0.0 released three weeks ago)
+=======================================================
+
+* Bug Fixes
+
+  * Fix a bug when unrolling double loops in JITted code
+
+  * Fix multiple memory leaks in the ssl module, one of which affected
+    `cpython` as well (thanks to Alex Gaynor for pointing those out)
+
+  * Use pkg-config to find ssl headers on OS-X
+
+  * Issues reported with our previous release were resolved_ after reports from users on
+    our issue tracker at https://bitbucket.org/pypy/pypy/issues or on IRC at
+    #pypy
+
+* New features:
+
+  * Internal cleanup of RPython class handling
+
+  * Support stackless and greenlets on PPC machines
+
+  * Improve debug logging in subprocesses: use PYPYLOG=jit:log.%d
+    for example to have all subprocesses write the JIT log to a file
+    called 'log.%d', with '%d' replaced with the subprocess' PID.
+
+  * Support PyOS_double_to_string in our cpyext capi compatibility layer
+
+* Numpy:
+
+  * Improve support for __array_interface__
+
+  * Propagate NAN mantissas through float16-float32-float64 conversions
+
+
+* Performance improvements and refactorings:
+
+  * Improvements in slicing byte arrays
+
+  * Improvements in enumerate()
+
+  * Silence some warnings while translating
+
+.. _resolved: http://doc.pypy.org/en/latest/whatsnew-4.0.1.html
+
+Please update, and continue to help us make PyPy better.
+
+Cheers
+
+The PyPy Team
+
diff --git a/pypy/doc/tool/makecontributor.py b/pypy/doc/tool/makecontributor.py
--- a/pypy/doc/tool/makecontributor.py
+++ b/pypy/doc/tool/makecontributor.py
@@ -69,7 +69,9 @@
     'Rami Chowdhury': ['necaris'],
     'Stanislaw Halik':['w31rd0'],
     'Wenzhu Man':['wenzhu man', 'wenzhuman'],
-    'Anton Gulenko':['anton gulenko'],
+    'Anton Gulenko':['anton gulenko', 'anton_gulenko'],
+    'Richard Lancaster':['richardlancaster'],
+    'William Leslie':['William ML Leslie'],
     }
 
 alias_map = {}
diff --git a/pypy/doc/whatsnew-4.0.1.rst b/pypy/doc/whatsnew-4.0.1.rst
new file mode 100644
--- /dev/null
+++ b/pypy/doc/whatsnew-4.0.1.rst
@@ -0,0 +1,35 @@
+=========================
+What's new in PyPy 4.0.1
+=========================
+
+.. this is a revision shortly after release-4.0.0
+.. startrev: 57c9a47c70f6
+
+.. branch: 2174-fix-osx-10-11-translation
+
+Use pkg-config to find ssl headers on OS-X
+
+.. branch: Zearin/minor-whatsnewrst-markup-tweaks-edited-o-1446387512092
+
+.. branch: ppc-stacklet
+
+The PPC machines now support the _continuation module (stackless, greenlets)
+
+.. branch: int_0/i-need-this-library-to-build-on-ubuntu-1-1446717626227
+
+Document that libgdbm-dev is required for translation/packaging
+
+.. branch: propogate-nans
+
+Ensure that ndarray conversion from int16->float16->float32->float16->int16
+preserves all int16 values, even across nan conversions. Also fix argmax, argmin
+for nan comparisons
+
+.. branch: array_interface
+
+Support common use-cases for __array_interface__, passes upstream tests
+
+.. branch: no-class-specialize
+
+Some refactoring of class handling in the annotator. 
+Remove class specialisation and _settled_ flag.
diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst
--- a/pypy/doc/whatsnew-head.rst
+++ b/pypy/doc/whatsnew-head.rst
@@ -1,10 +1,18 @@
 =========================
-What's new in PyPy 4.0.+
+What's new in PyPy 4.1.+
 =========================
 
-.. this is a revision shortly after release-4.0.0
-.. startrev: 57c9a47c70f6
+.. this is a revision shortly after release-4.0.1
+.. startrev: 4b5c840d0da2
 
-.. branch: 2174-fix-osx-10-11-translation
+.. branch: numpy-1.10
 
-Use pkg-config to find ssl headers on OS-X
+Fix tests to run cleanly with -A and start to fix micronumpy for upstream numpy
+which is now 1.10.2
+
+.. branch: osx-flat-namespace
+
+Fix the cpyext tests on OSX by linking with -flat_namespace
+
+.. branch: anntype
+Refactor and improve exception analysis in the annotator.
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -28,7 +28,6 @@
     """This is the abstract root class of all wrapped objects that live
     in a 'normal' object space like StdObjSpace."""
     __slots__ = ()
-    _settled_ = True
     user_overridden_class = False
 
     def getdict(self, space):
@@ -392,7 +391,7 @@
         self.check_signal_action = None   # changed by the signal module
         self.user_del_action = UserDelAction(self)
         self._code_of_sys_exc_info = None
-
+        
         # can be overridden to a subclass
         self.initialize()
 
diff --git a/pypy/interpreter/pycode.py b/pypy/interpreter/pycode.py
--- a/pypy/interpreter/pycode.py
+++ b/pypy/interpreter/pycode.py
@@ -50,6 +50,9 @@
     kwargname = varnames[argcount] if code.co_flags & CO_VARKEYWORDS else None
     return Signature(argnames, varargname, kwargname)
 
+class CodeHookCache(object):
+    def __init__(self, space):
+        self._code_hook = None
 
 class PyCode(eval.Code):
     "CPython-style code objects."
@@ -86,6 +89,15 @@
         self._signature = cpython_code_signature(self)
         self._initialize()
         self._init_ready()
+        self.new_code_hook()
+
+    def new_code_hook(self):
+        code_hook = self.space.fromcache(CodeHookCache)._code_hook
+        if code_hook is not None:
+            try:
+                self.space.call_function(code_hook, self)
+            except OperationError, e:
+                e.write_unraisable(self.space, "new_code_hook()")
 
     def _initialize(self):
         if self.co_cellvars:
diff --git a/pypy/interpreter/test/test_zzpickle_and_slow.py b/pypy/interpreter/test/test_zzpickle_and_slow.py
--- a/pypy/interpreter/test/test_zzpickle_and_slow.py
+++ b/pypy/interpreter/test/test_zzpickle_and_slow.py
@@ -390,15 +390,20 @@
 
     def test_pickle_enum(self):
         import pickle
-        e      = enumerate(range(10))
+        e = enumerate(range(100, 106))
         e.next()
         e.next()
         pckl   = pickle.dumps(e)
         result = pickle.loads(pckl)
-        e.next()
-        result.next()
+        res = e.next()
+        assert res == (2, 102)
+        res = result.next()
+        assert res == (2, 102)
         assert type(e) is type(result)
-        assert list(e) == list(result)
+        res = list(e)
+        assert res == [(3, 103), (4, 104), (5, 105)]
+        res = list(result)
+        assert res == [(3, 103), (4, 104), (5, 105)]
 
     def test_pickle_xrangeiter(self):
         import pickle
diff --git a/pypy/module/__builtin__/functional.py b/pypy/module/__builtin__/functional.py
--- a/pypy/module/__builtin__/functional.py
+++ b/pypy/module/__builtin__/functional.py
@@ -8,7 +8,7 @@
 from pypy.interpreter.error import OperationError
 from pypy.interpreter.gateway import interp2app, unwrap_spec, WrappedDefault
 from pypy.interpreter.typedef import TypeDef
-from rpython.rlib import jit
+from rpython.rlib import jit, rarithmetic
 from rpython.rlib.objectmodel import specialize
 from rpython.rlib.rarithmetic import r_uint, intmask
 from rpython.rlib.rbigint import rbigint
@@ -229,27 +229,70 @@
     return min_max(space, __args__, "min")
 
 
+
 class W_Enumerate(W_Root):
-    def __init__(self, w_iter, w_start):
-        self.w_iter = w_iter
+    def __init__(self, w_iter_or_list, start, w_start):
+        # 'w_index' should never be a wrapped int here; if it would be,
+        # then it is actually None and the unwrapped int is in 'index'.
+        self.w_iter_or_list = w_iter_or_list
+        self.index = start
         self.w_index = w_start
 
     def descr___new__(space, w_subtype, w_iterable, w_start=None):
-        self = space.allocate_instance(W_Enumerate, w_subtype)
+        from pypy.objspace.std.listobject import W_ListObject
+
         if w_start is None:
-            w_start = space.wrap(0)
+            start = 0
         else:
             w_start = space.index(w_start)
-        self.__init__(space.iter(w_iterable), w_start)
+            if space.is_w(space.type(w_start), space.w_int):
+                start = space.int_w(w_start)
+                w_start = None
+            else:
+                start = -1
+
+        if start == 0 and type(w_iterable) is W_ListObject:
+            w_iter = w_iterable
+        else:
+            w_iter = space.iter(w_iterable)
+
+        self = space.allocate_instance(W_Enumerate, w_subtype)
+        self.__init__(w_iter, start, w_start)
         return space.wrap(self)
 
     def descr___iter__(self, space):
         return space.wrap(self)
 
     def descr_next(self, space):
-        w_item = space.next(self.w_iter)
+        from pypy.objspace.std.listobject import W_ListObject
         w_index = self.w_index
-        self.w_index = space.add(w_index, space.wrap(1))
+        w_iter_or_list = self.w_iter_or_list
+        w_item = None
+        if w_index is None:
+            index = self.index
+            if type(w_iter_or_list) is W_ListObject:
+                try:
+                    w_item = w_iter_or_list.getitem(index)
+                except IndexError:
+                    self.w_iter_or_list = None
+                    raise OperationError(space.w_StopIteration, space.w_None)
+                self.index = index + 1
+            elif w_iter_or_list is None:
+                raise OperationError(space.w_StopIteration, space.w_None)
+            else:
+                try:
+                    newval = rarithmetic.ovfcheck(index + 1)
+                except OverflowError:
+                    w_index = space.wrap(index)
+                    self.w_index = space.add(w_index, space.wrap(1))
+                    self.index = -1
+                else:
+                    self.index = newval
+            w_index = space.wrap(index)
+        else:
+            self.w_index = space.add(w_index, space.wrap(1))
+        if w_item is None:
+            w_item = space.next(self.w_iter_or_list)
         return space.newtuple([w_index, w_item])
 
     def descr___reduce__(self, space):
@@ -257,12 +300,20 @@
         w_mod    = space.getbuiltinmodule('_pickle_support')
         mod      = space.interp_w(MixedModule, w_mod)
         w_new_inst = mod.get('enumerate_new')
-        w_info = space.newtuple([self.w_iter, self.w_index])
+        w_index = self.w_index
+        if w_index is None:
+            w_index = space.wrap(self.index)
+        w_info = space.newtuple([self.w_iter_or_list, w_index])
         return space.newtuple([w_new_inst, w_info])
 
 # exported through _pickle_support
-def _make_enumerate(space, w_iter, w_index):
-    return space.wrap(W_Enumerate(w_iter, w_index))
+def _make_enumerate(space, w_iter_or_list, w_index):
+    if space.is_w(space.type(w_index), space.w_int):
+        index = space.int_w(w_index)
+        w_index = None
+    else:
+        index = -1
+    return space.wrap(W_Enumerate(w_iter_or_list, index, w_index))
 
 W_Enumerate.typedef = TypeDef("enumerate",
     __new__=interp2app(W_Enumerate.descr___new__.im_func),
diff --git a/pypy/module/__builtin__/test/test_builtin.py b/pypy/module/__builtin__/test/test_builtin.py
--- a/pypy/module/__builtin__/test/test_builtin.py
+++ b/pypy/module/__builtin__/test/test_builtin.py
@@ -264,6 +264,7 @@
         raises(StopIteration,x.next)
 
     def test_enumerate(self):
+        import sys
         seq = range(2,4)
         enum = enumerate(seq)
         assert enum.next() == (0, 2)
@@ -274,6 +275,15 @@
         enum = enumerate(range(5), 2)
         assert list(enum) == zip(range(2, 7), range(5))
 
+        enum = enumerate(range(2), 2**100)
+        assert list(enum) == [(2**100, 0), (2**100+1, 1)]
+
+        enum = enumerate(range(2), sys.maxint)
+        assert list(enum) == [(sys.maxint, 0), (sys.maxint+1, 1)]
+
+        raises(TypeError, enumerate, range(2), 5.5)
+
+
     def test_next(self):
         x = iter(['a', 'b', 'c'])
         assert next(x) == 'a'
diff --git a/pypy/module/__pypy__/__init__.py b/pypy/module/__pypy__/__init__.py
--- a/pypy/module/__pypy__/__init__.py
+++ b/pypy/module/__pypy__/__init__.py
@@ -86,6 +86,7 @@
         'specialized_zip_2_lists'   : 'interp_magic.specialized_zip_2_lists',
         'set_debug'                 : 'interp_magic.set_debug',
         'locals_to_fast'            : 'interp_magic.locals_to_fast',
+        'set_code_callback'         : 'interp_magic.set_code_callback',
         'save_module_content_for_future_reload':
                           'interp_magic.save_module_content_for_future_reload',
     }
diff --git a/pypy/module/__pypy__/interp_magic.py b/pypy/module/__pypy__/interp_magic.py
--- a/pypy/module/__pypy__/interp_magic.py
+++ b/pypy/module/__pypy__/interp_magic.py
@@ -1,5 +1,6 @@
 from pypy.interpreter.error import OperationError, wrap_oserror
 from pypy.interpreter.gateway import unwrap_spec
+from pypy.interpreter.pycode import CodeHookCache
 from pypy.interpreter.pyframe import PyFrame
 from pypy.interpreter.mixedmodule import MixedModule
 from rpython.rlib.objectmodel import we_are_translated
@@ -151,3 +152,10 @@
 def specialized_zip_2_lists(space, w_list1, w_list2):
     from pypy.objspace.std.specialisedtupleobject import specialized_zip_2_lists
     return specialized_zip_2_lists(space, w_list1, w_list2)
+
+def set_code_callback(space, w_callable):
+    cache = space.fromcache(CodeHookCache)
+    if space.is_none(w_callable):
+        cache._code_hook = None
+    else:
+        cache._code_hook = w_callable
\ No newline at end of file
diff --git a/pypy/module/__pypy__/test/test_magic.py b/pypy/module/__pypy__/test/test_magic.py
--- a/pypy/module/__pypy__/test/test_magic.py
+++ b/pypy/module/__pypy__/test/test_magic.py
@@ -13,3 +13,21 @@
         #
         sys.dont_write_bytecode = d
         __pypy__.save_module_content_for_future_reload(sys)
+
+    def test_new_code_hook(self):
+        l = []
+
+        def callable(code):
+            l.append(code)
+
+        import __pypy__
+        __pypy__.set_code_callback(callable)
+        d = {}
+        try:
+            exec """
+def f():
+    pass
+""" in d
+        finally:
+            __pypy__.set_code_callback(None)
+        assert d['f'].__code__ in l
\ No newline at end of file
diff --git a/pypy/module/_cffi_backend/__init__.py b/pypy/module/_cffi_backend/__init__.py
--- a/pypy/module/_cffi_backend/__init__.py
+++ b/pypy/module/_cffi_backend/__init__.py
@@ -2,7 +2,7 @@
 from pypy.interpreter.mixedmodule import MixedModule
 from rpython.rlib import rdynload, clibffi
 
-VERSION = "1.3.0"
+VERSION = "1.3.1"
 
 FFI_DEFAULT_ABI = clibffi.FFI_DEFAULT_ABI
 try:
@@ -43,6 +43,7 @@
         'newp_handle': 'handle.newp_handle',
         'from_handle': 'handle.from_handle',
         '_get_types': 'func._get_types',
+        '_get_common_types': 'func._get_common_types',
         'from_buffer': 'func.from_buffer',
 
         'string': 'func.string',
diff --git a/pypy/module/_cffi_backend/cffi_opcode.py b/pypy/module/_cffi_backend/cffi_opcode.py
--- a/pypy/module/_cffi_backend/cffi_opcode.py
+++ b/pypy/module/_cffi_backend/cffi_opcode.py
@@ -110,6 +110,9 @@
 _UNKNOWN_FLOAT_PRIM    = -2
 _UNKNOWN_LONG_DOUBLE   = -3
 
+_IO_FILE_STRUCT        = -1
+
+
 PRIMITIVE_TO_INDEX = {
     'char':               PRIM_CHAR,
     'short':              PRIM_SHORT,
diff --git a/pypy/module/_cffi_backend/ffi_obj.py b/pypy/module/_cffi_backend/ffi_obj.py
--- a/pypy/module/_cffi_backend/ffi_obj.py
+++ b/pypy/module/_cffi_backend/ffi_obj.py
@@ -448,7 +448,7 @@
 
 'alloc' is called with the size as argument.  If it returns NULL, a
 MemoryError is raised.  'free' is called with the result of 'alloc'
-as argument.  Both can be either Python function or directly C
+as argument.  Both can be either Python functions or directly C
 functions.  If 'free' is None, then no free function is called.
 If both 'alloc' and 'free' are None, the default is used.
 
diff --git a/pypy/module/_cffi_backend/func.py b/pypy/module/_cffi_backend/func.py
--- a/pypy/module/_cffi_backend/func.py
+++ b/pypy/module/_cffi_backend/func.py
@@ -84,6 +84,20 @@
 
 # ____________________________________________________________
 
+def _get_common_types(space, w_dict):
+    from pypy.module._cffi_backend.parse_c_type import ll_enum_common_types
+    index = 0
+    while True:
+        p = ll_enum_common_types(rffi.cast(rffi.INT, index))
+        if not p:
+            break
+        key = rffi.charp2str(p)
+        value = rffi.charp2str(rffi.ptradd(p, len(key) + 1))
+        space.setitem_str(w_dict, key, space.wrap(value))
+        index += 1
+
+# ____________________________________________________________
+
 def _fetch_as_read_buffer(space, w_x):
     # xxx do we really need to implement the same mess as in CPython 2.7
     # w.r.t. buffers and memoryviews??
diff --git a/pypy/module/_cffi_backend/parse_c_type.py b/pypy/module/_cffi_backend/parse_c_type.py
--- a/pypy/module/_cffi_backend/parse_c_type.py
+++ b/pypy/module/_cffi_backend/parse_c_type.py
@@ -87,6 +87,8 @@
 ll_set_cdl_realize_global_int = llexternal('pypy_set_cdl_realize_global_int',
                                            [lltype.Ptr(GLOBAL_S)],
                                            lltype.Void)
+ll_enum_common_types = llexternal('pypy_enum_common_types',
+                                  [rffi.INT], rffi.CCHARP)
 
 def parse_c_type(info, input):
     p_input = rffi.str2charp(input)
diff --git a/pypy/module/_cffi_backend/realize_c_type.py b/pypy/module/_cffi_backend/realize_c_type.py
--- a/pypy/module/_cffi_backend/realize_c_type.py
+++ b/pypy/module/_cffi_backend/realize_c_type.py
@@ -74,7 +74,15 @@
     assert len(NAMES) == cffi_opcode._NUM_PRIM
 
     def __init__(self, space):
+        self.space = space
         self.all_primitives = [None] * cffi_opcode._NUM_PRIM
+        self.file_struct = None
+
+    def get_file_struct(self):
+        if self.file_struct is None:
+            self.file_struct = ctypestruct.W_CTypeStruct(self.space, "FILE")
+        return self.file_struct
+
 
 def get_primitive_type(ffi, num):
     space = ffi.space
@@ -266,6 +274,10 @@
 
 
 def _realize_c_struct_or_union(ffi, sindex):
+    if sindex == cffi_opcode._IO_FILE_STRUCT:
+        # returns a single global cached opaque type
+        return ffi.space.fromcache(RealizeCache).get_file_struct()
+
     s = ffi.ctxobj.ctx.c_struct_unions[sindex]
     type_index = rffi.getintfield(s, 'c_type_index')
     if ffi.cached_types[type_index] is not None:
@@ -281,7 +293,10 @@
             x = ctypestruct.W_CTypeUnion(space, name)
         else:
             name = _realize_name("struct ", s.c_name)
-            x = ctypestruct.W_CTypeStruct(space, name)
+            if name == "struct _IO_FILE":
+                x = space.fromcache(RealizeCache).get_file_struct()
+            else:
+                x = ctypestruct.W_CTypeStruct(space, name)
         if (c_flags & cffi_opcode.F_OPAQUE) == 0:
             assert c_first_field_index >= 0
             w_ctype = x
diff --git a/pypy/module/_cffi_backend/src/commontypes.c b/pypy/module/_cffi_backend/src/commontypes.c
new file mode 100644
--- /dev/null
+++ b/pypy/module/_cffi_backend/src/commontypes.c
@@ -0,0 +1,207 @@
+/* This file must be kept in alphabetical order.  See test_commontypes.py */
+
+#define EQ(key, value)    key "\0" value   /* string concatenation */
+#ifdef _WIN64
+#  define W32_64(X,Y)  Y
+# else
+#  define W32_64(X,Y)  X
+# endif
+
+
+static const char *common_simple_types[] = {
+
+#ifdef MS_WIN32   /* Windows types */
+    EQ("ATOM", "WORD"),
+    EQ("BOOL", "int"),
+    EQ("BOOLEAN", "BYTE"),
+    EQ("BYTE", "unsigned char"),
+    EQ("CCHAR", "char"),
+    EQ("CHAR", "char"),
+    EQ("COLORREF", "DWORD"),
+    EQ("DWORD", "unsigned long"),
+    EQ("DWORD32", "unsigned int"),
+    EQ("DWORD64", "unsigned long long"),
+    EQ("DWORDLONG", "ULONGLONG"),
+    EQ("DWORD_PTR", "ULONG_PTR"),
+#endif
+
+    EQ("FILE", "struct _IO_FILE"),
+
+#ifdef MS_WIN32   /* more Windows types */
+    EQ("FLOAT", "float"),
+    EQ("HACCEL", "HANDLE"),
+    EQ("HALF_PTR", W32_64("short","int")),
+    EQ("HANDLE", "PVOID"),
+    EQ("HBITMAP", "HANDLE"),
+    EQ("HBRUSH", "HANDLE"),
+    EQ("HCOLORSPACE", "HANDLE"),
+    EQ("HCONV", "HANDLE"),
+    EQ("HCONVLIST", "HANDLE"),
+    EQ("HCURSOR", "HICON"),
+    EQ("HDC", "HANDLE"),
+    EQ("HDDEDATA", "HANDLE"),
+    EQ("HDESK", "HANDLE"),
+    EQ("HDROP", "HANDLE"),
+    EQ("HDWP", "HANDLE"),
+    EQ("HENHMETAFILE", "HANDLE"),
+    EQ("HFILE", "int"),
+    EQ("HFONT", "HANDLE"),
+    EQ("HGDIOBJ", "HANDLE"),
+    EQ("HGLOBAL", "HANDLE"),
+    EQ("HHOOK", "HANDLE"),
+    EQ("HICON", "HANDLE"),
+    EQ("HINSTANCE", "HANDLE"),
+    EQ("HKEY", "HANDLE"),
+    EQ("HKL", "HANDLE"),
+    EQ("HLOCAL", "HANDLE"),
+    EQ("HMENU", "HANDLE"),
+    EQ("HMETAFILE", "HANDLE"),
+    EQ("HMODULE", "HINSTANCE"),
+    EQ("HMONITOR", "HANDLE"),
+    EQ("HPALETTE", "HANDLE"),
+    EQ("HPEN", "HANDLE"),
+    EQ("HRESULT", "LONG"),
+    EQ("HRGN", "HANDLE"),
+    EQ("HRSRC", "HANDLE"),
+    EQ("HSZ", "HANDLE"),
+    EQ("HWND", "HANDLE"),
+    EQ("INT", "int"),
+    EQ("INT16", "short"),
+    EQ("INT32", "int"),
+    EQ("INT64", "long long"),
+    EQ("INT8", "signed char"),
+    EQ("INT_PTR", W32_64("int","long long")),
+    EQ("LANGID", "WORD"),
+    EQ("LCID", "DWORD"),
+    EQ("LCTYPE", "DWORD"),
+    EQ("LGRPID", "DWORD"),
+    EQ("LONG", "long"),
+    EQ("LONG32", "int"),
+    EQ("LONG64", "long long"),
+    EQ("LONGLONG", "long long"),
+    EQ("LONG_PTR", W32_64("long","long long")),
+    EQ("LPARAM", "LONG_PTR"),
+    EQ("LPBOOL", "BOOL *"),
+    EQ("LPBYTE", "BYTE *"),
+    EQ("LPCOLORREF", "DWORD *"),
+    EQ("LPCSTR", "const char *"),
+    EQ("LPCVOID", "const void *"),
+    EQ("LPCWSTR", "const WCHAR *"),
+    EQ("LPDWORD", "DWORD *"),
+    EQ("LPHANDLE", "HANDLE *"),
+    EQ("LPINT", "int *"),
+    EQ("LPLONG", "long *"),
+    EQ("LPSTR", "CHAR *"),
+    EQ("LPVOID", "void *"),
+    EQ("LPWORD", "WORD *"),
+    EQ("LPWSTR", "WCHAR *"),
+    EQ("LRESULT", "LONG_PTR"),
+    EQ("PBOOL", "BOOL *"),
+    EQ("PBOOLEAN", "BOOLEAN *"),
+    EQ("PBYTE", "BYTE *"),
+    EQ("PCHAR", "CHAR *"),
+    EQ("PCSTR", "const CHAR *"),
+    EQ("PCWSTR", "const WCHAR *"),
+    EQ("PDWORD", "DWORD *"),
+    EQ("PDWORD32", "DWORD32 *"),
+    EQ("PDWORD64", "DWORD64 *"),
+    EQ("PDWORDLONG", "DWORDLONG *"),
+    EQ("PDWORD_PTR", "DWORD_PTR *"),
+    EQ("PFLOAT", "FLOAT *"),
+    EQ("PHALF_PTR", "HALF_PTR *"),
+    EQ("PHANDLE", "HANDLE *"),
+    EQ("PHKEY", "HKEY *"),
+    EQ("PINT", "int *"),
+    EQ("PINT16", "INT16 *"),
+    EQ("PINT32", "INT32 *"),
+    EQ("PINT64", "INT64 *"),
+    EQ("PINT8", "INT8 *"),
+    EQ("PINT_PTR", "INT_PTR *"),
+    EQ("PLCID", "PDWORD"),
+    EQ("PLONG", "LONG *"),
+    EQ("PLONG32", "LONG32 *"),
+    EQ("PLONG64", "LONG64 *"),
+    EQ("PLONGLONG", "LONGLONG *"),
+    EQ("PLONG_PTR", "LONG_PTR *"),
+    EQ("PSHORT", "SHORT *"),
+    EQ("PSIZE_T", "SIZE_T *"),
+    EQ("PSSIZE_T", "SSIZE_T *"),
+    EQ("PSTR", "CHAR *"),
+    EQ("PUCHAR", "UCHAR *"),
+    EQ("PUHALF_PTR", "UHALF_PTR *"),
+    EQ("PUINT", "UINT *"),
+    EQ("PUINT16", "UINT16 *"),
+    EQ("PUINT32", "UINT32 *"),
+    EQ("PUINT64", "UINT64 *"),
+    EQ("PUINT8", "UINT8 *"),
+    EQ("PUINT_PTR", "UINT_PTR *"),
+    EQ("PULONG", "ULONG *"),
+    EQ("PULONG32", "ULONG32 *"),
+    EQ("PULONG64", "ULONG64 *"),
+    EQ("PULONGLONG", "ULONGLONG *"),
+    EQ("PULONG_PTR", "ULONG_PTR *"),
+    EQ("PUSHORT", "USHORT *"),
+    EQ("PVOID", "void *"),
+    EQ("PWCHAR", "WCHAR *"),
+    EQ("PWORD", "WORD *"),
+    EQ("PWSTR", "WCHAR *"),
+    EQ("QWORD", "unsigned long long"),
+    EQ("SC_HANDLE", "HANDLE"),
+    EQ("SC_LOCK", "LPVOID"),
+    EQ("SERVICE_STATUS_HANDLE", "HANDLE"),
+    EQ("SHORT", "short"),
+    EQ("SIZE_T", "ULONG_PTR"),
+    EQ("SSIZE_T", "LONG_PTR"),
+    EQ("UCHAR", "unsigned char"),
+    EQ("UHALF_PTR", W32_64("unsigned short","unsigned int")),
+    EQ("UINT", "unsigned int"),
+    EQ("UINT16", "unsigned short"),
+    EQ("UINT32", "unsigned int"),
+    EQ("UINT64", "unsigned long long"),
+    EQ("UINT8", "unsigned char"),
+    EQ("UINT_PTR", W32_64("unsigned int","unsigned long long")),
+    EQ("ULONG", "unsigned long"),
+    EQ("ULONG32", "unsigned int"),
+    EQ("ULONG64", "unsigned long long"),
+    EQ("ULONGLONG", "unsigned long long"),
+    EQ("ULONG_PTR", W32_64("unsigned long","unsigned long long")),
+    EQ("USHORT", "unsigned short"),
+    EQ("USN", "LONGLONG"),
+    EQ("VOID", "void"),
+    EQ("WCHAR", "wchar_t"),
+    EQ("WINSTA", "HANDLE"),
+    EQ("WORD", "unsigned short"),
+    EQ("WPARAM", "UINT_PTR"),
+#endif
+
+    EQ("bool", "_Bool"),
+};
+
+
+#undef EQ
+#undef W32_64
+
+#define num_common_simple_types    \
+    (sizeof(common_simple_types) / sizeof(common_simple_types[0]))
+
+
+static const char *get_common_type(const char *search, size_t search_len)
+{
+    const char *entry;
+    int index = search_sorted(common_simple_types, sizeof(const char *),
+                              num_common_simple_types, search, search_len);
+    if (index < 0)
+        return NULL;
+
+    entry = common_simple_types[index];
+    return entry + strlen(entry) + 1;
+}
+
+RPY_EXTERN
+char *pypy_enum_common_types(int index)
+{
+    if (index < num_common_simple_types)
+        return (char *)(common_simple_types[index]);
+    else
+        return NULL;
+}
diff --git a/pypy/module/_cffi_backend/src/parse_c_type.c b/pypy/module/_cffi_backend/src/parse_c_type.c
--- a/pypy/module/_cffi_backend/src/parse_c_type.c
+++ b/pypy/module/_cffi_backend/src/parse_c_type.c
@@ -4,6 +4,7 @@
 #include <errno.h>
 
 #if defined(_MSC_VER)
+# define MS_WIN32
 typedef size_t uintptr_t;
 #else
 # include <stdint.h>
@@ -231,6 +232,8 @@
 #define MAX_SSIZE_T  (((size_t)-1) >> 1)
 
 static int parse_complete(token_t *tok);
+static const char *get_common_type(const char *search, size_t search_len);
+static int parse_common_type_replacement(token_t *tok, const char *replacement);
 
 static int parse_sequel(token_t *tok, int outer)
 {
@@ -387,11 +390,18 @@
 
             case TOK_INTEGER:
                 errno = 0;
-#ifndef _MSC_VER
-                if (sizeof(length) > sizeof(unsigned long))
+                if (sizeof(length) > sizeof(unsigned long)) {
+#ifdef MS_WIN32
+# ifdef _WIN64
+                    length = _strtoui64(tok->p, &endptr, 0);
+# else
+                    abort();  /* unreachable */
+# endif
+#else
                     length = strtoull(tok->p, &endptr, 0);
+#endif
+                }
                 else
-#endif
                     length = strtoul(tok->p, &endptr, 0);
                 if (endptr != tok->p + tok->size)
                     return parse_error(tok, "invalid number");
@@ -446,26 +456,34 @@
     return _CFFI_GETARG(result);
 }
 
+static int search_sorted(const char *const *base,
+                         size_t item_size, int array_len,
+                         const char *search, size_t search_len)
+{
+    int left = 0, right = array_len;
+    const char *baseptr = (const char *)base;
 
-#define MAKE_SEARCH_FUNC(FIELD)                                 \
-  RPY_EXTERN int                                                \
-  pypy_search_in_##FIELD(const struct _cffi_type_context_s *ctx,\
-                        const char *search, size_t search_len)  \
-  {                                                             \
-      int left = 0, right = ctx->num_##FIELD;                   \
-                                                                \
-      while (left < right) {                                    \
-          int middle = (left + right) / 2;                      \
-          const char *src = ctx->FIELD[middle].name;            \
-          int diff = strncmp(src, search, search_len);          \
-          if (diff == 0 && src[search_len] == '\0')             \
-              return middle;                                    \
-          else if (diff >= 0)                                   \
-              right = middle;                                   \
-          else                                                  \
-              left = middle + 1;                                \
-      }                                                         \
-      return -1;                                                \
+    while (left < right) {
+        int middle = (left + right) / 2;
+        const char *src = *(const char *const *)(baseptr + middle * item_size);
+        int diff = strncmp(src, search, search_len);
+        if (diff == 0 && src[search_len] == '\0')
+            return middle;
+        else if (diff >= 0)
+            right = middle;
+        else
+            left = middle + 1;
+    }
+    return -1;
+}
+
+#define MAKE_SEARCH_FUNC(FIELD)                                         \
+  RPY_EXTERN int                                                        \
+  pypy_search_in_##FIELD(const struct _cffi_type_context_s *ctx,        \
+                        const char *search, size_t search_len)          \
+  {                                                                     \
+      return search_sorted(&ctx->FIELD->name, sizeof(*ctx->FIELD),      \
+                           ctx->num_##FIELD, search, search_len);       \
   }
 
 MAKE_SEARCH_FUNC(globals)
@@ -719,6 +737,7 @@
             break;
         case TOK_IDENTIFIER:
         {
+            const char *replacement;
             int n = search_in_typenames(tok->info->ctx, tok->p, tok->size);
             if (n >= 0) {
                 t1 = _CFFI_OP(_CFFI_OP_TYPENAME, n);
@@ -729,6 +748,14 @@
                 t1 = _CFFI_OP(_CFFI_OP_PRIMITIVE, n);
                 break;
             }
+            replacement = get_common_type(tok->p, tok->size);
+            if (replacement != NULL) {
+                n = parse_common_type_replacement(tok, replacement);
+                if (n < 0)
+                    return parse_error(tok, "internal error, please report!");
+                t1 = _CFFI_OP(_CFFI_OP_NOOP, n);
+                break;
+            }
             return parse_error(tok, "undefined type name");
         }
         case TOK_STRUCT:
@@ -740,10 +767,15 @@
                 return parse_error(tok, "struct or union name expected");
 
             n = search_in_struct_unions(tok->info->ctx, tok->p, tok->size);
-            if (n < 0)
-                return parse_error(tok, "undefined struct/union name");
-            if (((tok->info->ctx->struct_unions[n].flags & _CFFI_F_UNION) != 0)
-                ^ (kind == TOK_UNION))
+            if (n < 0) {
+                if (kind == TOK_STRUCT && tok->size == 8 &&
+                        !memcmp(tok->p, "_IO_FILE", 8))
+                    n = _CFFI__IO_FILE_STRUCT;
+                else
+                    return parse_error(tok, "undefined struct/union name");
+            }
+            else if (((tok->info->ctx->struct_unions[n].flags & _CFFI_F_UNION)
+                      != 0) ^ (kind == TOK_UNION))
                 return parse_error(tok, "wrong kind of tag: struct vs union");
 
             t1 = _CFFI_OP(_CFFI_OP_STRUCT_UNION, n);
@@ -773,8 +805,9 @@
 }
 
 
-RPY_EXTERN
-int pypy_parse_c_type(struct _cffi_parse_info_s *info, const char *input)
+static
+int parse_c_type_from(struct _cffi_parse_info_s *info, size_t *output_index,
+                      const char *input)
 {
     int result;
     token_t token;
@@ -785,16 +818,33 @@
     token.p = input;
     token.size = 0;
     token.output = info->output;
-    token.output_index = 0;
+    token.output_index = *output_index;
 
     next_token(&token);
     result = parse_complete(&token);
 
+    *output_index = token.output_index;
     if (token.kind != TOK_END)
         return parse_error(&token, "unexpected symbol");
     return result;
 }
 
+RPY_EXTERN
+int pypy_parse_c_type(struct _cffi_parse_info_s *info, const char *input)
+{
+    size_t output_index = 0;
+    return parse_c_type_from(info, &output_index, input);
+}
+
+static
+int parse_common_type_replacement(token_t *tok, const char *replacement)
+{
+    return parse_c_type_from(tok->info, &tok->output_index, replacement);
+}
+
+
+#include "commontypes.c"      /* laziness hack: include this file here */
+
 
 /************************************************************/
 /* extra from cdlopen.c                                     */
diff --git a/pypy/module/_cffi_backend/src/parse_c_type.h b/pypy/module/_cffi_backend/src/parse_c_type.h
--- a/pypy/module/_cffi_backend/src/parse_c_type.h
+++ b/pypy/module/_cffi_backend/src/parse_c_type.h
@@ -5,7 +5,7 @@
 
 #define _CFFI_OP(opcode, arg)   (_cffi_opcode_t)(opcode | (((uintptr_t)(arg)) << 8))
 #define _CFFI_GETOP(cffi_opcode)    ((unsigned char)(uintptr_t)cffi_opcode)
-#define _CFFI_GETARG(cffi_opcode)   (((uintptr_t)cffi_opcode) >> 8)
+#define _CFFI_GETARG(cffi_opcode)   (((intptr_t)cffi_opcode) >> 8)
 
 #define _CFFI_OP_PRIMITIVE       1
 #define _CFFI_OP_POINTER         3
@@ -25,6 +25,8 @@
 #define _CFFI_OP_CONSTANT_INT   31
 #define _CFFI_OP_GLOBAL_VAR     33
 #define _CFFI_OP_DLOPEN_FUNC    35
+#define _CFFI_OP_DLOPEN_CONST   37
+#define _CFFI_OP_GLOBAL_VAR_F   39
 
 #define _CFFI_PRIM_VOID          0
 #define _CFFI_PRIM_BOOL          1
@@ -77,6 +79,11 @@
 #define _CFFI_PRIM_UINTMAX      47
 
 #define _CFFI__NUM_PRIM         48
+#define _CFFI__UNKNOWN_PRIM           (-1)
+#define _CFFI__UNKNOWN_FLOAT_PRIM     (-2)
+#define _CFFI__UNKNOWN_LONG_DOUBLE    (-3)
+
+#define _CFFI__IO_FILE_STRUCT         (-1)
 
 
 struct _cffi_global_s {
@@ -164,4 +171,6 @@
                              const char *search, size_t search_len);
 RPY_EXTERN
 void pypy_set_cdl_realize_global_int(struct _cffi_global_s *target);
+RPY_EXTERN
+char *pypy_enum_common_types(int index);
 #endif
diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py b/pypy/module/_cffi_backend/test/_backend_test_c.py
--- a/pypy/module/_cffi_backend/test/_backend_test_c.py
+++ b/pypy/module/_cffi_backend/test/_backend_test_c.py
@@ -1,7 +1,7 @@
 # ____________________________________________________________
 
 import sys
-assert __version__ == "1.3.0", ("This test_c.py file is for testing a version"
+assert __version__ == "1.3.1", ("This test_c.py file is for testing a version"
                                 " of cffi that differs from the one that we"
                                 " get from 'import _cffi_backend'")
 if sys.version_info < (3,):
@@ -3509,3 +3509,8 @@
         assert repr(BFunc) == "<ctype 'int(__stdcall *)(int, int)'>"
     else:
         assert repr(BFunc) == "<ctype 'int(*)(int, int)'>"
+
+def test_get_common_types():
+    d = {}
+    _get_common_types(d)
+    assert d['bool'] == '_Bool'
diff --git a/pypy/module/_cffi_backend/test/test_ffi_obj.py b/pypy/module/_cffi_backend/test/test_ffi_obj.py
--- a/pypy/module/_cffi_backend/test/test_ffi_obj.py
+++ b/pypy/module/_cffi_backend/test/test_ffi_obj.py
@@ -424,3 +424,26 @@
             return ffi.NULL
         alloc5 = ffi.new_allocator(myalloc5)
         raises(MemoryError, alloc5, "int[5]")
+
+    def test_bool_issue228(self):
+        import _cffi_backend as _cffi1_backend
+        ffi = _cffi1_backend.FFI()
+        fntype = ffi.typeof("int(*callback)(bool is_valid)")
+        assert repr(fntype.args[0]) == "<ctype '_Bool'>"
+
+    def test_FILE_issue228(self):
+        import _cffi_backend as _cffi1_backend
+        fntype1 = _cffi1_backend.FFI().typeof("FILE *")
+        fntype2 = _cffi1_backend.FFI().typeof("FILE *")
+        assert repr(fntype1) == "<ctype 'FILE *'>"
+        assert fntype1 is fntype2
+
+    def test_cast_from_int_type_to_bool(self):
+        import _cffi_backend as _cffi1_backend
+        ffi = _cffi1_backend.FFI()
+        for basetype in ['char', 'short', 'int', 'long', 'long long']:
+            for sign in ['signed', 'unsigned']:
+                type = '%s %s' % (sign, basetype)
+                assert int(ffi.cast("_Bool", ffi.cast(type, 42))) == 1
+                assert int(ffi.cast("bool", ffi.cast(type, 42))) == 1
+                assert int(ffi.cast("_Bool", ffi.cast(type, 0))) == 0
diff --git a/pypy/module/_cffi_backend/test/test_recompiler.py b/pypy/module/_cffi_backend/test/test_recompiler.py
--- a/pypy/module/_cffi_backend/test/test_recompiler.py
+++ b/pypy/module/_cffi_backend/test/test_recompiler.py
@@ -16,8 +16,8 @@
         from cffi import ffiplatform
     except ImportError:
         py.test.skip("system cffi module not found or older than 1.0.0")
-    if cffi.__version_info__ < (1, 2, 0):
-        py.test.skip("system cffi module needs to be at least 1.2.0")
+    if cffi.__version_info__ < (1, 3, 0):
+        py.test.skip("system cffi module needs to be at least 1.3.0")
     space.appexec([], """():
         import _cffi_backend     # force it to be initialized
     """)
@@ -28,6 +28,7 @@
     module_name = '_CFFI_' + module_name
     rdir = udir.ensure('recompiler', dir=1)
     rdir.join('Python.h').write(
+        '#include <stdio.h>\n'
         '#define PYPY_VERSION XX\n'
         '#define PyMODINIT_FUNC /*exported*/ void\n'
         )
@@ -1076,3 +1077,302 @@
         raises(ffi.error, getattr, lib, 'my_value')
         e = raises(ffi.error, setattr, lib, 'my_value', 50)
         assert str(e.value) == "global variable 'my_value' is at address NULL"
+
+    def test_const_fields(self):
+        ffi, lib = self.prepare(
+            """struct foo_s { const int a; void *const b; };""",
+            'test_const_fields',
+            """struct foo_s { const int a; void *const b; };""")
+        foo_s = ffi.typeof("struct foo_s")
+        assert foo_s.fields[0][0] == 'a'
+        assert foo_s.fields[0][1].type is ffi.typeof("int")
+        assert foo_s.fields[1][0] == 'b'
+        assert foo_s.fields[1][1].type is ffi.typeof("void *")
+
+    def test_restrict_fields(self):
+        ffi, lib = self.prepare(
+            """struct foo_s { void * restrict b; };""",
+            'test_restrict_fields',
+            """struct foo_s { void * __restrict b; };""")
+        foo_s = ffi.typeof("struct foo_s")
+        assert foo_s.fields[0][0] == 'b'
+        assert foo_s.fields[0][1].type is ffi.typeof("void *")
+
+    def test_volatile_fields(self):
+        ffi, lib = self.prepare(
+            """struct foo_s { void * volatile b; };""",
+            'test_volatile_fields',
+            """struct foo_s { void * volatile b; };""")
+        foo_s = ffi.typeof("struct foo_s")
+        assert foo_s.fields[0][0] == 'b'
+        assert foo_s.fields[0][1].type is ffi.typeof("void *")
+
+    def test_const_array_fields(self):
+        ffi, lib = self.prepare(
+            """struct foo_s { const int a[4]; };""",
+            'test_const_array_fields',
+            """struct foo_s { const int a[4]; };""")
+        foo_s = ffi.typeof("struct foo_s")
+        assert foo_s.fields[0][0] == 'a'
+        assert foo_s.fields[0][1].type is ffi.typeof("int[4]")
+
+    def test_const_array_fields_varlength(self):
+        ffi, lib = self.prepare(
+            """struct foo_s { const int a[]; ...; };""",
+            'test_const_array_fields_varlength',
+            """struct foo_s { const int a[4]; };""")
+        foo_s = ffi.typeof("struct foo_s")
+        assert foo_s.fields[0][0] == 'a'
+        assert foo_s.fields[0][1].type is ffi.typeof("int[]")
+
+    def test_const_array_fields_unknownlength(self):
+        ffi, lb = self.prepare(
+            """struct foo_s { const int a[...]; ...; };""",
+            'test_const_array_fields_unknownlength',
+            """struct foo_s { const int a[4]; };""")


More information about the pypy-commit mailing list