Author: Armin Rigo <ar...@tunes.org>
Branch: py3.5
Changeset: r94885:130fbb74dab5
Date: 2018-07-23 18:20 +0200
http://bitbucket.org/pypy/pypy/changeset/130fbb74dab5/

Log:    hg merge default

diff too long, truncating to 2000 out of 2216 lines

diff --git a/pypy/config/pypyoption.py b/pypy/config/pypyoption.py
--- a/pypy/config/pypyoption.py
+++ b/pypy/config/pypyoption.py
@@ -43,14 +43,10 @@
     "_jitlog",
 ])
 
-from rpython.jit.backend import detect_cpu
-try:
-    if detect_cpu.autodetect().startswith('x86'):
-        if not sys.platform.startswith('openbsd'):
-            working_modules.add('_vmprof')
-            working_modules.add('faulthandler')
-except detect_cpu.ProcessorAutodetectError:
-    pass
+import rpython.rlib.rvmprof.cintf
+if rpython.rlib.rvmprof.cintf.IS_SUPPORTED:
+    working_modules.add('_vmprof')
+    working_modules.add('faulthandler')
 
 translation_modules = default_modules.copy()
 translation_modules.update([
@@ -323,3 +319,4 @@
     parser = to_optparse(config) #, useoptions=["translation.*"])
     option, args = parser.parse_args()
     print config
+    print working_modules
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
@@ -7,9 +7,12 @@
 
 .. branch: cppyy-packaging
 
-Upgrade to backend 1.1.0, improved handling of templated methods and
+Upgrade to backend 1.2.0, improved handling of templated methods and
 functions (in particular automatic deduction of types), improved pythonization
-interface, and a range of compatibility fixes for Python3
+interface, range of compatibility fixes for Python3, free functions now take
+fast libffi path when possible, moves for strings (incl. from Python str),
+easier/faster handling of std::vector by numpy, improved and faster object
+identity preservation
 
 .. branch: socket_default_timeout_blockingness
 
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
@@ -3935,8 +3935,8 @@
 
 def test_char_pointer_conversion():
     import warnings
-    assert __version__.startswith(("1.8", "1.9", "1.10", "1.11", "1.12")), (
-        "consider turning the warning into an error")
+    assert __version__.startswith("1."), (
+        "the warning will be an error if we ever release cffi 2.x")
     BCharP = new_pointer_type(new_primitive_type("char"))
     BIntP = new_pointer_type(new_primitive_type("int"))
     BVoidP = new_pointer_type(new_void_type())
diff --git a/pypy/module/_cppyy/converter.py b/pypy/module/_cppyy/converter.py
--- a/pypy/module/_cppyy/converter.py
+++ b/pypy/module/_cppyy/converter.py
@@ -1,15 +1,12 @@
 import sys
 
 from pypy.interpreter.error import OperationError, oefmt
-
 from rpython.rtyper.lltypesystem import rffi, lltype
 from rpython.rlib.rarithmetic import r_singlefloat, r_longfloat
 from rpython.rlib import rfloat, rawrefcount
-
 from pypy.module._rawffi.interp_rawffi import letter2tp
 from pypy.module._rawffi.array import W_ArrayInstance
-
-from pypy.module._cppyy import helper, capi, ffitypes
+from pypy.module._cppyy import helper, capi, ffitypes, lowlevelviews
 
 # Converter objects are used to translate between RPython and C++. They are
 # defined by the type name for which they provide conversion. Uses are for
@@ -149,7 +146,8 @@
         # read access, so no copy needed
         address_value = self._get_raw_address(space, w_obj, offset)
         address = rffi.cast(rffi.ULONG, address_value)
-        return W_ArrayInstance(space, letter2tp(space, self.typecode), 
self.size, address)
+        return lowlevelviews.W_LowLevelView(
+            space, letter2tp(space, self.typecode), self.size, address)
 
     def to_memory(self, space, w_obj, w_value, offset):
         # copy the full array (uses byte copy for now)
@@ -190,7 +188,8 @@
         # read access, so no copy needed
         address_value = self._get_raw_address(space, w_obj, offset)
         address = rffi.cast(rffi.ULONGP, address_value)
-        return W_ArrayInstance(space, letter2tp(space, self.typecode), 
self.size, address[0])
+        return lowlevelviews.W_LowLevelView(
+            space, letter2tp(space, self.typecode), self.size, address[0])
 
     def to_memory(self, space, w_obj, w_value, offset):
         # copy only the pointer value
@@ -438,7 +437,7 @@
             from pypy.module._cppyy import interp_cppyy
             return interp_cppyy.get_nullptr(space)
         shape = letter2tp(space, 'P')
-        return W_ArrayInstance(space, shape, sys.maxint/shape.size, ptrval)
+        return lowlevelviews.W_LowLevelView(space, shape, 
sys.maxint/shape.size, ptrval)
 
     def to_memory(self, space, w_obj, w_value, offset):
         address = rffi.cast(rffi.VOIDPP, self._get_raw_address(space, w_obj, 
offset))
@@ -491,7 +490,7 @@
         from pypy.module._cppyy.interp_cppyy import W_CPPInstance
         if isinstance(w_obj, W_CPPInstance):
             from pypy.module._cppyy.interp_cppyy import 
INSTANCE_FLAGS_IS_RVALUE
-            if w_obj.flags & INSTANCE_FLAGS_IS_RVALUE:
+            if w_obj.rt_flags & INSTANCE_FLAGS_IS_RVALUE:
                 # reject moves as all are explicit
                 raise ValueError("lvalue expected")
             if capi.c_is_subtype(space, w_obj.clsdecl, self.clsdecl):
@@ -523,14 +522,14 @@
         from pypy.module._cppyy.interp_cppyy import W_CPPInstance, 
INSTANCE_FLAGS_IS_RVALUE
         obj = space.interp_w(W_CPPInstance, w_obj)
         if obj:
-            if obj.flags & INSTANCE_FLAGS_IS_RVALUE:
-                obj.flags &= ~INSTANCE_FLAGS_IS_RVALUE
+            if obj.rt_flags & INSTANCE_FLAGS_IS_RVALUE:
+                obj.rt_flags &= ~INSTANCE_FLAGS_IS_RVALUE
                 try:
                     return InstanceRefConverter._unwrap_object(self, space, 
w_obj)
                 except Exception:
                     # TODO: if the method fails on some other converter, then 
the next
                     # overload can not be an rvalue anymore
-                    obj.flags |= INSTANCE_FLAGS_IS_RVALUE
+                    obj.rt_flags |= INSTANCE_FLAGS_IS_RVALUE
                     raise
         raise oefmt(space.w_ValueError, "object is not an rvalue")
 
@@ -566,10 +565,6 @@
         from pypy.module._cppyy import interp_cppyy
         return interp_cppyy.wrap_cppinstance(space, address, self.clsdecl, 
do_cast=False)
 
-    def to_memory(self, space, w_obj, w_value, offset):
-        address = rffi.cast(rffi.VOIDPP, self._get_raw_address(space, w_obj, 
offset))
-        address[0] = rffi.cast(rffi.VOIDP, self._unwrap_object(space, w_value))
-
 class InstancePtrPtrConverter(InstancePtrConverter):
     typecode = 'o'
 
@@ -597,6 +592,25 @@
         return interp_cppyy.wrap_cppinstance(
             space, address, self.clsdecl, do_cast=False, is_ref=True)
 
+    def to_memory(self, space, w_obj, w_value, offset):
+        # the actual data member is of object* type, but we receive a pointer 
to that
+        # data member in order to modify its value, so by convention, the 
internal type
+        # used is object**
+        address = rffi.cast(rffi.VOIDPP, self._get_raw_address(space, w_obj, 
offset))
+        from pypy.module._cppyy.interp_cppyy import W_CPPInstance
+        cppinstance = space.interp_w(W_CPPInstance, w_value, can_be_None=True)
+        if cppinstance:
+            rawobject = cppinstance.get_rawobject()
+            offset = capi.c_base_offset(space, cppinstance.clsdecl, 
self.clsdecl, rawobject, 1)
+            obj_address = capi.direct_ptradd(rawobject, offset)
+            address[0] = rffi.cast(rffi.VOIDP, obj_address);
+            # register the value for potential recycling
+            from pypy.module._cppyy.interp_cppyy import memory_regulator
+            memory_regulator.register(cppinstance)
+        else:
+            raise oefmt(space.w_TypeError,
+                "cannot pass %T instance as %s", w_value, self.clsdecl.name)
+
     def finalize_call(self, space, w_obj):
         if self.ref_buffer:
             set_rawobject(space, w_obj, self.ref_buffer[0])
@@ -607,7 +621,6 @@
             self.ref_buffer = lltype.nullptr(rffi.VOIDPP.TO)
 
 class StdStringConverter(InstanceConverter):
-
     def __init__(self, space, extra):
         from pypy.module._cppyy import interp_cppyy
         cppclass = interp_cppyy.scope_byname(space, capi.std_string_name)
@@ -633,6 +646,34 @@
     def free_argument(self, space, arg):
         capi.c_destruct(space, self.clsdecl, rffi.cast(capi.C_OBJECT, 
rffi.cast(rffi.VOIDPP, arg)[0]))
 
+class StdStringMoveConverter(StdStringConverter):
+    def _unwrap_object(self, space, w_obj):
+        # moving is same as by-ref, but have to check that move is allowed
+        moveit_reason = 3
+        from pypy.module._cppyy.interp_cppyy import W_CPPInstance, 
INSTANCE_FLAGS_IS_RVALUE
+        try:
+            obj = space.interp_w(W_CPPInstance, w_obj)
+            if obj and obj.rt_flags & INSTANCE_FLAGS_IS_RVALUE:
+                obj.rt_flags &= ~INSTANCE_FLAGS_IS_RVALUE
+                moveit_reason = 1
+            else:
+                moveit_reason = 0
+        except:
+            pass
+
+        if moveit_reason:
+            try:
+                return StdStringConverter._unwrap_object(self, space, w_obj)
+            except Exception:
+                 if moveit_reason == 1:
+                    # TODO: if the method fails on some other converter, then 
the next
+                    # overload can not be an rvalue anymore
+                    obj = space.interp_w(W_CPPInstance, w_obj)
+                    obj.rt_flags |= INSTANCE_FLAGS_IS_RVALUE
+                    raise
+
+        raise oefmt(space.w_ValueError, "object is not an rvalue")
+
 class StdStringRefConverter(InstancePtrConverter):
     _immutable_fields_ = ['cppclass', 'typecode']
     typecode    = 'V'
@@ -885,6 +926,7 @@
 _converters["std::basic_string<char>"]           = StdStringConverter
 _converters["const std::basic_string<char>&"]    = StdStringConverter     # 
TODO: shouldn't copy
 _converters["std::basic_string<char>&"]          = StdStringRefConverter
+_converters["std::basic_string<char>&&"]         = StdStringMoveConverter
 
 _converters["PyObject*"]                         = PyObjectConverter
 
@@ -1002,6 +1044,7 @@
         ("std::basic_string<char>",         "string"),
         ("const std::basic_string<char>&",  "const string&"),
         ("std::basic_string<char>&",        "string&"),
+        ("std::basic_string<char>&&",       "string&&"),
 
         ("PyObject*",                       "_object*"),
     )
diff --git a/pypy/module/_cppyy/executor.py b/pypy/module/_cppyy/executor.py
--- a/pypy/module/_cppyy/executor.py
+++ b/pypy/module/_cppyy/executor.py
@@ -1,14 +1,10 @@
 import sys
 
 from pypy.interpreter.error import oefmt
-
 from rpython.rtyper.lltypesystem import rffi, lltype
 from rpython.rlib import jit_libffi
-
 from pypy.module._rawffi.interp_rawffi import letter2tp
-from pypy.module._rawffi.array import W_Array, W_ArrayInstance
-
-from pypy.module._cppyy import helper, capi, ffitypes
+from pypy.module._cppyy import helper, capi, ffitypes, lowlevelviews
 
 # Executor objects are used to dispatch C++ methods. They are defined by their
 # return type only: arguments are converted by Converter objects, and Executors
@@ -60,7 +56,7 @@
             from pypy.module._cppyy import interp_cppyy
             return interp_cppyy.get_nullptr(space)
         shape = letter2tp(space, self.typecode)
-        return W_ArrayInstance(space, shape, sys.maxint/shape.size, ptrval)
+        return lowlevelviews.W_LowLevelView(space, shape, 
sys.maxint/shape.size, ptrval)
 
 
 class VoidExecutor(Executor):
@@ -98,10 +94,10 @@
     def __init__(self, space, extra):
         Executor.__init__(self, space, extra)
         self.do_assign = False
-        self.item = rffi.cast(self.c_type, 0)
+        self.w_item = space.w_None
 
     def set_item(self, space, w_item):
-        self.item = self._unwrap_object(space, w_item)
+        self.w_item = w_item
         self.do_assign = True
 
     #def _wrap_object(self, space, obj):
@@ -109,7 +105,7 @@
 
     def _wrap_reference(self, space, rffiptr):
         if self.do_assign:
-            rffiptr[0] = self.item
+            rffiptr[0] = rffi.cast(self.c_type, self._unwrap_object(space, 
self.w_item))
         self.do_assign = False
         return self._wrap_object(space, rffiptr[0])    # all paths, for rtyper
 
diff --git a/pypy/module/_cppyy/interp_cppyy.py 
b/pypy/module/_cppyy/interp_cppyy.py
--- a/pypy/module/_cppyy/interp_cppyy.py
+++ b/pypy/module/_cppyy/interp_cppyy.py
@@ -41,6 +41,7 @@
              'void**'        : 100,
              'float'         :  30,
              'double'        :  10,
+             'bool'          :   1,
              'const string&' :   1, } # solves a specific string ctor overload
 
 from rpython.rlib.listsort import make_timsort_class
@@ -167,6 +168,7 @@
 #
 #  W_CPPOverload:                 instance methods (base class)
 #  W_CPPConstructorOverload:      constructors
+#  W_CPPAbstractCtorOverload:     to provent instantiation of abstract classes
 #  W_CPPStaticOverload:           free and static functions
 #  W_CPPTemplateOverload:         templated methods
 #  W_CPPTemplateStaticOverload:   templated free and static functions
@@ -258,7 +260,8 @@
         jit.promote(self)
         cif_descr = self.cif_descr
         # add extra space for const-ref support (see converter.py)
-        buffer = lltype.malloc(rffi.CCHARP.TO, 
cif_descr.exchange_size+len(self.arg_defs)*rffi.sizeof(rffi.DOUBLE), 
flavor='raw')
+        buffer = lltype.malloc(rffi.CCHARP.TO,
+            
cif_descr.exchange_size+len(self.arg_defs)*rffi.sizeof(rffi.DOUBLE), 
flavor='raw')
         thisoff = 0
         try:
             if cppthis:
@@ -412,8 +415,10 @@
 
     def priority(self):
         total_arg_priority = 0
-        for p in [priority.get(arg_type, 0) for arg_type, arg_dflt in 
self.arg_defs]:
-            total_arg_priority += p
+        for arg_type, arg_dflt in self.arg_defs:
+            total_arg_priority += priority.get(arg_type, 0)
+            if '&&' in arg_type:
+                total_arg_priority += 100
         return total_arg_priority
 
     @rgc.must_be_light_finalizer
@@ -433,7 +438,7 @@
 
 class CPPSetItem(CPPMethod):
     """Method dispatcher specific to Python's __setitem__ mapped onto C++'s
-    operator[](int). The former function takes an extra argument to assign to
+    operator[](T). The former function takes an extra argument to assign to
     the return type of the latter."""
 
     _attrs_ = []
@@ -502,6 +507,9 @@
     def descr_get(self, w_obj, w_cls=None):
         """functionobject.__get__(obj[, type]) -> method"""
         # TODO: check validity of w_cls if given
+        # TODO: this does not work for Python 3, which does not have
+        #  unbound methods (probably no common code possible, see also
+        #  pypy/interpreter/function.py)
         space = self.space
         asking_for_bound = (space.is_none(w_cls) or
                             not space.is_w(w_obj, space.w_None) or
@@ -581,6 +589,16 @@
             sig += '\n'+self.functions[i].prototype()
         return self.space.newtext(sig)
 
+    @unwrap_spec(signature='text')
+    def mp_overload(self, signature):
+        sig = '(%s)' % signature
+        for f in self.functions:
+            if f.signature(False) == sig:
+                if isinstance(self, W_CPPStaticOverload):
+                    return W_CPPStaticOverload(self.space, self.scope, [f])
+                return W_CPPOverload(self.space, self.scope, [f])
+        raise oefmt(self.space.w_LookupError, "signature '%s' not found", 
signature)
+
     # allow user to determine ffi use rules per overload
     def fget_useffi(self, space):
         return space.newbool(bool(self.flags & OVERLOAD_FLAGS_USE_FFI))
@@ -604,10 +622,11 @@
 
 W_CPPOverload.typedef = TypeDef(
     'CPPOverload',
-    __get__    = interp2app(W_CPPOverload.descr_get),
-    __call__   = interp2app(W_CPPOverload.call_args),
-    __useffi__ = GetSetProperty(W_CPPOverload.fget_useffi, 
W_CPPOverload.fset_useffi),
-    __doc__    = GetSetProperty(W_CPPOverload.fget_doc)
+    __get__      = interp2app(W_CPPOverload.descr_get),
+    __call__     = interp2app(W_CPPOverload.call_args),
+    __useffi__   = GetSetProperty(W_CPPOverload.fget_useffi, 
W_CPPOverload.fset_useffi),
+    __overload__ = interp2app(W_CPPOverload.mp_overload),
+    __doc__      = GetSetProperty(W_CPPOverload.fget_doc)
 )
 
 
@@ -629,21 +648,18 @@
     @unwrap_spec(args_w='args_w')
     def call_args(self, args_w):
         jit.promote(self)
-        #if isinstance(args_w[0], W_CPPInstance):
-            # free function used as bound method, leave in place
         return self.call_impl(capi.C_NULL_OBJECT, args_w)
-        # free functions are implemented as methods of 'namespace' classes, 
remove 'instance'
-        #return self.call_impl(capi.C_NULL_OBJECT, args_w[1:])
 
     def __repr__(self):
         return "W_CPPStaticOverload(%s)" % [f.prototype() for f in 
self.functions]
 
 W_CPPStaticOverload.typedef = TypeDef(
     'CPPStaticOverload',
-    __get__    = interp2app(W_CPPStaticOverload.descr_get),
-    __call__   = interp2app(W_CPPStaticOverload.call_args),
-    __useffi__ = GetSetProperty(W_CPPStaticOverload.fget_useffi, 
W_CPPStaticOverload.fset_useffi),
-    __doc__    = GetSetProperty(W_CPPStaticOverload.fget_doc)
+    __get__      = interp2app(W_CPPStaticOverload.descr_get),
+    __call__     = interp2app(W_CPPStaticOverload.call_args),
+    __useffi__   = GetSetProperty(W_CPPStaticOverload.fget_useffi, 
W_CPPStaticOverload.fset_useffi),
+    __overload__ = interp2app(W_CPPStaticOverload.mp_overload),
+    __doc__      = GetSetProperty(W_CPPStaticOverload.fget_doc)
 )
 
 
@@ -657,11 +673,6 @@
     @unwrap_spec(args_w='args_w')
     def call_args(self, args_w):
         jit.promote(self)
-        # TODO: factor out the following:
-        if capi.c_is_abstract(self.space, self.scope.handle):
-            raise oefmt(self.space.w_TypeError,
-                        "cannot instantiate abstract class '%s'",
-                        self.scope.name)
         cppinstance = self.space.interp_w(W_CPPInstance, args_w[0])
         w_result = self.call_impl(rffi.cast(capi.C_OBJECT, self.scope.handle), 
args_w[1:])
         newthis = rffi.cast(capi.C_OBJECT, self.space.uint_w(w_result))
@@ -674,9 +685,27 @@
 
 W_CPPConstructorOverload.typedef = TypeDef(
     'CPPConstructorOverload',
-    __get__    = interp2app(W_CPPConstructorOverload.descr_get),
-    __call__   = interp2app(W_CPPConstructorOverload.call_args),
-    __doc__    = GetSetProperty(W_CPPConstructorOverload.fget_doc)
+    __get__      = interp2app(W_CPPConstructorOverload.descr_get),
+    __call__     = interp2app(W_CPPConstructorOverload.call_args),
+    __overload__ = interp2app(W_CPPConstructorOverload.mp_overload),
+    __doc__      = GetSetProperty(W_CPPConstructorOverload.fget_doc)
+)
+
+class W_CPPAbstractCtorOverload(W_CPPOverload):
+    _attrs_ = []
+
+    @unwrap_spec(args_w='args_w')
+    def call_args(self, args_w):
+        raise oefmt(self.space.w_TypeError,
+            "cannot instantiate abstract class '%s'", self.scope.name)
+
+    def __repr__(self):
+        return "W_CPPAbstractCtorOverload"
+
+W_CPPAbstractCtorOverload.typedef = TypeDef(
+    'CPPAbstractCtorOverload',
+    __get__    = interp2app(W_CPPAbstractCtorOverload.descr_get),
+    __call__   = interp2app(W_CPPAbstractCtorOverload.call_args),
 )
 
 
@@ -699,7 +728,7 @@
                     if args_w:
                         # try to specialize the type match for the given object
                         cppinstance = self.space.interp_w(W_CPPInstance, 
args_w[i])
-                        if cppinstance.flags & INSTANCE_FLAGS_IS_RVALUE:
+                        if cppinstance.rt_flags & INSTANCE_FLAGS_IS_RVALUE:
                             sugar = "&&"
                         elif cppinstance.flags & INSTANCE_FLAGS_IS_REF:
                             sugar = "*"
@@ -839,11 +868,11 @@
 
 W_CPPTemplateOverload.typedef = TypeDef(
     'CPPTemplateOverload',
-    __get__     = interp2app(W_CPPTemplateOverload.descr_get),
-    __getitem__ = interp2app(W_CPPTemplateOverload.getitem),
-    __call__    = interp2app(W_CPPTemplateOverload.call_args),
-    __useffi__  = GetSetProperty(W_CPPTemplateOverload.fget_useffi, 
W_CPPTemplateOverload.fset_useffi),
-    __doc__     = GetSetProperty(W_CPPTemplateOverload.fget_doc)
+    __get__      = interp2app(W_CPPTemplateOverload.descr_get),
+    __getitem__  = interp2app(W_CPPTemplateOverload.getitem),
+    __call__     = interp2app(W_CPPTemplateOverload.call_args),
+    __useffi__   = GetSetProperty(W_CPPTemplateOverload.fget_useffi, 
W_CPPTemplateOverload.fset_useffi),
+    __doc__      = GetSetProperty(W_CPPTemplateOverload.fget_doc)
 )
 
 class W_CPPTemplateStaticOverload(W_CPPStaticOverload, TemplateOverloadMixin):
@@ -897,11 +926,11 @@
 
 W_CPPTemplateStaticOverload.typedef = TypeDef(
     'CPPTemplateStaticOverload',
-    __get__     = interp2app(W_CPPTemplateStaticOverload.descr_get),
-    __getitem__ = interp2app(W_CPPTemplateStaticOverload.getitem),
-    __call__    = interp2app(W_CPPTemplateStaticOverload.call_args),
-    __useffi__  = GetSetProperty(W_CPPTemplateStaticOverload.fget_useffi, 
W_CPPTemplateStaticOverload.fset_useffi),
-    __doc__     = GetSetProperty(W_CPPTemplateStaticOverload.fget_doc)
+    __get__      = interp2app(W_CPPTemplateStaticOverload.descr_get),
+    __getitem__  = interp2app(W_CPPTemplateStaticOverload.getitem),
+    __call__     = interp2app(W_CPPTemplateStaticOverload.call_args),
+    __useffi__   = GetSetProperty(W_CPPTemplateStaticOverload.fget_useffi, 
W_CPPTemplateStaticOverload.fset_useffi),
+    __doc__      = GetSetProperty(W_CPPTemplateStaticOverload.fget_doc)
 )
 
 
@@ -929,6 +958,7 @@
 
     def _get_offset(self, cppinstance):
         if cppinstance:
+            assert isinstance(cppinstance.clsdecl, W_CPPClassDecl)
             assert lltype.typeOf(cppinstance.clsdecl.handle) == 
lltype.typeOf(self.scope.handle)
             offset = self.offset + 
cppinstance.clsdecl.get_base_offset(cppinstance, self.scope)
         else:
@@ -1074,6 +1104,8 @@
         sig = '(%s)' % signature
         for f in overload.functions:
             if f.signature(False) == sig:
+                if isinstance(overload, W_CPPStaticOverload):
+                    return W_CPPStaticOverload(self.space, self, [f])
                 return W_CPPOverload(self.space, self, [f])
         raise oefmt(self.space.w_LookupError, "no overload matches signature")
 
@@ -1169,9 +1201,13 @@
 
 
 class W_CPPClassDecl(W_CPPScopeDecl):
-    _attrs_ = ['space', 'handle', 'name', 'overloads', 'datamembers']
+    _attrs_ = ['space', 'handle', 'name', 'overloads', 'datamembers', 
'cppobjects']
     _immutable_fields_ = ['handle', 'name', 'overloads[*]', 'datamembers[*]']
 
+    def __init__(self, space, opaque_handle, final_scoped_name):
+        W_CPPScopeDecl.__init__(self, space, opaque_handle, final_scoped_name)
+        self.cppobjects = rweakref.RWeakValueDictionary(int, W_CPPInstance)
+
     def _build_overloads(self):
         assert len(self.overloads) == 0
         methods_tmp = {}; ftype_tmp = {}
@@ -1210,7 +1246,10 @@
             ftype = ftype_tmp[pyname]
             CPPMethodSort(methods).sort()
             if ftype & FUNCTION_IS_CONSTRUCTOR:
-                overload = W_CPPConstructorOverload(self.space, self, 
methods[:])
+                if capi.c_is_abstract(self.space, self.handle):
+                    overload = W_CPPAbstractCtorOverload(self.space, self, 
methods[:])
+                else:
+                    overload = W_CPPConstructorOverload(self.space, self, 
methods[:])
             elif ftype & FUNCTION_IS_STATIC:
                 if ftype & FUNCTION_IS_TEMPLATE:
                     cppname = capi.c_method_name(self.space, 
methods[0].cppmethod)
@@ -1276,10 +1315,12 @@
         raise self.missing_attribute_error(name)
 
     def get_base_offset(self, cppinstance, calling_scope):
+        assert isinstance(cppinstance.clsdecl, W_CPPClassDecl)
         assert self == cppinstance.clsdecl
         return 0
 
     def get_cppthis(self, cppinstance, calling_scope):
+        assert isinstance(cppinstance.clsdecl, W_CPPClassDecl)
         assert self == cppinstance.clsdecl
         return cppinstance.get_rawobject()
 
@@ -1315,12 +1356,14 @@
 
 class W_CPPComplexClassDecl(W_CPPClassDecl):
     def get_base_offset(self, cppinstance, calling_scope):
+        assert isinstance(cppinstance.clsdecl, W_CPPComplexClassDecl)
         assert self == cppinstance.clsdecl
         offset = capi.c_base_offset(self.space,
-                                    self, calling_scope, 
cppinstance.get_rawobject(), 1)
+            self, calling_scope, cppinstance.get_rawobject(), 1)
         return offset
 
     def get_cppthis(self, cppinstance, calling_scope):
+        assert isinstance(cppinstance.clsdecl, W_CPPComplexClassDecl)
         assert self == cppinstance.clsdecl
         offset = self.get_base_offset(cppinstance, calling_scope)
         return capi.direct_ptradd(cppinstance.get_rawobject(), offset)
@@ -1340,9 +1383,9 @@
 
 
 class W_CPPInstance(W_Root):
-    _attrs_ = ['space', 'clsdecl', '_rawobject', 'smartdecl', 'deref', 'flags',
+    _attrs_ = ['space', 'clsdecl', '_rawobject', 'smartdecl', 'deref', 
'flags', 'rt_flags',
                'finalizer_registered']
-    _immutable_fields_ = ['clsdecl', 'smartdecl', 'deref']
+    _immutable_fields_ = ['clsdecl', 'smartdecl', 'deref', 'flags']
 
     finalizer_registered = False
 
@@ -1350,6 +1393,7 @@
                  smartdecl=None, deref=rffi.cast(capi.C_METHOD, 0)):
         self.space = space
         self.clsdecl = decl
+        assert isinstance(self.clsdecl, W_CPPClassDecl)
         assert lltype.typeOf(rawobject) == capi.C_OBJECT
         assert not isref or rawobject
         self._rawobject = rawobject
@@ -1357,15 +1401,16 @@
         self.flags = 0
         if isref or (smartdecl and deref):
             self.flags |= INSTANCE_FLAGS_IS_REF
+        self.rt_flags = 0
         if python_owns:
-            self.flags |= INSTANCE_FLAGS_PYTHON_OWNS
+            self.rt_flags |= INSTANCE_FLAGS_PYTHON_OWNS
             self._opt_register_finalizer()
         self.smartdecl = smartdecl
         self.deref     = deref
 
     def _opt_register_finalizer(self):
         if not self.finalizer_registered and not hasattr(self.space, "fake"):
-            assert self.flags & INSTANCE_FLAGS_PYTHON_OWNS
+            assert self.rt_flags & INSTANCE_FLAGS_PYTHON_OWNS
             self.register_finalizer(self.space)
             self.finalizer_registered = True
 
@@ -1377,17 +1422,18 @@
 
     # allow user to determine ownership rules on a per object level
     def fget_python_owns(self, space):
-        return space.newbool(bool(self.flags & INSTANCE_FLAGS_PYTHON_OWNS))
+        return space.newbool(bool(self.rt_flags & INSTANCE_FLAGS_PYTHON_OWNS))
 
     @unwrap_spec(value=bool)
     def fset_python_owns(self, space, value):
         if space.is_true(value):
-            self.flags |= INSTANCE_FLAGS_PYTHON_OWNS
+            self.rt_flags |= INSTANCE_FLAGS_PYTHON_OWNS
             self._opt_register_finalizer()
         else:
-            self.flags &= ~INSTANCE_FLAGS_PYTHON_OWNS
+            self.rt_flags &= ~INSTANCE_FLAGS_PYTHON_OWNS
 
     def get_cppthis(self, calling_scope):
+        assert isinstance(self.clsdecl, W_CPPClassDecl)
         return self.clsdecl.get_cppthis(self, calling_scope)
 
     def get_rawobject(self):
@@ -1494,6 +1540,7 @@
 
     def destruct(self):
         if self._rawobject:
+            assert isinstance(self.clsdecl, W_CPPClassDecl)
             if self.smartdecl and self.deref:
                 klass = self.smartdecl
             elif not (self.flags & INSTANCE_FLAGS_IS_REF):
@@ -1505,7 +1552,7 @@
             self._rawobject = capi.C_NULL_OBJECT
 
     def _finalize_(self):
-        if self.flags & INSTANCE_FLAGS_PYTHON_OWNS:
+        if self.rt_flags & INSTANCE_FLAGS_PYTHON_OWNS:
             self.destruct()
 
 W_CPPInstance.typedef = TypeDef(
@@ -1527,31 +1574,33 @@
 
 
 class MemoryRegulator:
-    # TODO: (?) An object address is not unique if e.g. the class has a
-    # public data member of class type at the start of its definition and
-    # has no virtual functions. A _key class that hashes on address and
-    # type would be better, but my attempt failed in the rtyper, claiming
-    # a call on None ("None()") and needed a default ctor. (??)
-    # Note that for now, the associated test carries an m_padding to make
-    # a difference in the addresses.
-    def __init__(self):
-        self.objects = rweakref.RWeakValueDictionary(int, W_CPPInstance)
+    _immutable_ = True
 
-    def register(self, obj):
+    @staticmethod
+    def register(obj):
         if not obj._rawobject:
             return
-        int_address = int(rffi.cast(rffi.LONG, obj._rawobject))
-        self.objects.set(int_address, obj)
+        addr_as_int = int(rffi.cast(rffi.LONG, obj.get_rawobject()))
+        clsdecl = obj.clsdecl
+        assert isinstance(clsdecl, W_CPPClassDecl)
+        clsdecl.cppobjects.set(addr_as_int, obj)
 
-    def unregister(self, obj):
+    @staticmethod
+    def unregister(obj):
         if not obj._rawobject:
             return
-        int_address = int(rffi.cast(rffi.LONG, obj._rawobject))
-        self.objects.set(int_address, None)
+        addr_as_int = int(rffi.cast(rffi.LONG, obj.get_rawobject()))
+        clsdecl = obj.clsdecl
+        assert isinstance(clsdecl, W_CPPClassDecl)
+        clsdecl.cppobjects.set(addr_as_int, None) # actually deletes (pops)
 
-    def retrieve(self, address):
-        int_address = int(rffi.cast(rffi.LONG, address))
-        return self.objects.get(int_address)
+    @staticmethod
+    def retrieve(clsdecl, address):
+        if not address:
+            return None
+        addr_as_int = int(rffi.cast(rffi.LONG, address))
+        assert isinstance(clsdecl, W_CPPClassDecl)
+        return clsdecl.cppobjects.get(addr_as_int)
 
 memory_regulator = MemoryRegulator()
 
@@ -1597,8 +1646,11 @@
 
     # try to recycle existing object if this one is not newly created
     if not fresh and rawobject:
-        obj = memory_regulator.retrieve(rawobject)
-        if obj is not None and obj.clsdecl is clsdecl:
+        address = rawobject
+        if is_ref:
+            address = rffi.cast(capi.C_OBJECT, rffi.cast(rffi.VOIDPP, 
address)[0])
+        obj = memory_regulator.retrieve(clsdecl, address)
+        if obj is not None:
             return obj
 
     # fresh creation
@@ -1649,7 +1701,7 @@
     """Casts the given instance into an C++-style rvalue."""
     obj = space.interp_w(W_CPPInstance, w_obj)
     if obj:
-        obj.flags |= INSTANCE_FLAGS_IS_RVALUE
+        obj.rt_flags |= INSTANCE_FLAGS_IS_RVALUE
     return w_obj
 
 
diff --git a/pypy/module/_cppyy/lowlevelviews.py 
b/pypy/module/_cppyy/lowlevelviews.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/_cppyy/lowlevelviews.py
@@ -0,0 +1,54 @@
+# Naked C++ pointers carry no useful size or layout information, but often
+# such information is externnally available. Low level views are arrays with
+# a few more methods allowing such information to be set. Afterwards, it is
+# simple to pass these views on to e.g. numpy (w/o the need to copy).
+
+from pypy.interpreter.error import oefmt
+from pypy.interpreter.gateway import interp2app, unwrap_spec
+from pypy.interpreter.typedef import TypeDef, GetSetProperty, 
interp_attrproperty_w
+from pypy.module._rawffi.array import W_ArrayInstance
+
+
+class W_LowLevelView(W_ArrayInstance):
+    def __init__(self, space, shape, length, address):
+        assert address   # if not address, base class will allocate memory
+        W_ArrayInstance.__init__(self, space, shape, length, address)
+
+    @unwrap_spec(args_w='args_w')
+    def reshape(self, space, args_w):
+        # llviews are only created from non-zero addresses, so we only need
+        # to adjust length and shape
+
+        nargs = len(args_w)
+        if nargs == 0:
+            raise oefmt(space.w_TypeError, "reshape expects a tuple argument")
+
+        newshape_w = args_w
+        if nargs != 1 or not space.isinstance_w(args_w[0], space.w_tuple) or \
+               not space.len_w(args_w[0]) == 1:
+            raise oefmt(space.w_TypeError,
+                "tuple object of length 1 expected, received %T", args_w[0])
+
+        w_shape = args_w[0]
+
+        # shape in W_ArrayInstance-speak is somewhat different from what
+        # e.g. numpy thinks of it: self.shape contains the info (itemcode,
+        # size, etc.) of a single entry; length is user-facing shape
+        self.length = space.int_w(space.getitem(w_shape, space.newint(0)))
+
+
+W_LowLevelView.typedef = TypeDef(
+    'LowLevelView',
+    __repr__    = interp2app(W_LowLevelView.descr_repr),
+    __setitem__ = interp2app(W_LowLevelView.descr_setitem),
+    __getitem__ = interp2app(W_LowLevelView.descr_getitem),
+    __len__     = interp2app(W_LowLevelView.getlength),
+    buffer      = GetSetProperty(W_LowLevelView.getbuffer),
+    shape       = interp_attrproperty_w('shape', W_LowLevelView),
+    free        = interp2app(W_LowLevelView.free),
+    byptr       = interp2app(W_LowLevelView.byptr),
+    itemaddress = interp2app(W_LowLevelView.descr_itemaddress),
+    reshape     = interp2app(W_LowLevelView.reshape),
+)
+W_ArrayInstance.typedef.acceptable_as_base_class = False
+
diff --git a/pypy/module/_cppyy/pythonify.py b/pypy/module/_cppyy/pythonify.py
--- a/pypy/module/_cppyy/pythonify.py
+++ b/pypy/module/_cppyy/pythonify.py
@@ -73,7 +73,8 @@
 
 # C++ namespace base class (the C++ class base class defined in 
_post_import_startup)
 class CPPNamespace(with_metaclass(CPPNamespaceMeta, object)):
-     pass
+    def __init__(self):
+        raise TypeError("cannot instantiate namespace '%s'", self.__cppname__)
 
 
 # TODO: this can be moved to the interp level (and share template argument
@@ -450,6 +451,14 @@
             return self.__real_init__(*args)
         pyclass.__init__ = vector_init
 
+        # size-up the return of data()
+        pyclass.__real_data = pyclass.data
+        def data_with_len(self):
+            arr = self.__real_data()
+            arr.reshape((len(self),))
+            return arr
+        pyclass.data = data_with_len
+
     # combine __getitem__ and __len__ to make a pythonized __getitem__
     if '__getitem__' in pyclass.__dict__ and '__len__' in pyclass.__dict__:
         pyclass._getitem__unchecked = pyclass.__getitem__
diff --git a/pypy/module/_cppyy/test/advancedcpp.cxx 
b/pypy/module/_cppyy/test/advancedcpp.cxx
--- a/pypy/module/_cppyy/test/advancedcpp.cxx
+++ b/pypy/module/_cppyy/test/advancedcpp.cxx
@@ -4,20 +4,32 @@
 
 
 // for testing of default arguments
-#define IMPLEMENT_DEFAULTER_CLASS(type, tname)                               \
+#define IMPLEMENT_DEFAULTERS(type, tname)                                    \
 tname##_defaulter::tname##_defaulter(type a, type b, type c) {               \
-   m_a = a; m_b = b; m_c = c;                                                \
+    m_a = a; m_b = b; m_c = c;                                               \
+}                                                                            \
+type tname##_defaulter_func(int idx, type a, type b, type c) {               \
+    if (idx == 0) return a;                                                  \
+    if (idx == 1) return b;                                                  \
+    if (idx == 2) return c;                                                  \
+    return (type)idx;                                                        \
 }
-IMPLEMENT_DEFAULTER_CLASS(short, short)
-IMPLEMENT_DEFAULTER_CLASS(unsigned short, ushort)
-IMPLEMENT_DEFAULTER_CLASS(int, int)
-IMPLEMENT_DEFAULTER_CLASS(unsigned, uint)
-IMPLEMENT_DEFAULTER_CLASS(long, long)
-IMPLEMENT_DEFAULTER_CLASS(unsigned long, ulong)
-IMPLEMENT_DEFAULTER_CLASS(long long, llong)
-IMPLEMENT_DEFAULTER_CLASS(unsigned long long, ullong)
-IMPLEMENT_DEFAULTER_CLASS(float, float)
-IMPLEMENT_DEFAULTER_CLASS(double, double)
+IMPLEMENT_DEFAULTERS(short, short)
+IMPLEMENT_DEFAULTERS(unsigned short, ushort)
+IMPLEMENT_DEFAULTERS(int, int)
+IMPLEMENT_DEFAULTERS(unsigned, uint)
+IMPLEMENT_DEFAULTERS(long, long)
+IMPLEMENT_DEFAULTERS(unsigned long, ulong)
+IMPLEMENT_DEFAULTERS(long long, llong)
+IMPLEMENT_DEFAULTERS(unsigned long long, ullong)
+IMPLEMENT_DEFAULTERS(float, float)
+IMPLEMENT_DEFAULTERS(double, double)
+
+std::string string_defaulter_func(int idx, const std::string& name1, 
std::string name2) {
+    if (idx == 0) return name1;
+    if (idx == 1) return name2;
+    return "mies";
+}
 
 
 // for esoteric inheritance testing
@@ -77,11 +89,11 @@
 double my_global_array[500];
 static double sd = 1234.;
 double* my_global_ptr = &sd;
+const char my_global_string2[] = "zus jet teun";
 some_int_holder my_global_int_holders[5] = {
     some_int_holder(13), some_int_holder(42), some_int_holder(88),
     some_int_holder(-1), some_int_holder(17) };
 
-
 // for life-line and identity testing
 int some_class_with_data::some_data::s_num_data = 0;
 
diff --git a/pypy/module/_cppyy/test/advancedcpp.h 
b/pypy/module/_cppyy/test/advancedcpp.h
--- a/pypy/module/_cppyy/test/advancedcpp.h
+++ b/pypy/module/_cppyy/test/advancedcpp.h
@@ -4,24 +4,27 @@
 
 
 //===========================================================================
-#define DECLARE_DEFAULTER_CLASS(type, tname)                                \
+#define DECLARE_DEFAULTERS(type, tname)                                     \
 class tname##_defaulter {                                                   \
 public:                                                                     \
     tname##_defaulter(type a = 11, type b = 22, type c = 33);               \
                                                                             \
 public:                                                                     \
     type m_a, m_b, m_c;                                                     \
-};
-DECLARE_DEFAULTER_CLASS(short, short)   // for testing of default arguments
-DECLARE_DEFAULTER_CLASS(unsigned short, ushort)
-DECLARE_DEFAULTER_CLASS(int, int)
-DECLARE_DEFAULTER_CLASS(unsigned, uint)
-DECLARE_DEFAULTER_CLASS(long, long)
-DECLARE_DEFAULTER_CLASS(unsigned long, ulong)
-DECLARE_DEFAULTER_CLASS(long long, llong)
-DECLARE_DEFAULTER_CLASS(unsigned long long, ullong)
-DECLARE_DEFAULTER_CLASS(float, float)
-DECLARE_DEFAULTER_CLASS(double, double)
+};                                                                          \
+type tname##_defaulter_func(int idx = 0, type a = 11, type b = 22, type c = 
33);
+DECLARE_DEFAULTERS(short, short)   // for testing of default arguments
+DECLARE_DEFAULTERS(unsigned short, ushort)
+DECLARE_DEFAULTERS(int, int)
+DECLARE_DEFAULTERS(unsigned, uint)
+DECLARE_DEFAULTERS(long, long)
+DECLARE_DEFAULTERS(unsigned long, ulong)
+DECLARE_DEFAULTERS(long long, llong)
+DECLARE_DEFAULTERS(unsigned long long, ullong)
+DECLARE_DEFAULTERS(float, float)
+DECLARE_DEFAULTERS(double, double)
+
+std::string string_defaulter_func(int idx, const std::string& name1 = "aap", 
std::string name2 = "noot");
 
 
 //===========================================================================
@@ -274,7 +277,8 @@
 extern double my_global_double;    // a couple of globals for access testing
 extern double my_global_array[500];
 extern double* my_global_ptr;
-static const char my_global_string[] = "aap " " noot " " mies";
+static const char my_global_string1[] = "aap " " noot " " mies";
+extern const char my_global_string2[];
 
 class some_int_holder {
 public:
@@ -311,6 +315,11 @@
     some_data m_data;
 };
 
+class refers_to_self {             // for data member reuse testing
+public:
+    refers_to_self* m_other = nullptr;
+};
+
 
 //===========================================================================
 class pointer_pass {               // for testing passing of void*'s
@@ -419,3 +428,34 @@
     void throw_anything();
     void throw_exception();
 };
+
+
+//===========================================================================
+class UsingBase {                  // using declaration testing
+public:
+    UsingBase(int n = 13) : m_int(n) {} 
+    virtual char vcheck() { return 'A'; }
+    int m_int;
+};
+
+class UsingDerived : public UsingBase {
+public:
+    using UsingBase::UsingBase;
+    virtual char vcheck() { return 'B'; }
+    int m_int2 = 42;
+};
+
+
+//===========================================================================
+class TypedefToPrivateClass {      // typedef resolution testing
+private:
+    class PC {
+    public:
+        PC(int i) : m_val(i) {}
+        int m_val;
+    };
+
+public:
+    typedef PC PP;
+    PP f() { return PC(42); }
+};
diff --git a/pypy/module/_cppyy/test/advancedcpp.xml 
b/pypy/module/_cppyy/test/advancedcpp.xml
--- a/pypy/module/_cppyy/test/advancedcpp.xml
+++ b/pypy/module/_cppyy/test/advancedcpp.xml
@@ -1,6 +1,7 @@
 <lcgdict>
 
   <class pattern="*_defaulter" />
+  <function pattern="*_defaulter_func" />
 
   <class name="base_class" />
   <class name="derived_class" />
@@ -32,6 +33,7 @@
   <class name="some_convertible" />
   <class name="some_class_with_data" />
   <class name="some_class_with_data::some_data" />
+  <class name="refers_to_self" />
 
   <class name="some_comparable" />
   <function name="operator==" />
@@ -59,5 +61,7 @@
   <class name="overload_the_other_way" />
 
   <class name="Thrower" />
+  <class pattern="Using*" />
+  <class name="TypedefToPrivateClass" />
 
 </lcgdict>
diff --git a/pypy/module/_cppyy/test/stltypes.cxx 
b/pypy/module/_cppyy/test/stltypes.cxx
--- a/pypy/module/_cppyy/test/stltypes.cxx
+++ b/pypy/module/_cppyy/test/stltypes.cxx
@@ -1,6 +1,20 @@
 #include "stltypes.h"
 
 
+//- explicit instantiations of used comparisons
+#if defined __clang__
+namespace std {
+#define ns_prefix std::
+#elif defined(__GNUC__) || defined(__GNUG__)
+namespace __gnu_cxx {
+#define ns_prefix
+#endif
+template bool ns_prefix operator==(const std::vector<int>::iterator&,
+                         const std::vector<int>::iterator&);
+template bool ns_prefix operator!=(const std::vector<int>::iterator&,
+                         const std::vector<int>::iterator&);
+}
+
 //- class with lots of std::string handling
 stringy_class::stringy_class(const char* s) : m_string(s) {}
 
@@ -9,3 +23,33 @@
 
 void stringy_class::set_string1(const std::string& s) { m_string = s; }
 void stringy_class::set_string2(std::string s) { m_string = s; }
+
+
+//- helpers for testing array
+int ArrayTest::get_pp_px(Point** p, int idx) {
+    return p[idx]->px;
+}
+
+int ArrayTest::get_pp_py(Point** p, int idx) {
+    return p[idx]->py;
+}
+
+int ArrayTest::get_pa_px(Point* p[], int idx) {
+    return p[idx]->px;
+}
+
+int ArrayTest::get_pa_py(Point* p[], int idx) {
+    return p[idx]->py;
+}
+
+
+// helpers for string testing
+std::string str_array_1[3] = {"a", "b", "c"};
+std::string str_array_2[]  = {"d", "e", "f", "g"};
+std::string str_array_3[3][2] = {{"a", "b"}, {"c", "d"}, {"e", "f"}};
+std::string str_array_4[4][2][2] = {
+     {{"a", "b"}, {"c", "d"}},
+     {{"e", "f"}, {"g", "h"}},
+     {{"i", "j"}, {"k", "l"}},
+     {{"m", "n"}, {"o", "p"}},
+};
diff --git a/pypy/module/_cppyy/test/stltypes.h 
b/pypy/module/_cppyy/test/stltypes.h
--- a/pypy/module/_cppyy/test/stltypes.h
+++ b/pypy/module/_cppyy/test/stltypes.h
@@ -37,3 +37,49 @@
    std::string operator[](double) { return "double"; }
    std::string operator[](const std::string&) { return "string"; }
 };      
+
+
+//- instantiations of used STL types
+namespace {
+
+    stl_like_class<int> stlc_1;
+
+} // unnamed namespace
+
+
+// comps for int only to allow testing: normal use of vector is looping over a
+// range-checked version of __getitem__
+#if defined(__clang__) && defined(__APPLE__)
+namespace std {
+#define ns_prefix std::
+#elif defined(__GNUC__) || defined(__GNUG__)
+namespace __gnu_cxx {
+#define ns_prefix
+#endif
+extern template bool ns_prefix operator==(const std::vector<int>::iterator&,
+                         const std::vector<int>::iterator&);
+extern template bool ns_prefix operator!=(const std::vector<int>::iterator&,
+                         const std::vector<int>::iterator&);
+}
+
+
+//- helpers for testing array
+namespace ArrayTest {
+
+struct Point {
+    int px, py;
+};
+
+int get_pp_px(Point** p, int idx);
+int get_pp_py(Point** p, int idx);
+int get_pa_px(Point* p[], int idx);
+int get_pa_py(Point* p[], int idx);
+
+} // namespace ArrayTest
+
+
+// helpers for string testing
+extern std::string str_array_1[3];
+extern std::string str_array_2[];
+extern std::string str_array_3[3][2];
+extern std::string str_array_4[4][2][2];
diff --git a/pypy/module/_cppyy/test/stltypes.xml 
b/pypy/module/_cppyy/test/stltypes.xml
--- a/pypy/module/_cppyy/test/stltypes.xml
+++ b/pypy/module/_cppyy/test/stltypes.xml
@@ -1,10 +1,13 @@
 <lcgdict>
 
-  <namespace name="std" />
+  <class name="just_a_class" />
+  <class name="stringy_class" />
+  <class pattern="stl_like_class<*>" />
 
-  <class name="just_a_class" />
+  <namespace name="ArrayTest" />
+  <class pattern="ArrayTest::*" />
+  <function pattern="ArrayTest::*" />
 
-  <class name="std::string" />
-  <class name="stringy_class" />
+  <variable pattern="str_array_*" />
 
 </lcgdict>
diff --git a/pypy/module/_cppyy/test/test_advancedcpp.py 
b/pypy/module/_cppyy/test/test_advancedcpp.py
--- a/pypy/module/_cppyy/test/test_advancedcpp.py
+++ b/pypy/module/_cppyy/test/test_advancedcpp.py
@@ -56,6 +56,12 @@
             assert d.m_b ==  t(4)
             assert d.m_c ==  t(5)
             d.__destruct__()
+
+            defaulter_func = getattr(cppyy.gbl, '%s_defaulter_func' %n)
+            answers = [11, 22, 33, 3]
+            for idx in range(4):
+                assert defaulter_func(idx) == answers[idx]
+
         test_defaulter('short',  int)
         test_defaulter('ushort', int)
         test_defaulter('int',    int)
@@ -67,6 +73,13 @@
         test_defaulter('float',  float)
         test_defaulter('double', float)
 
+        assert cppyy.gbl.string_defaulter_func(0)               == "aap"
+        assert cppyy.gbl.string_defaulter_func(0, "zus")        == "zus"
+        assert cppyy.gbl.string_defaulter_func(1)               == "noot"
+        assert cppyy.gbl.string_defaulter_func(1, "zus")        == "noot"
+        assert cppyy.gbl.string_defaulter_func(1, "zus", "jet") == "jet"
+        assert cppyy.gbl.string_defaulter_func(2)               == "mies"
+
     def test02_simple_inheritance(self):
         """Test binding of a basic inheritance structure"""
 
@@ -148,6 +161,8 @@
         assert gbl.a_ns.d_ns.e_class.f_class.s_f      == 66
         assert gbl.a_ns.d_ns.e_class.f_class().m_f    == -6
 
+        raises(TypeError, gbl.a_ns)
+
     def test03a_namespace_lookup_on_update(self):
         """Test whether namespaces can be shared across dictionaries."""
 
@@ -474,6 +489,23 @@
         d2.__destruct__()
         d1.__destruct__()
 
+        RTS = cppyy.gbl.refers_to_self
+
+        r1 = RTS()
+        r2 = RTS()
+        r1.m_other = r2
+
+        r3 = r1.m_other
+        r4 = r1.m_other
+        assert r3 is r4
+
+        assert r3 == r2
+        assert r3 is r2
+
+        r3.extra = 42
+        assert r2.extra == 42
+        assert r4.extra == 42
+
     def test11_multi_methods(self):
         """Test calling of methods from multiple inheritance"""
 
@@ -653,10 +685,18 @@
 
         assert cppyy.gbl.my_global_double == 12.
         assert len(cppyy.gbl.my_global_array) == 500
-        assert cppyy.gbl.my_global_string == "aap  noot  mies"
+        assert cppyy.gbl.my_global_string1 == "aap  noot  mies"
+        return     # next line currently crashes
+        assert cppyy.gbl.my_global_string2 == "zus jet teun"
         # TODO: currently fails b/c double** not understood as &double*
         #assert cppyy.gbl.my_global_ptr[0] == 1234.
 
+        v = cppyy.gbl.my_global_int_holders
+        assert len(v) == 5
+        expected_vals = [13, 42, 88, -1, 17]
+        for i in range(len(v)):
+            assert v[i].m_val == expected_vals[i]
+
     def test22_exceptions(self):
         """Catching of C++ exceptions"""
 
@@ -675,3 +715,35 @@
             t.throw_exception()
         except Exception as e:
             "C++ function failed" in str(e)
+
+    def test23_using(self):
+        """Accessibility of using declarations"""
+
+        import _cppyy as cppyy
+
+        assert cppyy.gbl.UsingBase().vcheck() == 'A'
+
+        B = cppyy.gbl.UsingDerived
+        assert not 'UsingBase' in B.__init__.__doc__
+
+        b1 = B()
+        assert b1.m_int    == 13
+        assert b1.m_int2   == 42
+        assert b1.vcheck() == 'B'
+ 
+        b2 = B(10)
+        assert b2.m_int    == 10
+        assert b2.m_int2   == 42
+        assert b2.vcheck() == 'B'
+
+        b3 = B(b2)
+        assert b3.m_int    == 10
+        assert b3.m_int2   == 42
+        assert b3.vcheck() == 'B'
+
+    def test24_typedef_to_private_class(self):
+        """Typedefs to private classes should not resolve"""
+
+        import _cppyy as cppyy
+
+        assert cppyy.gbl.TypedefToPrivateClass().f().m_val == 42
diff --git a/pypy/module/_cppyy/test/test_datatypes.py 
b/pypy/module/_cppyy/test/test_datatypes.py
--- a/pypy/module/_cppyy/test/test_datatypes.py
+++ b/pypy/module/_cppyy/test/test_datatypes.py
@@ -183,7 +183,7 @@
         names = ['uchar', 'short', 'ushort', 'int', 'uint', 'long', 'ulong']
         import array
         a = range(self.N)
-        atypes = ['B', 'h', 'H', 'i', 'I', 'l', 'L' ]
+        atypes = ['B', 'h', 'H', 'i', 'I', 'l', 'L']
         for j in range(len(names)):
             b = array.array(atypes[j], a)
             setattr(c, 'm_'+names[j]+'_array', b)     # buffer copies
@@ -191,6 +191,7 @@
                 assert eval('c.m_%s_array[i]' % names[j]) == b[i]
 
             setattr(c, 'm_'+names[j]+'_array2', b)    # pointer copies
+            assert 3 < self.N
             b[3] = 28
             for i in range(self.N):
                 assert eval('c.m_%s_array2[i]' % names[j]) == b[i]
@@ -212,7 +213,7 @@
 
         a = range(self.N)
         # test arrays in mixed order, to give overload resolution a workout
-        for t in ['d', 'i', 'f', 'H', 'I', 'h', 'L', 'l' ]:
+        for t in ['d', 'i', 'f', 'H', 'I', 'h', 'L', 'l']:
             b = array.array(t, a)
 
             # typed passing
@@ -691,9 +692,6 @@
                      'get_long_array',   'get_long_array2',
                      'get_ulong_array',  'get_ulong_array2']:
             arr = getattr(c, func)()
-            arr = arr.shape.fromaddress(arr.itemaddress(0), self.N)
-
-            """TODO: interface change ...
             arr.reshape((self.N,))
             assert len(arr) == self.N
 
@@ -705,7 +703,7 @@
 
             l = list(arr)
             for i in range(self.N):
-                assert arr[i] == l[i]"""
+                assert arr[i] == l[i]
 
     def test20_voidp(self):
         """Test usage of void* data"""
@@ -758,6 +756,15 @@
     def test21_function_pointers(self):
         """Function pointer passing"""
 
+        import os
+
+        # TODO: currently crashes if fast path disabled
+        try:
+            if os.environ['CPPYY_DISABLE_FASTPATH']:
+                return
+        except KeyError:
+            pass
+
         import _cppyy as cppyy
 
         f1 = cppyy.gbl.sum_of_int
diff --git a/pypy/module/_cppyy/test/test_overloads.py 
b/pypy/module/_cppyy/test/test_overloads.py
--- a/pypy/module/_cppyy/test/test_overloads.py
+++ b/pypy/module/_cppyy/test/test_overloads.py
@@ -58,15 +58,19 @@
         c = c_overload()
         raises(TypeError, c.__dispatch__, 'get_int', 12)
         raises(LookupError, c.__dispatch__, 'get_int', 'does_not_exist')
-        assert c.__dispatch__('get_int', 'a_overload*')(a_overload()) == 42
-        assert c.__dispatch__('get_int', 'b_overload*')(b_overload()) == 13
+        assert c.__dispatch__('get_int', 'a_overload*')(a_overload())          
   == 42
+        assert c_overload.get_int.__overload__('a_overload*')(c, a_overload()) 
   == 42
+        assert c.__dispatch__('get_int', 'b_overload*')(b_overload())          
   == 13
+        assert c_overload.get_int.__overload__('b_overload*')(c, b_overload()) 
   == 13
 
         assert c_overload().__dispatch__('get_int', 
'a_overload*')(a_overload())  == 42
         # TODO: #assert c_overload.__dispatch__('get_int', 'b_overload*')(c, 
b_overload()) == 13
 
         d = d_overload()
-        assert d.__dispatch__('get_int', 'a_overload*')(a_overload()) == 42
-        assert d.__dispatch__('get_int', 'b_overload*')(b_overload()) == 13
+        assert d.__dispatch__('get_int', 'a_overload*')(a_overload())          
   == 42
+        assert d_overload.get_int.__overload__('a_overload*')(d, a_overload()) 
   == 42
+        assert d.__dispatch__('get_int', 'b_overload*')(b_overload())          
   == 13
+        assert d_overload.get_int.__overload__('b_overload*')(d, b_overload()) 
   == 13
 
         nb = ns_a_overload.b_overload()
         raises(TypeError, nb.f, c_overload())
diff --git a/pypy/module/_cppyy/test/test_stltypes.py 
b/pypy/module/_cppyy/test/test_stltypes.py
--- a/pypy/module/_cppyy/test/test_stltypes.py
+++ b/pypy/module/_cppyy/test/test_stltypes.py
@@ -22,12 +22,12 @@
     def test01_builtin_type_vector_types(self):
         """Test access to std::vector<int>/std::vector<double>"""
 
-        import _cppyy
+        import _cppyy as cppyy
 
-        assert _cppyy.gbl.std        is _cppyy.gbl.std
-        assert _cppyy.gbl.std.vector is _cppyy.gbl.std.vector
+        assert cppyy.gbl.std        is cppyy.gbl.std
+        assert cppyy.gbl.std.vector is cppyy.gbl.std.vector
 
-        assert callable(_cppyy.gbl.std.vector)
+        assert callable(cppyy.gbl.std.vector)
 
         type_info = (
             ("int",     int),
@@ -36,14 +36,14 @@
         )
 
         for c_type, p_type in type_info:
-            tv1 = getattr(_cppyy.gbl.std, 'vector<%s>' % c_type)
-            tv2 = _cppyy.gbl.std.vector(p_type)
+            tv1 = getattr(cppyy.gbl.std, 'vector<%s>' % c_type)
+            tv2 = cppyy.gbl.std.vector(p_type)
             assert tv1 is tv2
-            assert tv1.iterator is _cppyy.gbl.std.vector(p_type).iterator
+            assert tv1.iterator is cppyy.gbl.std.vector(p_type).iterator
 
             #----- 
-            v = tv1(); v += range(self.N)    # default args from Reflex are 
useless :/
-            if p_type == int:                # only type with == and != 
reflected in .xml
+            v = tv1(); v += range(self.N)
+            if p_type == int:
                 assert v.begin().__eq__(v.begin())
                 assert v.begin() == v.begin()
                 assert v.end() == v.end()
@@ -58,6 +58,7 @@
 
             assert v.size() == self.N
             assert len(v) == self.N
+            assert len(v.data()) == self.N
 
             #-----
             v = tv1()
@@ -73,16 +74,16 @@
     def test02_user_type_vector_type(self):
         """Test access to an std::vector<just_a_class>"""
 
-        import _cppyy
+        import _cppyy as cppyy
 
-        assert _cppyy.gbl.std        is _cppyy.gbl.std
-        assert _cppyy.gbl.std.vector is _cppyy.gbl.std.vector
+        assert cppyy.gbl.std        is cppyy.gbl.std
+        assert cppyy.gbl.std.vector is cppyy.gbl.std.vector
 
-        assert callable(_cppyy.gbl.std.vector)
+        assert callable(cppyy.gbl.std.vector)
 
-        tv1 = getattr(_cppyy.gbl.std, 'vector<just_a_class>')
-        tv2 = _cppyy.gbl.std.vector('just_a_class')
-        tv3 = _cppyy.gbl.std.vector(_cppyy.gbl.just_a_class)
+        tv1 = getattr(cppyy.gbl.std, 'vector<just_a_class>')
+        tv2 = cppyy.gbl.std.vector('just_a_class')
+        tv3 = cppyy.gbl.std.vector(cppyy.gbl.just_a_class)
 
         assert tv1 is tv2
         assert tv2 is tv3
@@ -95,7 +96,7 @@
         assert hasattr(v, 'end' )
 
         for i in range(self.N):
-            v.push_back(_cppyy.gbl.just_a_class())
+            v.push_back(cppyy.gbl.just_a_class())
             v[i].m_i = i
             assert v[i].m_i == i
 
@@ -105,9 +106,9 @@
     def test03_empty_vector_type(self):
         """Test behavior of empty std::vector<int>"""
 
-        import _cppyy
+        import _cppyy as cppyy
 
-        v = _cppyy.gbl.std.vector(int)()
+        v = cppyy.gbl.std.vector(int)()
         for arg in v:
             pass
         v.__destruct__()
@@ -115,9 +116,9 @@
     def test04_vector_iteration(self):
         """Test iteration over an std::vector<int>"""
 
-        import _cppyy
+        import _cppyy as cppyy
 
-        v = _cppyy.gbl.std.vector(int)()
+        v = cppyy.gbl.std.vector(int)()
 
         for i in range(self.N):
             v.push_back(i)
@@ -140,9 +141,9 @@
     def test05_push_back_iterables_with_iadd(self):
         """Test usage of += of iterable on push_back-able container"""
 
-        import _cppyy
+        import _cppyy as cppyy
 
-        v = _cppyy.gbl.std.vector(int)()
+        v = cppyy.gbl.std.vector(int)()
 
         v += [1, 2, 3]
         assert len(v) == 3
@@ -159,7 +160,7 @@
         raises(TypeError, v.__iadd__, (7, '8'))  # string shouldn't pass
         assert len(v) == 7   # TODO: decide whether this should roll-back
 
-        v2 = _cppyy.gbl.std.vector(int)()
+        v2 = cppyy.gbl.std.vector(int)()
         v2 += [8, 9]
         assert len(v2) == 2
         assert v2[0] == 8
@@ -174,9 +175,9 @@
     def test06_vector_indexing(self):
         """Test python-style indexing to an std::vector<int>"""
 
-        import _cppyy
+        import _cppyy as cppyy
 
-        v = _cppyy.gbl.std.vector(int)()
+        v = cppyy.gbl.std.vector(int)()
 
         for i in range(self.N):
             v.push_back(i)
@@ -209,9 +210,9 @@
     def test01_string_argument_passing(self):
         """Test mapping of python strings and std::string"""
 
-        import _cppyy
-        std = _cppyy.gbl.std
-        stringy_class = _cppyy.gbl.stringy_class
+        import _cppyy as cppyy
+        std = cppyy.gbl.std
+        stringy_class = cppyy.gbl.stringy_class
 
         c, s = stringy_class(""), std.string("test1")
 
@@ -240,9 +241,9 @@
     def test02_string_data_access(self):
         """Test access to std::string object data members"""
 
-        import _cppyy
-        std = _cppyy.gbl.std
-        stringy_class = _cppyy.gbl.stringy_class
+        import _cppyy as cppyy
+        std = cppyy.gbl.std
+        stringy_class = cppyy.gbl.stringy_class
 
         c, s = stringy_class("dummy"), std.string("test string")
 
@@ -261,9 +262,9 @@
 
         return # don't bother; is fixed in cling-support
 
-        import _cppyy
-        std = _cppyy.gbl.std
-        stringy_class = _cppyy.gbl.stringy_class
+        import _cppyy as cppyy
+        std = cppyy.gbl.std
+        stringy_class = cppyy.gbl.stringy_class
 
         t0 = "aap\0noot"
         assert t0 == "aap\0noot"
@@ -288,8 +289,8 @@
     def test01_builtin_list_type(self):
         """Test access to a list<int>"""
 
-        import _cppyy
-        std = _cppyy.gbl.std
+        import _cppyy as cppyy
+        std = cppyy.gbl.std
 
         type_info = (
             ("int",     int),
@@ -299,9 +300,9 @@
 
         for c_type, p_type in type_info:
             tl1 = getattr(std, 'list<%s>' % c_type)
-            tl2 = _cppyy.gbl.std.list(p_type)
+            tl2 = cppyy.gbl.std.list(p_type)
             assert tl1 is tl2
-            assert tl1.iterator is _cppyy.gbl.std.list(p_type).iterator
+            assert tl1.iterator is cppyy.gbl.std.list(p_type).iterator
 
             #-----
             a = tl1()
@@ -323,8 +324,8 @@
     def test02_empty_list_type(self):
         """Test behavior of empty list<int>"""
 
-        import _cppyy
-        std = _cppyy.gbl.std
+        import _cppyy as cppyy
+        std = cppyy.gbl.std
 
         a = std.list(int)()
         for arg in a:
@@ -344,8 +345,8 @@
     def test01_builtin_map_type(self):
         """Test access to a map<int,int>"""
 
-        import _cppyy
-        std = _cppyy.gbl.std
+        import _cppyy as cppyy
+        std = cppyy.gbl.std
 
         a = std.map(int, int)()
         for i in range(self.N):
@@ -373,8 +374,8 @@
     def test02_keyed_maptype(self):
         """Test access to a map<std::string,int>"""
 
-        import _cppyy
-        std = _cppyy.gbl.std
+        import _cppyy as cppyy
+        std = cppyy.gbl.std
 
         a = std.map(std.string, int)()
         for i in range(self.N):
@@ -386,8 +387,8 @@
     def test03_empty_maptype(self):
         """Test behavior of empty map<int,int>"""
 
-        import _cppyy
-        std = _cppyy.gbl.std
+        import _cppyy as cppyy
+        std = cppyy.gbl.std
 
         m = std.map(int, int)()
         for key, value in m:
@@ -396,8 +397,9 @@
     def test04_unsignedvalue_typemap_types(self):
         """Test assignability of maps with unsigned value types"""
 
-        import _cppyy, math, sys
-        std = _cppyy.gbl.std
+        import _cppyy as cppyy
+        import math, sys
+        std = cppyy.gbl.std
 
         mui = std.map(str, 'unsigned int')()
         mui['one'] = 1
@@ -420,8 +422,8 @@
     def test05_STL_like_class_indexing_overloads(self):
         """Test overloading of operator[] in STL like class"""
 
-        import _cppyy
-        stl_like_class = _cppyy.gbl.stl_like_class
+        import _cppyy as cppyy
+        stl_like_class = cppyy.gbl.stl_like_class
 
         a = stl_like_class(int)()
         assert a["some string" ] == 'string'
@@ -430,8 +432,8 @@
     def test06_STL_like_class_iterators(self):
         """Test the iterator protocol mapping for an STL like class"""
 
-        import _cppyy
-        stl_like_class = _cppyy.gbl.stl_like_class
+        import _cppyy as cppyy
+        stl_like_class = cppyy.gbl.stl_like_class
 
         a = stl_like_class(int)()
         for i in a:
@@ -452,8 +454,8 @@
     def test01_builtin_vector_iterators(self):
         """Test iterator comparison with operator== reflected"""
 
-        import _cppyy
-        std = _cppyy.gbl.std
+        import _cppyy as cppyy
+        std = cppyy.gbl.std
 
         v = std.vector(int)()
         v.resize(1)
@@ -489,9 +491,9 @@
     def test01_explicit_templates(self):
         """Explicit use of Template class"""
 
-        import _cppyy
+        import _cppyy as cppyy
 
-        vector = _cppyy.Template('vector', _cppyy.gbl.std)
+        vector = cppyy.Template('vector', cppyy.gbl.std)
         assert vector[int] == vector(int)
 
         v = vector[int]()
@@ -501,3 +503,54 @@
         assert len(v) == N
         for i in range(N):
             assert v[i] == i
+
+
+class AppTestSTLARRAY:
+    spaceconfig = dict(usemodules=['_cppyy', '_rawffi', 'itertools'])
+
+    def setup_class(cls):
+        cls.w_test_dct  = cls.space.newtext(test_dct)
+        cls.w_stlarray = cls.space.appexec([], """():
+            import ctypes, _cppyy
+            _cppyy._post_import_startup()
+            return ctypes.CDLL(%r, ctypes.RTLD_GLOBAL)""" % (test_dct, ))
+
+    def test01_array_of_basic_types(self):
+        """Usage of std::array of basic types"""
+
+        import _cppyy as cppyy
+        std = cppyy.gbl.std
+
+        a = std.array[int, 4]()
+        assert len(a) == 4
+        for i in range(len(a)):
+            a[i] = i
+            assert a[i] == i
+
+    def test02_array_of_pods(self):
+        """Usage of std::array of PODs"""
+
+        import _cppyy as cppyy
+        gbl, std = cppyy.gbl, cppyy.gbl.std
+
+        a = std.array[gbl.ArrayTest.Point, 4]()
+        assert len(a) == 4
+        for i in range(len(a)):
+            a[i].px = i
+            assert a[i].px == i
+            a[i].py = i**2
+            assert a[i].py == i**2
+
+    def test03_array_of_pointer_to_pods(self):
+        """Usage of std::array of pointer to PODs"""
+
+        import cppyy
+        from cppyy import gbl
+        from cppyy.gbl import std
+
+        ll = [gbl.ArrayTest.Point() for i in range(4)]
+        for i in range(len(ll)):
+            ll[i].px = 13*i
+            ll[i].py = 42*i
+
+        # more tests in cppyy/test/test_stltypes.py, but currently not 
supported
diff --git a/pypy/module/_multiprocessing/interp_semaphore.py 
b/pypy/module/_multiprocessing/interp_semaphore.py
--- a/pypy/module/_multiprocessing/interp_semaphore.py
+++ b/pypy/module/_multiprocessing/interp_semaphore.py
@@ -60,7 +60,7 @@
         TIMESPEC = platform.Struct('struct timespec', [('tv_sec', rffi.TIME_T),
                                                        ('tv_nsec', rffi.LONG)])
         SEM_FAILED = platform.ConstantInteger('SEM_FAILED')
-        SEM_VALUE_MAX = platform.ConstantInteger('SEM_VALUE_MAX')
+        SEM_VALUE_MAX = platform.DefinedConstantInteger('SEM_VALUE_MAX')
         SEM_TIMED_WAIT = platform.Has('sem_timedwait')
         SEM_T_SIZE = platform.SizeOf('sem_t')
 
@@ -73,6 +73,8 @@
     #                rffi.cast(SEM_T, config['SEM_FAILED'])
     SEM_FAILED     = config['SEM_FAILED']
     SEM_VALUE_MAX  = config['SEM_VALUE_MAX']
+    if SEM_VALUE_MAX is None:      # on Hurd
+        SEM_VALUE_MAX = sys.maxint
     SEM_TIMED_WAIT = config['SEM_TIMED_WAIT']
     SEM_T_SIZE = config['SEM_T_SIZE']
     if sys.platform == 'darwin':
diff --git a/pypy/module/cpyext/cdatetime.py b/pypy/module/cpyext/cdatetime.py
--- a/pypy/module/cpyext/cdatetime.py
+++ b/pypy/module/cpyext/cdatetime.py
@@ -12,18 +12,19 @@
 from pypy.module.__pypy__.interp_pypydatetime import (W_DateTime_Date,
     W_DateTime_Time, W_DateTime_Delta)
 from rpython.tool.sourcetools import func_renamer
+from pypy.module.cpyext.state import State
 
 cts.parse_header(parse_dir / 'cpyext_datetime.h')
 
 
 PyDateTime_CAPI = cts.gettype('PyDateTime_CAPI')
 
-datetimeAPI_global = []
 
 @cpython_api([], lltype.Ptr(PyDateTime_CAPI))
 def _PyDateTime_Import(space):
-    if len(datetimeAPI_global) >0:
-        return datetimeAPI_global[0]
+    state = space.fromcache(State)
+    if len(state.datetimeAPI) > 0:
+        return state.datetimeAPI[0]
     datetimeAPI = lltype.malloc(PyDateTime_CAPI, flavor='raw',
                                 track_allocation=False)
 
@@ -66,8 +67,8 @@
         _PyDelta_FromDelta.api_func.functype,
         _PyDelta_FromDelta.api_func.get_wrapper(space))
 
-    datetimeAPI_global.append(datetimeAPI)
-    return datetimeAPI
+    state.datetimeAPI.append(datetimeAPI)
+    return state.datetimeAPI[0]
 
 PyDateTime_Time = cts.gettype('PyDateTime_Time*')
 PyDateTime_DateTime = cts.gettype('PyDateTime_DateTime*')
@@ -135,8 +136,10 @@
     '''Fills a newly allocated py_obj from the w_obj
     If it is a datetime.time or datetime.datetime, it may have tzinfo
     '''
-    assert len(datetimeAPI_global) > 0
-    if datetimeAPI_global[0].c_TimeType == py_obj.c_ob_type:
+    state = space.fromcache(State)
+    # cannot raise here, so just crash
+    assert len(state.datetimeAPI) > 0
+    if state.datetimeAPI[0].c_TimeType == py_obj.c_ob_type:
         py_datetime = rffi.cast(PyDateTime_Time, py_obj)
         w_tzinfo = space.getattr(w_obj, space.newtext('tzinfo'))
         if space.is_none(w_tzinfo):
@@ -145,7 +148,7 @@
         else:
             py_datetime.c_hastzinfo = cts.cast('unsigned char', 1)
             py_datetime.c_tzinfo = make_ref(space, w_tzinfo)
-    elif datetimeAPI_global[0].c_DateTimeType == py_obj.c_ob_type:
+    elif state.datetimeAPI[0].c_DateTimeType == py_obj.c_ob_type:
         # For now this is exactly the same structure as PyDateTime_Time
         py_datetime = rffi.cast(PyDateTime_DateTime, py_obj)
         w_tzinfo = space.getattr(w_obj, space.newtext('tzinfo'))
@@ -159,12 +162,14 @@
 @slot_function([PyObject], lltype.Void)
 def type_dealloc(space, py_obj):
     from pypy.module.cpyext.object import _dealloc
-    assert len(datetimeAPI_global) > 0
-    if datetimeAPI_global[0].c_TimeType == py_obj.c_ob_type:
+    state = space.fromcache(State)
+    # cannot raise here, so just crash
+    assert len(state.datetimeAPI) > 0
+    if state.datetimeAPI[0].c_TimeType == py_obj.c_ob_type:
         py_datetime = rffi.cast(PyDateTime_Time, py_obj)
         if (widen(py_datetime.c_hastzinfo) != 0):
             decref(space, py_datetime.c_tzinfo)
-    elif datetimeAPI_global[0].c_DateTimeType == py_obj.c_ob_type:
+    elif state.datetimeAPI[0].c_DateTimeType == py_obj.c_ob_type:
         py_datetime = rffi.cast(PyDateTime_DateTime, py_obj)
         if (widen(py_datetime.c_hastzinfo) != 0):
             decref(space, py_datetime.c_tzinfo)
diff --git a/pypy/module/cpyext/state.py b/pypy/module/cpyext/state.py
--- a/pypy/module/cpyext/state.py
+++ b/pypy/module/cpyext/state.py
@@ -42,6 +42,8 @@
         # A mapping {filename: copy-of-the-w_dict}, similar to CPython's
         # variable 'extensions' in Python/import.c.
         self.extensions = {}
+        # XXX will leak if _PyDateTime_Import already called
+        self.datetimeAPI = []
 
     def set_exception(self, operror):
         self.clear_exception()
diff --git a/rpython/jit/backend/detect_cpu.py 
b/rpython/jit/backend/detect_cpu.py
--- a/rpython/jit/backend/detect_cpu.py
+++ b/rpython/jit/backend/detect_cpu.py
@@ -57,6 +57,7 @@
             'i486': MODEL_X86,
             'i586': MODEL_X86,
             'i686': MODEL_X86,
+            'i686-AT386': MODEL_X86,  # Hurd
             'i86pc': MODEL_X86,    # Solaris/Intel
             'x86': MODEL_X86,      # Apple
             'Power Macintosh': MODEL_PPC_64,
diff --git a/rpython/rlib/buffer.py b/rpython/rlib/buffer.py
--- a/rpython/rlib/buffer.py
+++ b/rpython/rlib/buffer.py
@@ -6,7 +6,7 @@
 from rpython.rtyper.lltypesystem.rstr import STR
 from rpython.rtyper.lltypesystem.rlist import LIST_OF
 from rpython.rtyper.annlowlevel import llstr
-from rpython.rlib.objectmodel import specialize
+from rpython.rlib.objectmodel import specialize, we_are_translated
 from rpython.rlib import jit
 from rpython.rlib.rgc import (resizable_list_supporting_raw_ptr,
                               nonmoving_raw_ptr_for_resizable_list,
@@ -114,6 +114,12 @@
         """
         raise CannotWrite
 
+    def get_raw_address(self):
+        msg = "cannot take the raw address of this buffer"
+        if not we_are_translated():
+            msg += " '%s'" % (self,)
+        raise ValueError(msg)
+
 
 class RawBuffer(Buffer):
     """
diff --git a/rpython/rlib/rposix.py b/rpython/rlib/rposix.py
--- a/rpython/rlib/rposix.py
+++ b/rpython/rlib/rposix.py
@@ -1086,9 +1086,12 @@
         else:
             return bool(c_func(status))
 
-WAIT_MACROS = ['WCOREDUMP', 'WIFCONTINUED', 'WIFSTOPPED',
+WAIT_MACROS = ['WCOREDUMP', 'WIFSTOPPED',
                'WIFSIGNALED', 'WIFEXITED',
                'WEXITSTATUS', 'WSTOPSIG', 'WTERMSIG']
+if not sys.platform.startswith('gnu'):
+    WAIT_MACROS.append('WIFCONTINUED')
+
 for name in WAIT_MACROS:
     _make_waitmacro(name)
 
diff --git a/rpython/rlib/rvmprof/cintf.py b/rpython/rlib/rvmprof/cintf.py
--- a/rpython/rlib/rvmprof/cintf.py
+++ b/rpython/rlib/rvmprof/cintf.py
@@ -17,7 +17,7 @@
 
 # vmprof works only on x86 for now
 IS_SUPPORTED = False
-if sys.platform in ('darwin', 'linux', 'linux2'):
+if sys.platform in ('darwin', 'linux', 'linux2') or 
sys.platform.startswith('freebsd'):
     try:
         IS_SUPPORTED = detect_cpu.autodetect().startswith('x86')
     except detect_cpu.ProcessorAutodetectError:
diff --git a/rpython/rlib/rvmprof/dummy.py b/rpython/rlib/rvmprof/dummy.py
--- a/rpython/rlib/rvmprof/dummy.py
+++ b/rpython/rlib/rvmprof/dummy.py
@@ -1,6 +1,7 @@
 from rpython.rlib.objectmodel import specialize
 
 class DummyVMProf(object):
+    is_enabled = False
 
     def __init__(self):
         self._unique_id = 0
diff --git a/rpython/rlib/rvmprof/rvmprof.py b/rpython/rlib/rvmprof/rvmprof.py
--- a/rpython/rlib/rvmprof/rvmprof.py
+++ b/rpython/rlib/rvmprof/rvmprof.py
@@ -23,6 +23,7 @@
 VMPROF_GC_TAG = 5
 
 class VMProfError(Exception):
+    msg = ''   # annotation hack
     def __init__(self, msg):
         self.msg = msg
     def __str__(self):
diff --git a/rpython/rlib/rvmprof/src/shared/vmprof_unix.h 
b/rpython/rlib/rvmprof/src/shared/vmprof_unix.h
--- a/rpython/rlib/rvmprof/src/shared/vmprof_unix.h
+++ b/rpython/rlib/rvmprof/src/shared/vmprof_unix.h
@@ -24,6 +24,9 @@
 
 #include "vmprof_mt.h"
 
+#ifdef __FreeBSD__
+#include <ucontext.h>
+#endif
 #include <signal.h>
 
 RPY_EXTERN void vmprof_ignore_signals(int ignored);
diff --git a/rpython/rlib/rvmprof/traceback.py 
b/rpython/rlib/rvmprof/traceback.py
--- a/rpython/rlib/rvmprof/traceback.py
+++ b/rpython/rlib/rvmprof/traceback.py
@@ -13,6 +13,8 @@
     array_length).  The caller must free array_p.  Not for signal handlers:
     for these, call vmprof_get_traceback() from C code.
     """
+    if not cintf.IS_SUPPORTED:
+        return (None, 0)
     _cintf = rvmprof._get_vmprof().cintf
     size = estimate_number_of_entries * 2 + 4
     stack = cintf.get_rvmprof_stack()
@@ -47,6 +49,8 @@
     'code_obj' may be None if it can't be determined.  'loc' is one
     of the LOC_xxx constants.
     """
+    if not cintf.IS_SUPPORTED:
+        return
     i = 0
     while i < array_length - 1:
         tag = array_p[i]
diff --git a/rpython/rlib/unicodedata/generate_unicodedb.py 
b/rpython/rlib/unicodedata/generate_unicodedb.py
--- a/rpython/rlib/unicodedata/generate_unicodedb.py
+++ b/rpython/rlib/unicodedata/generate_unicodedb.py
@@ -913,8 +913,17 @@
 
     casefolds = {}
     for code, char in table.enum_chars():
-        if char.casefolding and char.casefolding != [char.lower]:
-            casefolds[code] = char.casefolding
+        full_casefold = char.casefolding
+        if full_casefold is None:
+            full_casefold = [code]
+        full_lower = char.lower
+        if full_lower is None:
+            full_lower = code
+        # if we don't write anything into the file, then the RPython
+        # program would compute the result 'full_lower' instead.
+        # Is that the right answer?
+        if full_casefold != [full_lower]:
+            casefolds[code] = full_casefold
     writeDict(outfile, '_casefolds', casefolds, base_mod)
     print >> outfile, '''
 
diff --git a/rpython/rlib/unicodedata/test/test_unicodedata.py 
b/rpython/rlib/unicodedata/test/test_unicodedata.py
--- a/rpython/rlib/unicodedata/test/test_unicodedata.py
+++ b/rpython/rlib/unicodedata/test/test_unicodedata.py
@@ -148,3 +148,15 @@
     def test_changed_in_version_8(self):
         assert unicodedb_6_2_0.toupper_full(0x025C) == [0x025C]
         assert unicodedb_8_0_0.toupper_full(0x025C) == [0xA7AB]
+
+    def test_casefold(self):
+        # returns None when we have no special casefolding rule,
+        # which means that tolower_full() should be used instead
+        assert unicodedb_8_0_0.casefold_lookup(0x1000) == None
+        assert unicodedb_8_0_0.casefold_lookup(0x0061) == None
+        assert unicodedb_8_0_0.casefold_lookup(0x0041) == None
+        # a case where casefold() != lower()
+        assert unicodedb_8_0_0.casefold_lookup(0x00DF) == [ord('s'), ord('s')]
+        # returns the argument itself, and not None, in rare cases
+        # where tolower_full() would return something different
+        assert unicodedb_8_0_0.casefold_lookup(0x13A0) == [0x13A0]
diff --git a/rpython/rlib/unicodedata/unicodedb_8_0_0.py 
b/rpython/rlib/unicodedata/unicodedb_8_0_0.py
--- a/rpython/rlib/unicodedata/unicodedb_8_0_0.py
+++ b/rpython/rlib/unicodedata/unicodedb_8_0_0.py
@@ -21307,6 +21307,92 @@
         return code
 
 _casefolds = {
+5024: [5024],
+5025: [5025],
+5026: [5026],
+5027: [5027],
+5028: [5028],
+5029: [5029],
+5030: [5030],
+5031: [5031],
+5032: [5032],
+5033: [5033],
+5034: [5034],
+5035: [5035],
+5036: [5036],
+5037: [5037],
+5038: [5038],
+5039: [5039],
+5040: [5040],
+5041: [5041],
+5042: [5042],
+5043: [5043],
+5044: [5044],
+5045: [5045],
+5046: [5046],
+5047: [5047],
+5048: [5048],
+5049: [5049],
+5050: [5050],
+5051: [5051],
+5052: [5052],
+5053: [5053],
+5054: [5054],
+5055: [5055],
+5056: [5056],
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to