)]}'
{
  "log": [
    {
      "commit": "0f5a59428e99ed7003d785dfea3b4381c0879c4c",
      "tree": "2c3d653a4d3ade887c502216b52d8fd32b5f54ed",
      "parents": [
        "bb5d46f6108ebbaf1d802a98f5e3ca9b37e8361d"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Tue Sep 15 21:16:42 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Wed Sep 16 23:38:05 2026 +0100"
      },
      "message": "[Python] Declare the module scope functions declared inside a class in the .pyi stub\n\nA friend function, a renamed constructor and a %rename\u0027d member are declared inside a\nclass but wrapped at module scope. The proxy writes them after the class body, but the\nthree sites writing stub declarations skipped anything coming from inside a class, so\nthe declaration was lost:\n\n  struct Foo {\n    %rename(MakeFoo) Foo(const Foo \u0026);\n    friend int value(const Foo \u0026);\n  };\n\nA .pyi shadows the .py for a type checker, so both names were invisible to anything\nimporting the module even though they work at runtime. 16 of the 806 test-suite modules\ngenerating both files were missing at least one, friends 15 of its 18.\n\nThe renamed constructor had no stub emission at all rather than a skipped one, which is\nwhy routing the other two sites to the globals buffer had not fixed it before.\n\nIssue #3528\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "bb5d46f6108ebbaf1d802a98f5e3ca9b37e8361d",
      "tree": "3801838f056b171cda2dc64cbb3039ed196c6a22",
      "parents": [
        "1bbbf24aa28bf9356b92df1dc7e663fadf247ff3"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Thu Sep 10 16:45:11 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Wed Sep 16 23:38:05 2026 +0100"
      },
      "message": "Don\u0027t probe for unsupported versions of Python in configure\n\nPython 3.5 is the minimum that SWIG supports.\n"
    },
    {
      "commit": "1bbbf24aa28bf9356b92df1dc7e663fadf247ff3",
      "tree": "74d8245d1125d0cca04da4b217505d59e24f1581",
      "parents": [
        "57f52fd5843f6e6ed73d1693bce78ebaf2f44719"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Thu Sep 10 16:45:02 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Wed Sep 16 23:38:05 2026 +0100"
      },
      "message": "Ignore the generated Python .pyi stub files\n\nThe examples generate \u003cmodule\u003e.pyi with -pyi, and _\u003cmodule\u003e.pyi with either -pyi or\n-typehints, and neither was ignored, so a -typehints or -pyi examples build left well\nover a hundred untracked files behind. The test-suite section already ignores its own\n*.pyi, so do the same for the examples.\n\nA glob covers the proxy stub, the low-level stub and every module name, unlike the .py\nentries above, which have to be listed individually so that the hand written runme.py\nfiles are not ignored along with them.\n\nThe errors test-suite ignores the .py files it generates but not the stub files, which\nswig_argout_container produces as it is run with -typehints.\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "57f52fd5843f6e6ed73d1693bce78ebaf2f44719",
      "tree": "77e5d86985a979b48c8e0a72b6c4045200fd50f5",
      "parents": [
        "bcc3f304eecfb03f312d0737a7565d45750223f0"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Tue Sep 15 21:58:12 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Wed Sep 16 23:38:05 2026 +0100"
      },
      "message": "[Python] Stop the C/C++ annotations generating PEP 484 support code\n\n%feature(\"python:annotations\", \"c\") generates C/C++ types, which are not type hints and\nare never type checked - both test cases using them strip -typehints. Code that exists\nonly to satisfy a type checker therefore has no business being generated for them.\nde6eb8b8e removed the _swig_dispatch decorator on those grounds; these are the four that\nwere missed.\n\nThe _swig_property helper and its typing.TYPE_CHECKING block are neither generated nor\nused, so a member variable creates its property directly:\n\n  class V(object):\n      val: \"float\" \u003d property(_example.V_val_get, _example.V_val_set)\n\nThe .pyi stub file no longer declares thisown, __disown__ or the cvar globals holder with\nthe typing.Any catch-all type. The test is for the C/C++ annotation mode alone rather than\nfor the PEP 484 one, as it is also not the PEP 484 mode when annotations are turned off\naltogether, and an untyped stub still has to declare what the module exports. The cvar\ndeclaration was gated on the global typehints flag although its comment already said it\nwas only for PEP 484 annotations, so -typehints -pyi together with a module wide\nannotations\u003d\"c\" feature emitted it anyway; it now uses the per node annotation mode like\nthe rest.\n\nBoth test cases now read their own generated files and reject the PEP 484 names. The check\nis for a quoted \"typing.Any\" as the unquoted form is the placeholder a .pyi needs for an\nannotations:novar member, which cannot be declared as a bare name and has no C/C++ type\nmeaning unspecified. python_annotations_c applies the feature per declaration rather than\nto the whole module, so its class is not itself C/C++ annotated and declares thisown as\nany other class does.\n\npython_pyi_untyped covers -pyi used without -typehints, which nothing exercised before.\n\nA type checker reading C/C++ annotations would now report bad-assignment on every\nannotated member variable again, as before _swig_property was added. Nothing checks them,\nwhich is the point.\n\nIssue #3528\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "bcc3f304eecfb03f312d0737a7565d45750223f0",
      "tree": "01c717b98d79655f3617a7cd23497c00f20002bc",
      "parents": [
        "ebbcda0b409002d0bf55cc30c9660d052cca556d"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Fri Sep 04 11:33:44 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Wed Sep 16 23:38:05 2026 +0100"
      },
      "message": "[Python] Declare thisown, __disown__ and the class constants in the .pyi stub\n\nA .pyi stub file shadows its .py file, so anything the .py defines but the stub\ndoes not is invisible to a type checker even though it works at runtime. Three of\nthese are now declared:\n\n  class Foo(object):\n      @property\n      def thisown(self) -\u003e \"typing.Any\":\n          ...\n      @thisown.setter\n      def thisown(self, v: \"typing.Any\") -\u003e \"None\":\n          ...\n      IMPULSE: \"int\"\n\n      def __disown__(self) -\u003e \"typing.Any\":\n          ...\n\nthisown is a property in the .py file, so it is declared as one rather than as an\nattribute, and its setter takes the same parameter name, otherwise a class deriving\nfrom another module\u0027s class is reported as overriding it inconsistently. It is\nannotated with the catch-all type as it is assigned an int as often as a bool.\n\nThe constants of a class were not declared at all. They are named after the class\nin the low-level module, but after the member in the proxy, which is the name the\nstub needs.\n\n__disown__ is declared for the director classes with and without -builtin.\n\nThis was the last of the pyrefly deficiencies in the Python examples, so the\nsuppression for missing-attribute is removed. Neither the examples nor the\ntest-suite now suppress any pyrefly check.\n\nIssue #3528\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "ebbcda0b409002d0bf55cc30c9660d052cca556d",
      "tree": "642d2ac5b1ae44c97d11f2567492a6721bd9d060",
      "parents": [
        "1f99bd4ee5312a264d693da5033bfee8cd75f56e"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Fri Sep 04 11:52:35 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Wed Sep 16 23:38:05 2026 +0100"
      },
      "message": "Modernise the operator examples\n\nA renamed constructor is quirky nowadays and removing it avoids a pyrefly missing-attribute\nerror. The tcl example is modernised the same way, keeping the assignment operator that its\nruntime test uses. The javascript example never had the rename, only a comment describing one.\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "1f99bd4ee5312a264d693da5033bfee8cd75f56e",
      "tree": "b83718f0aa4774423abfd5ffde510d9b1ab66d3f",
      "parents": [
        "085c9b3f0712f54bc8785fab2f7766141c59bfe5"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Fri Sep 04 10:06:13 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Wed Sep 16 23:38:05 2026 +0100"
      },
      "message": "[Python] Drop the f_ prefix from the non file variables in python.cxx\n\nThe f_ prefix names the files being generated, such as f_begin and f_wrappers, but\nwas also used for the strings that the generated code is accumulated in before\nbeing written to one of them, and for two hashes:\n\n  f_shadow             -\u003e shadow_code\n  f_shadow_begin       -\u003e shadow_begin\n  f_shadow_after_begin -\u003e shadow_after_begin\n  f_shadow_stubs       -\u003e shadow_stubs\n  f_shadow_imports     -\u003e shadow_imports\n  f_stub               -\u003e stub\n  f_stub_begin         -\u003e stub_begin\n  f_stub_imports       -\u003e stub_imports\n  f_stub_imports_seen  -\u003e stub_imports_seen\n  f_varlinks           -\u003e varlinks\n\nf_shadow cannot simply drop the prefix, as shadow is the option variable saying\nwhether to generate the proxy classes, so it is shadow_code.\n\nEvery remaining f_ variable is a file.\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "085c9b3f0712f54bc8785fab2f7766141c59bfe5",
      "tree": "99af52d29a732c9cbdf02b9739e81c688eb0cd7d",
      "parents": [
        "a835a6a5533590ff19169bd8207bd4625dba122c"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Fri Sep 04 09:37:15 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Wed Sep 16 23:38:05 2026 +0100"
      },
      "message": "[Python] Remove three pyrefly suppressions from the Python examples\n\nThe examples run pyrefly over the hand written runme.py scripts as well as the\ngenerated code, so they needed suppressions the test-suite did not. Three of them\nare no longer needed:\n\n  missing-module-attribute  the low-level module now has a .pyi stub file\n  bad-assignment            fixed by the _swig_property helper\n  bad-override              fixed by the _swig_dispatch helper and the container fixes\n\nThe stub file also declares the constants, the cvar holder and, with -builtin, the\nwrapped types, which is what the runme scripts use them for. With -builtin the\ngenerated module re-exports all of these with \u0027import *\u0027, so 143 errors reported\nthere are gone.\n\nmissing-attribute is still needed. The .pyi stub file does not declare everything\nthe .py file does, such as the enum constants of a class, so 14 errors remain with\n-pyi.\n\nIssue #3528\n"
    },
    {
      "commit": "a835a6a5533590ff19169bd8207bd4625dba122c",
      "tree": "e006e7339e8c4058ba9ebf374e062b6b7829fac7",
      "parents": [
        "ad1e218ff729ea2116a1b5a914011c7d7fe919f3"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Mon Aug 31 16:45:34 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Wed Sep 16 23:38:05 2026 +0100"
      },
      "message": "[Python] Generate a .pyi stub file for the low-level C/C++ module\n\nThe generated wrapper imports the low-level C/C++ module, which is a shared library\nthat a type checker cannot read, so the import itself was reported as an error:\n\n  ERROR Could not import `_callback` from `.` [missing-module-attribute]\n\nA stub file for it is now generated when -typehints or -pyi is used, named after the\nlow-level module itself, so _\u003cmodule\u003e.pyi normally and \u003cmod\u003e.pyi with -interface \u003cmod\u003e.\nIt is not generated with -noproxy, as there is then no proxy importing it. It declares\nwhat the module exports:\n\n  cvar: \"typing.Any\"\n  def new_A(*args: \"typing.Any\", **kwargs: \"typing.Any\") -\u003e \"typing.Any\":\n      ...\n\nThe wrappers are C functions called through the Python C API, so what they take and\nreturn is not known at the Python level and both are annotated with the catch-all\ntype. The same is used for what the module exports as values rather than functions:\nthe constants, the cvar holder for the global variables and, with -builtin, the\nwrapped types. Each is declared as it is wrapped, so the stub is in the same order\nas the interface file. The annotations describing the interface are the ones already\ngenerated on the proxy or in its own .pyi file; this stub exists so that the\nlow-level module resolves.\n\nEverything the module exports is declared, so the stub is a complete one in the sense\nPEP 484 gives the term, with no module level __getattr__ making an undeclared name\nvalid. A wrapper name missing from the stub is reported instead:\n\n  Object of type \u0027Module[_example]\u0027 has no attribute \u0027Foo_EnumVal1\u0027\n  [missing-attribute]\n\nA constant is added to the class dictionary rather than the module with -builtin, so\nit is not declared there.\n\nThe .pyi stub file generated by -pyi now declares the cvar holder as well, which it\ndid not before although the .py file assigns it.\n\nThe pyrefly suppression for this in the Python test-suite is removed.\n\nThe clean targets have to remove the new files as well. The .py* patterns in use do not\nmatch a name carrying the underscore prefix, and the errors test-suite\u0027s *.py does not\nmatch a .pyi at all, so the per test rule, the Python examples, the multi module test\ncases and the errors test-suite are all updated. Anything left behind is reported by\ncheck-maintainer-clean, which lists every file remaining after maintainer-clean in an\nout of source build.\n\nIssue #3528\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "ad1e218ff729ea2116a1b5a914011c7d7fe919f3",
      "tree": "7ffb797a1bfccecb7a052dd43f0c1b1558336f7f",
      "parents": [
        "1a9b5f765e185960c57078f963dee3e203c6eb51"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Mon Aug 31 11:27:57 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Wed Sep 16 23:38:05 2026 +0100"
      },
      "message": "Document the alphabetical ordering of makefile lists in the conventions skill\n\nThe test case lists in Examples/test-suite/common.mk and in each language\u0027s\nMakefile.in are kept in alphabetical order, but this was not written down\nanywhere, so a new test case is easily appended to the end of a list instead.\nNothing in the build checks the ordering.\n\nAlso records that the ordering treats an underscore as a word separator rather\nthan as a character to sort on, so that li_std_vectora comes before\nli_std_vector_extra and running a list through sort is wrong.\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "1a9b5f765e185960c57078f963dee3e203c6eb51",
      "tree": "cf7730f9e05103f7f75a5287d3370d64d1542e14",
      "parents": [
        "c0eb382ea82e82ea1eeebb34483fb7eeba6985a7"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Fri Aug 28 21:34:38 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Wed Sep 16 23:38:05 2026 +0100"
      },
      "message": "pyrefly bad-argument-type fixes in python constants example\n\nThe test was checking that some names/attributes don\u0027t exist and pyrefly\nwarns if there are missing names - minor test rewrite to avoid this problem\n"
    },
    {
      "commit": "c0eb382ea82e82ea1eeebb34483fb7eeba6985a7",
      "tree": "9aeed401bbacf8b050f4a0ce986ca23a52bec751",
      "parents": [
        "1bdc23230296a1dd5b2d331dc5655fd3304634d8"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Fri Aug 28 20:47:48 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Wed Sep 16 23:38:05 2026 +0100"
      },
      "message": "Add pytyping typemap for typehint support to python multimap example\n\nFixes pyrefly bad-argument-type error\n"
    },
    {
      "commit": "1bdc23230296a1dd5b2d331dc5655fd3304634d8",
      "tree": "2bd9913d259d81206afec859baee85f252cc3217",
      "parents": [
        "ed0fc44475861056ec85ee9da86ae50dcd12f506"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Wed Sep 16 08:11:57 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Wed Sep 16 23:38:05 2026 +0100"
      },
      "message": "[Python] Add the add and discard methods to the unordered set containers\n\nstd::unordered_set and std::unordered_multiset did not have the add and discard\nmethods that std::set and std::multiset have. They are needed to register the\ncontainers with collections.abc.MutableSet, which declares both abstract, so\nregistering them without the methods left classes which could not be instantiated:\n\n  TypeError: Can\u0027t instantiate abstract class UnorderedIntSet without an\n  implementation for abstract methods \u0027add\u0027, \u0027discard\u0027\n\npyabc.i registers the C++98 containers with the abstract base classes and has to\nremain usable without C++11, so the unordered containers are not registered there.\nThe new cpp11_python_abstractbase test case registers them itself with the\n%pythonabc macro pyabc.i provides, and tests the four unordered containers the way\npython_abstractbase tests the six C++98 ones.\n\nIssue #3528\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "ed0fc44475861056ec85ee9da86ae50dcd12f506",
      "tree": "373cecb6f82a1df46e122f623afc154e589bc25c",
      "parents": [
        "aee89fbc9842c4feb436b80018ebb49292e3264b"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Wed Sep 16 08:11:08 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Wed Sep 16 23:38:05 2026 +0100"
      },
      "message": "[Python] Return False from container __contains__ instead of raising TypeError\n\nThe x in c operator must not raise for an object that is not in the container, but\nthe container __contains__ converted its argument to the key or value type of the\ncontainer and raised if it could not:\n\n  \u003e\u003e\u003e \"not an int\" in IntSet([1])\n  TypeError: in method \u0027IntSet___contains__\u0027, argument 2 of type \u0027std::set\u003c int \u003e::value_type\u0027\n\nwhere a Python set returns False. __contains__ keeps the key type and gains an\noverload taking a PyObject * that returns False, covering std::set, std::multiset,\nstd::map, std::multimap and the unordered forms of all four. PyObject * has the\nlowest typecheck precedence, so the typed overload is always tried first.\n\nA container of Python objects has a key type that takes anything, which shadows the\ncatch-all overload, so that overload is ignored for those instantiations.\n\nli_std_set wraps std::set\u003cFoo\u003e, whose Foo has no default constructor, for every\nlanguage that supports std::set rather than for only some of them. Nothing the\ncontainers generate may require the key or value type to be default constructible.\n\nIssue #3528\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "aee89fbc9842c4feb436b80018ebb49292e3264b",
      "tree": "a208579a576f08b096a6e2568a6f99c4affa7b1d",
      "parents": [
        "9f383badb1080d64f41f799c69a796b1a5490f01"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Tue Sep 15 21:57:12 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Wed Sep 16 23:38:05 2026 +0100"
      },
      "message": "[Python] Add the optional index parameter to the container pop method\n\ncollections.abc.MutableSequence declares pop(index\u003d-1), but the pop generated for\nthe sequence containers took no arguments, so it was a narrower signature than the\nbase class method it overrides when pyabc.i is used:\n\n  def pop(self) -\u003e \"int\":\n\nwhich pyrefly reports as:\n\n  ERROR Class member `IntVector.pop` overrides parent class `MutableSequence` in an\n  inconsistent manner [bad-override]\n    `IntVector.pop` has type `(self: IntVector) -\u003e int`, which is not assignable to\n    `(self: IntVector, index: int \u003d -1, /) -\u003e Unknown`\n\npop now takes the index to remove, defaulting to the last element as before, so\nthat std::vector, std::list, std::deque and std::vector\u003cbool\u003e behave as a Python\nlist does. A negative index counts from the end and an out of range index raises\nIndexError, both as they already do for the other methods taking an index.\n\nThe last element keeps using back() and pop_back(), which reach it directly, as\nswig::getpos advances an iterator from begin() and that walks the whole of a\ncontainer with no random access iterator. getpos is used only for the elements in\nbetween.\n\nThe MutableSequence mixin implements pop with __getitem__ and __delitem__, which\nthe containers already provide, so the pop generated for them had been replacing a\nworking pop(index) with one that did less.\n\nstd::basic_string ignores pop, which now needs to ignore it by name as the\nsignature it named no longer matches.\n\nThis was the last bad-override deficiency in the test suite, so the suppression for\nit is removed.\n\nIssue #3528\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "9f383badb1080d64f41f799c69a796b1a5490f01",
      "tree": "8ceb08581b35654a7d5499543e8ccd570260eb08",
      "parents": [
        "5a99f40edcfd8cf9d7cc6f7975c0bde104013f3a"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Thu Aug 27 21:18:25 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Wed Sep 16 23:38:05 2026 +0100"
      },
      "message": "[Python] Rename the BaseClassData buffer helpers in the buffer interface test\n\nThe helper the derived classes call to implement the buffer protocol had the same\nname as the protocol method itself, but took a readonly flag in addition to the\nflags the protocol passes, so BaseClassData only appeared to implement it:\n\n  TypeError: BaseClassData.__buffer__() missing 1 required positional argument\n\nwhich pyrefly reports for the derived classes as:\n\n  ERROR Class member `ReadOnlyData.__buffer__` overrides parent class\n  `BaseClassData` in an inconsistent manner [bad-override]\n\nThe helpers are renamed bufferimpl and getbufferimpl, leaving the derived classes\nwith the __buffer__ and getbuffer signatures the protocol requires. Both the\nSWIGPYTHON_BUILTIN and the proxy class halves of the test had this.\n\nIssue #3528\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "5a99f40edcfd8cf9d7cc6f7975c0bde104013f3a",
      "tree": "b6efba9f157f7168bfb55e244a424c8ac3e8583d",
      "parents": [
        "9bbbb84b676b1277a35a04e2ae1afcfc0c6beb0d"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Wed Sep 16 08:09:56 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Wed Sep 16 23:38:05 2026 +0100"
      },
      "message": "[Python] Annotate the std::basic_string methods converted to str\n\nThe pytyping typemaps for strings were defined for std::string and std::wstring,\nbut the methods in std_basic_string.i are declared with the basic_string template\nthose are typedefs of, which none of them matched, so every one of those methods\nwas annotated with the catch-all type:\n\n  def substr(self, *args) -\u003e \"typing.Any\":\n  def __str__(self) -\u003e \"typing.Any\":\n\nThey are now annotated with str:\n\n  def substr(self, *args) -\u003e \"str\":\n  def __str__(self) -\u003e \"str\":\n\nOnly the by value form is annotated, as that is the one converted to a Python str.\nA pointer or a reference is wrapped as the proxy class instead, so __add__ and the\nrest keep the catch-all type.\n\nThe typemap is declared alongside the typemaps that do the converting, for\nstd::basic_string\u003cchar\u003e and std::basic_string\u003cwchar_t\u003e, so any other instantiation\nkeeps the catch-all type rather than claiming to be a str it is not. Only the value\nform is declared: adding the const reference form annotates the comparison dunders\ntaking a const basic_string \u0026, and narrowing __eq__ and __ne__ from the catch-all\ntype makes them inconsistent overrides of object.__eq__ and object.__ne__.\n\nIssue #3528\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "9bbbb84b676b1277a35a04e2ae1afcfc0c6beb0d",
      "tree": "f6091c742e435ebc77f4438d41702c416c591bf6",
      "parents": [
        "df6555e15d3aa0b85192dae97d36940eb683d447"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Thu Aug 27 18:22:47 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Wed Sep 16 19:43:06 2026 +0100"
      },
      "message": "[Python] Annotate the string dunder methods as returning str\n\nA char * is annotated typing.Optional[str], as it can be a null pointer, which is\nNone in Python. The Python data model does not allow __str__, __repr__ and\n__format__ to return None though - it raises\n\n  TypeError: __str__ returned non-string (type NoneType)\n\n- so the annotation is now str for those three:\n\n  struct Foo {\n    const char *__str__() const { return \"Foo\"; }\n  };\n\n  def __str__(self) -\u003e \"str\":\n      return _example.Foo___str__(self)\n\nobject declares all three as returning str, so the typing.Optional made every\nclass defining one of them an inconsistent override and pyrefly reported:\n\n  ERROR Class member `Foo.__str__` overrides parent class `object` in an\n  inconsistent manner [bad-override]\n\nThe typemaps are keyed on char * rather than on the method name alone, so only the\ntyping.Optional the null pointer introduced is removed. One of these methods\nreturning some other type is a genuine violation of the data model and is still\nannotated with that type for a type checker to report. Any other method returning\na char * is unchanged.\n\nThe number of pyrefly bad-override errors in the test suite drops from 10 to 8\nwith -typehints and from 14 to 12 with -pyi -typehints.\n\nIssue #3528\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "df6555e15d3aa0b85192dae97d36940eb683d447",
      "tree": "4870ece6e05ff2eaf87403bc16e0df36b3cb3b49",
      "parents": [
        "3ac66beb49aee1b8d40a4bb09f361c60209d6f8c"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Thu Sep 10 22:00:26 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Wed Sep 16 19:43:01 2026 +0100"
      },
      "message": "[Python] Do not annotate a disagreeing overload chain with one overload\u0027s type\n\nC++ overloads are wrapped as a single Python function which selects an overload\nat runtime, but it has just the one annotation to say what it returns. That\nannotation was whichever overload happened to be last, which is not necessarily\nthe one called:\n\n  int    value(int i);\n  double value(double d);\n\n  def value(*args) -\u003e \"float\":\n      return _example.value(*args)\n\nThe annotation is now typing.Any when the overloads do not all return the same\ntype, as which one runs is not known until the function is called:\n\n  def value(*args) -\u003e \"typing.Any\":\n      return _example.value(*args)\n\nThe C/C++ annotations generated by %feature(\"python:annotations\", \"c\") had the\nsame defect, but there is no C/C++ type meaning \"one of several\", so rather than\nname one of them nothing is annotated at all:\n\n  def over(self, *args):\n      return _example.K_over(self, *args)\n\nThis is what those annotations already do for the parameters of an overloaded\nfunction, which are not shown either. Overloads which do all return the same type\nare unchanged in both modes. The comparison is of the annotations rather than of\nthe C++ types, so overloads returning, for example, int and long still agree and\nkeep the int annotation.\n\nThis is not just a matter of precision, as the annotation could be wrong rather\nthan merely vague. std::set::erase is one of the overloads wrapped as\n\n  def erase(self, *args) -\u003e \"None\":\n\nalthough erase(key) returns the number of elements removed rather than nothing,\nand std::vector::insert was annotated the same way although insert(pos, x)\nreturns an iterator. 457 of the 1578 annotated dispatchers in the test suite\nwere describing something other than what all of their overloads return.\n\nThe annotation for each overload is recorded as the wrapper for it is generated\nrather than being worked out later. The type attribute of a node holds the type\nit returns only while that node is being wrapped - cDeclaration() in lang.cxx\nputs it there for the duration and then restores the type of the declaration\nitself, which for a function returning a pointer keeps the pointer in the decl\nattribute instead. Only the node currently being wrapped can therefore be asked\nwhat it returns. The annotation is recorded for overloads only, as looking up a\ntypemap also attaches it to the node, which for a member variable would then be\nused as its annotation in place of its own type.\n\nAn overload with no annotation recorded says nothing about what the others\nreturn and is skipped. An ignored overload is not wrapped at all and so is not\none of them to begin with, but an overload with annotations turned off is, and\nthe rest of the chain still agreeing on what they return is annotated with it.\n\nC/C++ annotations are not PEP 484 type hints and are not type checked - the two\ntest cases using them turn -typehints and Pyrefly off - so the output generated\nfor the benefit of type checkers is no longer generated for them either. They are\nnot decorated with the _swig_dispatch helper, which also stops the helper\u0027s\ntyping.TypeVar and typing.Callable definitions being generated into a module\nusing nothing else from typing, and the **kwargs added to a *args parameter list\nin the .pyi stub file is not added to them.\n\nAn overloaded function had not been used with the C/C++ annotations in the test\nsuite, so python_annotations_c.i now covers both an overload chain agreeing on\nwhat it returns and one which does not.\n\nThe number of pyrefly bad-override errors in the test suite drops from 17 to 10\nwith -typehints and from 19 to 14 with -pyi -typehints.\n\nIssue #3528\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "3ac66beb49aee1b8d40a4bb09f361c60209d6f8c",
      "tree": "2c93163ec4052d4365a0fac7af33a8d709edbc01",
      "parents": [
        "fdf902bc89558111108bc0b2fc2ba4857ab56538"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Wed Aug 26 22:14:59 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Wed Sep 16 19:40:22 2026 +0100"
      },
      "message": "[Python] Decorate overloaded methods with a _swig_dispatch helper\n\nAn overloaded method is generated as a *args dispatcher, as Python has no\noverloading and the C code selects the overload at runtime:\n\n  class Derived(Base):\n      def f(self, *args) -\u003e \"None\":\n          return _example.Derived_f(self, *args)\n\nA *args parameter list cannot accept the keyword arguments that a named parameter\nlist accepts, so the dispatcher is a narrower signature than the base class method\nit overrides and pyrefly reports:\n\n  ERROR Class member `Derived.f` overrides parent class `Base` in an inconsistent\n  manner [bad-override]\n\nThe dispatcher is now decorated with a helper which does nothing at runtime, but\nwhich type checkers see as replacing the parameter list with ..., compatible with\nany signature, while keeping the annotated return type:\n\n  if typing.TYPE_CHECKING:\n      _SwigT \u003d typing.TypeVar(\"_SwigT\")\n\n      def _swig_dispatch(f: typing.Callable[..., _SwigT]) -\u003e typing.Callable[..., _SwigT]:\n          ...\n  else:\n      def _swig_dispatch(f):\n          return f\n\nThis is not a workaround, but the mechanism the Python typing specification\nprovides for a signature which cannot be described. It defines ... in Callable as\na gradual form \"indicating that the type is consistent with any input signature\",\nwhich is precisely the situation here, as the parameters are resolved by the C\ncode at runtime and so are unknowable to a type checker:\n\n  https://typing.python.org/en/latest/spec/callables.html#meaning-of-in-callable\n\nThe specification gives two ways to reach that form. A parameter list of both\n*args and **kwargs, with neither annotated, is also treated as ..., but using that\nwould mean generating a **kwargs parameter and advertising keyword arguments which\nthe dispatcher can never accept. Decorating with Callable[..., _SwigT] reaches the\nsame gradual form without altering the generated parameter list, and unlike a\ntype: ignore comment it leaves the return type checked.\n\nThe generated code behaves exactly as it did before, as the decorator is the\nidentity function at runtime: the signature reported by inspect, the\n__annotations__ and the TypeError raised for a keyword argument are all unchanged.\n\nThe decorator is generated for any method with a *args parameter list, which is\nalso used for the compactdefaultargs and python:cdefaultargs features, for a\ndefault argument which cannot be represented in Python and for varargs. It is not\ngenerated for __init__, which type checkers do not check for override\ncompatibility, nor for free functions, which do not override anything. A .pyi stub\nis never executed, so every dispatcher declared in one, including the static\nmethods, the free functions and __init__, is widened with a **kwargs parameter\ninstead of being decorated.\n\nThe number of pyrefly bad-override errors in the test suite drops from 53 to 17\nwith -typehints and from 94 to 19 with -pyi -typehints. The errors which remain\nare not related to overloading, so the suppression is still required.\n\nIssue #3528\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "fdf902bc89558111108bc0b2fc2ba4857ab56538",
      "tree": "12dff977dd97819cdb2da3ea784038afa17fc343",
      "parents": [
        "35f12f23196289da12efa9f7cd035faf7f0bb35c"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Wed Aug 26 18:52:27 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Thu Sep 10 21:44:36 2026 +0100"
      },
      "message": "[Python] Create annotated member variables with a _swig_property helper\n\nA member variable is emitted as an annotated assignment, but the annotation declares\nthe type the property returns while the value assigned is a property object:\n\n  class V(object):\n      val: \"float\" \u003d property(_example.V_val_get, _example.V_val_set)\n\nwhich pyrefly reports as an error:\n\n  ERROR `property` is not assignable to `float` [bad-assignment]\n\nType checkers use the annotation on a class attribute to declare the type of the\nobject in the class dictionary and then apply that type\u0027s __get__ to work out the\ntype an attribute access returns, so the annotation has to name the property rather\nthan what the property returns. Pyrefly reported 759 of these errors in 250 test\ncases and mypy, pyright, basedpyright, ty and pyre all reject the same code.\n\nAn annotated member variable is now created by a helper which is an alias for property\nat runtime and is declared to return typing.Any when type checking, so that it is the\nannotated type which is used:\n\n  if typing.TYPE_CHECKING:\n      def _swig_property(fget: \"typing.Any\", fset: \"typing.Any\" \u003d ..., doc: \"typing.Any\" \u003d ...) -\u003e \"typing.Any\":\n          ...\n  else:\n      _swig_property \u003d property\n\nThe generated code behaves exactly as it did before, as the property object created is\nthe same one, and the class __annotations__ are unchanged. SWIG generated\n_swig_property in the same way until it was removed in 7c034ead3 as it was only needed\nfor Python versions before 2.2.\n\nThe helper is only generated when a member variable is annotated and is not used for\nthose that are not, so the generated code is unchanged when -typehints is not used,\nwhen -pyi is used and when the annotations:novar feature is used. Whether any member\nvariable is annotated is not known until they have all been emitted, so the helper is\nexpanded into a marker afterwards.\n\nStatic member variables and thisown are not annotated and so are unchanged.\n\nThis removes the need for the pyrefly bad-assignment suppression.\n\nIssue #3528\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "35f12f23196289da12efa9f7cd035faf7f0bb35c",
      "tree": "bffddb8f1955734ff54718075d11aa30f20c285e",
      "parents": [
        "d198bf1fd7228feeddd887589f79ab1a6b6b980e"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Tue Aug 25 16:59:44 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Thu Sep 10 21:44:36 2026 +0100"
      },
      "message": "[Python] Qualify the str builtin in the varargs and kwargs_feature test cases\n\nA member variable named \u0027str\u0027 binds that name in the generated proxy class body, so\nevery annotation in the same class that names str resolves to the member instead of\nthe builtin. pyrefly reported 7 not-a-type errors across the two test cases:\n\n  class VarargConstructor(object):\n      str: \"typing.Optional[str]\" \u003d property(...)\n      def __init__(self, fmt: \"typing.Optional[str]\"):\n\n  Expected a type form, got instance of \u0027str | None\u0027 [not-a-type]\n\nThe pytyping typemaps are the documented way for an interface file to control the\nannotations, so the test cases now use them to qualify str with the builtins module.\nThe typemaps match on the declaration name, which reaches the parameters, and on the\nfunction name for the return types. The member variable\u0027s own annotation is left\nalone as it was never a problem: the annotation of a binding is resolved before the\nbinding shadows the name.\n\nbuiltins has to be imported into the .py file and the .pyi file separately, and the\nexisting \u0027import builtins as __builtin__\u0027 in the .py file binds a different name.\n\nThis removes the need for the pyrefly not-a-type suppression.\n\nIssue #3528\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "d198bf1fd7228feeddd887589f79ab1a6b6b980e",
      "tree": "e669ac27b582251ad78e2064e6d5446553f16fb5",
      "parents": [
        "79ef5e450eff8a8e7348d0a7de7f5da0df4f421b"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Mon Aug 24 08:54:17 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Thu Sep 10 21:44:36 2026 +0100"
      },
      "message": "[Python] Declare \u0027this\u0027 in the proxy classes generated with -typehints\n\nThe \u0027this\u0027 attribute is added to each proxy instance by the C code, so it never\nappears in the generated class body and type checkers do not know about it. The\ngenerated code dereferences it in _swig_repr, in the thisown property and in\n__disown__, but only __disown__ was reported by pyrefly, as the other two reach it\nthrough an unannotated parameter rather than through self. It is present on every\nproxy instance, not just those of a director class, so declare it in every proxy\nclass body:\n\n  class Base(object):\n      if typing.TYPE_CHECKING:\n          this: \"typing.Any\"\n\nThe typing.TYPE_CHECKING guard keeps it out of the class __annotations__ at\nruntime, which are part of the PEP 526 variable annotation support and are checked\nby python_annotations_variable_c.\n\nThe declaration is a variable annotation, so the python:annotations:novar feature\nturns it off along with all the others. novar exists so that annotated code still\nworks with Python versions older than 3.6, where an annotated name is a syntax error\nwhether or not the block it sits in is ever executed, and this would otherwise be the\none piece of PEP 526 syntax left in a novar build. python_annotations_variable_typing\nchecks that \u0027this\u0027 is declared for an ordinary class and not for one with the feature\napplied to it.\n\nThe declaration is generated when -pyi is used too. The .pyi file holds the type\ninformation in that mode, but the .py file still contains the __disown__ method\nthat uses \u0027this\u0027, and pyrefly checks the .py file as well as the .pyi file. There\nwere 219 errors in 66 test cases without it, so the pyrefly missing-attribute\nsuppression is no longer needed at all.\n\nBug fix so that the type wrapper classes are no longer generated into the .py file\nwhen -pyi is specified, as they were always present in the .pyi file. They exist\nonly to give an annotation a named type to refer to, so with -pyi nothing in the\n.py file refers to them. python_pyi checks this.\n\nIssue #3528\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "79ef5e450eff8a8e7348d0a7de7f5da0df4f421b",
      "tree": "593f81cc6c136e9cff94ade20f8615ebbc01d6d5",
      "parents": [
        "3d0189eb9ea633e5fc83b2a0963fb94ccc20990d"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Sun Aug 23 17:34:10 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Thu Sep 10 21:44:36 2026 +0100"
      },
      "message": "[Python] Check the generated type hints with the pyrefly default preset\n\nPyrefly runs with no configuration file, so it falls back to its \u0027basic\u0027 preset,\nwhich leaves override validation, annotation completeness and most assignment\nchecking turned off. Pass --preset\u003ddefault in the test-suite and the examples so\nthe generated PEP 484 type hints are checked with the full default rule set.\n\nThe --error\u003dbad-function-definition added by the previous commit is included in\nthe default preset, so it is no longer needed.\n\nContrary to the note in that commit, --preset\u003ddefault does not enable\nexplicit-any, which the generated wrappers use deliberately. Only --preset\u003dall\nenables it; basic, default and strict all leave it off.\n\nThe preset reports several long standing deficiencies in the generated hints, so\neach is suppressed with an --ignore for now, one per line with a comment saying\nwhat the deficiency is. The suppressions are removed one at a time as each\ndeficiency is fixed. The test-suite and the examples need different sets: the\nexamples also type check the hand written runme scripts, which use module\nattributes re-exported from the extension module, and they hit a multi-argument\ntypemap annotated with the C type of its first parameter.\n\nIssue #3528\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "3d0189eb9ea633e5fc83b2a0963fb94ccc20990d",
      "tree": "5239214d6e5876840289e774b29710d497663c45",
      "parents": [
        "4c7d77e3076142a3f23bfc3e6a04a9a60401327a"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Thu Sep 10 21:31:25 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Thu Sep 10 21:34:38 2026 +0100"
      },
      "message": "4.5.1 release notes from the release-4.5 branch\n\nMove the five entries released in 4.5.1 out of the 4.6.0 CHANGES.current\nsection and into CHANGES: #3534, #3555, #3546, #3537 and #3531. Also add\nthe 4.5.1 RELEASENOTES summary.\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "4c7d77e3076142a3f23bfc3e6a04a9a60401327a",
      "tree": "76f5be9efcbf02f201969416f8d1b42f4f4098f4",
      "parents": [
        "336519f05adb82d7d3e7bb3de11e83db160f2f7b"
      ],
      "author": {
        "name": "Lars Kanis",
        "email": "lars@greiz-reinsdorf.de",
        "time": "Wed Aug 12 11:06:16 2026 +0200"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Thu Sep 03 13:19:02 2026 +0100"
      },
      "message": "Fix leftover of convertpath removal\n\nTools/convertpath was removed in favour of cygpath in f8d198bf6, but configure\nstill called it when computing SWIG_LIB_WIN_UNIX on MinGW:\n\n  ./configure: line 16298: ./Tools/convertpath: No such file or directory\n\nSWIG_LIB_WIN_UNIX was left empty as a result. It is the only search directory\npointing at the autotools install location in a native Windows build, as SWIG_LIB\nis derived from the executable location there, so a MinGW build installed to a\nUnix style prefix could not find the SWIG library files.\n\nQuote SWIG_LIB when passing it to cygpath, matching the other $CYGPATH -m uses,\nso that a prefix containing a space is converted as a single path.\n\nCloses #3534\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "336519f05adb82d7d3e7bb3de11e83db160f2f7b",
      "tree": "54db52cf01ae4e32c36a056da1f53af9fd840966",
      "parents": [
        "e849557108a7bd7a32c2aa070a7714fb115fa3f1"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Thu Sep 03 11:34:30 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Thu Sep 03 12:25:11 2026 +0100"
      },
      "message": "CMake: Remove the minimum PCRE2 version requirement\n\nThe CMake build required PCRE2 10.39, which is newer than the PCRE2 shipped by\nseveral distributions still in use, such as AlmaLinux 8 and RHEL 8 (10.32),\nUbuntu 18.04 (10.31) and CentOS 7 (10.23), so cmake configure failed there even\nthough the PCRE2 present was perfectly usable.\n\nSWIG only uses PCRE2 API that has been available since the very first release,\n10.00, so no minimum version is needed. This matches configure, which passes an\nempty version to AX_PATH_GENERIC and so accepts any PCRE2.\n\nTested by building with each of PCRE2 10.00, 10.10, 10.20, 10.23, 10.30, 10.32,\n10.36 and 10.39: all compile without warnings and generate identical wrappers\nfor the tests that use PCRE2 regular expressions.\n\nCloses #3555\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "e849557108a7bd7a32c2aa070a7714fb115fa3f1",
      "tree": "7735160ff097276ecf1684e685dc3b2eb3c1ee92",
      "parents": [
        "5872e9b4176cf59ce4e31b010c29a4cebf32960f"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Thu Sep 03 12:04:35 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Thu Sep 03 12:15:45 2026 +0100"
      },
      "message": "Add void parameter list name matching tests and docs\n\n#3556 A (void) parameter list must be matched exactly by %ignore, %rename\nand %feature, an empty parameter list does not match. This has always been\nthe case for global functions and since 1d9ace9f8 applies to class members\ntoo, so document it and add tests.\n\nvoidtest now has three %ignore directives using (void) covering a global\nfunction, a static member function and a non-static member function. The\nfunctions are declared to SWIG only and not defined in the C++ code, so the\nwrappers fail to compile should an %ignore stop matching. Three more\nfunctions of the same three kinds are renamed via a (void) match and called\nfrom the Python runme.\n\nAlso add a retrospective potential incompatibility note to the CHANGES entry\nfor the change.\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "5872e9b4176cf59ce4e31b010c29a4cebf32960f",
      "tree": "85277d5bbe28a36129aac22580ba6371fb2992c1",
      "parents": [
        "1f7acd59777090ee67fc307a6c1633cbf66881d7"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Fri Aug 28 00:03:34 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Fri Aug 28 13:14:03 2026 +0100"
      },
      "message": "Fix format %rename dropping a class template\u0027s partial specializations\n\nA %rename using a format string, such as the %rename(\"%(camelcase)s\") that\nRuby\u0027s -autorename applies to every class, had the template parameters\nstripped from the name before substitution. Each of a class template\u0027s\npartial specializations was therefore renamed to the name of the primary\ntemplate and dropped as a redefinition, so under -autorename std::vector\u0027s\nbool and pointer specializations produced no wrapper at all.\n\nThe stripping added in ce06e2f is needed for an instantiation created by\n%template, but not when parsing a template declaration, which is never\nwrapped under the name being substituted. need_name_warning() in the same\nfile already makes this distinction for the same reason.\n\nGating on the node being a class instead would also disable the stripping\nfor instantiated class templates and so regress the advanced template\nrenaming added in ce06e2f, including %interface_impl applied to a class\ntemplate. The tests added in 0b90e5130 cover that.\n\nRemove ruby_naming from the Ruby FAILING_CPP_TESTS list as the test added\nin 1f7acd597 now passes.\n\nCloses #3546\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "1f7acd59777090ee67fc307a6c1633cbf66881d7",
      "tree": "7d9212329dc4ba5fc15e394d31a25dc4ca1465f7",
      "parents": [
        "0b90e5130bd3fdcb0b26fbc3fc3e9f5a6173a945"
      ],
      "author": {
        "name": "Bradley Lowekamp",
        "email": "blowekamp@mail.nih.gov",
        "time": "Fri Aug 28 00:02:12 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Fri Aug 28 00:02:12 2026 +0100"
      },
      "message": "[Ruby] Add test for -autorename dropping std::vector partial specializations\n\nUnder -autorename, std::vector\u0027s bool and pointer partial specializations\ncollide with the primary template\u0027s default name and are dropped as a\nredefinition, so %template(VectorBool) produces no wrapper at all.\n\nThe test fails until this is fixed, so add ruby_naming to the Ruby\nFAILING_CPP_TESTS list for now.\n\nSee #3546\n"
    },
    {
      "commit": "0b90e5130bd3fdcb0b26fbc3fc3e9f5a6173a945",
      "tree": "3ebd06fbae406f8c02bf346b17b2b57aeb8f400e",
      "parents": [
        "03ec714c0b67cd45322354189c23e115812aeede"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Fri Aug 28 00:01:38 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Fri Aug 28 00:01:38 2026 +0100"
      },
      "message": "Add tests for advanced renaming of instantiated class templates\n\nThe advanced %rename support for templates added in ce06e2f works for\ninstantiated class templates as well as function templates, but only the\nfunction template cases were tested.\n\nAdd the three class template cases to template_advanced_rename, mirroring\nits existing function template cases, and extend the interface tests in\nmultiple_inheritance_interfaces with %interface_impl applied to an\ninstantiated class template. %interface_impl expands to a\n%rename(\"%sSwigImpl\") on a class, so the Java runtime test now also checks\nthat the interface, its implementation and a derived proxy class are all\ngenerated.\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "03ec714c0b67cd45322354189c23e115812aeede",
      "tree": "830a7a71112cff22b0f8b2e60077aeb6376bd0fe",
      "parents": [
        "223754e43d0c3e93cdf092f22e281a2aabc19313"
      ],
      "author": {
        "name": "Erez Geva",
        "email": "ErezGeva2@gmail.com",
        "time": "Thu Aug 27 09:01:29 2026 +0200"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Aug 27 08:01:29 2026 +0100"
      },
      "message": "Update Lua li_typemaps with recent changes (#3544)\n\nSigned-off-by: Erez Geva \u003cErezGeva2@gmail.com\u003e"
    },
    {
      "commit": "223754e43d0c3e93cdf092f22e281a2aabc19313",
      "tree": "5ded2a72da5c33270329a4652ef498d76a9e381e",
      "parents": [
        "2066f34425c7e5a73d672f0dc50553b5861a98cb"
      ],
      "author": {
        "name": "Erez Geva",
        "email": "ErezGeva2@gmail.com",
        "time": "Thu Aug 27 09:01:14 2026 +0200"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Aug 27 08:01:14 2026 +0100"
      },
      "message": "[Java, C#, D] Add multiple parameters to li_typemaps (#3545)\n\nSigned-off-by: Erez Geva \u003cErezGeva2@gmail.com\u003e"
    },
    {
      "commit": "2066f34425c7e5a73d672f0dc50553b5861a98cb",
      "tree": "3dcf0ef8c642a7c76e457a545c9f2109d6a1afeb",
      "parents": [
        "b0f7fce8b06d4d27ec12431a0f45434e16e34ec6"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Sun Aug 23 16:56:12 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Mon Aug 24 08:09:48 2026 +0100"
      },
      "message": "[Python] Emit SWIGPY_SLICEOBJECT from a fragment\n\nThe definition came from a code block at the top of pycontainer.swg, so it\nreached only the wrapper for the module that included the file. A module that\n%imports such a module and then instantiates a container of its own generates\nthe slice methods into its own wrapper, where the macro was never defined:\n\n  %module b\n  %import \"a.i\"             // a.i already has %include \u003cstd_vector.i\u003e\n  %include \u003cstd_vector.i\u003e\n  %template(DoubleVector) std::vector\u003cdouble\u003e;\n\nThe %include of std_vector.i in \u0027b\u0027 is a no-op, as the file was already read\nwhile processing the %import, so nothing put the definition into the wrapper\nfor \u0027b\u0027 and it failed to compile with \"\u0027SWIGPY_SLICEOBJECT\u0027 was not declared\nin this scope\".\n\nThe definition is now a fragment, pulled in next to SwigPySequence_Base by the\ncontainer macro that generates the slice methods, so it is emitted into every\nwrapper needing it. SWIGPY_SLICEOBJECT remains the type the slice typemaps are\nmatched on and is otherwise unchanged.\n\nThe macro was introduced in swig-4.1.0 and the same problem existed beforehand\nwith the SWIGPY_SLICE_ARG macro added in swig-2.0.4.\n\nReported by rlaboiss in #3537.\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "b0f7fce8b06d4d27ec12431a0f45434e16e34ec6",
      "tree": "aeb592ad9e550ea9c5cd432598298094b9813592",
      "parents": [
        "adc0df83cd0e9a46ef0c12b08552b230cdf874dd"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Sun Aug 23 16:32:49 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Sun Aug 23 17:08:35 2026 +0100"
      },
      "message": "[Python] Enable the pyrefly bad-function-definition check in the test suite\n\nPyrefly runs with no configuration file, so it falls back to its \u0027basic\u0027 preset,\nwhich leaves most checks off. It did not report the wrong annotation fixed by the\nprevious commit, where a parameter\u0027s default value of None was not accepted by\nits own annotation.\n\nForce the bad-function-definition rule on so that this fails the test case.\nRaising the preset to \u0027default\u0027 would turn on more, including explicit-any, which\nthe generated wrappers use deliberately.\n\nThe check only runs with SWIG_FEATURES\u003d-typehints.\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "adc0df83cd0e9a46ef0c12b08552b230cdf874dd",
      "tree": "a383d27b23e0e8de6fba2872b2aa9ee932cfdef0",
      "parents": [
        "9d44a5e0226631331d7bc1f4c12655e09125414f"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Sun Aug 23 16:32:11 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Sun Aug 23 17:08:35 2026 +0100"
      },
      "message": "Test the INPUT, OUTPUT and INOUT typemaps with more than one parameter\n\nli_typemaps had no function taking more than one INPUT parameter, and the\nexisting multi parameter cases were out_foo, which also returns a wrapped\npointer, and inoutr_int2, which uses the reference form. Add a simple function\nfor each of INPUT, OUTPUT and INOUT taking two parameters, with runtime tests\nfor the target languages using the Unified Typemap Library.\n\nR is the exception. It cannot call any of the three: INPUT and INOUT reject a\nplain value and OUTPUT fails in SET_VECTOR_ELT. Both predate this test, as the\nexisting out_int and out_foo fail the same way, so the R runme just says so.\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "9d44a5e0226631331d7bc1f4c12655e09125414f",
      "tree": "d4f6d34fdad57c60d87effab1c428648fe1be76a",
      "parents": [
        "ca70206168b3c4fbce8a085aac18cf605a33cbc5"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Sun Aug 23 16:28:21 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Sun Aug 23 17:08:28 2026 +0100"
      },
      "message": "[Python] Annotate the INPUT, INOUT and OUTPUT typemaps by what they accept\n\nThe pytyping typemaps added for the typemaps.i INPUT, INOUT and OUTPUT typemaps\ngave all six of them the same annotation, the plain wrapped type, which does not\ndescribe what they accept or return:\n\n- OUTPUT uses numinputs\u003d0, so it is not a parameter of the wrapped function at\n  all and always returns a value. The plain type is right.\n- The reference forms reject a null pointer, so they always take a value. The\n  plain type is right for them too.\n- The pointer forms accept a null pointer, which is None, as well as a value, so\n  they need typing.Optional. INOUT returns what it was given, so it returns None\n  when given None and its return type needs typing.Optional as well.\n\nSplit the definition three ways accordingly. This also removes the only case in\nthe library where SWIG generated a None default value for a parameter whose own\nannotation did not accept None, which a static type checker rejects:\n\n  %apply int *INPUT { int *bar };\n  int *foo(int *bar \u003d 0);\n\nwas annotated bar: \"int\"\u003dNone and is now bar: \"typing.Optional[int]\"\u003dNone.\n\nSee #3518.\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "ca70206168b3c4fbce8a085aac18cf605a33cbc5",
      "tree": "ef2d5366ec91bf025e2b2e16cd6bcdea922fd916",
      "parents": [
        "cbdcd40c66912a0d181d6d5c0de4a19cb4266e76"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Sun Aug 23 16:27:30 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Sun Aug 23 16:27:30 2026 +0100"
      },
      "message": "Fix crash passing a null pointer to a reference using the INPUT typemaps\n\nThe INPUT typemaps in typemaps.i accept a pointer as well as a value, as\nSWIG_INPUT_ACCEPT_PTRS is defined by default, and a null pointer converts\nsuccessfully. For Type *INPUT that is fine, the wrapped function is passed the\nnull pointer and can check for it. For Type \u0026INPUT it is not, as a reference\ncannot be bound to a null pointer: the wrapper dereferenced it when making the\ncall and crashed.\n\nGive Type \u0026INPUT its own in typemap adding a null check, so a null pointer is\nrejected with a null reference error. This is what the SWIGTYPE \u0026 typemaps\nalready do by passing SWIG_POINTER_NO_NULL, and what the INPUT typemaps for\ntypes such as std::string already do in %_ptr_input_typemap. Type *INPUT is\nunchanged. Type \u0026INOUT picks up the fix too, as its in typemap is copied from\nType \u0026INPUT.\n\nAdd a runtime test for this to li_typemaps for each of the target languages\nusing the Unified Typemap Library. Every one of them crashed before the fix.\nThe R proxy coerces its argument with as.integer(), which turns the null value\ninto integer(0) before it reaches the wrapper, so the R test calls the wrapper\ndirectly in order to pass a null pointer to it.\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "cbdcd40c66912a0d181d6d5c0de4a19cb4266e76",
      "tree": "ed552e1248f6f368dcc26029b450a29ed97c7d14",
      "parents": [
        "3c22ac7d61021aa47eba242235ee7b5dd08aa135"
      ],
      "author": {
        "name": "Nerixyz",
        "email": "nerixdev@outlook.de",
        "time": "Tue Jul 28 19:18:02 2026 +0200"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Sun Aug 23 00:07:42 2026 +0100"
      },
      "message": "[Python] Support INOUT/INPUT/OUTPUT for pytyping\n\nCorrects the pytyping types used for the INOUT, INPUT, OUTPUT typemaps\nto use the exact type rather than the catch-all typing.Any.\n\nThe python_typehints test cases using them are annotated with the real types\nrather than typing.Any.\n"
    },
    {
      "commit": "3c22ac7d61021aa47eba242235ee7b5dd08aa135",
      "tree": "3fe29dec0a190a3b01ac8ac5c440f991e51ef494",
      "parents": [
        "b47093524a8f27152e500eef20db32f9762e746a"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Fri Aug 21 19:25:19 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Sat Aug 22 14:56:18 2026 +0100"
      },
      "message": "[Python] Test an argout container that Python does not annotate\n\nThe container attribute names the container the argout typemaps append into\nand is not restricted to the list and tuple Python knows how to describe. A\ntypemap appending characters to a string is annotated with the catch-all type,\nwhich the python:annotations:catchall feature can supply the real type for.\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "b47093524a8f27152e500eef20db32f9762e746a",
      "tree": "b24c948c68f0def0bbc9964fabd64fd5e9532287",
      "parents": [
        "71c6dc62f10616fe983be681f590bc655dda77a1"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Fri Aug 21 19:21:54 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Sat Aug 22 14:55:59 2026 +0100"
      },
      "message": "[Python] Document the pytyping out attribute for argout parameters\n\nAn argout parameter is a returned value, so the out attribute of its pytyping\ntypemap is used in preference to the typemap body, which annotates the\nparameter. The body is unused by the examples in this section as their in\ntypemaps declare numinputs\u003d0, leaving nothing for it to annotate.\n\nSuggested by Nerixyz in #3532.\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "71c6dc62f10616fe983be681f590bc655dda77a1",
      "tree": "94562f85c369794bf75c7e9ad1cc54a661380db6",
      "parents": [
        "1f0ab388c1ede9a57e09b3fd8ff303f1185a0ac3"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Tue Aug 18 09:01:30 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Sat Aug 22 14:55:47 2026 +0100"
      },
      "message": "[Python] Attach the pytyping typemaps to the parameters just once\n\ncollectOutputTypes() copied the parameter list before attaching the pytyping\ntypemaps to it, but Swig_typemap_attach_parms() only sets attributes named\nafter the typemap method it is attaching, so it cannot disturb the in, argout\nand other typemaps the wrapper was generated from. Attaching to the parameter\nlist itself is what the other target languages do and lets wrap:outputparms\nstay on the node, rather than having to be deleted again because the\nparameters it points at are about to be freed.\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "1f0ab388c1ede9a57e09b3fd8ff303f1185a0ac3",
      "tree": "e23906f083d5540d9240be0b35cc1f6831190aa6",
      "parents": [
        "064ef86187d5b6a5ff973cda2fc8e5a2e9d6c1c2"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Fri Aug 14 22:20:49 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Sat Aug 22 14:55:36 2026 +0100"
      },
      "message": "[Python] Supply the argout return annotation SWIG cannot work out\n\nWarning 478 says that SWIG cannot work out the type of the values returned,\nwhich is not the same as there being no type. The values are nested in a way\nthat depends on the order the argout typemaps run in, which whoever wrote\nthose typemaps knows.\n\nThe new python:annotations:catchall feature supplies the annotation for one\nnamed function, and it is used in place of the catch-all typing.Any:\n\n  %feature(\"python:annotations:catchall\") tuple_then_list\n    \"typing.List[typing.Union[typing.Tuple[bool, int], int]]\"\n\nSupplying it also suppresses warning 478 for that function, as the feature\nsupplies what the function returns, so there is nothing left for the\nwarning to report. emit_output_summary() takes a parameter saying whether to\nwarn, as it is the target language that knows the type has been supplied.\n\nThe feature supplies a PEP 484 type, which the C/C++ annotation types have no\nuse for, so it neither annotates nor suppresses the warning in that mode.\n\nSuggested by Nerixyz in #3532.\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "064ef86187d5b6a5ff973cda2fc8e5a2e9d6c1c2",
      "tree": "934a887a3e3a336ecf4a1e27d9adb59bf743ca7a",
      "parents": [
        "f37a89ee30a72c6e9f4e7eb39910fa375bedab36"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Fri Aug 14 22:19:18 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Sat Aug 22 14:55:22 2026 +0100"
      },
      "message": "[Python] Test the annotation when the argout containers clash\n\nWarning 478 is issued when the argout typemaps matched for one function do\nnot all build the same container, and the return type is then annotated\ntyping.Any. The errors test-suite covers the warning, but nothing covered\nthe annotation it leads to or what such a function returns.\n\nThe documentation gains the text of warning 478 and an example showing that\nwhat is returned depends on the order the argout typemaps run in.\n\nReported by Nerixyz in #3532.\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "f37a89ee30a72c6e9f4e7eb39910fa375bedab36",
      "tree": "7ce4789975d6b71f7acf29fce4bb310f67aac60c",
      "parents": [
        "0d6472826a9fb6c46e36e331cd7a8559efa4e5ff"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Mon Aug 10 08:27:19 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Fri Aug 21 19:46:06 2026 +0100"
      },
      "message": "[Python] Annotate a suppressed return value in C annotation mode\n\nThe C annotations describe a function with argout typemaps by the types of its\nargout parameters, and fall back to the function return type when there are none.\nAn out typemap declaring numoutputs\u003d0 leaves nothing at all to return, so falling\nback described the function by a return type it does not return. It is now\nannotated void, the same as a function that returns nothing to begin with.\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "0d6472826a9fb6c46e36e331cd7a8559efa4e5ff",
      "tree": "70026e78c132bcd53302dd736a0c0f2dc8fe7882",
      "parents": [
        "2856c19acc80500f6a5119be8da78b6a3a578711"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Sun Aug 09 21:57:45 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Fri Aug 21 19:45:59 2026 +0100"
      },
      "message": "Use the container an overwriting argout typemap builds for a single value\n\nThe container attribute means two different things depending on the typemap it is\non. On an appending typemap it is what the typemap appends into, and a lone value\nis returned on its own rather than in a container. On an overwriting typemap it is\nwhat the typemap assigns to $result, so a lone value is in the container too.\n\nOnly the first was taken into account, so a function whose only returned value came\nfrom an overwriting typemap building a tuple was annotated with the type of the\nvalue rather than a tuple holding it.\n\nemit_output_summary() now records which of the two the container came from in the\nnew wrap:outputcontainerbuilt attribute.\n\nLeaving the attribute off an overwriting typemap says something else again: that\nthe type of the value already describes everything the typemap assigns and nothing\nfurther wraps it. That is what the case in #3469 needs, where the type describes\nthe whole list the typemap builds.\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "2856c19acc80500f6a5119be8da78b6a3a578711",
      "tree": "d7e76618344268b9e1818ed97ecda528fe730028",
      "parents": [
        "5390ba16e6f6beb29c32ddeedcb4161b58b34d23"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Sun Aug 09 21:55:18 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Fri Aug 21 19:45:59 2026 +0100"
      },
      "message": "Substitute $isvoidresult in all target languages\n\n$isvoidresult was documented as a general special variable but only the Python\nmodule substituted it. Every other module substituted $isvoid, of which\n$isvoidresult is a prefix, so a typemap using $isvoidresult in any other target\nlanguage was left with text such as 1result in the generated code.\n\nBoth special variables are now substituted by emit_isvoid_special_variables(),\nso the substitution order is decided in one place rather than in each of the\nseventeen modules that used to do it.\n\nThe Lua director method emitter replaced $symname only, so it substituted\nneither special variable and a director typemap using one kept the $ in front of\nthe name, which does not compile. It now substitutes them where the other target\nlanguages supporting directors do.\n\nThe typemap_isvoid test-suite case now uses $isvoidresult alongside $isvoid, so\nthe wrong order fails to compile in every target language.\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "5390ba16e6f6beb29c32ddeedcb4161b58b34d23",
      "tree": "867a2b7489e3a8f64afa3e38a497e02d9e191224",
      "parents": [
        "03726eef6d6d7d16eddabb92fd8e925d017ba19b"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Sun Aug 09 21:50:45 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Fri Aug 21 19:45:59 2026 +0100"
      },
      "message": "[Python] Annotate a suppressed return value with no argout typemaps\n\nThe return annotation was only worked out for a function with at least one argout\ntypemap, on the basis that nothing else can make the returned values differ from\nthe function return value. An out typemap declaring numoutputs\u003d0 does exactly\nthat, so a function using one without any argout parameters was annotated with\nits C++ return type while returning None at runtime.\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "03726eef6d6d7d16eddabb92fd8e925d017ba19b",
      "tree": "a8eb92bb489141ce4a4c487a1286f9d348bc9783",
      "parents": [
        "1aaf899c09a382920dbaaa40975473eea22024a4"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Sun Aug 09 21:49:43 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Fri Aug 21 19:45:59 2026 +0100"
      },
      "message": "Take a void return into account for $isvoidresult\n\nA void function has no return value for the argout typemaps to append to, which\n$isvoid said and $isvoidresult must say too. It was derived solely from the out\ntypemap numoutputs attribute, which defaults to 1, so a user defined out typemap\nfor void reported that there was a return value to append to. A single argout\nvalue was then appended to the None the out typemap sets, and the wrapped\nfunction returned [None, value] rather than value.\n\nThe out typemaps in the typemaps library declare numoutputs\u003d0 for void, so this\nonly affected a void out typemap written by the user.\n\nemit_output_summary() worked the returned values out the same way and so also\ndescribed such a function as returning its void return value.\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "1aaf899c09a382920dbaaa40975473eea22024a4",
      "tree": "6846696a32ac894f84043600a755d64a048d00b8",
      "parents": [
        "5bcc69240435f2d444884da619e0abd3dc9f63ac"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Sun Aug 09 14:14:15 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Fri Aug 21 19:45:59 2026 +0100"
      },
      "message": "Reject an invalid numinputs value in an in typemap\n\nGetInt() uses atoi(), which quietly turns anything it cannot parse into zero, so\na mistyped numinputs value such as numinputs\u003d\"abc\" was silently taken to mean\nnuminputs\u003d0 and the parameter was dropped from the wrapped function.\n\nThe value is now checked before use and has to be written as a non-negative\ninteger. This matches the check already done on the numoutputs attribute of the\nout and argout typemaps, which shares the same helper.\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "5bcc69240435f2d444884da619e0abd3dc9f63ac",
      "tree": "e63dc92759a8690e2be58b79f5f69fbef16faac9",
      "parents": [
        "b8aaf882b954ba6f3e6d2c46137474c86bed8f64"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Sat Aug 08 22:24:06 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Fri Aug 21 19:45:59 2026 +0100"
      },
      "message": "Add the container attribute to the argout typemap\n\nAn argout typemap using a replacement for SWIG_AppendOutput can build something\nother than the list the default helper builds. The container attribute says\nwhich, defaulting to \"list\" with \"tuple\" also supported, so that a target\nlanguage describing the return type of a wrapped function can name the right\none.\n\nThe container is a property of the whole function, as all the argout typemaps\nappend into the same $result. Mixing typemaps that build different containers\nproduces a nested result that no single type describes, so warning 478 is issued\nand the return type is left undescribed.\n\nLanguage::composeOutputType() is where a target language turns the values worked\nout by emit_output_summary() into a single type. The Python implementation\ncomposes typing.List[typing.Union[...]] or typing.Tuple[...] from the container,\nand typing.Any when warning 478 has been issued. The default implementation only\nhandles a single returned value.\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "b8aaf882b954ba6f3e6d2c46137474c86bed8f64",
      "tree": "23bcd6904b11320a0e5f2ef32fdd73d927a348b3",
      "parents": [
        "294107103c3dce24f8b9183a87e2b32a3ecab7f5"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Sat Aug 08 22:19:35 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Fri Aug 21 19:45:59 2026 +0100"
      },
      "message": "[Python] Use the argout numoutputs and overwrite attributes in annotations\n\nPEP 484 return annotations assumed every argout typemap appends exactly one\nvalue, which is the convention followed by the typemaps.i OUTPUT family but not\na requirement. An argout typemap that only checks an error code, or that\noverwrites $result instead of appending to it, was described as if it had\nappended a value, so the annotation did not match what the function returns.\n\nThe annotation is now built from emit_output_summary(), which works the returned\nvalues out from the numoutputs and overwrite attributes. A typemap declaring\nnumoutputs\u003d0 contributes nothing and one declaring overwrite\u003d1 discards the\ntypes collected before it, including the function return type.\n\nThis also makes the annotation exact where it was merely wide before. A function\nwith a replacing argout followed by an appending one is now annotated\ntyping.List[typing.Union[str, int]] rather than including the discarded return\ntype as well.\n\nAnnotations are unchanged for typemaps that do not use the new attributes.\n\nThe test cases from Nerixyz in #3469 are incorporated into the\npython_annotations_typing test-suite case.\n\nSee #3469 and #684.\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "294107103c3dce24f8b9183a87e2b32a3ecab7f5",
      "tree": "9464e77f76057b7d7d90f2640f3883e46514ed75",
      "parents": [
        "dcb21d7e298e82d4a951834f3418f6ae8a9d313d"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Sat Aug 08 22:13:45 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Fri Aug 21 19:45:47 2026 +0100"
      },
      "message": "Add $isvoidresult and support numoutputs\u003d0 in the out typemap\n\nAn out typemap declaring numoutputs\u003d0 does not return the function return value,\nso the values returned to the target language are only those appended by the\nargout typemaps. This suits a C function that reports errors through its return\nvalue, where the error becomes an exception and only the argout values matter.\n\nPreviously such an interface had to push a placeholder from the out typemap and\nunpick it again from a ret typemap, because SWIG_AppendOutput only discards the\nplaceholder when the C++ return type is void. This regressed in 4.3.0 when the\nis_void argument was added to SWIG_AppendOutput, see #3084.\n\nThe new $isvoidresult special variable expands to 1 when the wrapper has no\nreturn value of its own, which is a void return or an out typemap declaring\nnumoutputs\u003d0. The Python SWIG_AppendOutput macro uses it in place of $isvoid.\n$isvoid keeps its existing meaning of describing the C++ return type, which the\ncheck and ret typemaps rely on. $isvoidresult is substituted before $isvoid\nbecause $isvoid is a prefix of it.\n\nGenerated code is unchanged for existing interfaces.\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "dcb21d7e298e82d4a951834f3418f6ae8a9d313d",
      "tree": "1e021955916333bd2116380351947a9dc945d4ab",
      "parents": [
        "b4825b744ed994476bc3db43072c2ca3573c79bb"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Sat Aug 08 22:08:23 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Sun Aug 16 23:07:21 2026 +0100"
      },
      "message": "Add numoutputs, overwrite and container attributes to the out and argout typemaps\n\nThe number of values a wrapped function returns to the target language could\nonly be guessed at from the presence of an argout typemap, which assumes every\nargout typemap appends exactly one value. That is a convention followed by the\ntypemaps.i OUTPUT family, not a requirement, and argout typemaps that check an\nerror code without returning anything, or that overwrite $result instead of\nappending to it, are equally valid and are used in the SWIG documentation and\ntest suite.\n\nAttributes now let a typemap say what it does:\n\n  %typemap(argout, numoutputs\u003d0)     - contributes no returned value\n  %typemap(argout, overwrite\u003d1)      - discards the values accumulated so far\n  %typemap(argout, container\u003d\"tuple\")- appends into something other than a list\n  %typemap(out, numoutputs\u003d0)        - the function return value is not returned\n\nnumoutputs defaults to 1 and container to \"list\", so existing typemaps are\nunaffected. Only 0 and 1 are accepted for numoutputs, and an unparseable value\nis rejected rather than being quietly treated as 0 by GetInt(), which uses\natoi(). The check uses the new is_non_negative_integer() utility.\n\nemit_output_summary() works the returned values out from these attributes and\nrecords them on the node for the target language modules to use. It is the\noutput side counterpart of emit_num_arguments(). All the argout typemaps for a\nfunction append into the same $result, so they must agree on the container;\nwarning 478 reports it when they do not. No module uses any of this yet.\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "b4825b744ed994476bc3db43072c2ca3573c79bb",
      "tree": "5d2823cf7471b6d14de1cd2fb6c752256cc1ad2e",
      "parents": [
        "8338859a0af932304a1f8be5c57869346cc53176"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Sat Aug 08 22:04:15 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Sun Aug 16 23:07:21 2026 +0100"
      },
      "message": "[Python] Refactor argout return annotation into collect and format steps\n\nSplit argoutReturnTypeAnnotation() into collectOutputTypes(), which gathers one\ntype string per value the wrapped function returns, and formatOutputTypes(),\nwhich combines them into a single annotation. The aggregation shape was\npreviously built by string surgery spread across the collection loop, opening\n\"typing.List[typing.Union[\" on the transition from one returned value to two and\nclosing \"]]\" after the loop had finished.\n\nCollecting the types before formatting them keeps the two halves independent, so\nwhat is returned can be worked out without also deciding how to describe it.\n\nGenerated output is unchanged.\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "8338859a0af932304a1f8be5c57869346cc53176",
      "tree": "a14b47882dfd3ef4441153cbf42072b4c241e398",
      "parents": [
        "1af9fdd94243b546e81330389062559cb1b69f1a"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Sat Aug 08 22:20:34 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Sun Aug 16 23:07:21 2026 +0100"
      },
      "message": "[Python] Do not annotate the return type of __init__\n\nA constructor with a parameter using an argout typemap was given a return\nannotation built from the argout typemaps, such as\n\n  def __init__(self, v: \"int\") -\u003e \"typing.List[typing.Union[typing.Any, None]]\":\n\nPython requires __init__ to return None, and a constructor without such a\nparameter never had a return annotation, so drop it altogether.\n\nThis also removes the only way of reaching a malformed annotation. The\nannotation was built by opening \"typing.List[typing.Union[\" on the transition\nfrom one returned value to two and closing \"]]\" after the last one. When the\npytyping typemap lookup for the return type failed, which happened for\nconstructors and nothing else, the opening bracket was never written but the\nclosing \"]]\" still was, giving annotations such as -\u003e \"int]]\".\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "1af9fdd94243b546e81330389062559cb1b69f1a",
      "tree": "fa59591f36a33441a73b128ddf7e758951fbbd33",
      "parents": [
        "1861921967a2b7f116ff2fdc818a9a2fd1595a1f"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Fri Aug 14 20:21:15 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Fri Aug 14 22:17:40 2026 +0100"
      },
      "message": "Fix stray punctuation in cpp14_auto_return_type.i comments (S15)\n\nTwo comments ended with \u0027:.\u0027 - a colon followed by a full stop. Use a single\nfull stop.\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "1861921967a2b7f116ff2fdc818a9a2fd1595a1f",
      "tree": "6151233596658a6a5a8f4ba1ba005b4aa2bdfc07",
      "parents": [
        "dd5f38bb4e4c11c19f68fd6be5fe4c6dcd4438e0"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Fri Aug 14 20:21:10 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Fri Aug 14 22:17:40 2026 +0100"
      },
      "message": "Use the same bison warning flags in the CMake build (S13)\n\nSource/Makefile.am builds the parser with AM_YFLAGS \u003d -d -Wall -Werror, but\nCMakeLists.txt called BISON_TARGET with no COMPILE_FLAGS. Bison diagnostics\nthat fail the autotools build, such as a grammar conflict beyond the declared\n%expect count, were therefore accepted silently by the CMake build. Pass the\nsame flags so the two build systems agree on what is an error.\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "dd5f38bb4e4c11c19f68fd6be5fe4c6dcd4438e0",
      "tree": "f7a323b0e9c73a6eeaeb89dfe8ee0ba99d092c0b",
      "parents": [
        "1cf842d140c7f10ae432a7d4bebca2cd456d8c67"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Fri Aug 14 20:21:05 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Fri Aug 14 22:17:40 2026 +0100"
      },
      "message": "[Javascript, PHP] Stop warning 314 repeating the new name (S12)\n\nSwig_name_warning() appends a \", renaming to \u0027x\u0027\" clause to a keyword warning,\nbut the JAVASCRIPTKW and PHPKW_ok_as_function macros spelled the rename out in\ntheir own message text as well, so the warning said it twice:\n\n  Warning 314: \u0027this\u0027 is a javascript keyword, renaming to \u0027_this\u0027, renaming to \u0027_this\u0027\n\nStop the message at the keyword name, as the Java, C# and other PHP keyword\nmacros already do. This also removes a second place that had to be kept in step\nwith the rename\u003d prefix.\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "1cf842d140c7f10ae432a7d4bebca2cd456d8c67",
      "tree": "8f2c92434ae666f16835725cccb046ff3b296698",
      "parents": [
        "761661750f4cb0ca0fe322dbf1705bf5ea7c7b5a"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Fri Aug 14 20:20:55 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Fri Aug 14 22:17:40 2026 +0100"
      },
      "message": "[Octave] Show a null pointer default value as the empty matrix (S8)\n\nconvertValue() returned the Python literal \"None\" for a parameter defaulting\nto nullptr, NULL or a null pointer constant, which was copied from the Python\nmodule and is not an Octave value. The result is used only for the texinfo\ndocumentation generated by the autodoc feature, so a wrapped function was\ndocumented with a default argument no Octave user could type.\n\nUse \"[]\" instead. The empty matrix is what the Octave runtime converts to a\nnull pointer, and what it returns for one, so it is the Octave spelling of the\nsame value.\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "761661750f4cb0ca0fe322dbf1705bf5ea7c7b5a",
      "tree": "e8f14f9d165e49d68603abc174c9a03f4186829a",
      "parents": [
        "3d29bd559c63ca1221c9e5e8e9b451dddf499b9a"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Thu Aug 13 21:15:26 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Fri Aug 14 22:17:40 2026 +0100"
      },
      "message": "Parse a C++17 structured binding\n\nA structured binding at namespace or class scope was a syntax error, in every\nspelling the placeholder can carry:\n\n  auto [a, b] \u003d pt;\n  auto\u0026 [c, d] \u003d pt;\n  const auto\u0026 [e, f] \u003d pt;\n  auto\u0026\u0026 [g, h] \u003d Pt{1, 2};\n  static auto [i, j] \u003d pt;\n\nThe names are bound to the elements of the initialiser, and giving each one a\ntype means knowing how that initialiser decomposes: for a class type from its\nmembers, for an array from its length, and for a tuple-like type from the\nstd::tuple_size and std::tuple_element specialisations for it. SWIG resolves\nnone of these, so there is nothing to base a wrapper on and the declaration is\nparsed and ignored with the new warning 349.\n\nThe value of parsing it is recovery. A syntax error here stopped the rest of\nthe file being parsed, so a single structured binding in a header hid every\ndeclaration after it.\n\nThe initialiser has an error alternative alongside the ordinary one because a\nbraced initialiser such as the \u0027Pt{1, 2}\u0027 of an \u0027auto\u0026\u0026\u0027 binding is not one the\nexpression grammar accepts.\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "3d29bd559c63ca1221c9e5e8e9b451dddf499b9a",
      "tree": "43b5ac19550ed7731617ea27a54419707d887f00",
      "parents": [
        "35c8c6d84207ce7da7a231f422553449bc6c4407"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Thu Aug 13 21:07:24 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Fri Aug 14 22:17:40 2026 +0100"
      },
      "message": "Add support for the decltype(auto) placeholder\n\nThe C++14 \u0027decltype(auto)\u0027 placeholder was a syntax error in every position\nC++ allows it in: a variable, a return type, a member function, a conversion\nfunction, a trailing return type and a lambda return type.\n\nThe error could not be recovered from either. The operand of decltype is\nmatched by an expression rule with an \u0027error RPAREN\u0027 fallback, which calls\nskip_balanced() to step over the operand. By that point the scanner has already\nconsumed the opening parenthesis, so there was no balanced group left to skip\nand the rest of the file was swallowed, ending in \u0027Missing ). Reached end of\ninput.\u0027\n\nRather than extend the expression rule, the placeholder is now an alternative\nof auto_type_holder, the rule every use of the \u0027auto\u0027 placeholder already goes\nthrough. That is what makes all six positions work at once, and it keeps the\nnew spelling out of the expression grammar, so a decltype whose operand is an\nexpression is unaffected. No new parser conflicts, so %expect stays at 7.\n\nNote this does not fix issue #3041, which reports the same error message for a\ndecltype whose operand is an expression SWIG cannot parse, such as\n\u0027decltype(\"abc\"[1])\u0027 or \u0027decltype(1 \u003c 2)\u0027. Those still consume the rest of the\nfile. The \u0027error RPAREN\u0027 fallback it analyses is untouched here, the\nplaceholder simply no longer reaching it.\n\nThe trailing return type of a function now shares the rule the lambda return\ntype used, renamed from lambda_rettype to trailing_rettype since it is no\nlonger specific to a lambda. The placeholder is kept out of\ncpp_alternate_rettype because that rule is also used by the alias declaration,\nwhere a deduced return type is ill-formed.\n\nDeduction differs from \u0027auto\u0027: \u0027decltype(auto)\u0027 deduces the declared type of\nthe initialiser exactly, keeping the references and top level cv-qualifiers\nthat \u0027auto\u0027 drops. C++ requires the type to be \u0027decltype(auto)\u0027 on its own, so\nthere is no declarator decoration or cv-qualifier to account for and the\ndeduced type is used as it stands. Without this a \u0027decltype(auto)\u0027 variable\ninitialised from a const variable was wrapped as non-const, and the generated\nsetter did not compile.\n\nThe scanner ends a conversion function name at the opening parenthesis, which\ntruncated \u0027operator decltype(auto)\u0027 to \u0027operator decltype\u0027. It now takes the\nparenthesised operand of decltype into the name, so the name a diagnostic\nprints and the name a %rename or %warnfilter has to use are the same.\n\nWarning 345 advised adding a trailing return type even when no trailing return\ntype could help, which is the case when the trailing return type is itself a\nplaceholder, as in \u0027auto f() -\u003e auto\u0027, and when the declaration is a conversion\nfunction, which cannot have one at all. Those two now get a message without the\nadvice. This corrects the wording for \u0027operator auto()\u0027 and \u0027-\u003e auto\u0027 as well,\nboth of which are new in this release.\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "35c8c6d84207ce7da7a231f422553449bc6c4407",
      "tree": "08c41c9df27804ae40d0b2597868a781b2275223",
      "parents": [
        "6602551a49ddf9f29464d38906087814ea92f61f"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Thu Aug 13 20:07:48 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Fri Aug 14 22:17:40 2026 +0100"
      },
      "message": "Accept an undecorated auto parameter pack\n\nA C++20 abbreviated function template could introduce a parameter pack only\nwhen the placeholder carried a reference or pointer decoration. The decorated\nspellings parsed:\n\n  int sum(const auto\u0026... args) { return (args + ... + 0); }\n  int sum(auto\u0026\u0026... args) { return (args + ... + 0); }\n  int sum(auto*... args) { return (args + ... + 0); }\n\nwhile the undecorated one was a syntax error:\n\n  int sum(auto... args) { return (args + ... + 0); }\n\nThe decorated spellings parsed because the ellipsis is part of the declarator\nthere, the declarator having already been started by the reference or pointer.\nNothing follows an undecorated placeholder for the declarator to start with, so\nthe ellipsis looked like the one ending a C style variadic parameter list.\n\nThe parameter rule now takes the undecorated pack directly. The invented\ntemplate parameter is marked variadic, so the wrapper takes its arity from the\npack in the same way as one written with an explicit template parameter pack.\n\nThis also covers a non-type template parameter pack, template\u003cauto... Ns\u003e.\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "6602551a49ddf9f29464d38906087814ea92f61f",
      "tree": "d7884bcd7fa8c7a8b72e6aa27a10837014378c48",
      "parents": [
        "8bebe156ab1f6fa0ecaa574191fba983fd0d4f8d"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Thu Aug 13 18:46:59 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Fri Aug 14 22:17:40 2026 +0100"
      },
      "message": "Clarify the spaceship operator section of the manual and retire warning 397\n\nImprove the spaceship operator documentation.\n\nRetire warning 397, WARN_IGNORE_OPERATOR_LTEQUALGT, \"operator\u003c\u003d\u003e ignored\".\nIt has never been possible to emit it: %ignoreoperator is only applied to new,\ndelete, new[] and delete[] in Lib/swig.swg, and no target language library adds\nLTEQUALGT to that set, so nothing ever attaches the message to a node. What a\nuser actually gets is warning 503 for an unrenamed \u0027operator\u003c\u003d\u003e\u0027 and warning 345\nfor the defaulted spelling.\n\nRetired following 341, 342, 343 and 101-110: comment the define out in place in\nswigwarn.h so the number is not reused, delete the _MSG define from\nLib/swigwarnings.swg, and remove the entry from the manual warning list.\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "8bebe156ab1f6fa0ecaa574191fba983fd0d4f8d",
      "tree": "7f858a1749fb22687cdc4e8cb0b793efce931cb2",
      "parents": [
        "de430079f15879b86d4374e9107e241b40833b9d"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Wed Aug 12 19:59:32 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Fri Aug 14 22:17:40 2026 +0100"
      },
      "message": "Accept a cv-qualifier on a defaulted or deleted auto function\n\nCommit 23fe4ce53 made the \u0027auto\u0027 declaration rule take a declarator, which\nincidentally made a defaulted or deleted function with an \u0027auto\u0027 return type\nparse. It only covered the ones with nothing between the parameter list and\nthe \u0027\u003d\u0027, so the canonical C++20 defaulted three-way comparison operator was\nstill a syntax error:\n\n  struct S {\n    int v;\n    auto operator\u003c\u003d\u003e(const S\u0026) const \u003d default;\n  };\n\nThe declaration now takes the same cv-qualifier, ref-qualifier,\nnoexcept-specifier and trailing requires-clause as any other function\ndeclaration. As before, SWIG cannot deduce the return type, so a defaulted\nfunction is ignored with warning 345 and a deleted one silently.\n\nThe lambda declaration shares the same prefix and had to take the qualifier\ntoo, where it is always empty, so that the two can be told apart by the token\nafter the \u0027\u003d\u0027.\n\nAdds the tests owed for the cases 23fe4ce53 fixed as well as the ones fixed\nhere.\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "de430079f15879b86d4374e9107e241b40833b9d",
      "tree": "d230709174f619ea4aa78733431f2fac90186cd0",
      "parents": [
        "571a393c03e79323c37a90540c8f2b7b8879e622"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Wed Aug 12 19:44:01 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Fri Aug 14 22:17:40 2026 +0100"
      },
      "message": "Accept a trailing return type in an alias declaration\n\nThe typedef spelling of a function type written with the C++11 alternate\nfunction syntax parsed, but the using spelling of the same type did not:\n\n  typedef auto (*FP)(int) -\u003e int;   // accepted\n  using FP \u003d auto (*)(int) -\u003e int;  // syntax error\n  using F \u003d auto() -\u003e int;          // syntax error\n\nBoth spellings are now accepted and give the same type, for an alias\ndeclaration and for an alias template. The declarator is taken as written\nrather than through plain_declarator, which drops a function declarator, so\n\u0027using F \u003d auto() -\u003e int;\u0027 is a function type as it should be.\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "571a393c03e79323c37a90540c8f2b7b8879e622",
      "tree": "4a9a3067c3095952517e757c511627ebfb6bae58",
      "parents": [
        "ae02aad58c59f9b4b08397f4297b7005d363749b"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Wed Aug 12 19:36:31 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Fri Aug 14 22:17:40 2026 +0100"
      },
      "message": "Add support for a conversion function with a deduced return type\n\nThe C++14 \u0027operator auto()\u0027 was a syntax error, the conversion function rule\ntaking a type and \u0027auto\u0027 deliberately not being one:\n\n  struct S {\n    operator auto() const { return 42; }\n  };\n\nThe \u0027auto\u0027 placeholder is now accepted, in all of its spellings including the\nC++20 constrained form. SWIG cannot deduce the type from the body, so the\nconversion function is ignored with warning 345 like any other function with\nan \u0027auto\u0027 return type and no trailing return type.\n\nA conversion function whose deduced type carries a declarator, such as\n\u0027operator auto*()\u0027, is still a syntax error.\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "ae02aad58c59f9b4b08397f4297b7005d363749b",
      "tree": "dee215957269e31d3a8e55060e2136eac69ed66b",
      "parents": [
        "df1d1ef3d57e257e2e9dd7fecec6a3087bda54de"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Wed Aug 12 19:30:27 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Fri Aug 14 22:17:40 2026 +0100"
      },
      "message": "Accept any type as a lambda trailing return type\n\nA lambda\u0027s explicit trailing return type only accepted the same limited set\nof types as an ordinary function\u0027s, and never the C++14 \u0027auto\u0027 placeholder,\nso these were a syntax error:\n\n  auto negate_value \u003d [](int x) -\u003e auto { return -x; };\n  auto address_of_thing \u003d [](int) -\u003e auto* { return \u0026thing; };\n  auto address \u003d [](int \u0026x) -\u003e int * { return \u0026x; };\n\nThe return type is now a type-id or an \u0027auto\u0027 placeholder with an optional\ndeclarator. A lambda is still wrapped as an opaque object, so the type is\nonly parsed, never used.\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "df1d1ef3d57e257e2e9dd7fecec6a3087bda54de",
      "tree": "c3801bc5266f26b501d6031eaa96d51e89b12acf",
      "parents": [
        "dd9566dbef347f4bf194af9c448c085239c48452"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Wed Aug 12 19:20:18 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Fri Aug 14 22:17:39 2026 +0100"
      },
      "message": "Accept a requires-clause after a trailing return type\n\nA C++20 trailing requires-clause comes after the trailing return type, that\nbeing the end of the declarator, but only the position before the trailing\nreturn type was accepted, so this was a syntax error:\n\n  template\u003ctypename T\u003e auto f(T t) -\u003e T requires Numeric\u003cT\u003e { return t; }\n\nThe constraint is attached to the node the same way as for a function\nwithout a trailing return type, and is conjoined with any type-constraint on\nthe \u0027auto\u0027 placeholder and with any prefix requires-clause on the template\nhead.\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "dd9566dbef347f4bf194af9c448c085239c48452",
      "tree": "9680e90c1e69b5b6159f2a6ad152143ff998d20a",
      "parents": [
        "ac55c6633fc5f4d3c1b25047e11def684e7474cf"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Wed Aug 12 19:14:47 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Fri Aug 14 22:17:39 2026 +0100"
      },
      "message": "Accept any type as a trailing return type\n\nThe C++11 trailing return type is a type-id, but cpp_alternate_rettype\nenumerated the types it accepted by hand and had no pointer alternative at\nall, and reference alternatives only for a class type. So all of these were\na syntax error:\n\n  auto count() -\u003e const int\u0026;\n  auto data() -\u003e int *;\n  auto values() -\u003e int (\u0026)[3];\n  auto callback() -\u003e int (*)(int);\n\nThe rule now takes a type followed by an optional abstract declarator.\n\nThe abstract declarator alternatives starting with a pointer to member are\nexcluded, as they start with a scope name, which can be spelt \u0027override\u0027 or\n\u0027final\u0027 since those are contextual keywords, and that is ambiguous with the\nvirt-specifier that can end a member function declaration. The parenthesised\nspelling is therefore a SWIG requirement, not a C++ one: SWIG accepts\n\"auto member() -\u003e int (S::*);\" but not the unparenthesised\n\"auto member() -\u003e int S::*;\", which C++ accepts equally well. Neither spelling\nparsed before this change, so nothing regresses.\n\nExplicit instantiation of a function template keeps the hand enumerated types\nunder a rule of its own. An explicit instantiation of a class template is\n\u0027template cpptype idcolon\u0027, such as \u0027template class Foo\u003cint\u003e;\u0027, which a full\ntype also matches, so using a full type as the function template return type\nmakes the two indistinguishable with one token of lookahead and gives 16\nreduce/reduce conflicts.\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "ac55c6633fc5f4d3c1b25047e11def684e7474cf",
      "tree": "0735102a75c363a7111dd689aec1cf4b4e98ec7b",
      "parents": [
        "66833aef25fc44b7253fe0ca95c4a8d03b8af69a"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Wed Aug 12 13:21:42 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Fri Aug 14 22:17:39 2026 +0100"
      },
      "message": "Add an errors test for a bad C++23 explicit object parameter\n\nCovers the member function with an explicit object parameter declared static,\nvirtual, cv-qualified or ref-qualified, an explicit object parameter with a\ndefault argument or with no parameter declaration at all, and an explicit\nobject parameter on a function that is not a member function.\n"
    },
    {
      "commit": "66833aef25fc44b7253fe0ca95c4a8d03b8af69a",
      "tree": "aae0094f3b4d7c34ae016141c27ed17395785e3a",
      "parents": [
        "d38566716c1587531ff318a5480cc121c77265e4"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Wed Aug 12 13:21:42 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Fri Aug 14 22:17:39 2026 +0100"
      },
      "message": "Add support for the C++23 explicit object parameter\n\nA member function can declare its first parameter with the \u0027this\u0027 specifier,\nnaming the object the function is called on. That parameter is not one of the\nfunction\u0027s arguments, so it is dropped from the parameter list and from the\ndeclarator and the member function is wrapped with the arguments that follow\nit.\n\nThe deduced spelling \u0027auto m(this auto\u0026\u0026 self)\u0027 parsed before this change, but\n\u0027this\u0027 matched the idcolon of the C++20 type-constraint alternative of\nauto_type_holder, so the placeholder was taken as a concept named \u0027this\u0027 and\nthe method was wrapped as taking one argument. The non-deduced spelling\n\u0027int m(this S\u0026 self)\u0027 was a syntax error. Both are now wrapped as a member\nfunction taking no arguments.\n\nA deduced explicit object parameter makes the member function a template in\nC++, but the object type is deduced from the object the wrapper passes, so the\ndeclaration is not promoted to an abbreviated function template and needs no\n%template.\n\nA lambda parameter list takes an explicit object parameter too, which is how a\nrecursive lambda is written. A lambda is still wrapped as an opaque object.\n\n\u0027this\u0027 has always been a C++ keyword; what C++23 adds is a new position for it,\nas the first parameter of a member function. SWIG\u0027s scanner handed \u0027this\u0027 to\nthe parser as an ordinary identifier, which worked only because \u0027this\u0027 had\nuntil now appeared solely where the parser skips or looks loosely, and it\nreturns a keyword token in C++ mode now. The expression grammar takes that\ntoken as a primary and as the left hand side of \u0027-\u003e\u0027 so that a default member\ninitialiser such as \u0027Node *parent \u003d this;\u0027 parses exactly as it did before. C\nmode is unchanged, where \u0027this\u0027 is an ordinary identifier.\n\nC++ requires such a member function to be neither static nor virtual and to\nhave no cv-qualifier or ref-qualifier, and an explicit object parameter is not\nvalid on a function that is not a member function. Each is now diagnosed.\n\nThe bookkeeping every function declarator rule repeated - build the function\ntype from the parameter list, record the parameters unless an inner declarator\nalready supplied them, and push the result onto the declarator\u0027s type - moves\ninto declarator_add_function(), shared by the new rules and the existing ones.\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "d38566716c1587531ff318a5480cc121c77265e4",
      "tree": "fefe6f109677310651dfe8b2b53722a389f4cdc4",
      "parents": [
        "38429a92465e81c9bfe9b732c3b666e2234cbbe9"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Wed Aug 12 12:57:10 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Fri Aug 14 22:17:39 2026 +0100"
      },
      "message": "Mark the invented template parameter for an auto pack as variadic\n\nAn \u0027auto\u0027 parameter pack in a C++20 abbreviated function template invents a\ntemplate parameter pack, exactly as the equivalent \u0027template\u003ctypename... T\u003e\u0027\nspelling does. promote_abbreviated_template() invented a plain \u0027typename\u0027\nparameter instead, even though it kept the \u0027v.\u0027 variadic prefix on the\nparameter type, so the two paths disagreed about the same declaration and no\n%template instantiation of such a function could be matched.\n\nAlso drop the whole expansion of an invented parameter pack from the emitted\nC++ template argument list rather than one argument per invented parameter: a\npack absorbs every remaining template argument, so subtracting one left the\ncall spelled with a partial argument list.\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "38429a92465e81c9bfe9b732c3b666e2234cbbe9",
      "tree": "5418c48cd18d5fb3f4eea234c9ab3acb061d3466",
      "parents": [
        "fcdf074c7bc89f3a6746149469dedabd7034a998"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Wed Aug 12 01:21:54 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Fri Aug 14 22:17:39 2026 +0100"
      },
      "message": "Say what stopped an auto type being deduced in warnings 345 and 346\n\nThe two warnings read the same whether SWIG understood the initialiser but\ncould not deduce a type from it, or the declaration was in a form SWIG does\nnot support, so there was no way to tell which of the two to work around.\n\nWarning 346 now names the initialiser it could not deduce from, or says the\ninitialiser is unsupported when the declaration reached the parse tree with\nno initialiser SWIG could parse. Warning 345 says the return type is\nundeducible without a trailing return type, which is the form the function\nhas to be declared with for SWIG to wrap it.\n\nThe auto section of the C++11 chapter of the manual is brought up to date\nwith the deduction the recent changes added, including what a declaration\ndeclaring more than one variable does and the inconsistent deduction warning.\nEvery warning the section shows is now the output of a declaration the\nsection also shows, rather than of a variable the reader never sees declared.\n\nThe null pointer constant section says what the target languages do with\nnullptr rather than leaving it at \"treated like NULL\": where a target\nlanguage writes default argument values of its own instead of leaving them\nto the C++ layer, Python generates None for a nullptr default and Ruby\ndocuments nil.\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "fcdf074c7bc89f3a6746149469dedabd7034a998",
      "tree": "71ef468c1a17c0c369500d6d26a00a58da6d6755",
      "parents": [
        "fcd7d29db2d19bd83db418c21ad6f9b945c5ec63"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Wed Aug 12 01:18:31 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Fri Aug 14 22:17:39 2026 +0100"
      },
      "message": "Deduce the type of a named cast\n\nA named cast such as static_cast\u003cdouble\u003e(y) reaches the expression grammar\nas a template-id followed by a parenthesised expression, indistinguishable\nthere from a constructor cast or a function call, so the type it casts to was\ndiscarded and an auto variable initialised with one was ignored. The four\nnamed casts are now recognised and the type cast to is used, as long as it is\na type SWIG has a built in type code for - a cast to a class or to a\nreference stays undeducible.\n\nThis applies to decltype as well as to an auto variable.\n\nThe type code is what the grammar carries for any value expression, so the\ndeduction also reaches the two other places that read it. A %constant with no\nexplicit type was previously always an int, and is now the type cast to:\n\n  %constant CD \u003d static_cast\u003cdouble\u003e(3);\n\nAn enumerator initialised with a cast to char or bool is typed the same way\nas one initialised with a character or boolean literal, and one initialised\nwith a cast to a non-integral type is now the existing \"Type error. Expecting\nan integral type\" rather than being silently treated as an int. Such an\nenumerator is not valid C++ either.\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "fcd7d29db2d19bd83db418c21ad6f9b945c5ec63",
      "tree": "5d781a24ec5be53975cf7780676097f75e8544ca",
      "parents": [
        "809dc6cfc6013ef205df5b543f085cef825b21d9"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Wed Aug 12 01:16:21 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Fri Aug 14 22:17:39 2026 +0100"
      },
      "message": "Update the decltype tests for the now deducible address of an object\n\ndecltype(\u0026x) deduces a pointer to the type of x since deduction started\nusing the declaration the name refers to, so the cases the tests recorded as\nunsupported are no longer unsupported.\n\ncpp_decltype_unsupported.i loses its address of case, and cpp11_decltype.i\nwraps the members that used to be ignored for it, with the python runme\nchecking the deduced pointer comes back.\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "809dc6cfc6013ef205df5b543f085cef825b21d9",
      "tree": "1270cb2475d73f56fc5012ec7f071a2d6206641e",
      "parents": [
        "ae320c03bd9bc5badda9e2f1863f2c9e64dfc782"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Wed Aug 12 01:09:01 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Fri Aug 14 22:17:39 2026 +0100"
      },
      "message": "Deduce an auto variable type from a braced initialiser\n\nThe braces of\n\n  auto v{42};\n\nmatched the rule for an auto function body, so the initialiser was skipped\nalong with everything else between the braces. The declaration reached the\nparse tree with no value at all and was ignored with warning 346, which read\nas though the type could not be deduced when it was the form of the\ninitialiser that was never looked at.\n\nThe braces are now recognised as a braced initialiser rather than a function\nbody when the declarator is not a function declarator, and the type is\ndeduced from a single element initialiser the same way as from an \u0027\u003d\u0027\ninitialiser, including from an identifier or an address. The value is kept on\nthe node.\n\nThe type-constraint of a deduced auto variable is dropped by the \u0027\u003d\u0027\ninitialiser branch, recorded as a side issue to fix separately. Attaching it\nin the braced initialiser branch only would have made the two differ, so it is\nleft alone there too.\n\nDeducing the element type is the C++17 rule; C++11 and C++14 as published\ndeduced std::initializer_list here, but compilers implementing N3922 apply\nthe C++17 rule in those modes too. An empty or multiple element braced\ninitialiser stays undeducible - neither is valid C++ for an auto variable.\n\nThe testcase is prefixed cpp17_ rather than cpp11_ because the deduction\nbeing tested is the C++17 one: the declaration is C++11 grammar, but a\nstrictly conforming C++11 compiler gives it a different type, so the test is\nonly correct when compiled as C++17.\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "ae320c03bd9bc5badda9e2f1863f2c9e64dfc782",
      "tree": "7960c7895bdd5174d4f723d26cb04fc252329eec",
      "parents": [
        "63ee4cfb8a201810b87f0192040b5c7a631a4736"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Wed Aug 12 01:01:04 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Fri Aug 14 22:17:39 2026 +0100"
      },
      "message": "Fix an auto declaration declaring more than one variable\n\nThe C++11 auto variable rule required the semicolon straight after the\ninitialiser, so a declaration with more than one declarator never reached it:\n\n  auto x \u003d 1, y \u003d 2;\n\nOnly \u0027x\u0027 was produced, with no initialiser to deduce from, so it was ignored\nwith warning 346 and \u0027y\u0027 was never mentioned at all.\n\nThe rule now ends with the same declarator list tail an ordinary declaration\nuses. The list production is split out of c_decl_tail as c_decl_list_tail so\nthat the auto rule does not also pick up c_decl_tail\u0027s error alternative,\nwhich would turn an initialiser SWIG cannot parse into a fatal error instead\nof the ignored declaration it produces today.\n\nOne type is deduced for the whole declaration. N4861 (C++20) [dcl.spec.auto]\nparagraph 7 says:\n\n  \"If the init-declarator-list contains more than one init-declarator, they\n  shall all form declarations of variables. The type of each declared variable\n  is determined by placeholder type deduction, and if the type that replaces\n  the placeholder type is not the same in each deduction, the program is\n  ill-formed.\"\n\n  [Example:\n    auto x \u003d 5, *y \u003d \u0026x;            // OK: auto is int\n    auto a \u003d 5, b \u003d { 1, 2 };       // error: different types for auto\n  - end example]\n\nThe same wording is [dcl.spec.auto.general] paragraph 9 in the current working\ndraft.\n\nEach declarator is deduced from its own initialiser, and one SWIG cannot\ndeduce from takes the type its siblings deduced, which the paragraph above\nguarantees is its type too. Only a declaration where no declarator deduces a\ntype is dropped, and warning 346 then names each variable\u0027s own initialiser\ninstead of blaming one declarator for another\u0027s failure.\n\nDeducing each declarator separately needs the initialiser of the declarators\nafter the first, which reach the deduction as parse tree nodes holding the\ninitialiser text rather than the value the grammar evaluated for it, so\nliteral_type_code() reads a type code back from that text. The scanner already\nmaps its literal tokens to grammar tokens and grammar tokens to type codes, in\ntwo switch statements, so both are replaced by one table the new function\nshares with them.\n\nDeclarators deducing different types is ill-formed, and while a C++ compiler\ndiagnoses it, giving one of the variables the other\u0027s type is a defect SWIG\ncan avoid, so the new warning 348 reports it and each variable keeps the type\nits own initialiser deduced. It is a condition of its own rather than another\n346: the program does not compile as it stands and the variable is wrapped\nrather than ignored, so it is worth suppressing separately. Only fundamental\ntypes are compared, because a typedef name is not resolvable while the\ndeclaration is being parsed and would look like a mismatch against the type it\nstands for.\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "63ee4cfb8a201810b87f0192040b5c7a631a4736",
      "tree": "10a2f6aaebdbd185184dfb691fd23209aba387a7",
      "parents": [
        "fbbaa9a013257af1fb26e8d34764fac3e76156b3"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Wed Aug 12 00:54:09 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Fri Aug 14 22:17:39 2026 +0100"
      },
      "message": "Deduce an auto variable type from the initialiser\u0027s declaration\n\nType deduction resolved an identifier through the symbol table and returned\nthe \"type\" attribute of the node it found, ignoring the \"decl\" attribute, so\nthe declarator of the initialiser was lost:\n\n  int *pg;\n  auto x \u003d pg;    // deduced int, not int *\n  auto* x2 \u003d pg;  // right only because the declarator supplied the pointer\n\nDeduction now uses the declaration\u0027s type with its declarator applied, and\nthe declarator on the placeholder is matched against it and removed, so both\nof the above deduce int * and the second keeps the pointer in the declarator\nrather than in the type.\n\nThe address of something in scope now deduces too, giving a pointer to its\ntype, so \u0027auto* p \u003d \u0026g;\u0027 and \u0027auto* fp \u003d \u0026fn;\u0027 are wrapped instead of being\nignored with warning 346. Taking the address of a constexpr object gives a\npointer to const, which SWIG keeps in the storage attribute rather than the\ntype, so the qualifier is added back for the deduction.\n\nThe name of a function is not something a variable or a decltype can be\ndeduced from, so deduce_type() discards it and falls through to the other\nways of deducing a type.\n\nTop level cv-qualifiers of the initialiser are dropped unless the variable is\na reference, as C++ requires.\n\ndecltype uses the same deduction, so decltype(pg) is now int * rather than\nint.\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "fbbaa9a013257af1fb26e8d34764fac3e76156b3",
      "tree": "4e5914fd3ef13072b9ee2aafef230a204ce3270f",
      "parents": [
        "13b03be2f29024bcef017eabf32fb53187fa60a0"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Tue Aug 11 22:29:02 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Fri Aug 14 22:17:39 2026 +0100"
      },
      "message": "Add an errors test for a concept declaration with no semicolon\n\nThe C++20 concept declaration rule reads ahead over the constraint expression to\ncapture its text, so check that never finding the terminating semicolon leaves\nthe parser reporting a syntax error rather than running off the end of the text\nbeing scanned.\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "13b03be2f29024bcef017eabf32fb53187fa60a0",
      "tree": "76c5d96c56eaeb9a4cdcccf6b60bb03b0e451c8a",
      "parents": [
        "8eec478b27b191b460db15390de854ce0f47d7c7"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Tue Aug 11 22:24:11 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Fri Aug 14 22:17:39 2026 +0100"
      },
      "message": "Fix parsing of an auto variable declared with a declarator\n\nThe C++11 \u0027auto\u0027 variable rule matched a bare identifier where it needed a\ndeclarator, so there was nowhere for a \u0027\u0026\u0027, \u0027\u0026\u0026\u0027 or \u0027*\u0027 to attach and every\ndecorated spelling was a syntax error, despite the same decorations having\nalways worked on an \u0027auto\u0027 function parameter:\n\n  auto\u0026 r1 \u003d g;             const auto* p2 \u003d \u0026g;\n  const auto\u0026 r2 \u003d g;       auto* const p3 \u003d \u0026g;\n  auto\u0026\u0026 r3 \u003d 42;           const auto* const p4 \u003d \u0026g;\n  auto* p1 \u003d \u0026g;            auto** p5 \u003d \u0026pg;\n  Numeric auto\u0026 r4 \u003d g;\n\nThe rule and its error recovery twin now take a declarator, which is kept on the\nnode as its \u0027decl\u0027, so \u0027auto\u0026\u0026 r3 \u003d 42;\u0027 wraps as \u0027int \u0026\u0026\u0027 rather than being\nrejected. Deduction of the placeholder itself is unchanged: the \u0027\u0026g\u0027 pointer\ninitialisers above are still ones SWIG cannot deduce a type from, so those\nvariables continue to be ignored after warning 346.\n\nThe three lambda rules share the same \u0027storage_class auto_type_holder declarator\nEQUAL\u0027 prefix, so they take a declarator too rather than introducing a grammar\nconflict. This also makes \u0027auto\u0026\u0026 lambda \u003d [](int x) { return x; };\u0027 parse. The\nnumber of expected conflicts is unchanged.\n\nA function declarator reaching the variable rule means the placeholder is a\ndeduced return type, as in \u0027auto f() \u003d delete;\u0027, so no attempt is made to deduce\nit from the initialiser.\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "8eec478b27b191b460db15390de854ce0f47d7c7",
      "tree": "97ed4c586b8845781c0c7792095ad2e3009a5221",
      "parents": [
        "644b3b70ecee0eaee502196e6ba173de531a8878"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Tue Aug 11 22:16:09 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Fri Aug 14 22:17:39 2026 +0100"
      },
      "message": "Fix parsing of a C++20 concept body that is an ordinary expression\n\nA constraint-expression is any logical-or-expression, but the constraint\nsubgrammar only models a chain of concept-ids, parenthesised primaries and\nrequires-expressions joined by \u0027\u0026\u0026\u0027 and \u0027||\u0027. Anything else was a syntax error,\nso a bare boolean literal was rejected while the same literal parenthesised was\naccepted:\n\n  template\u003ctypename T\u003e concept Anything \u003d true;          // was an error\n  template\u003ctypename T\u003e concept NonEmpty \u003d sizeof(T) \u003e 0; // was an error\n  template\u003ctypename T\u003e concept Paren \u003d (true);           // accepted\n\nThe concept body text is now captured before it is parsed, using the new\nScanner_get_raw_text_to_semicolon() which reads ahead to the semicolon ending\nthe declaration without changing scanner state. When the structural parse of the\nbody does not work out, an error rule recovers and the captured text is kept as\na single opaque \"expression\" constraint atom, the same representation the\nparenthesised form already used. Bodies the subgrammar does model are unaffected\nand keep their structured constraint subtree.\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "644b3b70ecee0eaee502196e6ba173de531a8878",
      "tree": "2fc42e179e6e18014bb071add9d0090d9d0b912c",
      "parents": [
        "2a8dc61871dd7605fae193f91bc2302b7eff9f2f"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Tue Aug 11 21:18:59 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Fri Aug 14 22:17:39 2026 +0100"
      },
      "message": "Add support for the C++26 reason on a deleted function\n\nA deleted function can carry an explanatory message in C++26:\n\n  void f() \u003d delete(\"use g() instead\");\n\nThe reason is parsed and discarded, so the declaration behaves exactly like one\nusing a plain \u0027\u003d delete\u0027. The reason is accepted by the \u0027deleted_definition\u0027\nrule itself rather than at each use, so every rule that reaches a deleted\ndefinition through \u0027default_delete\u0027 or \u0027definetype\u0027 accepts both spellings.\n\nThe C++23 and C++26 manual chapters are filled in here too. The C++23 chapter\nrecords that -std\u003dc++23 sets __cplusplus to 202302L but that no C++23 core\nlanguage support has been added yet. The C++26 chapter states that C++26 is\nstill a draft standard which SWIG does not enable, as -std\u003dc++26 is not accepted\nand the C++26 test cases are not run as part of a normal test suite run, and\ndocuments the deleted function reason as the one C++26 construct SWIG parses.\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "2a8dc61871dd7605fae193f91bc2302b7eff9f2f",
      "tree": "1ca70fc4ede983d9a40ec6c7021db83c7cae5f56",
      "parents": [
        "8a0eb610367ab970a8de1231a1a949b39a8bfc79"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Tue Aug 11 21:18:12 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Fri Aug 14 22:17:39 2026 +0100"
      },
      "message": "Add empty C++23 and C++26 chapters to the manual\n\nTwo placeholder chapters so that C++23 and C++26 support has a home in the\nmanual as it is added, registered in the chapters list and the sections summary.\n\nThe content is added separately. This commit is the file creation and the\nmechanical renumbering that comes with it: make maketoc renumbers every chapter\nfollowing C++20 and regenerates Contents.html, so the bulk of the diff is that\nchurn rather than anything to review.\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "8a0eb610367ab970a8de1231a1a949b39a8bfc79",
      "tree": "1bd09651b843d74017f9bc8acb13535513647af1",
      "parents": [
        "1bf67ba198ca46b307056f0dc81ed807874fd4f7"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Tue Aug 11 19:46:26 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Fri Aug 14 22:17:39 2026 +0100"
      },
      "message": "Fix test suite failures when compiling as C++23 or later\n\nThe JavaScript test shell returned 0 from a function returning std::string;\nconstructing a std::string from a null pointer is ill-formed since C++23 and\nfailed to compile.\n\nThree test cases compared against the output of std::to_string(double), which\nC++26 changed to the shortest round trip form, so \"2.500000\" became \"2.5\". They\nnow format the value with snprintf so the expected strings are the same in every\nstandard.\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "1bf67ba198ca46b307056f0dc81ed807874fd4f7",
      "tree": "c863558542ea465a1b4b9c5b831a84dfb9ea060e",
      "parents": [
        "2d56d348db556a96c1221a336d3a9bc3a04d43ab"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Tue Aug 11 20:46:25 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Fri Aug 14 22:17:39 2026 +0100"
      },
      "message": "Add C++23 and C++26 test suite buckets\n\nconfigure now detects C++23 support and substitutes HAVE_CXX23 into the test\nsuite makefiles, and the test suite gains cpp23_ and cpp26_ test case buckets\nalongside the existing cpp11_ to cpp20_ ones.\n\nBecause C++26 is still a draft standard, the C++26 test cases are not run for\nnow. configure deliberately does not probe for C++26 and HAVE_CXX26 defaults to\n0, so the cpp26_ bucket stays out of a normal test suite run. The tests can be\nrun deliberately with a compiler supporting C++26, for example:\n\n  make CXX\u003dg++-16 CXXFLAGS\u003d-std\u003dc++26 check-cpp26\n\nPassing HAVE_CXX26\u003d1 to configure includes them in the normal run instead.\n\nNote that the configure cascade picks the newest standard the compiler supports,\nso on a compiler with C++23 the whole test suite is now compiled as C++23 rather\nthan C++20.\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "2d56d348db556a96c1221a336d3a9bc3a04d43ab",
      "tree": "99ea7e5d5182a33e3b708ccdf937cce18acafb95",
      "parents": [
        "c19e4d2fba4a67ca3843b7a5cf3d026f9e836dd1"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Fri Aug 14 19:21:36 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Fri Aug 14 22:17:39 2026 +0100"
      },
      "message": "Add trailing continuations to test case lists\n\nKeep existing list entries unchanged when future test cases are appended.\n\nAssisted-by: OpenCode (GPT-5.6 Sol)\n"
    },
    {
      "commit": "c19e4d2fba4a67ca3843b7a5cf3d026f9e836dd1",
      "tree": "a4c4f9eeab0addbb33a11b0e48fd543adb1ce023",
      "parents": [
        "ec83964d651e8182f0cf5119b723f85d7cc357c8"
      ],
      "author": {
        "name": "Karl Wette",
        "email": "karl.wette@anu.edu.au",
        "time": "Fri Aug 14 19:21:20 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Fri Aug 14 22:17:39 2026 +0100"
      },
      "message": "Restore custom string allocator support\n\nRestore \u0027%typemaps_string_alloc\u0027 using the two-argument copy allocator\nfragment interface introduced for \u0027%typemaps_string\u0027 in SWIG 4.5.0.\n\nAdd runtime coverage for all eight UTL target languages that provide\nthis interface.\n\nCloses #3531\n\nAssisted-by: OpenCode (GPT-5.6 Sol)\n"
    },
    {
      "commit": "ec83964d651e8182f0cf5119b723f85d7cc357c8",
      "tree": "ee156b4481d09047b1fe4d018d2f6b7e96f85108",
      "parents": [
        "79422d53fd9806222459670ddcf2ad6a9a42e43c"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Tue Aug 11 18:30:07 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Tue Aug 11 21:26:19 2026 +0100"
      },
      "message": "[JavaScript] Speed up node and napi test-suite runs\n\nnode-gyp\u0027s Release configuration hardcodes -O3, and the test-suite compiles one\nwrapper per test case, so the optimiser dominates the time taken to run it. The\njsc and v8 engines, like every other language test-suite, compile with no -O\noption at all, which is why the node and napi runs take so much longer than the\nothers. The effect is largest for napi, where the -O3 is applied to the large\namount of inline template code in napi.h.\n\nAdd GYP_OPTFLAGS, appended to GYP_CXXFLAGS so that it lands after the flags\nnode-gyp adds itself and the last -O option wins. It defaults to -O0, matching\nthe other engines. Set it on the make command line to compile the wrappers\noptimised, for example:\n\n  make check-javascript-test-suite GYP_OPTFLAGS\u003d-O2\n\nTimings are in seconds, wall clock, on an otherwise idle 16 core machine running\ncheck-javascript-examples followed by check-javascript-test-suite, with node\nv22.22.1 and node-addon-api 8.6.0. The full test-suite, 736 test cases, runs\nclean before and after. The examples are built from Examples/Makefile.in, which\nthis change does not touch, so they are unchanged and are listed only for\ncompleteness. jsc is unaffected and is shown for reference.\n\n-j4, which matches the Github Actions runners, as they have 4 cores:\n\n                  examples   test-suite   total\n    node before          5          264     269\n    node after           5          208     213   -21%\n    napi before          8          554     562\n    napi after           8          316     324   -42%\n    jsc                  2           73      75\n\n-j8:\n\n                  examples   test-suite   total\n    node before          3          189     192\n    node after           4          154     158   -18%\n    napi before          6          401     407\n    napi after           6          226     232   -43%\n    jsc                  2           55      56\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "79422d53fd9806222459670ddcf2ad6a9a42e43c",
      "tree": "d96da5c6ace859462f7f942767df068ef9cccace",
      "parents": [
        "07631e139aeef8eeee8eff75ca37490a30bdeb71"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Tue Aug 11 12:01:10 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Tue Aug 11 14:03:47 2026 +0100"
      },
      "message": "Fix parsing of a cv-qualified auto placeholder\n\nA cv-qualified \u0027auto\u0027 placeholder was a syntax error, in either ordering, as a\nfunction return type, a variable type or a lambda type:\n\n  const auto\u0026 cref();\n  auto const\u0026 cref2();\n  static const auto cz \u003d 2;\n  const auto lambda \u003d [](int x) { return x; };\n\nThe same applies to the C++20 constrained placeholder, so \u0027const Numeric auto\u0026\u0027\nwas rejected as well, and a function parameter only accepted the qualifier\nbefore the placeholder, never after it:\n\n  const Numeric auto\u0026 cref3();\n  int fn(auto const\u0026 x);\n\nAUTO is deliberately not an alternative of type_right, as it would collide with\nthe declarator that follows the placeholder, so each use site spelled the\nplaceholder out for itself and only ever spelled out the undecorated forms.\nGive the placeholder a rule of its own, auto_type_holder, covering all six\nspellings, and use it from every site: the return type, variable, lambda and\nparameter rules. That fixes the qualified spellings everywhere at once and\nremoves the duplicated alternatives that only differed by whether the\nplaceholder carried a type-constraint.\n\nA cv-qualifier is kept on the placeholder type, giving \u0027q(const).auto\u0027, and on\na deduced variable type, so \u0027cz\u0027 above is a \u0027q(const).int\u0027 wrapped read only.\n\nThe warn and ignore gate in add_symbols compared the type against the literal\n\"auto\", which a decorated placeholder no longer matches, so it now uses\nSwigType_isauto. Without this a cv-qualified auto return type would escape the\ngate and generate a wrapper for a type SWIG cannot deduce.\n\nA trailing return type requires the placeholder on its own, so combining one\nwith a cv-qualifier is now reported as an error instead of being accepted by\nthe shared rule.\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "07631e139aeef8eeee8eff75ca37490a30bdeb71",
      "tree": "bebf58037f2edca844cc6ad516804792299eeb0c",
      "parents": [
        "bc3a015ac7644c768c55e758b7d5691f6a887aaa"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Tue Aug 11 12:01:02 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Tue Aug 11 12:01:02 2026 +0100"
      },
      "message": "Add SwigType_new_auto() and SwigType_add_auto()\n\nThe \u0027auto\u0027 placeholder functions in typeobj.c had query and utility functions\nbut no constructors, so each caller had to open code the \u0027auto\u0027 base, the\n\u0027c(\u003cid\u003e)\u0027 concept-id base and the \u0027auto.\u0027 prefix that pairs with it.\n\nCollect the family under an \u0027Auto placeholders\u0027 section header, in the style of\nthe other type element sections, so the encoding is described in one place.\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "bc3a015ac7644c768c55e758b7d5691f6a887aaa",
      "tree": "c82c0abd68dbe85c40c13c748e71afddf6bf760c",
      "parents": [
        "edbbe014f935c5f9e86941c771cde8a24d3d7e74"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Mon Aug 10 19:51:13 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Mon Aug 10 22:42:57 2026 +0100"
      },
      "message": "[OCaml] Remove std_complex.i\n\nLib/ocaml/std_complex.i was a verbatim copy of the Python library file. Every\ntypemap in it calls the Python C API (PyComplex_Check, PyFloat_AsDouble,\nPyInt_Check, PyErr_SetString and friends), so it could never have produced\nusable OCaml wrappers.\n\nNothing includes it: no file in Lib/ocaml, the OCaml examples or the OCaml test\nsuite references std_complex.i or std::complex, and it is only reachable through\nan explicit %include. Wrapping std::complex has therefore never worked for\nOCaml.\n\nPyInt_Check and PyInt_AsLong were also among the Python 2 compatibility macros\nremoved in 4.5.0.\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "edbbe014f935c5f9e86941c771cde8a24d3d7e74",
      "tree": "2405fdefee02a017674a3b7c715ea939574fe2e3",
      "parents": [
        "72ebb34a27eea5de2e7a06511d557ae0e2c222cf"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Mon Aug 10 19:47:47 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Mon Aug 10 22:42:57 2026 +0100"
      },
      "message": "[Python] Accept str in the varargs example typemaps\n\nThe varargs and libffi typemap examples in the manual now convert a Python str\nwith PyUnicode_AsUTF8 instead of requiring a bytes object, so bring the matching\nexample interface files into line.\n\nThe libffi runme no longer needs byte string literals for the printf format\nstring, the printf arguments or the execlp arguments.\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "72ebb34a27eea5de2e7a06511d557ae0e2c222cf",
      "tree": "4988c67c11dad037109b35f76082f6b790133fc4",
      "parents": [
        "1941f20fdf1a332819513b7359ed87f56353f464"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Sun Aug 09 21:54:50 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Mon Aug 10 22:42:39 2026 +0100"
      },
      "message": "Update the Python 2 C API usage in the documentation\n\nThe manual still used the Python 2 compatibility macros in its typemap\nexamples. These were removed from the generated code in 4.5.0, so the examples\nno longer compile.\n\nEach macro is replaced with the Python 3 API that keeps the example working as\ndocumented: PyUnicode_* where the example converts Python text (char *str,\nchar *argv[], const char *fmt, std::string and the char and char * typecheck\ntypemaps) and PyBytes_* for the read()/write() example, which passes a binary\nbuffer. The read/write session transcript is updated to bytes literals and\nPython 3 octal syntax to match.\n\nThe \"Useful Python Functions\" section of the Python chapter listed the\nPyString_* functions and the Python 2 only PyFile_FromFile and PyFile_AsFile.\nThese are replaced by the PyUnicode_*, PyBytes_* and PyObject_AsFileDescriptor\nequivalents. A compatibility note is added listing every removed macro\nalongside the Python 3 API it expanded to.\n\nAlso fix the \"newfree\" typemap example in the Ruby chapter, which called\nPyString_FromString instead of rb_str_new2.\n\nCloses #3530\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "1941f20fdf1a332819513b7359ed87f56353f464",
      "tree": "7eb9f19ce71a2ef704f931862948753bbf9a6960",
      "parents": [
        "d598176759f5d199e288cf78413cfaa3bf84449f"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Fri Aug 07 07:50:12 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Fri Aug 07 07:50:12 2026 +0100"
      },
      "message": "Bump version to 4.6.0\n"
    },
    {
      "commit": "d598176759f5d199e288cf78413cfaa3bf84449f",
      "tree": "0f3e5309413457d123a5e52eab40c7ac34785c3c",
      "parents": [
        "7a137da8f3fb55a98ff06562c1ced934fb841624"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Wed Aug 05 22:56:41 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Thu Aug 06 00:12:37 2026 +0100"
      },
      "message": "swig-4.5.0 release notes and date\n"
    },
    {
      "commit": "7a137da8f3fb55a98ff06562c1ced934fb841624",
      "tree": "a7950a849cf6e2f49fd81104359d48bddbb7f1b0",
      "parents": [
        "f06d86749c60dddb551ceacde8411878d6c292f3"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Tue Aug 04 17:49:01 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Tue Aug 04 23:41:57 2026 +0100"
      },
      "message": "[Python] Check annotations in .pyi stubs with -builtin and -fastproxy\n\nThe annotation tests skipped their checks with -builtin or -fastproxy as\nneither adds __annotations__ to the generated runtime objects. That is no\nlonger a reason to skip when -pyi is also used, as the annotations are then\nin the generated stub file, but the stub lookup only worked for -builtin.\n\nWith -fastproxy a method is the flat C wrapper function, so its __qualname__\nis Class_method instead of Class.method. Pass a fastproxy flag from each\nrunme down to the stub lookup so that such a name is split on the stub class\nnames only when it really is a flat name. Reword the comment explaining when\nannotations_supported is false, which was misleading with -pyi.\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "f06d86749c60dddb551ceacde8411878d6c292f3",
      "tree": "2482eae9837a49d0954a89bfb385c7ae56b29072",
      "parents": [
        "afc39844b49c9528eb35f14df8ed465a0d422993"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Tue Aug 04 01:10:10 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Tue Aug 04 23:41:57 2026 +0100"
      },
      "message": "[Python] Fix empty classes and imported bases in .pyi files\n\nA generated stub class with no wrapped members had an empty suite, which\nis invalid Python syntax. Stubs could also refer to base classes from\n%imported modules without importing the corresponding Python proxy\nmodule, leaving those names unresolved.\n\nTrack whether each stub class emits a member and use an ellipsis when\nits body would otherwise be empty. Collect modules referenced through\n%import and emit them before declarations, using the same package and\nrelative import rules as the generated Python proxy.\n\nKeep annotation tests active with -pyi by parsing annotations from the\ngenerated stub instead of expecting them on runtime objects. Include\neach generated .pyi file in multi-module Pyrefly checks.\n\nAdd Python 3.14 Linux CI configurations for -pyi -typehints with and\nwithout -builtin.\n\nSee #3473.\n\nAssisted-by: Codex (GPT-5.6 Sol)\n"
    },
    {
      "commit": "afc39844b49c9528eb35f14df8ed465a0d422993",
      "tree": "269c85fe684bbc17bbf65543d88994e65f7512fc",
      "parents": [
        "b9cbc4e6243ac990bdf9151afe97eec1a138af7b"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Tue Aug 04 01:05:21 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Tue Aug 04 23:41:57 2026 +0100"
      },
      "message": "[Python] Add %pythonstubcode and %pythonstubbegin directives\n\nThese are the .pyi stub file equivalents of %pythoncode and %pythonbegin,\nfor adding Python code to the stub file generated by the -pyi and -pyifile\noptions. They do nothing unless a stub file is being generated.\n\n%pythonstubcode inserts the code at the point the directive appears,\nindenting it into the class body when used inside a class. %pythonstubbegin\ninserts the code just after the SWIG banner, before any real code.\n\nThe stub file is generated independently of the .py file, so code added with\n%pythoncode or %pythonbegin does not appear in it. Classes configured with\n%pythonabc use names from collections.abc as generated base classes and\npyabc.i imports this module into the .py file, but a separately generated\nstub had no import, leaving its base class unresolved. Add the equivalent\n%pythonstubcode block to pyabc.i.\n\nExtend the python_pyi test with a collections.abc base class and blocks\nexercising both new directives.\n\nSee #3473.\n\nAssisted-by: Claude Code (Opus 5)\n"
    },
    {
      "commit": "b9cbc4e6243ac990bdf9151afe97eec1a138af7b",
      "tree": "a2ed8944a783782d5adb08dea4f22bd7223438b6",
      "parents": [
        "c8f052749e8dc07e879dad6638ff464acaf0eef3"
      ],
      "author": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Mon Aug 03 22:35:02 2026 +0100"
      },
      "committer": {
        "name": "William S Fulton",
        "email": "wsf@fultondesigns.co.uk",
        "time": "Tue Aug 04 23:41:57 2026 +0100"
      },
      "message": "[Python] Clean all generated stub files\n\nRemove generated .pyi files alongside Python proxy files during\ntest-suite and example cleanup. Use .py* patterns so stubs produced\nwith SWIG_FEATURES\u003d-pyi and other Python sidecar files are covered by\nthe existing clean rules.\n"
    }
  ],
  "next": "c8f052749e8dc07e879dad6638ff464acaf0eef3"
}
