diff --git a/doc/doxygen.rst b/doc/doxygen.rst
index 3ea8d5a7..b04faee7 100644
--- a/doc/doxygen.rst
+++ b/doc/doxygen.rst
@@ -1396,6 +1396,8 @@ Property Description
:py:`compound.footer_navigation` Footer navigation of a page. See
`Navigation properties`_ for details.
:py:`compound.brief` Brief description. Can be empty. [1]_
+:py:`compound.is_final` Whether the class is :cpp:`final`. Set
+ only for classes.
:py:`compound.is_deprecated` Whether the compound is deprecated. [7]_
:py:`compound.description` Detailed description. Can be empty. [2]_
:py:`compound.modules` List of submodules in this compound.
@@ -1636,8 +1638,11 @@ Property Description
:py:`class.is_deprecated` Whether the class is deprecated. [7]_
:py:`class.is_protected` Whether this is a protected base class. Set only
for base classes.
-:py:`class.is_virtual` Whether this is a virtual base class. Set only for
- base classes.
+:py:`class.is_virtual` Whether this is a virtual base class or a
+ virtually derived class. Set only for base /
+ derived classes.
+:py:`class.is_final` Whether this is a final derived class. Set only for
+ derived classes.
=========================== ===================================================
`Enum properties`_
@@ -1743,65 +1748,75 @@ a list of functions, where every item has the following properties:
.. class:: m-table m-fullwidth
-=============================== ===============================================
-Property Description
-=============================== ===============================================
-:py:`func.base_url` Base URL of file containing detailed
- description [3]_
-:py:`func.include` Corresponding :cpp:`#include` to get the
- function declaration. Present only for
- functions inside modules or inside namespaces
- that are spread over multiple files. See
- `Include properties`_ for more information.
-:py:`func.id` Identifier hash [3]_
-:py:`func.type` Function return type [6]_
-:py:`func.name` Function name [4]_
-:py:`func.templates` Template specification. See
- `Template properties`_ for details.
-:py:`func.has_template_details` If template parameters have description
-:py:`func.params` List of function parameters. See below for
- details.
-:py:`func.has_param_details` If function parameters have description
-:py:`func.return_value` Return value description. Can be empty.
-:py:`func.return_values` Description of particular return values. See
- below for details.
-:py:`func.exceptions` Description of particular exception types. See
- below for details.
-:py:`func.brief` Brief description. Can be empty. [1]_
-:py:`func.description` Detailed description. Can be empty. [2]_
-:py:`func.has_details` If there is enough content for the full
- description block [5]_
-:py:`func.prefix` Function signature prefix, containing keywords
- such as :cpp:`static`. Information about
- :cpp:`constexpr`\ ness, :cpp:`explicit`\ ness
- and :cpp:`virtual`\ ity is removed from the
- prefix and available via other properties.
-:py:`func.suffix` Function signature suffix, containing keywords
- such as :cpp:`const` and r-value overloads.
- Information about :cpp:`noexcept`, pure
- :cpp:`virtual`\ ity and :cpp:`delete`\ d /
- :cpp:`default`\ ed functions is removed from
- the suffix and available via other properties.
-:py:`func.is_deprecated` Whether the function is deprecated. [7]_
-:py:`func.is_protected` If the function is :cpp:`protected`. Set only
- for member functions.
-:py:`func.is_private` If the function is :cpp:`private`. Set only for
- member functions.
-:py:`func.is_explicit` If the function is :cpp:`explicit`. Set only
- for member functions.
-:py:`func.is_virtual` If the function is :cpp:`virtual`. Set only for
- member functions.
-:py:`func.is_pure_virtual` If the function is pure :cpp:`virtual`. Set
- only for member functions.
-:py:`func.is_noexcept` If the function is :cpp:`noexcept`
-:py:`func.is_constexpr` If the function is :cpp:`constexpr`
-:py:`func.is_defaulted` If the function is :cpp:`default`\ ed
-:py:`func.is_deleted` If the function is :cpp:`delete`\ d
-:py:`func.is_signal` If the function is a Qt signal. Set only for
- member functions.
-:py:`func.is_slot` If the function is a Qt slot. Set only for
- member functions.
-=============================== ===============================================
+=================================== ===========================================
+Property Description
+=================================== ===========================================
+:py:`func.base_url` Base URL of file containing detailed
+ description [3]_
+:py:`func.include` Corresponding :cpp:`#include` to get the
+ function declaration. Present only for
+ functions inside modules or inside
+ namespaces that are spread over multiple
+ files. See `Include properties`_ for more
+ information.
+:py:`func.id` Identifier hash [3]_
+:py:`func.type` Function return type [6]_
+:py:`func.name` Function name [4]_
+:py:`func.templates` Template specification. See
+ `Template properties`_ for details.
+:py:`func.has_template_details` If template parameters have description
+:py:`func.params` List of function parameters. See below for
+ details.
+:py:`func.has_param_details` If function parameters have description
+:py:`func.return_value` Return value description. Can be empty.
+:py:`func.return_values` Description of particular return values.
+ See below for details.
+:py:`func.exceptions` Description of particular exception types.
+ See below for details.
+:py:`func.brief` Brief description. Can be empty. [1]_
+:py:`func.description` Detailed description. Can be empty. [2]_
+:py:`func.has_details` If there is enough content for the full
+ description block [5]_
+:py:`func.prefix` Function signature prefix, containing
+ keywords such as :cpp:`static`. Information
+ about :cpp:`constexpr`\ ness,
+ :cpp:`explicit`\ ness and
+ :cpp:`virtual`\ ity is removed from the
+ prefix and available via other properties.
+:py:`func.suffix` Function signature suffix, containing
+ keywords such as :cpp:`const` and r-value
+ overloads. Information about
+ :cpp:`noexcept`, pure :cpp:`virtual`\ ity
+ and :cpp:`delete`\ d / :cpp:`default`\ ed
+ functions is removed from the suffix and
+ available via other properties.
+:py:`func.is_deprecated` Whether the function is deprecated. [7]_
+:py:`func.is_protected` If the function is :cpp:`protected`. Set
+ only for member functions.
+:py:`func.is_private` If the function is :cpp:`private`. Set only
+ for member functions.
+:py:`func.is_explicit` If the function is :cpp:`explicit`. Set
+ only for member functions.
+:py:`func.is_virtual` If the function is :cpp:`virtual` (or pure
+ virtual). Set only for member functions.
+:py:`func.is_pure_virtual` If the function is pure :cpp:`virtual`. Set
+ only for member functions.
+:py:`func.is_override` If the function is an :cpp:`override`. Set
+ only for member functions.
+:py:`func.is_final` If the function is a :cpp:`final override`.
+ Set only for member functions.
+:py:`func.is_noexcept` If the function is :cpp:`noexcept` (even
+ conditionally)
+:py:`func.is_conditional_noexcept` If the function is conditionally
+ :cpp:`noexcept`.
+:py:`func.is_constexpr` If the function is :cpp:`constexpr`
+:py:`func.is_defaulted` If the function is :cpp:`default`\ ed
+:py:`func.is_deleted` If the function is :cpp:`delete`\ d
+:py:`func.is_signal` If the function is a Qt signal. Set only
+ for member functions.
+:py:`func.is_slot` If the function is a Qt slot. Set only for
+ member functions.
+=================================== ===========================================
The :py:`func.params` is a list of function parameters and their description.
Each item has the following properties:
diff --git a/doxygen/dox2html5.py b/doxygen/dox2html5.py
index 9a17afa1..7f6460c8 100755
--- a/doxygen/dox2html5.py
+++ b/doxygen/dox2html5.py
@@ -354,6 +354,8 @@ def __init__(self):
self.url: str
self.brief: str
self.has_details: bool
+ self.is_deprecated: bool
+ self.is_final: bool = None
self.children: List[str]
self.parent: str = None
@@ -1790,12 +1792,9 @@ def parse_func(state: State, element: ET.Element):
func.is_virtual = element.attrib['virt'] != 'non-virtual'
if element.attrib['static'] == 'yes':
func.prefix += 'static '
- signature = element.find('argsstring').text
- if signature.endswith(' noexcept'):
- signature = signature[:-9]
- func.is_noexcept = True
- else:
- func.is_noexcept = False
+ # Extract additional C++11 stuff from the signature. Order matters, going
+ # from the keywords that can be rightmost to the leftmost.
+ signature: str = element.find('argsstring').text
if signature.endswith('=default'):
signature = signature[:-8]
func.is_defaulted = True
@@ -1811,6 +1810,32 @@ def parse_func(state: State, element: ET.Element):
func.is_pure_virtual = True
else:
func.is_pure_virtual = False
+ # Final tested twice because it can be both `override final`
+ func.is_final = False
+ if signature.endswith(' final'):
+ signature = signature[:-6]
+ func.is_final = True
+ if signature.endswith(' override'):
+ signature = signature[:-9]
+ func.is_override = True
+ else:
+ func.is_override = False
+ # ... and `final override`
+ if signature.endswith(' final'):
+ signature = signature[:-6]
+ func.is_final = True
+ if signature.endswith(' noexcept'):
+ signature = signature[:-9]
+ func.is_noexcept = True
+ func.is_conditional_noexcept = False
+ elif ' noexcept(' in signature:
+ signature = signature[:signature.index(' noexcept(')]
+ func.is_noexcept = True
+ func.is_conditional_noexcept = True
+ else:
+ func.is_noexcept = False
+ func.is_conditional_noexcept = False
+ # Put the rest (const, volatile, ...) into a suffix
func.suffix = html.escape(signature[signature.rindex(')') + 1:].strip())
if func.suffix: func.suffix = ' ' + func.suffix
# Protected / private makes no sense for friend functions
@@ -1995,6 +2020,7 @@ def extract_metadata(state: State, xml):
compound.has_details = compound.kind in ['group', 'page'] or compound.brief or compounddef.find('detaileddescription')
compound.children = []
+ # Deprecation status
compound.is_deprecated = False
for i in compounddef.find('detaileddescription').findall('.//xrefsect'):
id = i.attrib['id']
@@ -2004,6 +2030,12 @@ def extract_metadata(state: State, xml):
compound.is_deprecated = True
break
+ # Final classes
+ if compound.kind in ['struct', 'class', 'union'] and compounddef.attrib.get('final') == 'yes':
+ compound.is_final = True
+ else:
+ compound.is_final = False
+
if compound.kind in ['class', 'struct', 'union']:
# Fix type spacing
compound.name = fix_type_spacing(compound.name)
@@ -2360,6 +2392,12 @@ def parse_xml(state: State, xml: str):
else:
state.current_prefix = []
+ # Final classes
+ if compound.kind in ['struct', 'class', 'union'] and compounddef.attrib.get('final') == 'yes':
+ compound.is_final = True
+ else:
+ compound.is_final = False
+
# Decide about the include file for this compound. Classes get it always,
# namespaces without any members too.
state.current_kind = compound.kind
@@ -2537,6 +2575,8 @@ def parse_xml(state: State, xml: str):
class_.brief = symbol.brief
class_.templates = symbol.templates
class_.is_deprecated = symbol.is_deprecated
+ class_.is_virtual = compounddef_child.attrib['virt'] == 'virtual'
+ class_.is_final = symbol.is_final
compound.derived_classes += [class_]
diff --git a/doxygen/templates/base-class-reference.html b/doxygen/templates/base-class-reference.html
index 0515dbb0..67f6aefb 100644
--- a/doxygen/templates/base-class-reference.html
+++ b/doxygen/templates/base-class-reference.html
@@ -24,7 +24,9 @@
{% set j = joiner(', ') %}
template<{% for t in compound.templates %}{{ j() }}{{ t.type }}{% if t.name %} {{ t.name }}{% endif %}{% if t.default %} = {{ t.default }}{% endif%}{% endfor %}>
{% endif %}
- {%+ for name, target in compound.breadcrumb[:-1] %}{{ name }}::{% endfor %}{{ compound.breadcrumb[-1][0] }} {{ compound.kind }}
+ {%+ for name, target in compound.breadcrumb[:-1] %}{{ name }}::{% endfor %}{{ compound.breadcrumb[-1][0] }} {{ compound.kind }}{% if compound.is_final %} final{% endif %}
+ {# need an explicit space here otherwise the newline gets removed #}
+
{% if compound.include and compound.templates == None %}