Author: Matti Picus <matti.pi...@gmail.com> Branch: py3.6 Changeset: r98159:e5d59224adb8 Date: 2019-11-26 08:47 -0800 http://bitbucket.org/pypy/pypy/changeset/e5d59224adb8/
Log: merge default into py3.6 diff --git a/LICENSE b/LICENSE --- a/LICENSE +++ b/LICENSE @@ -99,16 +99,16 @@ Spenser Bauman Michal Bendowski Jan de Mooij + Stefano Rivera Tyler Wade + Stefan Beyer Vincent Legoll Michael Foord Stephan Diehl - Stefano Rivera Jean-Paul Calderone Stefan Schwarzer Tomek Meka Valentino Volonghi - Stefan Beyer Patrick Maupin Devin Jeanpierre Bob Ippolito @@ -137,9 +137,10 @@ Jean-Philippe St. Pierre Guido van Rossum Pavel Vinogradov + Stian Andreassen + Julian Berman William Leslie Paweł Piotr Przeradowski - Stian Andreassen marky1991 Ilya Osadchiy Tobias Oberstein @@ -150,7 +151,7 @@ tav Georg Brandl Joannah Nanjekye - Julian Berman + Yannick Jadoul Bert Freudenberg Wanja Saatkamp Mike Blume @@ -275,6 +276,7 @@ Lutz Paelike Ian Foote Philipp Rustemeuer + Bernd Schoeller Logan Chien Catalin Gabriel Manciu Jacob Oscarson @@ -302,7 +304,6 @@ Laurens Van Houtven Bobby Impollonia Roberto De Ioris - Yannick Jadoul Jeong YunWon Christopher Armstrong Aaron Tubbs @@ -357,6 +358,7 @@ Daniil Yarancev Min RK OlivierBlanvillain + bernd.schoel...@inf.ethz.ch dakar...@gmail.com Jonas Pfannschmidt Zearin @@ -398,6 +400,7 @@ Jesdi Konrad Delong Dinu Gherman + Sam Edwards pizi Tomáš Pružina James Robert diff --git a/pypy/doc/conf.py b/pypy/doc/conf.py --- a/pypy/doc/conf.py +++ b/pypy/doc/conf.py @@ -73,7 +73,7 @@ # The short X.Y version. version = '7.3' # The full version, including alpha/beta/rc tags. -release = '7.3.0' +release = '7.3.1' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/pypy/doc/contributor.rst b/pypy/doc/contributor.rst --- a/pypy/doc/contributor.rst +++ b/pypy/doc/contributor.rst @@ -65,16 +65,16 @@ Spenser Bauman Michal Bendowski Jan de Mooij + Stefano Rivera Tyler Wade + Stefan Beyer Vincent Legoll Michael Foord Stephan Diehl - Stefano Rivera Jean-Paul Calderone Stefan Schwarzer Tomek Meka Valentino Volonghi - Stefan Beyer Patrick Maupin Devin Jeanpierre Bob Ippolito @@ -103,9 +103,10 @@ Jean-Philippe St. Pierre Guido van Rossum Pavel Vinogradov + Stian Andreassen + Julian Berman William Leslie Paweł Piotr Przeradowski - Stian Andreassen marky1991 Ilya Osadchiy Tobias Oberstein @@ -116,7 +117,7 @@ tav Georg Brandl Joannah Nanjekye - Julian Berman + Yannick Jadoul Bert Freudenberg Wanja Saatkamp Mike Blume @@ -241,6 +242,7 @@ Lutz Paelike Ian Foote Philipp Rustemeuer + Bernd Schoeller Logan Chien Catalin Gabriel Manciu Jacob Oscarson @@ -253,7 +255,6 @@ Lene Wagner Tomo Cocoa Miro Hrončok - Anthony Sottile David Lievens Neil Blakey-Milner Henrik Vendelbo @@ -269,7 +270,6 @@ Laurens Van Houtven Bobby Impollonia Roberto De Ioris - Yannick Jadoul Jeong YunWon Christopher Armstrong Aaron Tubbs @@ -324,6 +324,7 @@ Daniil Yarancev Min RK OlivierBlanvillain + bernd.schoel...@inf.ethz.ch dakar...@gmail.com Jonas Pfannschmidt Zearin @@ -365,6 +366,7 @@ Jesdi Konrad Delong Dinu Gherman + Sam Edwards pizi Tomáš Pružina James Robert 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-v7.3.0.rst release-v7.2.0.rst release-v7.1.1.rst release-v7.1.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-pypy2-7.3.0.rst whatsnew-pypy2-7.2.0.rst whatsnew-pypy2-7.1.0.rst whatsnew-pypy2-7.0.0.rst @@ -43,6 +44,7 @@ .. toctree:: whatsnew-pypy3-head.rst + whatsnew-pypy3-7.3.0.rst whatsnew-pypy3-7.2.0.rst whatsnew-pypy3-7.1.0.rst diff --git a/pypy/doc/release-v7.3.0.rst b/pypy/doc/release-v7.3.0.rst new file mode 100644 --- /dev/null +++ b/pypy/doc/release-v7.3.0.rst @@ -0,0 +1,213 @@ +==================================== +PyPy v7.3.0: release of 2.7, and 3.6 +==================================== + +The PyPy team is proud to release the version 7.3.0 of PyPy, which includes +two different interpreters: + + - PyPy2.7, which is an interpreter supporting the syntax and the features of + Python 2.7 including the stdlib for CPython 2.7.13 + + - PyPy3.6: which is an interpreter supporting the syntax and the features of + Python 3.6, including the stdlib for CPython 3.6.9. + +The interpreters are based on much the same codebase, thus the double +release. + +We have worked with the python packaging group to support tooling around +building third party packages for python, so this release changes the ABI tag +for PyPy. + +The `CFFI`_ backend has been updated to version 1.13.1. We recommend using CFFI +rather than c-extensions to interact with C. + +The built-in ``_cppyy`` module was upgraded to 1.10.6, which +provides, among others, better template resolution, stricter ``enum`` handling, +anonymous struct/unions, cmake fragments for distribution, optimizations for +PODs, and faster wrapper calls. We reccomend using cppyy_ for performant +wrapping of C++ code for Python. + +The vendored pyrepl package for interaction inside the REPL was updated. + +Support for codepage encoding and decoding was added for Windows. + +As always, this release fixed several issues and bugs raised by the growing +community of PyPy users. We strongly recommend updating. Many of the fixes are +the direct result of end-user bug reports, so please continue reporting issues +as they crop up. + +You can download the v7.3 releases here: + + http://pypy.org/download.html + +We would like to thank our donors for the continued support of the PyPy +project. If PyPy is not quite good enough for your needs, we are available for +direct consulting work. + +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. Since the +previous release, we have accepted contributions from 3 new contributors, +thanks for pitching in. + +.. _`PyPy`: index.html +.. _`RPython`: https://rpython.readthedocs.org +.. _`help`: project-ideas.html +.. _`CFFI`: http://cffi.readthedocs.io +.. _`cppyy`: https://cppyy.readthedocs.io +.. _`available as wheels`: https://github.com/antocuni/pypy-wheels + +What is PyPy? +============= + +PyPy is a very compliant Python interpreter, almost a drop-in replacement for +CPython 2.7, 3.6. 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 PyPy release supports: + + * **x86** machines on most common operating systems + (Linux 32/64 bits, Mac OS X 64 bits, Windows 32 bits, OpenBSD, FreeBSD) + + * big- and little-endian variants of **PPC64** running Linux, + + * **s390x** running Linux + + * 64-bit **ARM** machines running Linux. + +Unfortunately at the moment of writing our ARM buildbots are out of service, +so for now we are **not** releasing any binary for the ARM architecture (32 +bit), although PyPy does support ARM 32 bit processors. + +.. _`PyPy and CPython 2.7.x`: http://speed.pypy.org +.. _`dynamic languages`: http://rpython.readthedocs.io/en/latest/examples.html + + +Changelog +========= + +Changes shared across versions +------------------------------ + +* Fix segfault when calling descr-methods with no arguments +* Change the SOABI and subsequently change the reported ABI tag. +* Update the builtin ``_cppyy`` backend to 1.10.6 +* Performance improvements in string/unicode handling +* Fix compilation error when building `revdb`_ (`issue 3084`_, actually + released in PyPy 7.2 but not mentioned in the release notes) +* Add JIT options to documentation and an option for JIT help via ``pypy --jit + help`` +* Fix regex escapes in pyrepl (`issue 3097`_) +* Allow reloading of subclasses of module (`issue 3099`_) +* Work around a gcc bug, which was reported to them and fixed (`issue 3086`_) +* Fix (again) faulty logic when decoding invalid UTF-8 (`issue 2389`_) +* Fix up LICENSE file +* Turn all ``http`` links in the documentation to ``https`` +* Update the bndled pip and setuptools (used in ``pypy -mensurepip`` to version + that support `manylinux2010`_ wheels +* Link the ``DEFAULT_SOABI`` to the ``PYPY_VERSION`` +* Workaround for programs calling ``sys.setrecursionlimit(huge_value)`` (`issue + 3094`_) +* Set minimal ``MACOSX_DEPLOYMENT_TARGET`` to 10.7 on macOS; cpython uses 10.5 +* Fix a JIT bug causing rare register corruption on aarch64 +* Add discovery of ``ncursesw`` when building ``_minimal_curses`` and improve + handling of old curses versions (`issue 2970`_) +* Improve the error message for ``class X(random_object)`` (`issue 3109`_) +* Deal with json dicts containing repeated keys in the new map based parser + (`issue 3108`_) +* Port parts of the `portable pypy`_ repackaging scripts to add an option for + ``RPATH`` manipulation on linux +* Check for overflow in ctypes array creation +* Better support and report MSVC versions used to compile on windows +* Allow any kind of buffer in socket.setsockopt(), like CPython (`issue 3114`_) + +C-API (cpyext) and c-extensions +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +* Add ``_PySet_Next``, ``_PySet_NextEntry`` +* Correctly swallow exceptions happening inside ``PyDict_GetItem()`` (`issue + 3098`_) +* Respect tp_dict on PyType_Ready (`issue XXX`_) +* Allow calling ``PyType_Ready`` on a subclass with a partially built + ``tp_base`` (issue 3117`_) +* Rename ``tuple_new`` to ``_PyPy_tuple_new`` to follow the naming convention of + exported symbols in ``libpypy-c.so`` +* Actually restore the traceback in ``PyErr_Restore`` (`issue 3120`_) + +Python 3.6 only +--------------- + +* Don't grow the ``lzma.decompress()`` buffer past ``max_length`` (`issue 3088`_) +* Backport fix from CPython for failure of ``lzma`` to decompress a file + (`issue 3090`_) +* Fix ``asyncgen_hooks`` and refactor ``coroutine execution`` +* Fix range checking in GB18030 decoder (CPython issue `29990`_) +* Fix handling escape characters in HZ codec (CPython issue `30003`_) +* Reject null characters in a few more functions (CPython issue `13617`_) +* Fix build on macOS without ``clock_gettime`` (before 10.12 and xcode 8, + released 2016) +* Backport 3.7.5 changes to ``timedelta.__eq__`` and ``time.__eq__`` (CPython + issue `37579`_) +* Backport more fixes to comparisons in ``datetime.py`` (CPython issue `37985`_) +* Use the python tag in ``pyc`` file names, not the abi tag +* Handle string formatting with a single ``[`` in the format string (`issue + 3100`_) +* Backport some of the patches in `macports pypy`_ +* Add missing ``HAVE_FACCESSAT`` to ``posix._have_functions`` +* Update pyrepl from upstream package (`issue 2971`_) +* Fix ``PyFrame._guess_function_name_parens()`` +* Fix range of allowed years in ``time.mktime`` to match CPython `13312`_ +* Generators need to store the old current ``exc_info`` in a place that is + visible, because in one corner case a call to ``sys.exc_info()`` might need + it. (`issue 3096`_) +* Remove incorrect clobbering of the ``locals`` after running ``exec()`` +* Adds encoding, decoding codepages on win32 + +Python 3.6 C-API +~~~~~~~~~~~~~~~~ + +* Add ``PyObject_GenericGetDict``, ``PyObject_GenericSetDict``, ``_Py_strhex``, + ``_Py_strhex_bytes``, ``PyUnicodeNew``, ``_PyFinalizing``, + ``PySlice_Unpack``, ``PySlice_AdjustIndices`` +* Implement ``pystrhex.h`` (`issue 2687`_) +* Make ``PyUnicodeObject`` slightly more compact +* Fix memory leak when releasing a ``PyUnicodeObject`` + +.. _`revdb`: fix broken link +.. _`portable pypy`: fix broken link +.. _`manylinux2010`: fix broken link +.. _`macports pypy`: https://github.com/macports/macports-ports/blob/master/lang/pypy/files/darwin.py.diff + +.. _`issue 2389`: https://bitbucket.com/pypy/pypy/issues/2389 +.. _`issue 2687`: https://bitbucket.com/pypy/pypy/issues/2687 +.. _`issue 2970`: https://bitbucket.com/pypy/pypy/issues/2970 +.. _`issue 2971`: https://bitbucket.com/pypy/pypy/issues/2971 +.. _`issue 3084`: https://bitbucket.com/pypy/pypy/issues/3084 +.. _`issue 3086`: https://bitbucket.com/pypy/pypy/issues/3086 +.. _`issue 3088`: https://bitbucket.com/pypy/pypy/issues/3088 +.. _`issue 3090`: https://bitbucket.com/pypy/pypy/issues/3090 +.. _`issue 3094`: https://bitbucket.com/pypy/pypy/issues/3094 +.. _`issue 3096`: https://bitbucket.com/pypy/pypy/issues/3096 +.. _`issue 3097`: https://bitbucket.com/pypy/pypy/issues/3097 +.. _`issue 3098`: https://bitbucket.com/pypy/pypy/issues/3098 +.. _`issue 3099`: https://bitbucket.com/pypy/pypy/issues/3099 +.. _`issue 3100`: https://bitbucket.com/pypy/pypy/issues/3100 +.. _`issue 3108`: https://bitbucket.com/pypy/pypy/issues/3108 +.. _`issue 3109`: https://bitbucket.com/pypy/pypy/issues/3109 +.. _`issue 3114`: https://bitbucket.com/pypy/pypy/issues/3114 +.. _`issue 3117`: https://bitbucket.com/pypy/pypy/issues/3117 +.. _`issue 3120`: https://bitbucket.com/pypy/pypy/issues/3120 + +.. _13312: https://bugs.python.org/issue13312 +.. _13617: https://bugs.python.org/issue13617 +.. _29990: https://bugs.python.org/issue29990 +.. _30003: https://bugs.python.org/issue30003 +.. _37579: https://bugs.python.org/issue37579 +.. _37985: https://bugs.python.org/issue37985 +.. _37985: https://bugs.python.org/issue37985 + + 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,22 +1,8 @@ -========================== -What's new in PyPy2.7 7.3+ -========================== +============================ +What's new in PyPy2.7 7.3.0+ +============================ -.. this is a revision shortly after release-pypy-7.2.0 -.. startrev: a511d86377d6 +.. this is a revision shortly after release-pypy-7.3.0 +.. startrev: dbbbae99135f -.. branch: fix-descrmismatch-crash -Fix segfault when calling descr-methods with no arguments - -.. branch: https-readme - -Convert http -> https in README.rst - -.. branch: license-update - -Update list directories in LICENSE - -.. branch: allow-forcing-no-embed - -When packaging, allow suppressing embedded dependencies via PYPY_NO_EMBED_DEPENDENCIES diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-pypy2-7.3.0.rst copy from pypy/doc/whatsnew-head.rst copy to pypy/doc/whatsnew-pypy2-7.3.0.rst --- a/pypy/doc/whatsnew-head.rst +++ b/pypy/doc/whatsnew-pypy2-7.3.0.rst @@ -1,6 +1,6 @@ -========================== -What's new in PyPy2.7 7.3+ -========================== +=========================== +What's new in PyPy2.7 7.3.0 +=========================== .. this is a revision shortly after release-pypy-7.2.0 .. startrev: a511d86377d6 @@ -19,4 +19,15 @@ .. branch: allow-forcing-no-embed -When packaging, allow suppressing embedded dependencies via PYPY_NO_EMBED_DEPENDENCIES +When packaging, allow suppressing embedded dependencies via +PYPY_NO_EMBED_DEPENDENCIES + +.. branch: int-test-is-zero + +.. branch: cppyy-dev + +Upgraded the built-in ``_cppyy`` module to ``cppyy-backend 1.10.6``, which +provides, among others, better template resolution, stricter ``enum`` handling, +anonymous struct/unions, cmake fragments for distribution, optimizations for +PODs, and faster wrapper calls. + diff --git a/pypy/doc/whatsnew-pypy3-head.rst b/pypy/doc/whatsnew-pypy3-7.3.0.rst copy from pypy/doc/whatsnew-pypy3-head.rst copy to pypy/doc/whatsnew-pypy3-7.3.0.rst --- a/pypy/doc/whatsnew-pypy3-head.rst +++ b/pypy/doc/whatsnew-pypy3-7.3.0.rst @@ -1,6 +1,6 @@ -======================== -What's new in PyPy3 7.2+ -======================== +========================= +What's new in PyPy3 7.3.0 +========================= .. this is the revision after release-pypy3.6-v7.2 .. startrev: 6d2f8470165b diff --git a/pypy/doc/whatsnew-pypy3-head.rst b/pypy/doc/whatsnew-pypy3-head.rst --- a/pypy/doc/whatsnew-pypy3-head.rst +++ b/pypy/doc/whatsnew-pypy3-head.rst @@ -1,9 +1,9 @@ -======================== -What's new in PyPy3 7.2+ -======================== +========================== +What's new in PyPy3 7.3.0+ +========================== -.. this is the revision after release-pypy3.6-v7.2 -.. startrev: 6d2f8470165b +.. this is the revision after release-pypy3.6-v7.3.0 +.. startrev: 78b4d0a7cf2e .. branch: py3.6-asyncgen diff --git a/pypy/module/_cppyy/capi/loadable_capi.py b/pypy/module/_cppyy/capi/loadable_capi.py --- a/pypy/module/_cppyy/capi/loadable_capi.py +++ b/pypy/module/_cppyy/capi/loadable_capi.py @@ -1,4 +1,4 @@ -import os +import os, sys from rpython.rtyper.lltypesystem import rffi, lltype from rpython.rlib.rarithmetic import intmask @@ -20,17 +20,20 @@ from pypy.module._cppyy.capi.capi_types import C_SCOPE, C_TYPE, C_OBJECT,\ C_METHOD, C_INDEX, C_INDEX_ARRAY, WLAVC_INDEX, C_FUNC_PTR - -backend_library = 'libcppyy_backend.so' +backend_ext = '.so' +if 'win32' in sys.platform: + backend_ext = '.dll' +backend_library = 'libcppyy_backend' # this is not technically correct, but will do for now -std_string_name = 'std::basic_string<char>' +std_string_name = 'std::string' class _Arg: # poor man's union _immutable_ = True - def __init__(self, tc, h = 0, l = -1, d = -1., s = '', p = rffi.cast(rffi.VOIDP, 0)): + def __init__(self, tc, h = 0, u = 0, l = -1, d = -1., s = '', p = rffi.cast(rffi.VOIDP, 0)): self.tc = tc self._handle = h + self._index = u self._long = l self._double = d self._string = s @@ -41,6 +44,11 @@ def __init__(self, val): _Arg.__init__(self, 'h', h = val) +class _ArgU(_Arg): # separate class for rtyper + _immutable_ = True + def __init__(self, val): + _Arg.__init__(self, 'u', u = val) + class _ArgL(_Arg): _immutable_ = True def __init__(self, val): @@ -95,7 +103,10 @@ misc.write_raw_signed_data(data, rffi.cast(rffi.LONG, obj._long), argtype.size) elif obj.tc == 'h': assert isinstance(argtype, ctypeprim.W_CTypePrimitiveUnsigned) - misc.write_raw_unsigned_data(data, rffi.cast(rffi.ULONG, obj._handle), argtype.size) + misc.write_raw_unsigned_data(data, rffi.cast(rffi.UINTPTR_T, obj._handle), argtype.size) + elif obj.tc == 'u': + assert isinstance(argtype, ctypeprim.W_CTypePrimitiveUnsigned) + misc.write_raw_unsigned_data(data, rffi.cast(rffi.SIZE_T, obj._index), argtype.size) elif obj.tc == 'p': assert obj._voidp != rffi.cast(rffi.VOIDP, 0) data = rffi.cast(rffi.VOIDPP, data) @@ -142,13 +153,17 @@ # TODO: the following need to match up with the globally defined C_XYZ low-level # types (see capi/__init__.py), but by using strings here, that isn't guaranteed - c_opaque_ptr = state.c_ulong # not ptrdiff_t (which is signed) + c_opaque_ptr = state.c_uintptr_t # not size_t (which is signed) + c_size_t = state.c_size_t + c_ptrdiff_t = state.c_ptrdiff_t + c_intptr_t = state.c_intptr_t + c_uintptr_t = state.c_uintptr_t c_scope = c_opaque_ptr c_type = c_scope - c_object = c_opaque_ptr # not voidp (to stick with one handle type) - c_method = c_opaque_ptr - c_index = state.c_long + c_object = c_opaque_ptr # not voidp (to stick with one handle type) + c_method = c_uintptr_t # not intptr_t (which is signed) + c_index = c_size_t c_index_array = state.c_voidp c_void = state.c_void @@ -166,10 +181,10 @@ c_ccharp = state.c_ccharp c_voidp = state.c_voidp - c_size_t = nt.new_primitive_type(space, 'size_t') - c_ptrdiff_t = nt.new_primitive_type(space, 'ptrdiff_t') + self.capi_call_ifaces = { + # direct interpreter access + 'compile' : ([c_ccharp], c_int), - self.capi_call_ifaces = { # name to opaque C++ scope representation 'resolve_name' : ([c_ccharp], c_ccharp), 'resolve_enum' : ([c_ccharp], c_ccharp), @@ -221,12 +236,17 @@ 'get_all_cpp_names' : ([c_scope, c_voidp], c_voidp), # const char** + # namespace reflection information + 'get_using_namespaces' : ([c_scope], c_index), + # type/class reflection information 'final_name' : ([c_type], c_ccharp), 'scoped_final_name' : ([c_type], c_ccharp), + 'has_virtual_destructor' : ([c_type], c_int), 'has_complex_hierarchy' : ([c_type], c_int), 'num_bases' : ([c_type], c_int), 'base_name' : ([c_type, c_int], c_ccharp), + 'is_smartptr' : ([c_type], c_int), 'is_subtype' : ([c_type, c_type], c_int), 'smartptr_info' : ([c_ccharp, c_voidp, c_voidp], c_int), 'add_smartptr_type' : ([c_ccharp], c_void), @@ -245,9 +265,11 @@ 'method_result_type' : ([c_method], c_ccharp), 'method_num_args' : ([c_method], c_int), 'method_req_args' : ([c_method], c_int), + 'method_arg_name' : ([c_method, c_int], c_ccharp), 'method_arg_type' : ([c_method, c_int], c_ccharp), 'method_arg_default' : ([c_method, c_int], c_ccharp), 'method_signature' : ([c_method, c_int], c_ccharp), + 'method_signature_max' : ([c_method, c_int, c_int], c_ccharp), 'method_prototype' : ([c_scope, c_method, c_int], c_ccharp), 'is_const_method' : ([c_method], c_int), @@ -269,7 +291,7 @@ 'num_datamembers' : ([c_scope], c_int), 'datamember_name' : ([c_scope, c_int], c_ccharp), 'datamember_type' : ([c_scope, c_int], c_ccharp), - 'datamember_offset' : ([c_scope, c_int], c_ptrdiff_t), + 'datamember_offset' : ([c_scope, c_int], c_intptr_t), 'datamember_index' : ([c_scope, c_ccharp], c_int), # data member properties @@ -311,7 +333,15 @@ state.backend = W_Library(space, space.newtext(libname), dldflags) else: # try usual lookups - state.backend = W_Library(space, space.newtext(backend_library), dldflags) + try: + if backend_library[-len(backend_ext):] == backend_ext: + fullname = backend_library + else: + fullname = backend_library+backend_ext + state.backend = W_Library(space, space.newtext(fullname), dldflags) + except Exception as e: + # TODO: where to find the value '.pypy-41'? Note that this only matters for testing. + state.backend = W_Library(space, space.newtext(backend_library+'.pypy-41'+backend_ext), dldflags) if state.backend: # fix constants @@ -354,7 +384,10 @@ return rffi.cast(rffi.SIZE_T, space.uint_w(w_cdata)) def _cdata_to_ptrdiff_t(space, w_cdata): - return rffi.cast(rffi.LONG, space.int_w(w_cdata)) + return rffi.cast(rffi.PTRDIFF_T, space.int_w(w_cdata)) + +def _cdata_to_intptr_t(space, w_cdata): + return rffi.cast(rffi.INTPTR_T, space.int_w(w_cdata)) def _cdata_to_ptr(space, w_cdata): # TODO: this is both a hack and dreadfully slow w_cdata = space.interp_w(cdataobj.W_CData, w_cdata, can_be_None=False) @@ -365,6 +398,10 @@ ptr = _cdata_to_ptr(space, w_cdata) # see above ... something better? return rffi.cast(rffi.CCHARP, ptr) +# direct interpreter access +def c_compile(space, code): + return space.int_w(call_capi(space, 'compile', [_ArgS(code)])) + # name to opaque C++ scope representation ------------------------------------ def c_resolve_name(space, name): return charp2str_free(space, call_capi(space, 'resolve_name', [_ArgS(name)])) @@ -488,11 +525,17 @@ c_free(space, rffi.cast(rffi.VOIDP, rawnames)) # id. return allnames +# namespace reflection information +def c_get_using_namespaces(space, cppscope): + return space.uint_w(call_capi(space, 'get_using_namespaces', [_ArgH(cppscope)])) + # type/class reflection information ------------------------------------------ def c_final_name(space, cpptype): return charp2str_free(space, call_capi(space, 'final_name', [_ArgH(cpptype)])) def c_scoped_final_name(space, cpptype): return charp2str_free(space, call_capi(space, 'scoped_final_name', [_ArgH(cpptype)])) +def c_has_virtual_destructor(space, handle): + return space.bool_w(call_capi(space, 'has_virtual_destructor', [_ArgH(handle)])) def c_has_complex_hierarchy(space, handle): return space.bool_w(call_capi(space, 'has_complex_hierarchy', [_ArgH(handle)])) def c_num_bases(space, cppclass): @@ -500,6 +543,8 @@ def c_base_name(space, cppclass, base_index): args = [_ArgH(cppclass.handle), _ArgL(base_index)] return charp2str_free(space, call_capi(space, 'base_name', args)) +def c_is_smartptr(space, handle): + return space.bool_w(call_capi(space, 'is_smartptr', [_ArgH(handle)])) def c_is_subtype(space, derived, base): jit.promote(base) if derived == base: @@ -552,7 +597,7 @@ return py_indices def c_get_method(space, cppscope, index): - args = [_ArgH(cppscope.handle), _ArgL(index)] + args = [_ArgH(cppscope.handle), _ArgU(index)] return rffi.cast(C_METHOD, space.uint_w(call_capi(space, 'get_method', args))) def c_method_name(space, cppmeth): @@ -567,6 +612,9 @@ return space.int_w(call_capi(space, 'method_num_args', [_ArgH(cppmeth)])) def c_method_req_args(space, cppmeth): return space.int_w(call_capi(space, 'method_req_args', [_ArgH(cppmeth)])) +def c_method_arg_name(space, cppmeth, arg_index): + args = [_ArgH(cppmeth), _ArgL(arg_index)] + return charp2str_free(space, call_capi(space, 'method_arg_name', args)) def c_method_arg_type(space, cppmeth, arg_index): args = [_ArgH(cppmeth), _ArgL(arg_index)] return charp2str_free(space, call_capi(space, 'method_arg_type', args)) @@ -576,6 +624,9 @@ def c_method_signature(space, cppmeth, show_formalargs=True): args = [_ArgH(cppmeth), _ArgL(show_formalargs)] return charp2str_free(space, call_capi(space, 'method_signature', args)) +def c_method_signature_max(space, cppmeth, show_formalargs, maxargs): + args = [_ArgH(cppmeth), _ArgL(show_formalargs), _ArgL(maxargs)] + return charp2str_free(space, call_capi(space, 'method_signature_max', args)) def c_method_prototype(space, cppscope, cppmeth, show_formalargs=True): args = [_ArgH(cppscope.handle), _ArgH(cppmeth), _ArgL(show_formalargs)] return charp2str_free(space, call_capi(space, 'method_prototype', args)) @@ -583,24 +634,24 @@ return space.bool_w(call_capi(space, 'is_const_method', [_ArgH(cppmeth)])) def c_get_num_templated_methods(space, cppscope): - return space.int_w(call_capi(space, 'method_is_template', [_ArgH(cppscope.handle)])) + return space.int_w(call_capi(space, 'get_num_templated_methods', [_ArgH(cppscope.handle)])) def c_get_templated_method_name(space, cppscope, index): - args = [_ArgH(cppscope.handle), _ArgL(index)] - return charp2str_free(space, call_capi(space, 'method_is_template', args)) + args = [_ArgH(cppscope.handle), _ArgU(index)] + return charp2str_free(space, call_capi(space, 'get_templated_method_name', args)) def c_exists_method_template(space, cppscope, name): args = [_ArgH(cppscope.handle), _ArgS(name)] return space.bool_w(call_capi(space, 'exists_method_template', args)) def c_method_is_template(space, cppscope, index): - args = [_ArgH(cppscope.handle), _ArgL(index)] + args = [_ArgH(cppscope.handle), _ArgU(index)] return space.bool_w(call_capi(space, 'method_is_template', args)) def c_get_method_template(space, cppscope, name, proto): args = [_ArgH(cppscope.handle), _ArgS(name), _ArgS(proto)] - return rffi.cast(C_METHOD, space.uint_w(call_capi(space, 'get_method_template', args))) + return rffi.cast(C_METHOD, space.int_w(call_capi(space, 'get_method_template', args))) def c_get_global_operator(space, nss, lc, rc, op): if nss is not None: args = [_ArgH(nss.handle), _ArgH(lc.handle), _ArgH(rc.handle), _ArgS(op)] - return rffi.cast(WLAVC_INDEX, space.int_w(call_capi(space, 'get_global_operator', args))) + return rffi.cast(WLAVC_INDEX, space.uint_w(call_capi(space, 'get_global_operator', args))) return rffi.cast(WLAVC_INDEX, -1) # method properties ---------------------------------------------------------- @@ -624,7 +675,7 @@ return charp2str_free(space, call_capi(space, 'datamember_type', args)) def c_datamember_offset(space, cppscope, datamember_index): args = [_ArgH(cppscope.handle), _ArgL(datamember_index)] - return _cdata_to_ptrdiff_t(space, call_capi(space, 'datamember_offset', args)) + return _cdata_to_intptr_t(space, call_capi(space, 'datamember_offset', args)) def c_datamember_index(space, cppscope, name): args = [_ArgH(cppscope.handle), _ArgS(name)] 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 @@ -993,7 +993,7 @@ _converters["void*&"] = VoidPtrRefConverter # special cases (note: 'string' aliases added below) -_converters["std::basic_string<char>"] = StdStringConverter +_converters["std::string"] = StdStringConverter _converters["const std::basic_string<char>&"] = StdStringConverter # TODO: shouldn't copy _converters["std::basic_string<char>&"] = StdStringRefConverter _converters["std::basic_string<char>&&"] = StdStringMoveConverter @@ -1126,7 +1126,8 @@ ("char", "signed char"), # TODO: check ("const char*", "char*"), - ("std::basic_string<char>", "string"), + ("std::string", "string"), + ("std::string", "std::basic_string<char>"), ("const std::basic_string<char>&", "const string&"), ("std::basic_string<char>&", "string&"), ("std::basic_string<char>&&", "string&&"), 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 @@ -388,7 +388,7 @@ # special cases (note: 'string' aliases added below) _executors["constructor"] = ConstructorExecutor -_executors["std::basic_string<char>"] = StdStringExecutor +_executors["std::string"] = StdStringExecutor _executors["const std::basic_string<char>&"] = StdStringRefExecutor _executors["std::basic_string<char>&"] = StdStringRefExecutor @@ -457,7 +457,8 @@ aliases = ( ("const char*", "char*"), - ("std::basic_string<char>", "string"), + ("std::string", "string"), + ("std::string", "std::basic_string<char>"), ("const std::basic_string<char>&", "const string&"), ("std::basic_string<char>&", "string&"), diff --git a/pypy/module/_cppyy/ffitypes.py b/pypy/module/_cppyy/ffitypes.py --- a/pypy/module/_cppyy/ffitypes.py +++ b/pypy/module/_cppyy/ffitypes.py @@ -38,6 +38,8 @@ # special types self.c_size_t = nt.new_primitive_type(space, 'size_t') self.c_ptrdiff_t = nt.new_primitive_type(space, 'ptrdiff_t') + self.c_intptr_t = nt.new_primitive_type(space, 'intptr_t') + self.c_uintptr_t = nt.new_primitive_type(space, 'uintptr_t') class BoolTypeMixin(object): _mixin_ = True diff --git a/pypy/module/_cppyy/include/capi.h b/pypy/module/_cppyy/include/capi.h --- a/pypy/module/_cppyy/include/capi.h +++ b/pypy/module/_cppyy/include/capi.h @@ -2,22 +2,26 @@ #define CPPYY_CAPI #include <stddef.h> +#include <stdint.h> #include "src/precommondefs.h" #ifdef __cplusplus extern "C" { #endif // ifdef __cplusplus - typedef ptrdiff_t cppyy_scope_t; + typedef size_t cppyy_scope_t; typedef cppyy_scope_t cppyy_type_t; typedef void* cppyy_object_t; - typedef ptrdiff_t cppyy_method_t; + typedef intptr_t cppyy_method_t; - typedef long cppyy_index_t; + typedef size_t cppyy_index_t; typedef void* cppyy_funcaddr_t; typedef unsigned long cppyy_exctype_t; + /* direct interpreter access ---------------------------------------------- */ + int cppyy_compile(const char* code); + /* name to opaque C++ scope representation -------------------------------- */ RPY_EXTERN char* cppyy_resolve_name(const char* cppitem_name); @@ -103,12 +107,17 @@ RPY_EXTERN const char** cppyy_get_all_cpp_names(cppyy_scope_t scope, size_t* count); + /* namespace reflection information --------------------------------------- */ + cppyy_index_t* cppyy_get_using_namespaces(cppyy_scope_t scope); + /* class reflection information ------------------------------------------- */ RPY_EXTERN char* cppyy_final_name(cppyy_type_t type); RPY_EXTERN char* cppyy_scoped_final_name(cppyy_type_t type); RPY_EXTERN + int cppyy_has_virtual_destructor(cppyy_type_t type); + RPY_EXTERN int cppyy_has_complex_hierarchy(cppyy_type_t type); RPY_EXTERN int cppyy_num_bases(cppyy_type_t type); @@ -117,6 +126,8 @@ RPY_EXTERN int cppyy_is_subtype(cppyy_type_t derived, cppyy_type_t base); RPY_EXTERN + int cppyy_is_smartptr(cppyy_type_t type); + RPY_EXTERN int cppyy_smartptr_info(const char* name, cppyy_type_t* raw, cppyy_method_t* deref); RPY_EXTERN void cppyy_add_smartptr_type(const char* type_name); @@ -147,20 +158,24 @@ RPY_EXTERN int cppyy_method_req_args(cppyy_method_t); RPY_EXTERN + char* cppyy_method_arg_name(cppyy_method_t,int arg_index); + RPY_EXTERN char* cppyy_method_arg_type(cppyy_method_t, int arg_index); RPY_EXTERN char* cppyy_method_arg_default(cppyy_method_t, int arg_index); RPY_EXTERN char* cppyy_method_signature(cppyy_method_t, int show_formalargs); RPY_EXTERN + char* cppyy_method_signature_max(cppyy_method_t, int show_formalargs, int maxargs); + RPY_EXTERN char* cppyy_method_prototype(cppyy_scope_t scope, cppyy_method_t, int show_formalargs); RPY_EXTERN int cppyy_is_const_method(cppyy_method_t); RPY_EXTERN - int get_num_templated_methods(cppyy_scope_t scope); + int cppyy_get_num_templated_methods(cppyy_scope_t scope); RPY_EXTERN - char* get_templated_method_name(cppyy_scope_t scope, cppyy_index_t imeth); + char* cppyy_get_templated_method_name(cppyy_scope_t scope, cppyy_index_t imeth); RPY_EXTERN int cppyy_exists_method_template(cppyy_scope_t scope, const char* name); RPY_EXTERN @@ -190,7 +205,7 @@ RPY_EXTERN char* cppyy_datamember_type(cppyy_scope_t scope, int datamember_index); RPY_EXTERN - ptrdiff_t cppyy_datamember_offset(cppyy_scope_t scope, int datamember_index); + intptr_t cppyy_datamember_offset(cppyy_scope_t scope, int datamember_index); RPY_EXTERN int cppyy_datamember_index(cppyy_scope_t scope, const char* name); 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 @@ -978,8 +978,8 @@ ) class W_CPPTemplateStaticOverload(W_CPPStaticOverload, TemplateOverloadMixin): - """App-level dispatcher to allow both lookup/instantiation of templated methods and - dispatch among overloads between templated and non-templated method.""" + """Dispatcher to allow both lookup/instantiation of templated methods and + select among templated and non-templated method overloads.""" _attrs_ = ['name', 'tmpl_args', 'overloads', 'master', 'w_this'] _immutable_fields_ = ['name', 'tmpl_args'] @@ -993,7 +993,8 @@ self.w_this = space.w_None def clone(self, tmpl_args): - other = W_CPPTemplateStaticOverload(self.space, self.name, tmpl_args, self.scope, self.functions, self.flags) + other = W_CPPTemplateStaticOverload(self.space, self.name, + tmpl_args, self.scope, self.functions, self.flags) other.overloads = self.overloads other.master = self.master other.w_this = self.w_this @@ -1004,7 +1005,8 @@ if isinstance(w_cppinstance, W_CPPInstance): cppinstance = self.space.interp_w(W_CPPInstance, w_cppinstance) if cppinstance.clsdecl.handle != self.scope.handle: - cppol = W_CPPTemplateStaticOverload(self.space, self.name, self.tmpl_args, self.scope, self.functions, self.flags) + cppol = W_CPPTemplateStaticOverload(self.space, self.name, + self.tmpl_args, self.scope, self.functions, self.flags) cppol.w_this = w_cppinstance cppol.master = self.master return cppol # bound @@ -1253,10 +1255,10 @@ return self.handle != other.handle -# For now, keep namespaces and classes separate as namespaces are extensible +# Namespaces and classes are separate as namespaces are (more) extensible # with info from multiple dictionaries and do not need to bother with meta -# classes for inheritance. Both are python classes, though, and refactoring -# may be in order at some point. +# classes for inheritance. Both are python classes, though, and further +# refactoring may be in order at some point. class W_CPPNamespaceDecl(W_CPPScopeDecl): _attrs_ = ['space', 'handle', 'name', 'overloads', 'datamembers'] _immutable_fields_ = ['handle', 'name'] @@ -1352,6 +1354,8 @@ def _build_overloads(self): assert len(self.overloads) == 0 methods_tmp = {}; ftype_tmp = {} + + # add all ordinary methods (incl. pre-instantiated templates) for idx in range(capi.c_num_methods(self.space, self)): cppmeth = capi.c_get_method(self.space, self, idx) if capi.c_is_constructor(self.space, cppmeth): @@ -1369,6 +1373,7 @@ ftype_tmp[pyname] |= self._make_cppfunction(pyname, cppmeth, methods) if capi.c_method_is_template(self.space, self, idx): ftype_tmp[pyname] |= FUNCTION_IS_TEMPLATE + # the following covers the case where the only kind of operator[](idx) # returns are the ones that produce non-const references; these can be # used for __getitem__ just as much as for __setitem__, though @@ -1404,6 +1409,11 @@ overload = W_CPPOverload(self.space, self, methods[:]) self.overloads[pyname] = overload + # add placeholders for all non-instantiated templated methods + for idx in range(capi.c_get_num_templated_methods(self.space, self)): + cppname = capi.c_get_templated_method_name(self.space, self, idx) + self.overloads[cppname] = W_CPPTemplateOverload(self.space, cppname, None, self, []) + def _make_cppfunction(self, pyname, cppmeth, funcs): num_args = capi.c_method_num_args(self.space, cppmeth) args_required = capi.c_method_req_args(self.space, cppmeth) 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 @@ -439,14 +439,17 @@ # also the fallback on the indexed __getitem__, but that is slower) add_checked_item = False if name.find('std::vector', 0, 11) != 0: - if ('begin' in pyclass.__dict__ and 'end' in pyclass.__dict__): + if 'begin' in pyclass.__dict__ and 'end' in pyclass.__dict__: if _cppyy._scope_byname(name+'::iterator') or \ _cppyy._scope_byname(name+'::const_iterator'): def __iter__(self): i = self.begin() - while i != self.end(): + end = self.size() + count = 0 + while count != end: yield i.__deref__() i.__preinc__() + count += 1 i.__destruct__() raise StopIteration pyclass.__iter__ = __iter__ diff --git a/pypy/module/_cppyy/src/dummy_backend.cxx b/pypy/module/_cppyy/src/dummy_backend.cxx --- a/pypy/module/_cppyy/src/dummy_backend.cxx +++ b/pypy/module/_cppyy/src/dummy_backend.cxx @@ -160,7 +160,7 @@ struct Cppyy_InitPseudoReflectionInfo { Cppyy_InitPseudoReflectionInfo() { // class example01 -- - static long s_scope_id = 0; + static cppyy_scope_t s_scope_id = 0; { // namespace '' s_handles[""] = (cppyy_scope_t)++s_scope_id; @@ -450,14 +450,14 @@ Cppyy_PseudoMethodInfo* idx = (Cppyy_PseudoMethodInfo*)method; if (idx == s_methods["static_example01::staticSetPayload_payload*_double"]) { assert(!self && nargs == 2); - dummy::example01::staticSetPayload((dummy::payload*)(*(long*)&((CPPYY_G__value*)args)[0]), + dummy::example01::staticSetPayload((dummy::payload*)(*(intptr_t*)&((CPPYY_G__value*)args)[0]), ((CPPYY_G__value*)args)[1].obj.d); } else if (idx == s_methods["static_example01::setCount_int"]) { assert(!self && nargs == 1); dummy::example01::setCount(((CPPYY_G__value*)args)[0].obj.in); } else if (idx == s_methods["example01::setPayload_payload*"]) { assert(self && nargs == 1); - ((dummy::example01*)self)->setPayload((dummy::payload*)(*(long*)&((CPPYY_G__value*)args)[0])); + ((dummy::example01*)self)->setPayload((dummy::payload*)(*(intptr_t*)&((CPPYY_G__value*)args)[0])); } else if (idx == s_methods["CppyyTestData::destroy_arrays"]) { assert(self && nargs == 0); ((dummy::CppyyTestData*)self)->destroy_arrays(); @@ -591,11 +591,11 @@ result = dummy::example01::staticAddOneToInt(((CPPYY_G__value*)args)[0].obj.in); } else if (idx == s_methods["static_example01::staticAddOneToInt_int_int"]) { assert(!self && nargs == 2); - result = dummy::example01::staticAddOneToInt( + result = dummy::example01::staticAddOneToInt( ((CPPYY_G__value*)args)[0].obj.in, ((CPPYY_G__value*)args)[1].obj.in); } else if (idx == s_methods["static_example01::staticAtoi_cchar*"]) { assert(!self && nargs == 1); - result = dummy::example01::staticAtoi((const char*)(*(long*)&((CPPYY_G__value*)args)[0])); + result = dummy::example01::staticAtoi((const char*)(*(intptr_t*)&((CPPYY_G__value*)args)[0])); } else if (idx == s_methods["static_example01::getCount"]) { assert(!self && nargs == 0); result = dummy::example01::getCount(); @@ -605,7 +605,7 @@ } else if (idx == s_methods["example01::addDataToAtoi_cchar*"]) { assert(self && nargs == 1); result = ((dummy::example01*)self)->addDataToAtoi( - (const char*)(*(long*)&((CPPYY_G__value*)args)[0])); + (const char*)(*(intptr_t*)&((CPPYY_G__value*)args)[0])); } else if (idx == s_methods["CppyyTestData::get_int"]) { assert(self && nargs == 0); result = ((dummy::CppyyTestData*)self)->get_int(); @@ -621,20 +621,20 @@ if (idx == s_methods["static_example01::staticStrcpy_cchar*"]) { assert(!self && nargs == 1); result = (long)dummy::example01::staticStrcpy( - (const char*)(*(long*)&((CPPYY_G__value*)args)[0])); + (const char*)(*(intptr_t*)&((CPPYY_G__value*)args)[0])); } else if (idx == s_methods["static_example01::staticCyclePayload_payload*_double"]) { assert(!self && nargs == 2); result = (long)dummy::example01::staticCyclePayload( - (dummy::payload*)(*(long*)&((CPPYY_G__value*)args)[0]), + (dummy::payload*)(*(intptr_t*)&((CPPYY_G__value*)args)[0]), ((CPPYY_G__value*)args)[1].obj.d); } else if (idx == s_methods["example01::addToStringValue_cchar*"]) { assert(self && nargs == 1); result = (long)((dummy::example01*)self)->addToStringValue( - (const char*)(*(long*)&((CPPYY_G__value*)args)[0])); + (const char*)(*(intptr_t*)&((CPPYY_G__value*)args)[0])); } else if (idx == s_methods["example01::cyclePayload_payload*"]) { assert(self && nargs == 1); result = (long)((dummy::example01*)self)->cyclePayload( - (dummy::payload*)(*(long*)&((CPPYY_G__value*)args)[0])); + (dummy::payload*)(*(intptr_t*)&((CPPYY_G__value*)args)[0])); } else if (idx == s_methods["CppyyTestData::get_uint"]) { assert(self && nargs == 0); result = (long)((dummy::CppyyTestData*)self)->get_uint(); @@ -731,7 +731,7 @@ } else if (idx == s_methods["CppyyTestData::pass_void_array_l"]) { assert(self && nargs == 1); result = (long)((dummy::CppyyTestData*)self)->pass_void_array_l( - (*(long**)&((CPPYY_G__value*)args)[0])); + (*(intptr_t**)&((CPPYY_G__value*)args)[0])); } else if (idx == s_methods["CppyyTestData::pass_array_ulong"]) { assert(self && nargs == 1); result = (long)((dummy::CppyyTestData*)self)->pass_array( @@ -739,7 +739,7 @@ } else if (idx == s_methods["CppyyTestData::pass_void_array_L"]) { assert(self && nargs == 1); result = (long)((dummy::CppyyTestData*)self)->pass_void_array_L( - (*(unsigned long**)&((CPPYY_G__value*)args)[0])); + (*(uintptr_t**)&((CPPYY_G__value*)args)[0])); } else if (idx == s_methods["CppyyTestData::pass_array_float"]) { assert(self && nargs == 1); result = (long)((dummy::CppyyTestData*)self)->pass_array( @@ -868,7 +868,7 @@ Cppyy_PseudoMethodInfo* idx = (Cppyy_PseudoMethodInfo*)method; if (idx == s_methods["static_example01::staticStrcpy_cchar*"]) { assert(!self && nargs == 1); - result = dummy::example01::staticStrcpy((const char*)(*(long*)&((CPPYY_G__value*)args)[0])); + result = dummy::example01::staticStrcpy((const char*)(*(intptr_t*)&((CPPYY_G__value*)args)[0])); } else { assert(!"method unknown in cppyy_call_s"); } @@ -903,7 +903,8 @@ /* handling of function argument buffer ----------------------------------- */ void* cppyy_allocate_function_args(int nargs) { - CPPYY_G__value* args = (CPPYY_G__value*)malloc(nargs*sizeof(CPPYY_G__value)); + /* nargs parameters + one unsigned long for exception status output */ + CPPYY_G__value* args = (CPPYY_G__value*)malloc(nargs*sizeof(CPPYY_G__value)+sizeof(unsigned long)); for (int i = 0; i < nargs; ++i) args[i].type = 'l'; return (void*)args; @@ -1023,6 +1024,10 @@ return cppstring_to_cstring(""); } +int cppyy_get_num_templated_methods(cppyy_scope_t scope) { + return 0; +} + int cppyy_exists_method_template(cppyy_scope_t scope, const char* name) { return 0; } diff --git a/pypy/module/_cppyy/test/Makefile b/pypy/module/_cppyy/test/Makefile --- a/pypy/module/_cppyy/test/Makefile +++ b/pypy/module/_cppyy/test/Makefile @@ -15,7 +15,7 @@ HASGENREFLEX:=$(shell command -v genreflex 2> /dev/null) -cppflags=-std=c++14 -O3 -fPIC -rdynamic +cppflags=$(shell cling-config --cppflags) -O3 -fPIC -rdynamic ifdef HASGENREFLEX genreflex_flags:=$(shell genreflex --cppflags) cppflags+=$(genreflex_flags) diff --git a/pypy/module/_cppyy/test/templates.cxx b/pypy/module/_cppyy/test/templates.cxx --- a/pypy/module/_cppyy/test/templates.cxx +++ b/pypy/module/_cppyy/test/templates.cxx @@ -10,3 +10,28 @@ long MyTemplatedMethodClass::get_float_size() { return (long)sizeof(float); } long MyTemplatedMethodClass::get_double_size() { return (long)sizeof(double); } long MyTemplatedMethodClass::get_self_size() { return (long)sizeof(MyTemplatedMethodClass); } + + +// variadic templates +#ifdef WIN32 +__declspec(dllexport) +#endif +std::string some_variadic::gTypeName = ""; + + +// template with empty body +namespace T_WithEmptyBody { + +#ifdef WIN32 +__declspec(dllexport) +#endif +std::string side_effect = "not set"; + +template<typename T> +void some_empty() { + side_effect = "side effect"; +} + +template void some_empty<int>(); + +} // namespace T_WithRValue diff --git a/pypy/module/_cppyy/test/templates.h b/pypy/module/_cppyy/test/templates.h --- a/pypy/module/_cppyy/test/templates.h +++ b/pypy/module/_cppyy/test/templates.h @@ -1,12 +1,33 @@ +#ifndef CPPYY_TEST_TEMPLATES_H +#define CPPYY_TEST_TEMPLATES_H + +#include <stdexcept> #include <string> #include <sstream> #include <vector> +#ifndef WIN32 +#include <cxxabi.h> +inline std::string demangle_it(const char* name, const char* errmsg) { + int status; + std::string res = abi::__cxa_demangle(name, 0, 0, &status); + if (status != 0) throw std::runtime_error(errmsg); + return res; +} +#else +inline std::string demangle_it(const char* name, const char*) { + return name; // typeinfo's name() is already demangled +} +#endif + //=========================================================================== class MyTemplatedMethodClass { // template methods public: - long get_size(); // to get around bug in genreflex + template<class A> long get_size(A&); + template<class A> long get_size(const A&); + + long get_size(); template<class B> long get_size(); long get_char_size(); @@ -21,6 +42,16 @@ double m_data[3]; }; +template<class A> +long MyTemplatedMethodClass::get_size(A&) { + return sizeof(A); +} + +template<class A> +long MyTemplatedMethodClass::get_size(const A&) { + return sizeof(A)+1; +} + template<class B> inline long MyTemplatedMethodClass::get_size() { return sizeof(B); @@ -63,7 +94,7 @@ }; template <class I, typename O = float> -SomeResult<O> global_get_some_result(const std::vector<I>& carrier) { +SomeResult<O> global_get_some_result(const I& carrier) { SomeResult<O> r{}; r.m_retval = O(carrier[0]); return r; @@ -156,3 +187,295 @@ T m_value; }; */ + + +//=========================================================================== +// templated callable +class TemplatedCallable { +public: + template <class I , class O = double> + O operator() (const I& in) const { return O(in); } +}; + + +//=========================================================================== +// templated typedefs +namespace TemplatedTypedefs { + +template<typename TYPE_IN, typename TYPE_OUT, size_t _vsize = 4> +struct BaseWithEnumAndTypedefs { + enum { vsize = _vsize }; + typedef TYPE_IN in_type; + typedef TYPE_OUT out_type; +}; + +template <typename TYPE_IN, typename TYPE_OUT, size_t _vsize = 4> +struct DerivedWithUsing : public BaseWithEnumAndTypedefs<TYPE_IN, TYPE_OUT, _vsize> +{ + typedef BaseWithEnumAndTypedefs<TYPE_IN, TYPE_OUT, _vsize> base_type; + using base_type::vsize; + using typename base_type::in_type; + typedef typename base_type::in_type in_type_tt; + using typename base_type::out_type; +}; + +struct SomeDummy {}; + +} // namespace TemplatedTypedefs + + +//=========================================================================== +// hiding templated methods +namespace TemplateHiding { + +struct Base { + template<class T> + int callme(T t = T(1)) { return 2*t; } +}; + +struct Derived : public Base { + int callme(int t = 2) { return t; } +}; + +} // namespace TemplateHiding + + +//=========================================================================== +// 'using' of templates +template<typename T> using DA_vector = std::vector<T>; + +#if __cplusplus > 201402L +namespace using_problem { + +template <typename T, size_t SZ> +struct vector { + vector() : m_val(SZ) {} + T m_val; +}; + +template <typename T, size_t ... sizes> +struct matryoshka { + typedef T type; +}; + +template <typename T, size_t SZ, size_t ... sizes> +struct matryoshka<T, SZ, sizes ... > { + typedef vector<typename matryoshka<T, sizes ...>::type, SZ> type; +}; + +template <typename T, size_t ... sizes> +using make_vector = typename matryoshka<T, sizes ...>::type; + typedef make_vector<int, 2, 3> iiv_t; +}; +#endif + +namespace using_problem { + +template<typename T> +class Base { +public: + template<typename R> + R get1(T t) { return t + R{5}; } + T get2() { return T{5}; } + template<typename R> + R get3(T t) { return t + R{5}; } + T get3() { return T{5}; } +}; + +template<typename T> +class Derived : public Base<T> { +public: + typedef Base<T> _Mybase; + using _Mybase::get1; + using _Mybase::get2; + using _Mybase::get3; +}; + +} // namespace using_problem + + +//=========================================================================== +// template with r-value +namespace T_WithRValue { + +template<typename T> +bool is_valid(T&& new_value) { + return new_value != T{}; +} + +} // namespace T_WithRValue + + +//=========================================================================== +// variadic templates +namespace some_variadic { + +#ifdef WIN32 +extern __declspec(dllimport) std::string gTypeName; +#else +extern std::string gTypeName; +#endif + +template <typename ... Args> +class A { +public: + A() { + gTypeName = demangle_it(typeid(A<Args...>).name(), "A::A"); + } + A(const A&) = default; + A(A&&) = default; + A& operator=(const A&) = default; + A& operator=(A&&) = default; + + template <typename ... FArgs> + void a(FArgs&&... args) { + gTypeName = demangle_it(typeid(&A<Args...>::a<FArgs...>).name(), "A::a-2"); + } + + template <typename T, typename ... FArgs> + T a_T(FArgs&&... args) { + gTypeName = demangle_it(typeid(&A<Args...>::a_T<T, FArgs...>).name(), "A::a_T-2"); + return T{}; + } + + template <typename ... FArgs> + static void sa(FArgs&&... args) { + gTypeName = demangle_it(typeid(A<Args...>).name(), "A::sa-1"); + gTypeName += "::"; + gTypeName += demangle_it(typeid(A<Args...>::sa<FArgs...>).name(), "A::sa-2"); + } + + template <typename T, typename ... FArgs> + static T sa_T(FArgs&&... args) { + gTypeName = demangle_it(typeid(A<Args...>).name(), "A::sa_T-1"); + gTypeName += "::"; + gTypeName += demangle_it(typeid(A<Args...>::sa_T<T, FArgs...>).name(), "A::sa_T-2"); + return T{}; + } +}; + +class B { +public: + B() { + gTypeName = demangle_it(typeid(B).name(), "B::B"); + } + B(const B&) = default; + B(B&&) = default; + B& operator=(const B&) = default; + B& operator=(B&&) = default; + + template <typename ... FArgs> + void b(FArgs&&... args) { + gTypeName = demangle_it(typeid(&B::b<FArgs...>).name(), "B::b-2"); + } + + template <typename T, typename ... FArgs> + T b_T(FArgs&&... args) { + gTypeName = demangle_it(typeid(&B::b_T<T, FArgs...>).name(), "B::b_T-2"); + return T{}; + } + + template <typename ... FArgs> + static void sb(FArgs&&... args) { + gTypeName = demangle_it(typeid(B).name(), "B::sb-1"); + gTypeName += "::"; + gTypeName += demangle_it(typeid(B::sb<FArgs...>).name(), "B::sb-2"); + } + + template <typename T, typename ... FArgs> + static T sb_T(FArgs&&... args) { + gTypeName = demangle_it(typeid(B).name(), "B::sb_T-1"); + gTypeName += "::"; + gTypeName += demangle_it(typeid(B::sb_T<T, FArgs...>).name(), "B::sb_T-2"); + return T{}; + } +}; + +template <typename ... Args> +void fn(Args&&... args) { + gTypeName = demangle_it(typeid(fn<Args...>).name(), "fn"); +} + +template <typename T, typename ... Args> +T fn_T(Args&&... args) { + gTypeName = demangle_it(typeid(fn<Args...>).name(), "fn_T"); + return T{}; +} + +} // namespace some_variadic + + +//=========================================================================== +// template with empty body +namespace T_WithEmptyBody { + +#ifdef WIN32 +extern __declspec(dllimport) std::string side_effect; +#else +extern std::string side_effect; +#endif + +template<typename T> +void some_empty(); + +} // namespace T_WithEmptyBody + + +//=========================================================================== +// template with catch-all (void*, void**)overloads +namespace T_WithGreedyOverloads { + +class SomeClass { + double fD; +}; + +class WithGreedy1 { +public: + template<class T> + int get_size(T*) { return (int)sizeof(T); } + int get_size(void*, bool force=false) { return -1; } +}; + +class WithGreedy2 { +public: + template<class T> + int get_size(T*) { return (int)sizeof(T); } + int get_size(void**, bool force=false) { return -1; } +}; + +class DoesNotExist; + +class WithGreedy3 { +public: + template<class T> + int get_size(T*) { return (int)sizeof(T); } + int get_size(DoesNotExist*, bool force=false) { return -1; } +}; + +} // namespace T_WithGreedyOverloads + + +//=========================================================================== +// template with overloaded non-templated and templated setitem +namespace TemplateWithSetItem { + +template <typename T> +class MyVec { +private: + std::vector<T> fData; + +public: + using size_type = typename std::vector<T>::size_type; + + MyVec(size_type count) : fData(count) {} + + T & operator[](size_type index) { return fData[index]; } + + // The definition of this templated operator causes the issue + template <typename V> + MyVec operator[](const MyVec<V> &conds) const { return MyVec(2); } +}; + +} // namespace TemplateWithSetItem + +#endif // !CPPYY_TEST_TEMPLATES_H diff --git a/pypy/module/_cppyy/test/templates.xml b/pypy/module/_cppyy/test/templates.xml --- a/pypy/module/_cppyy/test/templates.xml +++ b/pypy/module/_cppyy/test/templates.xml @@ -16,4 +16,21 @@ <function name="SomeNS::some_bar" /> <function name="SomeNS::tuplify" /> + <class name="TemplatedCallable" /> + + <namespace name="TemplateHiding" /> + <class pattern="TemplateHiding::*" /> + + <namespace name="using_problem" /> + + <namespace name="some_variadic" /> + <class pattern="some_variadic::*" /> + <function pattern="some_variadic::*" /> + <variable pattern="some_variadic::*" /> + + <namespace name="T_WithEmptyBody" /> + + <namespace name="T_WithGreedyOverloads" /> + <class pattern="T_WithGreedyOverloads::*" /> + </lcgdict> diff --git a/pypy/module/_cppyy/test/test_fragile.py b/pypy/module/_cppyy/test/test_fragile.py --- a/pypy/module/_cppyy/test/test_fragile.py +++ b/pypy/module/_cppyy/test/test_fragile.py @@ -35,7 +35,7 @@ assert fragile.B == fragile.B assert fragile.B().check() == ord('B') - raises(AttributeError, getattr, fragile.B().gime_no_such(), "__cppdecl__") + assert not fragile.B().gime_no_such() assert fragile.C == fragile.C assert fragile.C().check() == ord('C') diff --git a/pypy/module/_cppyy/test/test_regression.py b/pypy/module/_cppyy/test/test_regression.py new file mode 100644 --- /dev/null +++ b/pypy/module/_cppyy/test/test_regression.py @@ -0,0 +1,50 @@ +import py, os, sys +from .support import setup_make + +from pypy.module._cppyy import interp_cppyy, executor + + +class AppTestREGRESSION: + spaceconfig = dict(usemodules=['_cppyy', '_rawffi', 'itertools']) + + def setup_class(cls): + cls.w_example01 = cls.space.appexec([], """(): + import ctypes, _cppyy + _cppyy._post_import_startup()""") + + def test01_dir(self): + """These dir() methods used to crash.""" + + import _cppyy as cppyy + + cppyy.gbl.gInterpreter.Declare("namespace cppyy_regression_test { void iii() {}; }") + + assert not 'iii' in cppyy.gbl.cppyy_regression_test.__dict__ + assert not '__abstractmethods__' in dir(cppyy.gbl.cppyy_regression_test) + assert '__class__' in dir(cppyy.gbl.cppyy_regression_test) + assert 'iii' in dir(cppyy.gbl.cppyy_regression_test) + + assert not 'iii' in cppyy.gbl.cppyy_regression_test.__dict__ + assert cppyy.gbl.cppyy_regression_test.iii + assert 'iii' in cppyy.gbl.cppyy_regression_test.__dict__ + + def test02_default_template_arguments(self): + """Calling a templated method on a templated class with all defaults used to crash.""" + + import _cppyy as cppyy + + cppyy.gbl.gInterpreter.Declare(""" + template<typename T> + class AllDefault { + public: + AllDefault(int val) : m_t(val) {} + template<int aap=1, int noot=2> + int do_stuff() { return m_t+aap+noot; } + + public: + T m_t; + };""") + + a = cppyy.gbl.AllDefault[int](24) + a.m_t = 21; + assert a.do_stuff() == 24 diff --git a/pypy/module/_cppyy/test/test_templates.py b/pypy/module/_cppyy/test/test_templates.py --- a/pypy/module/_cppyy/test/test_templates.py +++ b/pypy/module/_cppyy/test/test_templates.py @@ -25,20 +25,35 @@ m = _cppyy.gbl.MyTemplatedMethodClass() + # implicit (called before other tests to check caching) + assert m.get_size(1) == m.get_int_size()+1 + assert 'get_size<int>' in dir(_cppyy.gbl.MyTemplatedMethodClass) + # pre-instantiated assert m.get_size['char']() == m.get_char_size() assert m.get_size[int]() == m.get_int_size() # specialized - assert m.get_size[long]() == m.get_long_size() + if sys.hexversion >= 0x3000000: + targ = 'long' + else: + targ = long + assert m.get_size[targ]() == m.get_long_size() + + import ctypes + assert m.get_size(ctypes.c_double(3.14)) == m.get_size['double']() + assert m.get_size(ctypes.c_double(3.14).value) == m.get_size['double']()+1 # auto-instantiation assert m.get_size[float]() == m.get_float_size() assert m.get_size['double']() == m.get_double_size() assert m.get_size['MyTemplatedMethodClass']() == m.get_self_size() + assert 'get_size<MyTemplatedMethodClass>' in dir(_cppyy.gbl.MyTemplatedMethodClass) # auto through typedef assert m.get_size['MyTMCTypedef_t']() == m.get_self_size() + assert 'get_size<MyTMCTypedef_t>' in dir(_cppyy.gbl.MyTemplatedMethodClass) + assert m.get_size['MyTemplatedMethodClass']() == m.get_self_size() def test02_non_type_template_args(self): """Use of non-types as template arguments""" @@ -90,15 +105,13 @@ assert type(ggsr(vector['int']([5])).m_retval) == float assert ggsr(vector['int']([5])).m_retval == 5. # float in, int out - # TODO: this now matches the earlier overload - #ggsr = cppyy.gbl.global_get_some_result['std::vector<float>, int'] - #assert type(ggsr(vector['float']([0.3])).m_retval) == int - #assert ggsr(vector['float']([0.3])).m_retval == 0 + ggsr = cppyy.gbl.global_get_some_result['std::vector<float>, int'] + assert type(ggsr(vector['float']([0.3])).m_retval) == int + assert ggsr(vector['float']([0.3])).m_retval == 0 # int in, int out - # TODO: same as above, matches earlier overload - #ggsr = cppyy.gbl.global_get_some_result['std::vector<int>, int'] - #assert type(ggsr(vector['int']([5])).m_retval) == int - #assert ggsr(vector['int']([5])).m_retval == 5 + ggsr = cppyy.gbl.global_get_some_result['std::vector<int>, int'] + assert type(ggsr(vector['int']([5])).m_retval) == int + assert ggsr(vector['int']([5])).m_retval == 5 def test04_variadic_function(self): """Call a variadic function""" diff --git a/pypy/module/_cppyy/test/test_zjit.py b/pypy/module/_cppyy/test/test_zjit.py --- a/pypy/module/_cppyy/test/test_zjit.py +++ b/pypy/module/_cppyy/test/test_zjit.py @@ -228,6 +228,9 @@ assert isinstance(w_obj, FakeString) return w_obj.val + def fsencode_w(self, w_obj): + return self.bytes_w(w_obj) + def text_w(self, w_obj): assert isinstance(w_obj, FakeString) return w_obj.val diff --git a/pypy/module/cpyext/include/patchlevel.h b/pypy/module/cpyext/include/patchlevel.h --- a/pypy/module/cpyext/include/patchlevel.h +++ b/pypy/module/cpyext/include/patchlevel.h @@ -32,8 +32,8 @@ * module/sys/version.py * doc/conf.py */ -#define PYPY_VERSION "7.3.0-alpha0" -#define PYPY_VERSION_NUM 0x07030000 +#define PYPY_VERSION "7.3.1-alpha0" +#define PYPY_VERSION_NUM 0x07030100 /* Defined to mean a PyPy where cpyext holds more regular references to PyObjects, e.g. staying alive as long as the internal PyPy object stays alive. */ diff --git a/pypy/module/sys/version.py b/pypy/module/sys/version.py --- a/pypy/module/sys/version.py +++ b/pypy/module/sys/version.py @@ -13,7 +13,7 @@ # make sure to keep PYPY_VERSION in sync with: # module/cpyext/include/patchlevel.h # doc/conf.py -PYPY_VERSION = (7, 3, 0, "alpha", 0) +PYPY_VERSION = (7, 3, 1, "alpha", 0) import pypy _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit