C++, support bit-fields

Fixes sphinx-doc/sphinx#6707
This commit is contained in:
Jakob Lykke Andersen
2019-10-06 11:20:00 +02:00
parent e8963e84ed
commit 9671267009
3 changed files with 74 additions and 5 deletions

View File

@@ -16,6 +16,8 @@ Deprecated
Features added
--------------
* #6707: C++, support bit-fields.
Bugs fixed
----------

View File

@@ -3191,6 +3191,52 @@ class ASTDeclaratorNameParamQual(ASTBase):
self.paramQual.describe_signature(signode, mode, env, symbol)
class ASTDeclaratorNameBitField(ASTBase):
def __init__(self, declId, size):
self.declId = declId
self.size = size
@property
def name(self):
# type: () -> ASTNestedName
return self.declId
def get_param_id(self, version): # only the parameters (if any)
# type: (int) -> str
return ''
def get_ptr_suffix_id(self, version): # only the array specifiers
# type: (int) -> str
return ''
# ------------------------------------------------------------------------
def require_space_after_declSpecs(self):
# type: () -> bool
return self.declId is not None
def is_function_type(self):
# type: () -> bool
return False
def _stringify(self, transform):
# type: (Callable[[Any], str]) -> str
res = []
if self.declId:
res.append(transform(self.declId))
res.append(" : ")
res.append(transform(self.size))
return ''.join(res)
def describe_signature(self, signode, mode, env, symbol):
# type: (addnodes.desc_signature, str, BuildEnvironment, Symbol) -> None
_verify_description_mode(mode)
if self.declId:
self.declId.describe_signature(signode, mode, env, symbol)
signode.append(nodes.Text(' : ', ' : '))
self.size.describe_signature(signode, mode, env, symbol)
class ASTParenExprList(ASTBase):
def __init__(self, exprs):
# type: (List[Any]) -> None
@@ -5716,8 +5762,12 @@ class DefinitionParser:
trailing = None
return ASTDeclSpecs(outer, leftSpecs, rightSpecs, trailing)
def _parse_declarator_name_param_qual(self, named, paramMode, typed):
# type: (Union[bool, str], str, bool) -> ASTDeclaratorNameParamQual
def _parse_declarator_name_suffix(self,
named, # type: Union[bool, str]
paramMode, # type: str
typed # type: bool
):
# type: (...) -> Union[ASTDeclaratorNameParamQual, ASTDeclaratorNameBitField]
# now we should parse the name, and then suffixes
if named == 'maybe':
pos = self.pos
@@ -5760,6 +5810,13 @@ class DefinitionParser:
else:
break
paramQual = self._parse_parameters_and_qualifiers(paramMode)
if paramQual is None and len(arrayOps) == 0:
# perhaps a bit-field
if named and paramMode == 'type' and typed:
self.skip_ws()
if self.skip_string(':'):
size = self._parse_constant_expression(inTemplate=False)
return ASTDeclaratorNameBitField(declId=declId, size=size)
return ASTDeclaratorNameParamQual(declId=declId, arrayOps=arrayOps,
paramQual=paramQual)
@@ -5842,8 +5899,8 @@ class DefinitionParser:
pos = self.pos
try:
# assume this is params and quals
res = self._parse_declarator_name_param_qual(named, paramMode,
typed)
res = self._parse_declarator_name_suffix(named, paramMode,
typed)
return res
except DefinitionError as exParamQual:
prevErrors.append((exParamQual, "If declId, parameters, and qualifiers"))
@@ -5868,7 +5925,7 @@ class DefinitionParser:
raise self._make_multi_error(prevErrors, header)
pos = self.pos
try:
return self._parse_declarator_name_param_qual(named, paramMode, typed)
return self._parse_declarator_name_suffix(named, paramMode, typed)
except DefinitionError as e:
self.pos = pos
prevErrors.append((e, "If declarator-id"))

View File

@@ -334,6 +334,16 @@ def test_member_definitions():
check('member', 'thread_local extern int myInt', {1: 'myInt__i', 2: '5myInt'},
'extern thread_local int myInt')
# tests based on https://en.cppreference.com/w/cpp/language/bit_field
check('member', 'int b : 3', {1: 'b__i', 2: '1b'})
check('member', 'int b : 8 = 42', {1: 'b__i', 2: '1b'})
check('member', 'int b : 8{42}', {1: 'b__i', 2: '1b'})
# TODO: enable once the ternary operator is supported
#check('member', 'int b : true ? 8 : a = 42', {1: 'b__i', 2: '1b'})
# TODO: enable once the ternary operator is supported
#check('member', 'int b : (true ? 8 : a) = 42', {1: 'b__i', 2: '1b'})
check('member', 'int b : 1 || new int{0}', {1: 'b__i', 2: '1b'})
def test_function_definitions():
check('function', 'void f(volatile int)', {1: "f__iV", 2: "1fVi"})