From b94a60dc8941eb005844bb8789d68695f805973b Mon Sep 17 00:00:00 2001 From: Jakob Lykke Andersen Date: Thu, 24 Jun 2021 19:39:15 +0200 Subject: [PATCH] C++, support consteval and constinit --- CHANGES | 6 +++- sphinx/domains/cpp.py | 70 ++++++++++++++++++++++++++-------------- tests/test_domain_cpp.py | 2 ++ 3 files changed, 53 insertions(+), 25 deletions(-) diff --git a/CHANGES b/CHANGES index 98a18a0fa..c862f0cb6 100644 --- a/CHANGES +++ b/CHANGES @@ -53,7 +53,11 @@ Features added * #9097: Optimize the paralell build * #9131: Add :confval:`nitpick_ignore_regex` to ignore nitpicky warnings using regular expressions -* C++, add support for inline variables. +* C++, add support for + + - ``inline`` variables, + - ``consteval`` functions, + - ``constinit`` variables. Bugs fixed diff --git a/sphinx/domains/cpp.py b/sphinx/domains/cpp.py index b51cbd7e1..3e5aabc49 100644 --- a/sphinx/domains/cpp.py +++ b/sphinx/domains/cpp.py @@ -320,7 +320,8 @@ _fold_operator_re = re.compile(r'''(?x) _keywords = [ 'alignas', 'alignof', 'and', 'and_eq', 'asm', 'auto', 'bitand', 'bitor', 'bool', 'break', 'case', 'catch', 'char', 'char16_t', 'char32_t', 'class', - 'compl', 'concept', 'const', 'constexpr', 'const_cast', 'continue', + 'compl', 'concept', 'const', 'consteval', 'constexpr', 'constinit', + 'const_cast', 'continue', 'decltype', 'default', 'delete', 'do', 'double', 'dynamic_cast', 'else', 'enum', 'explicit', 'export', 'extern', 'false', 'float', 'for', 'friend', 'goto', 'if', 'inline', 'int', 'long', 'mutable', 'namespace', 'new', @@ -2101,14 +2102,17 @@ class ASTParametersQualifiers(ASTBase): class ASTDeclSpecsSimple(ASTBase): def __init__(self, storage: str, threadLocal: bool, inline: bool, virtual: bool, - explicit: bool, constexpr: bool, volatile: bool, const: bool, - friend: bool, attrs: List[ASTAttribute]) -> None: + explicit: bool, consteval: bool, constexpr: bool, constinit: bool, + volatile: bool, const: bool, friend: bool, + attrs: List[ASTAttribute]) -> None: self.storage = storage self.threadLocal = threadLocal self.inline = inline self.virtual = virtual self.explicit = explicit + self.consteval = consteval self.constexpr = constexpr + self.constinit = constinit self.volatile = volatile self.const = const self.friend = friend @@ -2122,7 +2126,9 @@ class ASTDeclSpecsSimple(ASTBase): self.inline or other.inline, self.virtual or other.virtual, self.explicit or other.explicit, + self.consteval or other.consteval, self.constexpr or other.constexpr, + self.constinit or other.constinit, self.volatile or other.volatile, self.const or other.const, self.friend or other.friend, @@ -2143,8 +2149,12 @@ class ASTDeclSpecsSimple(ASTBase): res.append('virtual') if self.explicit: res.append('explicit') + if self.consteval: + res.append('consteval') if self.constexpr: res.append('constexpr') + if self.constinit: + res.append('constinit') if self.volatile: res.append('volatile') if self.const: @@ -2177,8 +2187,12 @@ class ASTDeclSpecsSimple(ASTBase): addSpace = _add(signode, 'virtual') if self.explicit: addSpace = _add(signode, 'explicit') + if self.consteval: + addSpace = _add(signode, 'consteval') if self.constexpr: addSpace = _add(signode, 'constexpr') + if self.constinit: + addSpace = _add(signode, 'constinit') if self.volatile: addSpace = _add(signode, 'volatile') if self.const: @@ -5930,13 +5944,23 @@ class DefinitionParser(BaseParser): inline = None virtual = None explicit = None + consteval = None constexpr = None + constinit = None volatile = None const = None friend = None attrs = [] while 1: # accept any permutation of a subset of some decl-specs self.skip_ws() + if not const and typed: + const = self.skip_word('const') + if const: + continue + if not volatile and typed: + volatile = self.skip_word('volatile') + if volatile: + continue if not storage: if outer in ('member', 'function'): if self.skip_word('static'): @@ -5952,18 +5976,29 @@ class DefinitionParser(BaseParser): if self.skip_word('register'): storage = 'register' continue - if not threadLocal and outer == 'member': - threadLocal = self.skip_word('thread_local') - if threadLocal: - continue - if not inline and outer in ('function', 'member'): inline = self.skip_word('inline') if inline: continue + if not constexpr and outer in ('member', 'function'): + constexpr = self.skip_word("constexpr") + if constexpr: + continue + if outer == 'member': + if not constinit: + constinit = self.skip_word('constinit') + if constinit: + continue + if not threadLocal: + threadLocal = self.skip_word('thread_local') + if threadLocal: + continue if outer == 'function': - # function-specifiers + if not consteval: + consteval = self.skip_word('consteval') + if consteval: + continue if not friend: friend = self.skip_word('friend') if friend: @@ -5976,27 +6011,14 @@ class DefinitionParser(BaseParser): explicit = self.skip_word('explicit') if explicit: continue - - if not constexpr and outer in ('member', 'function'): - constexpr = self.skip_word("constexpr") - if constexpr: - continue - if not volatile and typed: - volatile = self.skip_word('volatile') - if volatile: - continue - if not const and typed: - const = self.skip_word('const') - if const: - continue attr = self._parse_attribute() if attr: attrs.append(attr) continue break return ASTDeclSpecsSimple(storage, threadLocal, inline, virtual, - explicit, constexpr, volatile, const, - friend, attrs) + explicit, consteval, constexpr, constinit, + volatile, const, friend, attrs) def _parse_decl_specs(self, outer: str, typed: bool = True) -> ASTDeclSpecs: if outer: diff --git a/tests/test_domain_cpp.py b/tests/test_domain_cpp.py index 9bf6da4f8..47e5bf379 100644 --- a/tests/test_domain_cpp.py +++ b/tests/test_domain_cpp.py @@ -436,6 +436,7 @@ def test_domain_cpp_ast_member_definitions(): check('member', 'int b : 1 || new int{0}', {1: 'b__i', 2: '1b'}) check('member', 'inline int n', {1: 'n__i', 2: '1n'}) + check('member', 'constinit int n', {1: 'n__i', 2: '1n'}) def test_domain_cpp_ast_function_definitions(): @@ -567,6 +568,7 @@ def test_domain_cpp_ast_function_definitions(): check("function", "void f(int *volatile const p)", {1: "f__iPVC", 2: "1fPVCi"}) check('function', 'extern int f()', {1: 'f', 2: '1fv'}) + check('function', 'consteval int f()', {1: 'f', 2: '1fv'}) check('function', 'decltype(auto) f()', {1: 'f', 2: "1fv"})