C++, support consteval and constinit

This commit is contained in:
Jakob Lykke Andersen 2021-06-24 19:39:15 +02:00
parent 57237dbb07
commit b94a60dc89
3 changed files with 53 additions and 25 deletions

View File

@ -53,7 +53,11 @@ Features added
* #9097: Optimize the paralell build * #9097: Optimize the paralell build
* #9131: Add :confval:`nitpick_ignore_regex` to ignore nitpicky warnings using * #9131: Add :confval:`nitpick_ignore_regex` to ignore nitpicky warnings using
regular expressions regular expressions
* C++, add support for inline variables. * C++, add support for
- ``inline`` variables,
- ``consteval`` functions,
- ``constinit`` variables.
Bugs fixed Bugs fixed

View File

@ -320,7 +320,8 @@ _fold_operator_re = re.compile(r'''(?x)
_keywords = [ _keywords = [
'alignas', 'alignof', 'and', 'and_eq', 'asm', 'auto', 'bitand', 'bitor', 'alignas', 'alignof', 'and', 'and_eq', 'asm', 'auto', 'bitand', 'bitor',
'bool', 'break', 'case', 'catch', 'char', 'char16_t', 'char32_t', 'class', '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', 'decltype', 'default', 'delete', 'do', 'double', 'dynamic_cast', 'else',
'enum', 'explicit', 'export', 'extern', 'false', 'float', 'for', 'friend', 'enum', 'explicit', 'export', 'extern', 'false', 'float', 'for', 'friend',
'goto', 'if', 'inline', 'int', 'long', 'mutable', 'namespace', 'new', 'goto', 'if', 'inline', 'int', 'long', 'mutable', 'namespace', 'new',
@ -2101,14 +2102,17 @@ class ASTParametersQualifiers(ASTBase):
class ASTDeclSpecsSimple(ASTBase): class ASTDeclSpecsSimple(ASTBase):
def __init__(self, storage: str, threadLocal: bool, inline: bool, virtual: bool, def __init__(self, storage: str, threadLocal: bool, inline: bool, virtual: bool,
explicit: bool, constexpr: bool, volatile: bool, const: bool, explicit: bool, consteval: bool, constexpr: bool, constinit: bool,
friend: bool, attrs: List[ASTAttribute]) -> None: volatile: bool, const: bool, friend: bool,
attrs: List[ASTAttribute]) -> None:
self.storage = storage self.storage = storage
self.threadLocal = threadLocal self.threadLocal = threadLocal
self.inline = inline self.inline = inline
self.virtual = virtual self.virtual = virtual
self.explicit = explicit self.explicit = explicit
self.consteval = consteval
self.constexpr = constexpr self.constexpr = constexpr
self.constinit = constinit
self.volatile = volatile self.volatile = volatile
self.const = const self.const = const
self.friend = friend self.friend = friend
@ -2122,7 +2126,9 @@ class ASTDeclSpecsSimple(ASTBase):
self.inline or other.inline, self.inline or other.inline,
self.virtual or other.virtual, self.virtual or other.virtual,
self.explicit or other.explicit, self.explicit or other.explicit,
self.consteval or other.consteval,
self.constexpr or other.constexpr, self.constexpr or other.constexpr,
self.constinit or other.constinit,
self.volatile or other.volatile, self.volatile or other.volatile,
self.const or other.const, self.const or other.const,
self.friend or other.friend, self.friend or other.friend,
@ -2143,8 +2149,12 @@ class ASTDeclSpecsSimple(ASTBase):
res.append('virtual') res.append('virtual')
if self.explicit: if self.explicit:
res.append('explicit') res.append('explicit')
if self.consteval:
res.append('consteval')
if self.constexpr: if self.constexpr:
res.append('constexpr') res.append('constexpr')
if self.constinit:
res.append('constinit')
if self.volatile: if self.volatile:
res.append('volatile') res.append('volatile')
if self.const: if self.const:
@ -2177,8 +2187,12 @@ class ASTDeclSpecsSimple(ASTBase):
addSpace = _add(signode, 'virtual') addSpace = _add(signode, 'virtual')
if self.explicit: if self.explicit:
addSpace = _add(signode, 'explicit') addSpace = _add(signode, 'explicit')
if self.consteval:
addSpace = _add(signode, 'consteval')
if self.constexpr: if self.constexpr:
addSpace = _add(signode, 'constexpr') addSpace = _add(signode, 'constexpr')
if self.constinit:
addSpace = _add(signode, 'constinit')
if self.volatile: if self.volatile:
addSpace = _add(signode, 'volatile') addSpace = _add(signode, 'volatile')
if self.const: if self.const:
@ -5930,13 +5944,23 @@ class DefinitionParser(BaseParser):
inline = None inline = None
virtual = None virtual = None
explicit = None explicit = None
consteval = None
constexpr = None constexpr = None
constinit = None
volatile = None volatile = None
const = None const = None
friend = None friend = None
attrs = [] attrs = []
while 1: # accept any permutation of a subset of some decl-specs while 1: # accept any permutation of a subset of some decl-specs
self.skip_ws() 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 not storage:
if outer in ('member', 'function'): if outer in ('member', 'function'):
if self.skip_word('static'): if self.skip_word('static'):
@ -5952,18 +5976,29 @@ class DefinitionParser(BaseParser):
if self.skip_word('register'): if self.skip_word('register'):
storage = 'register' storage = 'register'
continue continue
if not threadLocal and outer == 'member':
threadLocal = self.skip_word('thread_local')
if threadLocal:
continue
if not inline and outer in ('function', 'member'): if not inline and outer in ('function', 'member'):
inline = self.skip_word('inline') inline = self.skip_word('inline')
if inline: if inline:
continue 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': if outer == 'function':
# function-specifiers if not consteval:
consteval = self.skip_word('consteval')
if consteval:
continue
if not friend: if not friend:
friend = self.skip_word('friend') friend = self.skip_word('friend')
if friend: if friend:
@ -5976,27 +6011,14 @@ class DefinitionParser(BaseParser):
explicit = self.skip_word('explicit') explicit = self.skip_word('explicit')
if explicit: if explicit:
continue 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() attr = self._parse_attribute()
if attr: if attr:
attrs.append(attr) attrs.append(attr)
continue continue
break break
return ASTDeclSpecsSimple(storage, threadLocal, inline, virtual, return ASTDeclSpecsSimple(storage, threadLocal, inline, virtual,
explicit, constexpr, volatile, const, explicit, consteval, constexpr, constinit,
friend, attrs) volatile, const, friend, attrs)
def _parse_decl_specs(self, outer: str, typed: bool = True) -> ASTDeclSpecs: def _parse_decl_specs(self, outer: str, typed: bool = True) -> ASTDeclSpecs:
if outer: if outer:

View File

@ -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', 'int b : 1 || new int{0}', {1: 'b__i', 2: '1b'})
check('member', 'inline int n', {1: 'n__i', 2: '1n'}) 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(): 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", "void f(int *volatile const p)", {1: "f__iPVC", 2: "1fPVCi"})
check('function', 'extern int f()', {1: 'f', 2: '1fv'}) 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"}) check('function', 'decltype(auto) f()', {1: 'f', 2: "1fv"})