[neon/forks/sip6/Neon/release] debian: Add a patch to support enum base types.

Dmitry Shachnev null at kde.org
Sun Aug 17 07:48:50 BST 2025


Git commit efd45145f0cc16aaafd9a8acd8f9e112f1003dcc by Dmitry Shachnev.
Committed on 24/05/2025 at 19:14.
Pushed by carlosdem into branch 'Neon/release'.

Add a patch to support enum base types.

Refs: #1088101.

M  +6    -0    debian/changelog
A  +292  -0    debian/patches/enum_base_types.diff
M  +1    -0    debian/patches/series

https://invent.kde.org/neon/forks/sip6/-/commit/efd45145f0cc16aaafd9a8acd8f9e112f1003dcc

diff --git a/debian/changelog b/debian/changelog
index 9761f2b..cb3b609 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+sip6 (6.10.0-2) UNRELEASED; urgency=medium
+
+  * Add a patch to support enum base types (refs: #1088101).
+
+ -- Dmitry Shachnev <mitya57 at debian.org>  Sat, 24 May 2025 22:13:15 +0300
+
 sip6 (6.10.0-1) unstable; urgency=medium
 
   * New upstream release.
diff --git a/debian/patches/enum_base_types.diff b/debian/patches/enum_base_types.diff
new file mode 100644
index 0000000..f242770
--- /dev/null
+++ b/debian/patches/enum_base_types.diff
@@ -0,0 +1,292 @@
+From: Phil Thompson <phil at riverbankcomputing.com>
+Date: Sat, 24 May 2025 17:04:25 +0100
+Subject: Support enum base types
+
+---
+ docs/specification_files.rst                |  5 +++-
+ sipbuild/generator/outputs/code/code.py     | 35 +++++++++++++++++++++--
+ sipbuild/generator/parser/parser_manager.py |  6 ++--
+ sipbuild/generator/parser/rules.py          | 32 ++++++++++++++++++---
+ sipbuild/generator/resolver/resolver.py     | 44 +++++++++++++++++++++++++++--
+ sipbuild/generator/specification.py         |  3 ++
+ 6 files changed, 113 insertions(+), 12 deletions(-)
+
+diff --git a/docs/specification_files.rst b/docs/specification_files.rst
+index dce839a..fd5b330 100644
+--- a/docs/specification_files.rst
++++ b/docs/specification_files.rst
+@@ -203,10 +203,13 @@ file.
+     *mapped-type-template* :: = **template** **<** *type-list* **>**
+             *mapped-type*
+ 
+-    *enum* ::= **enum** [*enum-key*] [*name*] [*enum-annotations*] **{** {*enum-line*} **};**
++    *enum* ::= **enum** [*enum-key*] [*name*] [**:** *enum-base*]
++            [*enum-annotations*] **{** {*enum-line*} **};**
+ 
+     *enum-key* ::= [**class** | **struct**]
+ 
++    *enum-base* ::= *base-type*
++
+     *enum-line* ::= [:directive:`%If` | *name* [*enum-annotations*] **,**
+ 
+     *function* ::= *typed-name* **(** [*argument-list*] **)** [**noexcept**]
+diff --git a/sipbuild/generator/outputs/code/code.py b/sipbuild/generator/outputs/code/code.py
+index 997e3c3..f243956 100644
+--- a/sipbuild/generator/outputs/code/code.py
++++ b/sipbuild/generator/outputs/code/code.py
+@@ -5371,6 +5371,10 @@ def _call_args(sf, spec, cpp_signature, py_signature):
+             if nr_derefs == 1:
+                 indirection = '&'
+ 
++            if _arg_is_small_enum(arg):
++                prefix = 'static_cast<' + fmt_enum_as_cpp_type(arg.definition) + '>('
++                suffix = ')'
++
+         # See if we need to cast a Python void * to the correct C/C++ pointer
+         # type.  Note that we assume that the arguments correspond and are just
+         # different types.
+@@ -5452,6 +5456,8 @@ def _argument_variable(sf, spec, scope, arg, arg_nr):
+     saved_is_reference = arg.is_reference
+     saved_is_const = arg.is_const
+ 
++    use_typename = True
++
+     if arg.type in (ArgumentType.ASCII_STRING, ArgumentType.LATIN1_STRING, ArgumentType.UTF8_STRING, ArgumentType.SSTRING, ArgumentType.USTRING, ArgumentType.STRING, ArgumentType.WSTRING):
+         if not arg.is_reference:
+             if nr_derefs == 2:
+@@ -5465,6 +5471,10 @@ def _argument_variable(sf, spec, scope, arg, arg_nr):
+     else:
+         arg.derefs = []
+ 
++        if _arg_is_small_enum(arg):
++            arg.type = ArgumentType.INT
++            use_typename = False
++
+     # Array sizes are always Py_ssize_t.
+     if arg.array is ArrayArgument.ARRAY_SIZE:
+         arg.type = ArgumentType.SSIZE
+@@ -5475,7 +5485,7 @@ def _argument_variable(sf, spec, scope, arg, arg_nr):
+         arg.is_const = False
+ 
+     modified_arg_cpp_type = fmt_argument_as_cpp_type(spec, arg,
+-            scope=scope_iface_file)
++            scope=scope_iface_file, use_typename=use_typename)
+ 
+     sf.write(f'        {modified_arg_cpp_type} {arg_name}')
+ 
+@@ -5492,8 +5502,14 @@ def _argument_variable(sf, spec, scope, arg, arg_nr):
+         if arg.type in (ArgumentType.CLASS, ArgumentType.MAPPED) and (nr_derefs == 0 or arg.is_reference):
+             sf.write(f'&{arg_name}def')
+         else:
++            if _arg_is_small_enum(arg):
++                sf.write('static_cast<int>(')
++
+             sf.write(fmt_value_list_as_cpp_expression(spec, arg.default_value))
+ 
++            if _arg_is_small_enum(arg):
++                sf.write(')')
++
+     sf.write(';\n')
+ 
+     # Some types have supporting variables.
+@@ -7496,9 +7512,16 @@ def _get_slot_arg(spec, overload, arg_nr):
+ 
+     arg = overload.py_signature.args[arg_nr]
+ 
+-    dereference = '*' if arg.type in (ArgumentType.CLASS, ArgumentType.MAPPED) and len(arg.derefs) == 0 else ''
++    prefix = suffix = ''
+ 
+-    return dereference + fmt_argument_as_name(spec, arg, arg_nr)
++    if arg.type in (ArgumentType.CLASS, ArgumentType.MAPPED):
++        if len(arg.derefs) == 0:
++            prefix = '*'
++    elif _arg_is_small_enum(arg):
++        prefix = 'static_cast<' + fmt_enum_as_cpp_type(arg.definition) + '>('
++        suffix = ')'
++
++    return prefix + fmt_argument_as_name(spec, arg, arg_nr) + suffix
+ 
+ 
+ # A map of operators and their complements.
+@@ -8993,6 +9016,12 @@ def _optional_ptr(is_ptr, name):
+     return name if is_ptr else 'SIP_NULLPTR'
+ 
+ 
++def _arg_is_small_enum(arg):
++    """ Return True if an argument refers to a small C++11 enum. """
++
++    return arg.type is ArgumentType.ENUM and arg.definition.enum_base_type is not None
++
++
+ # The map of slots to C++ names.
+ _SLOT_NAME_MAP = {
+     PySlot.ADD:         'operator+',
+diff --git a/sipbuild/generator/parser/parser_manager.py b/sipbuild/generator/parser/parser_manager.py
+index 202c243..8bdc35f 100644
+--- a/sipbuild/generator/parser/parser_manager.py
++++ b/sipbuild/generator/parser/parser_manager.py
+@@ -565,7 +565,8 @@ class ParserManager:
+         if self.parsing_virtual or len(scope.dealloc_code) != 0:
+             scope.needs_shadow = True
+ 
+-    def add_enum(self, p, symbol, cpp_name, is_scoped, annotations, members):
++    def add_enum(self, p, symbol, cpp_name, is_scoped, enum_base_type,
++            annotations, members):
+         """ Create a new enum and add it to the current scope. """
+ 
+         if self.scope_access_specifier is AccessSpecifier.PRIVATE:
+@@ -616,7 +617,8 @@ class ParserManager:
+ 
+         w_enum = WrappedEnum(base_type, fq_cpp_name, self.module_state.module,
+                 cached_fq_cpp_name=cached_fq_cpp_name, is_scoped=is_scoped,
+-                py_name=py_name, scope=self.scope)
++                enum_base_type=enum_base_type, py_name=py_name,
++                scope=self.scope)
+ 
+         if self.scope_access_specifier is AccessSpecifier.PROTECTED:
+             if not self._protected_is_public:
+diff --git a/sipbuild/generator/parser/rules.py b/sipbuild/generator/parser/rules.py
+index 85090e1..ca9e0e3 100644
+--- a/sipbuild/generator/parser/rules.py
++++ b/sipbuild/generator/parser/rules.py
+@@ -2186,28 +2186,52 @@ _ENUM_MEMBER_ANNOTATIONS = (
+ 
+ 
+ def p_enum_decl(p):
+-    "enum_decl : enum opt_enum_key opt_name opt_annos '{' opt_enum_body '}' ';'"
++    "enum_decl : enum opt_enum_key opt_name opt_enum_base opt_annos '{' opt_enum_body '}' ';'"
+ 
+     pm = p.parser.pm
+ 
+     if pm.skipping:
+         return
+ 
+-    pm.check_annotations(p, 4, "enum", _ENUM_ANNOTATIONS)
++    pm.check_annotations(p, 5, "enum", _ENUM_ANNOTATIONS)
+ 
+-    pm.add_enum(p, 1, p[3], p[2], p[4], p[6])
++    pm.add_enum(p, 1, p[3], p[2], p[4], p[5], p[7])
+ 
+ 
+ def p_opt_enum_key(p):
+     """opt_enum_key : class
+         | struct
+-        | union
+         | empty"""
+ 
++    pm = p.parser.pm
++
++    if pm.skipping:
++        return
++
++    if p[1] is not None:
++        pm.cpp_only(p, 1, "enum keys")
++
+     # Return True if the enum is scoped.
+     p[0] = p[1] is not None
+ 
+ 
++def p_opt_enum_base(p):
++    """opt_enum_base : ':' base_type
++        | empty"""
++
++    pm = p.parser.pm
++
++    if pm.skipping:
++        return
++
++    if len(p) == 3:
++        pm.cpp_only(p, 1, "enum bases")
++
++        p[0] = p[2]
++    else:
++        p[0] = None
++
++
+ def p_opt_enum_body(p):
+     """opt_enum_body : enum_body
+         | empty"""
+diff --git a/sipbuild/generator/resolver/resolver.py b/sipbuild/generator/resolver/resolver.py
+index e4211f0..5ec6194 100644
+--- a/sipbuild/generator/resolver/resolver.py
++++ b/sipbuild/generator/resolver/resolver.py
+@@ -196,8 +196,9 @@ def _resolve_module(spec, mod, error_log, final_checks, seen=None):
+     for imported_mod in mod.imports:
+         _resolve_module(spec, imported_mod, error_log, final_checks, seen=seen)
+ 
+-    # Resolve typedefs, variables and global functions.
++    # Resolve typedefs, enums, variables and global functions.
+     _resolve_typedefs(spec, mod, error_log)
++    _resolve_enums(spec, mod, error_log)
+     _resolve_variables(spec, mod, error_log)
+     _resolve_scope_overloads(spec, mod.overloads, error_log, final_checks)
+ 
+@@ -920,7 +921,6 @@ def _resolve_scope_overloads(spec, overloads, error_log, final_checks,
+                     break
+ 
+         if isinstance(scope, WrappedClass):
+-
+             if scope.deprecated and not overload.deprecated :
+                 overload.deprecated = scope.deprecated
+ 
+@@ -928,6 +928,46 @@ def _resolve_scope_overloads(spec, overloads, error_log, final_checks,
+                 scope.is_abstract = True
+ 
+ 
++# The supported enum base types.  Note that we use the STRING types and the
++# BYTE types because there is no opportunity to apply the /PyInt/ annotation
++# and there can be no confusion about context.  We still need the BYTE types
++# because /PyInt/ could have been specified in a typedef.
++_ENUM_BASE_TYPES = (
++    ArgumentType.STRING,
++    ArgumentType.SSTRING,
++    ArgumentType.USTRING,
++    ArgumentType.BYTE,
++    ArgumentType.SBYTE,
++    ArgumentType.UBYTE,
++    ArgumentType.SHORT,
++    ArgumentType.USHORT,
++    ArgumentType.INT,
++    ArgumentType.UINT,
++)
++
++def _resolve_enums(spec, mod, error_log):
++    """ Resolve the base types for the enums of a module. """
++
++    for enum in spec.enums:
++        if enum.module is mod:
++            base_type = enum.enum_base_type
++
++            if base_type is None:
++                continue
++
++            _resolve_type(spec, enum.module, enum.scope, base_type, error_log)
++
++            # The current ABI implementations only support enums no larger than
++            # an int.
++            if base_type.type not in _ENUM_BASE_TYPES or len(base_type.derefs) != 0:
++                error_log.log(f"unsupported enum base type",
++                        source_location=base_type.source_location)
++
++            # The default is int.
++            if base_type.type is ArgumentType.INT:
++                enum.enum_base_type = None
++
++
+ def _resolve_variables(spec, mod, error_log):
+     """ Resolve the data types for the variables of a module. """
+ 
+diff --git a/sipbuild/generator/specification.py b/sipbuild/generator/specification.py
+index 57376ba..d0c1ea2 100644
+--- a/sipbuild/generator/specification.py
++++ b/sipbuild/generator/specification.py
+@@ -1666,6 +1666,9 @@ class WrappedEnum:
+     # The defining module.
+     module: Module
+ 
++    # The C++11 enum base type.
++    enum_base_type: Optional[Argument] = None
++
+     # The cached fully qualified C++ name.
+     cached_fq_cpp_name: Optional[CachedName] = None
+ 
diff --git a/debian/patches/series b/debian/patches/series
index 457087d..27cf999 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1,2 +1,3 @@
 intersphinx_local.diff
 system_ply.diff
+enum_base_types.diff



More information about the Neon-commits mailing list