[neon/forks/sip6/Neon/release] /: New upstream version 6.7.6+dfsg

Dmitry Shachnev null at kde.org
Sat Feb 4 02:04:46 GMT 2023


Git commit 147325fbcc2a836d58c00e1b95a56ad35a9464ae by Dmitry Shachnev.
Committed on 28/01/2023 at 17:56.
Pushed by carlosdem into branch 'Neon/release'.

New upstream version 6.7.6+dfsg

M  +72   -0    ChangeLog
M  +4    -1    NEWS
M  +1    -1    PKG-INFO
M  +66   -59   code_generator/gencode.c
M  +35   -41   code_generator/py2c.c
M  +0    -1    code_generator/sip.h
M  +1    -1    sip.egg-info/PKG-INFO
M  +3    -3    sipbuild/bindings.py
M  +1    -1    sipbuild/generator/outputs/api.py
M  +32   -12   sipbuild/generator/outputs/pyi.py
M  +1    -4    sipbuild/generator/outputs/xml.py
M  +13   -9    sipbuild/generator/parser/parser_manager.py
M  +1    -1    sipbuild/generator/parser/rules.py
M  +46   -59   sipbuild/generator/resolver/resolver.py
M  +2    -2    sipbuild/generator/specification.py
M  +1    -1    sipbuild/module/source/12/sip.h.in
M  +6    -1    sipbuild/module/source/12/siplib.c
M  +1    -1    sipbuild/module/source/13/sip.h.in
M  +1    -1    sipbuild/module/source/13/sip_core.c
M  +2    -2    sipbuild/version.py

https://invent.kde.org/neon/forks/sip6/commit/147325fbcc2a836d58c00e1b95a56ad35a9464ae

diff --git a/ChangeLog b/ChangeLog
index 98554e6..d8122e9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,75 @@
+2023-01-25  Phil Thompson  <phil at riverbankcomputing.com>
+
+	* NEWS, code_generator/py2c.c:
+	Reduce the use of the heap when converting from Python to C data
+	structures.
+	[67273f43bdbf] [6.7.6] <6.7-maint>
+
+2023-01-12  Phil Thompson  <phil at riverbankcomputing.com>
+
+	* code_generator/gencode.c:
+	Fixed a regression so that enums are not registered if there is no
+	meta-object.
+	[f4ccf3303e59] <6.7-maint>
+
+	* NEWS, code_generator/gencode.c:
+	Ensure that all enums (including global enums) are registered with
+	Qt so that they can be used in queued connections.
+	[259096e57fd7] <6.7-maint>
+
+2022-12-16  Phil Thompson  <phil at riverbankcomputing.com>
+
+	* NEWS, sipbuild/module/source/13/sip.h.in,
+	sipbuild/module/source/13/sip_core.c:
+	Fixed the implementation of /Transfer/ for global functions in ABI
+	v13.
+	[bc56c45dd235] <6.7-maint>
+
+2022-12-14  Phil Thompson  <phil at riverbankcomputing.com>
+
+	* NEWS, sipbuild/module/source/12/sip.h.in,
+	sipbuild/module/source/12/siplib.c:
+	In API v12 prevent an attempt to sub-class from an enum. The API
+	version number is now v12.11.1.
+	[91cda197b6ca] <6.7-maint>
+
+	* NEWS, sipbuild/generator/outputs/pyi.py:
+	Fixed type hints when a signal is overloaded with a method.
+	[6343b9aeceb9] <6.7-maint>
+
+2022-12-13  Phil Thompson  <phil at riverbankcomputing.com>
+
+	* NEWS, sipbuild/generator/outputs/pyi.py:
+	Fixed the .pyi file for enums with no members.
+	[b828fb046720] <6.7-maint>
+
+2022-12-05  Phil Thompson  <phil at riverbankcomputing.com>
+
+	* NEWS, sipbuild/generator/outputs/pyi.py:
+	Fixed the representation of Qt signals in the .pyi files.
+	[ba2933733f6c] <6.7-maint>
+
+2022-11-21  Phil Thompson  <phil at riverbankcomputing.com>
+
+	* code_generator/gencode.c, code_generator/py2c.c,
+	code_generator/sip.h, sipbuild/bindings.py,
+	sipbuild/generator/outputs/api.py,
+	sipbuild/generator/outputs/pyi.py,
+	sipbuild/generator/outputs/xml.py,
+	sipbuild/generator/parser/parser_manager.py,
+	sipbuild/generator/parser/rules.py,
+	sipbuild/generator/resolver/resolver.py,
+	sipbuild/generator/specification.py:
+	Re-factored Specification so that it just has the module that code
+	will be generated for rather than a list of all modules.
+	[be55cf9e3e79] <6.7-maint>
+
+2022-11-19  Phil Thompson  <phil at riverbankcomputing.com>
+
+	* .hgtags:
+	Added tag 6.7.5 for changeset 43c1391748cf
+	[bc0278714cdd] <6.7-maint>
+
 2022-11-15  Phil Thompson  <phil at riverbankcomputing.com>
 
 	* NEWS, sipbuild/generator/outputs/extracts.py:
diff --git a/NEWS b/NEWS
index 3009588..c2803b9 100644
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,7 @@
-v6.7.5 15th November 2022
+v6.7.6 25th January 2023
+  - The latest version of ABI v13 is v13.4.1.
+  - The latest version of ABI v12 is v12.11.1.
+  - Significantly reduced the memory requirements.
   - Bug fixes.
 
 v6.7.4 29th October 2022
diff --git a/PKG-INFO b/PKG-INFO
index 9b814a8..d6b037b 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: sip
-Version: 6.7.5
+Version: 6.7.6
 Summary: A Python bindings generator for C/C++ libraries
 Home-page: https://www.riverbankcomputing.com/software/sip/
 Author: Riverbank Computing Limited
diff --git a/code_generator/gencode.c b/code_generator/gencode.c
index 0ca5354..9fc917c 100644
--- a/code_generator/gencode.c
+++ b/code_generator/gencode.c
@@ -461,6 +461,61 @@ void generateExpression(valueDef *vd, int in_str, FILE *fp)
 }
 
 
+/*
+ * Generate the #defines for each feature defined in a module.
+ */
+static int generateFeatureDefines(moduleDef *mod,
+        stringList *needed_qualifiers, stringList *xsl, int noIntro, FILE *fp)
+{
+    qualDef *qd;
+
+    for (qd = mod->qualifiers; qd != NULL; qd = qd->next)
+    {
+        const char *qtype = NULL;
+
+        switch (qd->qtype)
+        {
+        case time_qualifier:
+            if (selectedQualifier(needed_qualifiers, qd))
+                qtype = "TIMELINE";
+
+            break;
+
+        case platform_qualifier:
+            if (selectedQualifier(needed_qualifiers, qd))
+                qtype = "PLATFORM";
+
+            break;
+
+        case feature_qualifier:
+            if (!excludedFeature(xsl, qd))
+                qtype = "FEATURE";
+
+            break;
+        }
+
+        if (qtype != NULL)
+        {
+            if (noIntro)
+            {
+                prcode(fp,
+"\n"
+"/* These are the qualifiers that are enabled. */\n"
+                    );
+
+                noIntro = FALSE;
+            }
+
+            prcode(fp,
+"#define SIP_%s_%s\n"
+                , qtype, qd->name);
+        }
+    }
+
+    return noIntro;
+}
+
+
 /*
  * Generate the C++ internal module API header file and return its path name on
  * the heap.
@@ -474,7 +529,6 @@ static const char *generateInternalAPIHeader(sipSpec *pt, moduleDef *mod,
     int noIntro;
     FILE *fp;
     nameDef *nd;
-    moduleDef *imp;
     moduleListDef *mld;
 
     hfile = concat(codeDir, "/sipAPI", mname, ".h", NULL);
@@ -504,55 +558,11 @@ static const char *generateInternalAPIHeader(sipSpec *pt, moduleDef *mod,
             );
 
     /* Define the qualifiers. */
-    noIntro = TRUE;
-
-    for (imp = pt->modules; imp != NULL; imp = imp->next)
-    {
-        qualDef *qd;
-
-        for (qd = imp->qualifiers; qd != NULL; qd = qd->next)
-        {
-            const char *qtype = NULL;
-
-            switch (qd->qtype)
-            {
-            case time_qualifier:
-                if (selectedQualifier(needed_qualifiers, qd))
-                    qtype = "TIMELINE";
-
-                break;
+    noIntro = generateFeatureDefines(mod, needed_qualifiers, xsl, TRUE, fp);
 
-            case platform_qualifier:
-                if (selectedQualifier(needed_qualifiers, qd))
-                    qtype = "PLATFORM";
-
-                break;
-
-            case feature_qualifier:
-                if (!excludedFeature(xsl, qd))
-                    qtype = "FEATURE";
-
-                break;
-            }
-
-            if (qtype != NULL)
-            {
-                if (noIntro)
-                {
-                    prcode(fp,
-"\n"
-"/* These are the qualifiers that are enabled. */\n"
-                        );
-
-                    noIntro = FALSE;
-                }
-
-                prcode(fp,
-"#define SIP_%s_%s\n"
-                    , qtype, qd->name);
-            }
-        }
-    }
+    for (mld = mod->allimports; mld != NULL; mld = mld->next)
+        noIntro = generateFeatureDefines(mld->module, needed_qualifiers, xsl,
+                noIntro, fp);
 
     if (!noIntro)
         prcode(fp,
@@ -1034,7 +1044,7 @@ static int generateCompositeCpp(sipSpec *pt, const char *codeDir,
         stringList **generated, int py_debug)
 {
     char *cppfile;
-    moduleDef *mod;
+    moduleListDef *mld;
     FILE *fp;
 
     cppfile = concat(codeDir, "/sip", pt->module->name, "cmodule.c", NULL);
@@ -1087,11 +1097,11 @@ static int generateCompositeCpp(sipSpec *pt, const char *codeDir,
 "\n"
         );
 
-    for (mod = pt->modules; mod != NULL; mod = mod->next)
-        if (mod->container == pt->module)
+    for (mld = pt->module->allimports; mld != NULL; mld = mld->next)
+        if (mld->module->container == pt->module)
             prcode(fp,
 "    sip_import_component_module(sipModuleDict, \"%s\");\n"
-                , mod->fullname->text);
+                , mld->module->fullname->text);
 
     prcode(fp,
 "\n"
@@ -2169,11 +2179,8 @@ static const char *generateCpp(sipSpec *pt, moduleDef *mod,
             , mname, mod->nrexceptions);
 
     /*
-     * Generate the enum meta-type registrations for PyQt6.  Qt6 registers
-     * these as and when it needs them which means that PyQt6 might handle them
-     * differently at different times.  It can be a particular problem with
-     * QMetaObject.invokeMethod().  The safest option is to register them all
-     * at the start.
+     * Generate the enum meta-type registrations for PyQt6 so that they can be
+     * used in queued connections.
      */
     if (pluginPyQt6(pt))
     {
@@ -2185,7 +2192,7 @@ static const char *generateCpp(sipSpec *pt, moduleDef *mod,
             if (isProtectedEnum(ed))
                 continue;
 
-            if (ed->ecd == NULL || noPyQtQMetaObject(ed->ecd))
+            if (ed->ecd != NULL && noPyQtQMetaObject(ed->ecd))
                 continue;
 
             prcode(fp,
diff --git a/code_generator/py2c.c b/code_generator/py2c.c
index af2f708..2e6b3f3 100644
--- a/code_generator/py2c.c
+++ b/code_generator/py2c.c
@@ -234,9 +234,10 @@ static void *search_str_cache(const strCache *cache, char *py_str)
 
 
 /* Forward declarations of convertors. */
-static argDef *argument(sipSpec *pt, PyObject *obj, const char *encoding);
-static argDef *argument_attr(sipSpec *pt, PyObject *obj, const char *name,
-        const char *encoding);
+static void argument(sipSpec *pt, PyObject *obj, const char *encoding,
+        argDef *value);
+static void argument_attr(sipSpec *pt, PyObject *obj, const char *name,
+        const char *encoding, argDef *value);
 static argList *argument_list_attr(sipSpec *pt, PyObject *obj,
         const char *name, const char *encoding);
 static int bool_attr(PyObject *obj, const char *name);
@@ -319,9 +320,9 @@ static scopedNameDef *scopedname(PyObject *obj, const char *encoding);
 static scopedNameDef *scopedname_attr(PyObject *obj, const char *name,
         const char *encoding);
 static signatureDef *signature(sipSpec *pt, PyObject *obj,
-        const char *encoding);
+        const char *encoding, signatureDef *value);
 static signatureDef *signature_attr(sipSpec *pt, PyObject *obj,
-        const char *name, const char *encoding);
+        const char *name, const char *encoding, signatureDef *value);
 static sourceLocation sourcelocation(PyObject *obj, const char *encoding);
 static sourceLocation sourcelocation_attr(PyObject *obj, const char *name,
         const char *encoding);
@@ -398,8 +399,7 @@ sipSpec *py2c(PyObject *spec, const char *encoding)
 
     pt = sipMalloc(sizeof (sipSpec));
 
-    pt->modules = module_list_attr(pt, spec, "modules", encoding);
-    pt->module = pt->modules;
+    pt->module = module_attr(pt, spec, "module", encoding);
     pt->namecache = cachedname_list_attr(spec, "name_cache", encoding);
     pt->ifacefiles = ifacefile_list_attr(pt, spec, "iface_files", encoding);
     pt->classes = class_list_attr(pt, spec, "classes", encoding);
@@ -428,9 +428,9 @@ sipSpec *py2c(PyObject *spec, const char *encoding)
 /*
  * Convert an optional Argument object.
  */
-static argDef *argument(sipSpec *pt, PyObject *obj, const char *encoding)
+static void argument(sipSpec *pt, PyObject *obj, const char *encoding,
+        argDef *value)
 {
-    argDef *value = sipMalloc(sizeof (argDef));
     PyObject *derefs_obj, *definition;
     int key, xfer, array;
     Py_ssize_t i;
@@ -438,7 +438,7 @@ static argDef *argument(sipSpec *pt, PyObject *obj, const char *encoding)
     if (obj == Py_None)
     {
         value->atype = no_type;
-        return value;
+        return;
     }
 
     value->atype = (argType)enum_attr(obj, "type");
@@ -523,7 +523,7 @@ static argDef *argument(sipSpec *pt, PyObject *obj, const char *encoding)
     switch (value->atype)
     {
     case function_type:
-        value->u.sa = signature(pt, definition, encoding);
+        value->u.sa = signature(pt, definition, encoding, NULL);
         break;
 
     case template_type:
@@ -560,27 +560,22 @@ static argDef *argument(sipSpec *pt, PyObject *obj, const char *encoding)
     }
 
     Py_DECREF(definition);
-
-    return value;
 }
 
 
 /*
  * Convert an optional Argument attribute.
  */
-static argDef *argument_attr(sipSpec *pt, PyObject *obj, const char *name,
-        const char *encoding)
+static void argument_attr(sipSpec *pt, PyObject *obj, const char *name,
+        const char *encoding, argDef *value)
 {
     PyObject *attr = PyObject_GetAttrString(obj, name);
-    argDef *value;
 
     assert(attr != NULL);
 
-    value = argument(pt, attr, encoding);
+    argument(pt, attr, encoding, value);
 
     Py_DECREF(attr);
-
-    return value;
 }
 
 
@@ -603,7 +598,7 @@ static argList *argument_list_attr(sipSpec *pt, PyObject *obj,
     {
         argList *item = sipMalloc(sizeof (argList));
 
-        item->arg = *argument(pt, PyList_GetItem(attr, i), encoding);
+        argument(pt, PyList_GetItem(attr, i), encoding, &item->arg);
 
         *tail = item;
         tail = &item->next;
@@ -1046,7 +1041,7 @@ static ctorDef *constructor(sipSpec *pt, PyObject *obj, const char *encoding)
     py_sig_obj = PyObject_GetAttrString(obj, "py_signature");
     assert(py_sig_obj != NULL);
 
-    value->pysig = *signature(pt, py_sig_obj, encoding);
+    signature(pt, py_sig_obj, encoding, &value->pysig);
 
     cpp_sig_obj = PyObject_GetAttrString(obj, "cpp_signature");
     assert(cpp_sig_obj != NULL);
@@ -1056,7 +1051,7 @@ static ctorDef *constructor(sipSpec *pt, PyObject *obj, const char *encoding)
         if (cpp_sig_obj == py_sig_obj)
             value->cppsig = &value->pysig;
         else
-            value->cppsig = signature(pt, cpp_sig_obj, encoding);
+            value->cppsig = signature(pt, cpp_sig_obj, encoding, NULL);
     }
 
     Py_DECREF(py_sig_obj);
@@ -1272,7 +1267,7 @@ static fcallDef *functioncall(sipSpec *pt, PyObject *obj, const char *encoding)
     PyObject *args_obj;
     Py_ssize_t i;
 
-    value->type = *argument_attr(pt, obj, "result", encoding);
+    argument_attr(pt, obj, "result", encoding, &value->type);
 
     args_obj = PyObject_GetAttrString(obj, "args");
     assert(args_obj != NULL);
@@ -1482,7 +1477,7 @@ static mappedTypeDef *mappedtype(sipSpec *pt, PyObject *obj,
     if (bool_attr(obj, "needs_user_state"))
         setNeedsUserState(value);
 
-    value->type = *argument_attr(pt, obj, "type", encoding);
+    argument_attr(pt, obj, "type", encoding, &value->type);
     value->pyname = cachedname_attr(obj, "py_name", encoding);
     value->cname = cachedname_attr(obj, "cpp_name", encoding);
     typehints_attr(obj, "type_hints", encoding, &value->typehint_in,
@@ -1719,8 +1714,8 @@ static moduleDef *module(sipSpec *pt, PyObject *obj, const char *encoding)
         value->needed_types = sipCalloc(nr_needed_types, sizeof (argDef));
 
         for (i = 0; i < nr_needed_types; ++i)
-            value->needed_types[i] = *argument(pt,
-                    PyList_GetItem(needed_types_obj, i), encoding);
+            argument(pt, PyList_GetItem(needed_types_obj, i), encoding,
+                    &value->needed_types[i]);
 
         value->nr_needed_types = nr_needed_types;
     }
@@ -1938,7 +1933,7 @@ static overDef *over(sipSpec *pt, PyObject *obj, const char *encoding)
     py_sig_obj = PyObject_GetAttrString(obj, "py_signature");
     assert(py_sig_obj != NULL);
 
-    value->pysig = *signature(pt, py_sig_obj, encoding);
+    signature(pt, py_sig_obj, encoding, &value->pysig);
 
     cpp_sig_obj = PyObject_GetAttrString(obj, "cpp_signature");
     assert(cpp_sig_obj != NULL);
@@ -1946,7 +1941,7 @@ static overDef *over(sipSpec *pt, PyObject *obj, const char *encoding)
     if (cpp_sig_obj == py_sig_obj)
         value->cppsig = &value->pysig;
     else
-        value->cppsig = signature(pt, cpp_sig_obj, encoding);
+        value->cppsig = signature(pt, cpp_sig_obj, encoding, NULL);
 
     Py_DECREF(py_sig_obj);
     Py_DECREF(cpp_sig_obj);
@@ -2170,25 +2165,25 @@ static scopedNameDef *scopedname_attr(PyObject *obj, const char *name,
  * Convert an optional Signature object.
  */
 static signatureDef *signature(sipSpec *pt, PyObject *obj,
-        const char *encoding)
+        const char *encoding, signatureDef *value)
 {
-    signatureDef *value;
     PyObject *args_obj;
     Py_ssize_t i;
 
     if (obj == Py_None)
         return NULL;
 
-    value = sipMalloc(sizeof (signatureDef));
+    if (value == NULL)
+        value = sipMalloc(sizeof (signatureDef));
 
-    value->result = *argument_attr(pt, obj, "result", encoding);
+    argument_attr(pt, obj, "result", encoding, &value->result);
 
     args_obj = PyObject_GetAttrString(obj, "args");
     assert(args_obj != NULL);
     assert(PyList_Check(args_obj));
 
     for (i = 0; i < PyList_Size(args_obj) && i < MAX_NR_ARGS; ++i)
-        value->args[i] = *argument(pt, PyList_GetItem(args_obj, i), encoding);
+        argument(pt, PyList_GetItem(args_obj, i), encoding, &value->args[i]);
 
     value->nrArgs = i;
 
@@ -2202,14 +2197,13 @@ static signatureDef *signature(sipSpec *pt, PyObject *obj,
  * Convert an optional Signature attribute.
  */
 static signatureDef *signature_attr(sipSpec *pt, PyObject *obj,
-        const char *name, const char *encoding)
+        const char *name, const char *encoding, signatureDef *value)
 {
     PyObject *attr = PyObject_GetAttrString(obj, name);
-    signatureDef *value;
 
     assert(attr != NULL);
 
-    value = signature(pt, attr, encoding);
+    value = signature(pt, attr, encoding, value);
 
     Py_DECREF(attr);
 
@@ -2337,7 +2331,7 @@ static templateDef *template(sipSpec *pt, PyObject *obj, const char *encoding)
     value = sipMalloc(sizeof (templateDef));
 
     value->fqname = scopedname_attr(obj, "cpp_name", encoding);
-    value->types = *signature_attr(pt, obj, "types", encoding);
+    signature_attr(pt, obj, "types", encoding, &value->types);
 
     return value;
 }
@@ -2678,8 +2672,8 @@ static virtHandlerDef *virtualhandler(sipSpec *pt, PyObject *obj,
 
     value = sipMalloc(sizeof (virtHandlerDef));
 
-    value->cppsig = signature_attr(pt, obj, "cpp_signature", encoding);
-    value->pysig = signature_attr(pt, obj, "py_signature", encoding);
+    value->cppsig = signature_attr(pt, obj, "cpp_signature", encoding, NULL);
+    value->pysig = signature_attr(pt, obj, "py_signature", encoding, NULL);
     value->virtcode = codeblock_list_attr(obj, "virtual_catcher_code",
             encoding);
     value->veh = virtualerrorhandler_attr(pt, obj, "virtual_error_handler",
@@ -3031,7 +3025,7 @@ static typedefDef *wrappedtypedef(sipSpec *pt, PyObject *obj,
     value->fqname = scopedname_attr(obj, "fq_cpp_name", encoding);
     value->ecd = class_attr(pt, obj, "scope", encoding);
     value->module = module_attr(pt, obj, "module", encoding);
-    value->type = *argument_attr(pt, obj, "type", encoding);
+    argument_attr(pt, obj, "type", encoding, &value->type);
 
     return value;
 }
@@ -3107,7 +3101,7 @@ static varDef *wrappedvariable(sipSpec *pt, PyObject *obj,
     if (bool_attr(obj, "needs_handler"))
         setNeedsHandler(value);
 
-    value->type = *argument_attr(pt, obj, "type", encoding);
+    argument_attr(pt, obj, "type", encoding, &value->type);
     value->accessfunc = codeblock_list_attr(obj, "access_code", encoding);
     value->getcode = codeblock_list_attr(obj, "get_code", encoding);
     value->setcode = codeblock_list_attr(obj, "set_code", encoding);
diff --git a/code_generator/sip.h b/code_generator/sip.h
index 31fcbb0..23b3f49 100644
--- a/code_generator/sip.h
+++ b/code_generator/sip.h
@@ -1259,7 +1259,6 @@ typedef struct _autoPyNameDef {
 /* The parse tree corresponding to the specification file. */
 typedef struct {
     moduleDef *module;                  /* The module being generated. */
-    moduleDef *modules;                 /* The list of modules. */
     nameDef *namecache;                 /* The name cache. */
     ifaceFileDef *ifacefiles;           /* The list of interface files. */
     classDef *classes;                  /* The list of classes. */
diff --git a/sip.egg-info/PKG-INFO b/sip.egg-info/PKG-INFO
index 9b814a8..d6b037b 100644
--- a/sip.egg-info/PKG-INFO
+++ b/sip.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: sip
-Version: 6.7.5
+Version: 6.7.6
 Summary: A Python bindings generator for C/C++ libraries
 Home-page: https://www.riverbankcomputing.com/software/sip/
 Author: Riverbank Computing Limited
diff --git a/sipbuild/bindings.py b/sipbuild/bindings.py
index 7f0a40e..a2346c7 100644
--- a/sipbuild/bindings.py
+++ b/sipbuild/bindings.py
@@ -163,17 +163,17 @@ class Bindings(Configurable):
         encoding = 'UTF-8'
 
         # Parse the input file.
-        spec, sip_files = parse(self.sip_file, SIP_VERSION, encoding,
+        spec, modules, sip_files = parse(self.sip_file, SIP_VERSION, encoding,
                 project.abi_version, self.tags, self.disabled_features,
                 self.protected_is_public, self._sip_include_dirs,
                 project.sip_module or 'sip')
 
         # Resolve the types.
-        resolve(spec)
+        resolve(spec, modules)
 
         pt = py2c(spec, encoding)
 
-        module = spec.modules[0]
+        module = spec.module
 
         uses_limited_api = module.use_limited_api or module.is_composite
 
diff --git a/sipbuild/generator/outputs/api.py b/sipbuild/generator/outputs/api.py
index 4a5fde0..b76e601 100644
--- a/sipbuild/generator/outputs/api.py
+++ b/sipbuild/generator/outputs/api.py
@@ -44,7 +44,7 @@ def output_api(spec, api_filename):
     """ Output a QScintilla API file. """
 
     with open(api_filename, 'w') as af:
-        module = spec.modules[0]
+        module = spec.module
 
         _enums(af, spec, module)
         _variables(af, spec, module)
diff --git a/sipbuild/generator/outputs/pyi.py b/sipbuild/generator/outputs/pyi.py
index f601b9c..b554366 100644
--- a/sipbuild/generator/outputs/pyi.py
+++ b/sipbuild/generator/outputs/pyi.py
@@ -24,7 +24,7 @@
 from ...version import SIP_VERSION_STR
 
 from ..specification import (AccessSpecifier, ArgumentType, ArrayArgument,
-        EnumBaseType, IfaceFileType, PySlot)
+        EnumBaseType, IfaceFileType, PyQtMethodSpecifier, PySlot)
 from ..utils import append_iface_file, find_method
 
 from .formatters import (ArgumentFormatter, ClassFormatter, format_copying,
@@ -35,7 +35,7 @@ def output_pyi(spec, pyi_filename):
     """ Output a .pyi file. """
 
     with open(pyi_filename, 'w') as pf:
-        module = spec.modules[0]
+        module = spec.module
 
         # Write the header.
         copying = format_copying(module.copying, '#')
@@ -58,8 +58,8 @@ f'''# The PEP 484 type hints stub file for the {module.py_name} module.
 def _composite_module(pf, spec, module):
     """ Output the type hints for a composite module. """
 
-    for mod in spec.modules:
-        if mod.composite is module:
+    for mod in spec.module.all_imports:
+        if mod.composite is spec.module:
             pf.write(f'from {mod.fq_py_name.name} import *\n')
 
 
@@ -386,8 +386,16 @@ def _enums(pf, spec, module, defined=None, scope=None, indent=0):
                 elif enum.base_type is EnumBaseType.INT_FLAG:
                     superclass = 'enum.IntFlag'
 
+            # Handle an enum with no members.
+            for member in enum.members:
+                if not member.no_type_hint:
+                    trivial = ''
+                    break
+            else:
+                trivial = ' ...'
+
             s = _indent(indent)
-            s+= f'class {enum.py_name.name}({superclass}):\n'
+            s+= f'class {enum.py_name.name}({superclass}):{trivial}\n'
             pf.write(s)
 
             indent += 1
@@ -395,12 +403,10 @@ def _enums(pf, spec, module, defined=None, scope=None, indent=0):
             enum_type = 'int'
 
         for member in enum.members:
-            if member.no_type_hint:
-                continue
-
-            s = _indent(indent)
-            s += f'{member.py_name.name} = ... # type: {enum_type}\n'
-            pf.write(s)
+            if not member.no_type_hint:
+                s = _indent(indent)
+                s += f'{member.py_name.name} = ... # type: {enum_type}\n'
+                pf.write(s)
 
         if enum.py_name is not None:
             indent -= 1
@@ -447,6 +453,18 @@ def _callable(pf, spec, module, member, overloads, is_method, defined,
         if overload.no_type_hint:
             continue
 
+        # Signals can have the same name as ordinary methods however
+        # 'typing.overload' cannot be used with ClassVar.  We choose to
+        # generate a type hint for the signal rather than any method.
+        if overload.pyqt_method_specifier is PyQtMethodSpecifier.SIGNAL:
+            scope = '' if module.py_name == 'QtCore' else 'QtCore.'
+
+            s = _indent(indent)
+            s += f'{overload.common.py_name.name}: typing.ClassVar[{scope}pyqtsignal]\n'
+            pf.write(s)
+
+            return
+
         nr_overloads += 1
 
     # Handle each overload.
@@ -518,6 +536,8 @@ def _overload(pf, spec, module, overload, overloaded, overload_nr, is_method,
     if is_method and overload.is_static:
         pf.write(_indent(indent) + '@staticmethod\n')
 
+    s = _indent(indent)
+
     if is_eq_slot:
         signature = '(self, other: object)'
     else:
@@ -526,8 +546,8 @@ def _overload(pf, spec, module, overload, overloaded, overload_nr, is_method,
         signature = _python_signature(spec, module, overload.py_signature,
                 defined, need_self=need_self)
 
-    s = _indent(indent)
     s += f'def {overload.common.py_name.name}{signature}: ...\n'
+
     pf.write(s)
 
 
diff --git a/sipbuild/generator/outputs/xml.py b/sipbuild/generator/outputs/xml.py
index c180395..b92a848 100644
--- a/sipbuild/generator/outputs/xml.py
+++ b/sipbuild/generator/outputs/xml.py
@@ -42,10 +42,7 @@ def output_xml(spec, module_name):
 
     # Note that we don't yet handle mapped types, templates or exceptions.
 
-    for module in spec.modules:
-        if module.py_name == module_name:
-            break
-    else:
+    if spec.module.py_name != module_name:
         return None
 
     root = Element('Module', version=_XML_VERSION_NR, name=module.py_name)
diff --git a/sipbuild/generator/parser/parser_manager.py b/sipbuild/generator/parser/parser_manager.py
index b55c5f6..6608f75 100644
--- a/sipbuild/generator/parser/parser_manager.py
+++ b/sipbuild/generator/parser/parser_manager.py
@@ -81,6 +81,9 @@ class ParserManager:
                 tuple([int(v) for v in abi_version.split('.')]), is_strict,
                 sip_module)
 
+        # The module is initially unnamed.
+        self.modules = [self.spec.module]
+
         self.c_bindings = None
         self.code_block = None
         self.module_state = None
@@ -1207,7 +1210,7 @@ class ParserManager:
             # The current file was %Included so create a new Module and
             # ModuleState as if it had been %Imported.
             module = Module()
-            self.spec.modules.append(module)
+            self.modules.append(module)
             self.module_state = ModuleState(module, self._sip_file, self)
 
         self._file_stack.append(
@@ -1317,7 +1320,7 @@ class ParserManager:
     def find_qualifier(self, p, symbol, name, required=True):
         """ Return a Qualifier or None if one doesn't exist. """
 
-        for module in self.spec.modules:
+        for module in self.modules:
             for qual in module.qualifiers:
                 if qual.name == name:
                     return qual
@@ -1458,7 +1461,7 @@ class ParserManager:
 
         module = self.module_state.module
 
-        return module is self.spec.modules[0] or module.composite is not None
+        return module is self.spec.module or module.composite is not None
 
     def instantiate_class_template(self, p, symbol, fq_cpp_name, template,
             py_name, no_type_name, docstring):
@@ -1487,9 +1490,10 @@ class ParserManager:
                         column=self._get_column_from_lexpos(t.lexpos)))
 
     def parse(self, sip_file):
-        """ Parse a .sip file and return a Specification object and a list of
-        the .sip files that specify the module to be generated.  A
-        UserException is raised if there was an error.
+        """ Parse a .sip file and return a 3-tuple of a Specification object, a
+        list of Module objects and a list of the .sip files that specify the
+        module to be generated.  A UserException is raised if there was an
+        error.
         """
 
         # Note that the retention of the 'raw' filename, ie. that which was
@@ -1499,7 +1503,7 @@ class ParserManager:
         raw_sip_file = sip_file
         sip_file = os.path.abspath(sip_file)
 
-        self.module_state = ModuleState(self.spec.modules[0], sip_file, self)
+        self.module_state = ModuleState(self.spec.module, sip_file, self)
 
         try:
             self._parser.parse(self._read(sip_file, raw_sip_file),
@@ -1538,7 +1542,7 @@ class ParserManager:
         for klass in self._template_arg_classes:
             self.spec.classes.remove(klass)
 
-        return self.spec, self._sip_files
+        return self.spec, self.modules, self._sip_files
 
     def parser_error(self, p, symbol, text):
         """ Record an error caused by a symbol in a production. """
@@ -1643,7 +1647,7 @@ class ParserManager:
                     break
             else:
                 module = Module()
-                self.spec.modules.append(module)
+                self.modules.append(module)
 
                 module.default_exception = self.module_state.module.default_exception
                 old_module_state = self.module_state
diff --git a/sipbuild/generator/parser/rules.py b/sipbuild/generator/parser/rules.py
index feea8d5..0c3ad03 100644
--- a/sipbuild/generator/parser/rules.py
+++ b/sipbuild/generator/parser/rules.py
@@ -210,7 +210,7 @@ def p_composite_module(p):
 
     module = pm.module_state.module
 
-    if module is not pm.spec.modules[0]:
+    if module is not pm.modules[0]:
         pm.parser_error(p, 1, "a %CompositeModule cannot be %Imported")
 
     if module.fq_py_name is not None:
diff --git a/sipbuild/generator/resolver/resolver.py b/sipbuild/generator/resolver/resolver.py
index 6097a78..e5fdd06 100644
--- a/sipbuild/generator/resolver/resolver.py
+++ b/sipbuild/generator/resolver/resolver.py
@@ -41,7 +41,7 @@ from ..utils import (append_iface_file, argument_as_str, cached_name,
         same_signature, search_typedefs)
 
 
-def resolve(spec):
+def resolve(spec, modules):
     """ Resolve all types of a parsed specification and create additional views
     so that code can be generated.
     """
@@ -49,7 +49,7 @@ def resolve(spec):
     error_log = ErrorLog()
 
     # Build the list of all imports for each module.
-    for mod in spec.modules:
+    for mod in modules:
         _set_all_imports(mod, error_log)
 
         # Set the base name of the module.  This is done for efficiency.
@@ -57,19 +57,18 @@ def resolve(spec):
 
     # Set the default meta-type for the main module if it doesn't have one
     # explicitly set.
-    main_mod = spec.modules[0]
-
-    if main_mod.default_metatype is None:
-        for mod in main_mod.all_imports:
+    if spec.module.default_metatype is None:
+        for mod in spec.module.all_imports:
             if mod.default_metatype is None:
                 continue
 
-            if main_mod.default_metatype is None:
-                main_mod.default_metatype = mod.default_metatype
-            elif main_mod.default_metatype is not mod.default_metatype:
+            if spec.module.default_metatype is None:
+                spec.module.default_metatype = mod.default_metatype
+            elif spec.module.default_metatype is not mod.default_metatype:
                 error_log.log(
                         "'{0}' module has imported different default meta-types '{1}' and '{2}'".format(
-                                main_mod.fq_py_name, main_mod.default_metatype,
+                                spec.module.fq_py_name,
+                                spec.module.default_metatype,
                                 mod.default_metatype))
 
     # Check each class has been defined.
@@ -95,7 +94,7 @@ def resolve(spec):
         _set_mro(spec, klass, error_log)
 
     # Resolve the various types in the modules.
-    _resolve_module(spec, spec.modules[0], error_log)
+    _resolve_module(spec, spec.module, error_log)
 
     # Handle default ctors now that the argument types are resolved.
     for klass in spec.classes:
@@ -112,18 +111,14 @@ def resolve(spec):
 
     # Move casts and slots around to their correct classes (if in the same
     # module) or create proxies for them (if cross-module).
-    for mod in spec.modules:
-        if _generating_code_for_module(spec, mod):
-            _move_main_module_casts_slots(spec, mod, error_log)
+    _move_main_module_casts_slots(spec, error_log)
 
     # Automatically generate missing complementary slots.
     for klass in spec.classes:
         _add_complementary_slots(spec, klass)
 
-    for mod in spec.modules:
-        if _generating_code_for_module(spec, mod):
-            for klass in mod.proxies:
-                _add_complementary_slots(spec, klass)
+    for klass in spec.module.proxies:
+        _add_complementary_slots(spec, klass)
 
     # Generate the different class views.
     for klass in spec.classes:
@@ -143,7 +138,7 @@ def resolve(spec):
                 _iface_files_are_used_by_overload(spec, klass.iface_file.used,
                         overload)
 
-    for mod in spec.modules:
+    for mod in modules:
         # Create the list of numbered types sorted by type name.
         _create_sorted_numbered_types(spec, mod, error_log)
 
@@ -166,8 +161,8 @@ def resolve(spec):
         # Include the %TypeHeaderCode for exceptions defined in the main
         # module.
         if spec.abi_version >= (13, 1) or (spec.abi_version >= (12, 9) and spec.abi_version < (13, 0)):
-            if exception_mod is spec.modules[0]:
-                append_iface_file(spec.modules[0].used, exception.iface_file)
+            if exception_mod is spec.module:
+                append_iface_file(spec.module.used, exception.iface_file)
 
         # Skip those that don't require a Python exception object to be
         # created.
@@ -177,15 +172,15 @@ def resolve(spec):
         if exception.builtin_base_exception is None and exception.defined_base_exception is None:
             continue
 
-        if exception_mod is spec.modules[0] or exception.needed:
+        if exception_mod is spec.module or exception.needed:
             exception.exception_nr = exception_mod.nr_exceptions
             exception_mod.nr_exceptions += 1
 
     # For PyQt6 mark all enum interface files as being used.
     if 'PyQt6' in spec.plugins:
         for enum in spec.enums:
-            if enum.module is spec.modules[0]:
-                _enum_iface_file_is_used(enum, spec.modules[0])
+            if enum.module is spec.module:
+                _enum_iface_file_is_used(enum, spec.module)
 
     # Create the name cache as seen by the legacy code.
     name_cache = spec.name_cache
@@ -411,21 +406,21 @@ def _set_all_imports(mod, error_log, seen=None):
     seen.remove(mod)
 
 
-def _move_main_module_casts_slots(spec, mod, error_log):
+def _move_main_module_casts_slots(spec, error_log):
     """ Move the casts and slots to the correct place for a main module (ie.
     the one we are generating code for).
     """
 
     for klass in spec.classes:
-        if klass.iface_file.module is mod:
-            _move_class_casts(spec, mod, klass, error_log)
+        if klass.iface_file.module is spec.module:
+            _move_class_casts(spec, klass, error_log)
 
-    for member in mod.global_functions:
-        if member.py_slot is not None and member.module is mod:
-            _move_global_slot(spec, mod, member, error_log)
+    for member in spec.module.global_functions:
+        if member.py_slot is not None and member.module is spec.module:
+            _move_global_slot(spec, member, error_log)
 
 
-def _move_class_casts(spec, mod, klass, error_log):
+def _move_class_casts(spec, klass, error_log):
     """ Move any class casts to its correct class, or publish as a ctor
     extender.
     """
@@ -443,9 +438,9 @@ def _move_class_casts(spec, mod, klass, error_log):
                 cpp_signature=signature, is_cast=True)
 
         # If the destination class is in a different module then use a proxy.
-        if dst_klass.iface_file.module is not mod:
-            _iface_file_is_used(mod.used, arg)
-            dst_klass = _get_proxy(mod, dst_klass)
+        if dst_klass.iface_file.module is not spec.module:
+            _iface_file_is_used(spec.module.used, arg)
+            dst_klass = _get_proxy(spec.module, dst_klass)
             ctor.no_typehint = True
 
         _iface_file_is_used(dst_klass.iface_file.used, arg)
@@ -461,10 +456,10 @@ def _move_class_casts(spec, mod, klass, error_log):
         dst_klass.ctors.append(ctor)
 
 
-def _move_global_slot(spec, mod, global_slot, error_log):
+def _move_global_slot(spec, global_slot, error_log):
     """ If possible, move a global slot to its correct class. """
 
-    for overload in list(mod.overloads):
+    for overload in list(spec.module.overloads):
         if overload.common is not global_slot:
             continue
 
@@ -559,7 +554,7 @@ def _move_global_slot(spec, mod, global_slot, error_log):
                     proxy.members.insert(0, proxy_member)
 
                 # Remove the overload from the list.
-                mod.overloads.remove(overload)
+                spec.module.overloads.remove(overload)
 
                 # Add the overload to the proxy.
                 overload.common = proxy_member
@@ -573,7 +568,7 @@ def _move_global_slot(spec, mod, global_slot, error_log):
             continue
 
         # Remove from the list.
-        mod.overloads.remove(overload)
+        spec.module.overloads.remove(overload)
 
         if arg_enum is not None:
             _enum_iface_file_is_used(arg_enum, arg_module)
@@ -676,7 +671,7 @@ def _add_auto_overload(spec, auto_klass, auto_overload):
                 overload.is_autogenerated = False
                 klass.overloads.insert(0, overload)
 
-                if _generating_code_for_module(spec, klass.iface_file.module):
+                if klass.iface_file.module is spec.module:
                     member.py_name.used = True
 
                 break
@@ -734,7 +729,7 @@ def _set_mro(spec, klass, error_log, seen=None):
                 if superklass_mro not in klass.mro:
                     klass.mro.append(superklass_mro)
 
-                if _generating_code_for_module(spec, klass.iface_file.module):
+                if klass.iface_file.module is spec.module:
                     superklass_mro.iface_file.needed = True
 
                 if superklass_mro.deprecated:
@@ -767,7 +762,7 @@ def _set_mro(spec, klass, error_log, seen=None):
         if klass.metatype is None and len(klass.superclasses) == 0:
             klass.metatype = klass.iface_file.module.default_metatype
 
-        if klass.metatype is not None and _generating_code_for_module(spec, klass.iface_file.module):
+        if klass.metatype is not None and klass.iface_file.module is spec.module:
             klass.metatype.used = True
 
         # If the class doesn't have an explicit super-type then inherit from
@@ -781,7 +776,7 @@ def _set_mro(spec, klass, error_log, seen=None):
             if klass.supertype.name.endswith('sip.wrapper'):
                 klass.supertype = None
 
-        if klass.supertype is not None and _generating_code_for_module(spec, klass.iface_file.module):
+        if klass.supertype is not None and klass.iface_file.module is spec.module:
             klass.supertype.used = True
 
     # Make sure that the module in which a sub-class convertor will be created
@@ -1005,7 +1000,7 @@ def _get_visible_py_members(spec, klass):
                         if overload.is_abstract:
                             klass.is_abstract = True
 
-                        if _generating_code_for_module(spec, klass.iface_file.module) and (klass is mro_klass or (overload.access_specifier is AccessSpecifier.PROTECTED and klass.has_shadow)):
+                        if klass.iface_file.module is spec.module and (klass is mro_klass or (overload.access_specifier is AccessSpecifier.PROTECTED and klass.has_shadow)):
                             need_types = True
                             member.py_name.used = True
 
@@ -1072,7 +1067,7 @@ def _add_virtual_overload(spec, overload, klass, error_log):
 
     # If this class is defined in the main module then make sure the virtuals
     # have a handler.
-    if _generating_code_for_module(spec, klass.iface_file.module):
+    if klass.iface_file.module is spec.module:
         virtual_handler = _get_virtual_handler(spec, overload, klass,
                 error_log)
 
@@ -1081,7 +1076,7 @@ def _add_virtual_overload(spec, overload, klass, error_log):
 
         # Make sure we have the interface files and type definitions for the
         # virtual handler.
-        _iface_files_are_used_by_overload(spec, spec.modules[0].used, overload,
+        _iface_files_are_used_by_overload(spec, spec.module.used, overload,
                 need_types=True)
     else:
         virtual_handler = None
@@ -1764,7 +1759,7 @@ def _resolve_type(spec, mod, scope, type, error_log, allow_defined=False):
 
     # If we are in the main module then mark any generated types as being
     # needed.
-    if _generating_code_for_module(spec, mod):
+    if mod is spec.module:
         _set_needed_type(type)
 
 
@@ -1780,7 +1775,7 @@ def _set_needed_type(arg):
 def _set_needed_exceptions(spec, mod, throw_args):
     """ Specify that a set of thrown arguments are needed. """
 
-    if _generating_code_for_module(spec, mod) and throw_args is not None and throw_args.arguments is not None:
+    if mod is spec.module and throw_args is not None and throw_args.arguments is not None:
         for exception in throw_args.arguments:
             _set_needs_exception(exception)
 
@@ -1835,7 +1830,7 @@ def _instantiate_mapped_type_template(spec, mod, mapped_type_template, type,
     mapped_type.type.is_reference = False
     mapped_type.cpp_name = cached_name(spec, argument_as_str(mapped_type.type))
 
-    if _generating_code_for_module(spec, mod):
+    if mod is spec.module:
         mapped_type.cpp_name.used = True
 
     proto_mapped_type = mapped_type_template.mapped_type
@@ -2114,7 +2109,7 @@ def _create_sorted_numbered_types(spec, mod, error_log):
         if klass.iface_file.module is not mod:
             continue
 
-        if _generating_code_for_module(spec, mod) or klass.iface_file.needed:
+        if mod is spec.module or klass.iface_file.needed:
             if not klass.is_hidden_namespace:
                 mod.needed_types.append(Argument(ArgumentType.CLASS,
                         definition=klass, name=klass.iface_file.cpp_name))
@@ -2123,7 +2118,7 @@ def _create_sorted_numbered_types(spec, mod, error_log):
         if mapped_type.iface_file.module is not mod:
             continue
 
-        if _generating_code_for_module(spec, mod) or mapped_type.iface_file.needed:
+        if mod is spec.module or mapped_type.iface_file.needed:
             mod.needed_types.append(Argument(ArgumentType.MAPPED,
                     definition=mapped_type, name=mapped_type.cpp_name))
 
@@ -2134,7 +2129,7 @@ def _create_sorted_numbered_types(spec, mod, error_log):
         if enum.fq_cpp_name is None:
             continue
 
-        if _generating_code_for_module(spec, mod) or enum.needed:
+        if mod is spec.module or enum.needed:
             mod.needed_types.append(Argument(ArgumentType.ENUM,
                     definition=enum, name=enum.cached_fq_cpp_name))
 
@@ -2164,14 +2159,6 @@ def _create_sorted_numbered_types(spec, mod, error_log):
         needed_type_nr += 1
 
 
-def _generating_code_for_module(spec, mod):
-    """ Return True if we are generating code for a module, ie. we are the main
-    module.
-    """
-
-    return spec.modules[0] is mod
-
-
 def _check_properties(klass, error_log):
     """ Check that any properties are valid. """
 
diff --git a/sipbuild/generator/specification.py b/sipbuild/generator/specification.py
index 62f711d..eecaaab 100644
--- a/sipbuild/generator/specification.py
+++ b/sipbuild/generator/specification.py
@@ -1322,8 +1322,8 @@ class Specification:
     # The mapped types.
     mapped_types: List[MappedType] = field(default_factory=list)
 
-    # The list of modules.  Initially there is an unnamed module.
-    modules: List[Module] = field(default_factory=lambda: [Module()])
+    # The module for which code is to be generated.
+    module: Module = field(default_factory=Module)
 
     # The cache of names that may be required as strings in the generated code.
     name_cache: Dict[int, List[CachedName]] = field(default_factory=dict)
diff --git a/sipbuild/module/source/12/sip.h.in b/sipbuild/module/source/12/sip.h.in
index 433acc0..fc7ff74 100644
--- a/sipbuild/module/source/12/sip.h.in
+++ b/sipbuild/module/source/12/sip.h.in
@@ -46,7 +46,7 @@ extern "C" {
 /* The version of the ABI. */
 #define SIP_ABI_MAJOR_VERSION       12
 #define SIP_ABI_MINOR_VERSION       11
-#define SIP_MODULE_PATCH_VERSION    0
+#define SIP_MODULE_PATCH_VERSION    1
 
 
 /*
diff --git a/sipbuild/module/source/12/siplib.c b/sipbuild/module/source/12/siplib.c
index 8bfb92a..e107698 100644
--- a/sipbuild/module/source/12/siplib.c
+++ b/sipbuild/module/source/12/siplib.c
@@ -12198,7 +12198,12 @@ static PyObject *sipEnumType_alloc(PyTypeObject *self, Py_ssize_t nitems)
     sipEnumTypeObject *py_type;
     sipPySlotDef *psd;
 
-    assert(currentType != NULL);
+    if (currentType == NULL)
+    {
+        PyErr_SetString(PyExc_TypeError, "enums cannot be sub-classed");
+        return NULL;
+    }
+
     assert(sipTypeIsEnum(currentType));
 
     /* Call the standard super-metatype alloc. */
diff --git a/sipbuild/module/source/13/sip.h.in b/sipbuild/module/source/13/sip.h.in
index 65867fa..7ed19b0 100644
--- a/sipbuild/module/source/13/sip.h.in
+++ b/sipbuild/module/source/13/sip.h.in
@@ -46,7 +46,7 @@ extern "C" {
 /* The version of the ABI. */
 #define SIP_ABI_MAJOR_VERSION       13
 #define SIP_ABI_MINOR_VERSION       4
-#define SIP_MODULE_PATCH_VERSION    0
+#define SIP_MODULE_PATCH_VERSION    1
 
 
 /*
diff --git a/sipbuild/module/source/13/sip_core.c b/sipbuild/module/source/13/sip_core.c
index 34c2948..c72f13a 100644
--- a/sipbuild/module/source/13/sip_core.c
+++ b/sipbuild/module/source/13/sip_core.c
@@ -4922,7 +4922,7 @@ static int parsePass2(PyObject *self, int selfarg, PyObject *sipArgs,
                 p = va_arg(va, void **);
 
                 if (flags & FMT_AP_TRANSFER)
-                    xfer = (isstatic ? arg : self);
+                    xfer = ((isstatic || self == NULL) ? arg : self);
                 else if (flags & FMT_AP_TRANSFER_BACK)
                     xfer = Py_None;
                 else
diff --git a/sipbuild/version.py b/sipbuild/version.py
index ad361fa..4755178 100644
--- a/sipbuild/version.py
+++ b/sipbuild/version.py
@@ -1,2 +1,2 @@
-SIP_VERSION = 0x060705
-SIP_VERSION_STR = '6.7.5'
+SIP_VERSION = 0x060706
+SIP_VERSION_STR = '6.7.6'



More information about the Neon-commits mailing list