sphinx
sphinx copied to clipboard
cpp: structs with designated member initialization fail to parse
Describe the bug
Parsing C++ code that includes aggregate initialization w/ designated initializers fails.
Example error:
E sphinx.util.cfamily.DefinitionError: Invalid C++ declaration: Expected identifier in nested name. [error at 26]
E StructType struct_name = {.member_type = 0}
How to Reproduce
Add the following code to tests/test_domains/test_domain_cpp.py, then run the test suite:
def test_domain_cpp_struct_parsing():
parse('member', 'StructType struct_name = {0}') # works
parse('member', 'StructType struct_name = {.member_type = 0}') # doesn't work
Environment Information
Latest commit of the Sphinx master branch (discovered on 7.26.0)
Platform: linux; (Linux-5.15.0-91-generic-x86_64-with-glibc2.35)
Python version: 3.10.12 (main, Nov 20 2023, 15:14:05) [GCC 11.4.0])
Python implementation: CPython
Sphinx version: 7.3.0+/fa2900495
Docutils version: 0.20.1
Jinja2 version: 3.1.3
Pygments version: 2.17.2
Sphinx extensions
N/A
Additional context
Originally discovered via building docs with doxygen -> breathe pipeline. Same error message as https://github.com/sphinx-doc/sphinx/issues/10152, though that is due to a lambda function, while this is just struct initialization.
Stack trace for failed test:
tests/test_domains/test_domain_cpp.py:39: in parse
ast = parser.parse_declaration(name, name)
sphinx/domains/cpp/_parser.py:2035: in parse_declaration
declaration = self._parse_type_with_init(named=True, outer='member')
sphinx/domains/cpp/_parser.py:1622: in _parse_type_with_init
init = self._parse_initializer(outer=outer)
sphinx/domains/cpp/_parser.py:1506: in _parse_initializer
bracedInit = self._parse_braced_init_list()
sphinx/domains/cpp/_parser.py:364: in _parse_braced_init_list
exprs, trailingComma = self._parse_initializer_list("braced-init-list", '{', '}')
sphinx/domains/cpp/_parser.py:325: in _parse_initializer_list
expr = self._parse_initializer_clause()
sphinx/domains/cpp/_parser.py:359: in _parse_initializer_clause
return self._parse_assignment_expression(inTemplate=False)
sphinx/domains/cpp/_parser.py:727: in _parse_assignment_expression
leftExpr = self._parse_logical_or_expression(inTemplate=inTemplate)
sphinx/domains/cpp/_parser.py:697: in _parse_logical_or_expression
return _parse_bin_op_expr(self, 0, inTemplate=inTemplate)
sphinx/domains/cpp/_parser.py:667: in _parse_bin_op_expr
exprs.append(parser(inTemplate=inTemplate))
sphinx/domains/cpp/_parser.py:664: in parser
return _parse_bin_op_expr(self, opId + 1, inTemplate=inTemplate)
sphinx/domains/cpp/_parser.py:667: in _parse_bin_op_expr
exprs.append(parser(inTemplate=inTemplate))
sphinx/domains/cpp/_parser.py:664: in parser
return _parse_bin_op_expr(self, opId + 1, inTemplate=inTemplate)
sphinx/domains/cpp/_parser.py:667: in _parse_bin_op_expr
exprs.append(parser(inTemplate=inTemplate))
sphinx/domains/cpp/_parser.py:664: in parser
return _parse_bin_op_expr(self, opId + 1, inTemplate=inTemplate)
sphinx/domains/cpp/_parser.py:667: in _parse_bin_op_expr
exprs.append(parser(inTemplate=inTemplate))
sphinx/domains/cpp/_parser.py:664: in parser
return _parse_bin_op_expr(self, opId + 1, inTemplate=inTemplate)
sphinx/domains/cpp/_parser.py:667: in _parse_bin_op_expr
exprs.append(parser(inTemplate=inTemplate))
sphinx/domains/cpp/_parser.py:664: in parser
return _parse_bin_op_expr(self, opId + 1, inTemplate=inTemplate)
sphinx/domains/cpp/_parser.py:667: in _parse_bin_op_expr
exprs.append(parser(inTemplate=inTemplate))
sphinx/domains/cpp/_parser.py:664: in parser
return _parse_bin_op_expr(self, opId + 1, inTemplate=inTemplate)
sphinx/domains/cpp/_parser.py:667: in _parse_bin_op_expr
exprs.append(parser(inTemplate=inTemplate))
sphinx/domains/cpp/_parser.py:664: in parser
return _parse_bin_op_expr(self, opId + 1, inTemplate=inTemplate)
sphinx/domains/cpp/_parser.py:667: in _parse_bin_op_expr
exprs.append(parser(inTemplate=inTemplate))
sphinx/domains/cpp/_parser.py:664: in parser
return _parse_bin_op_expr(self, opId + 1, inTemplate=inTemplate)
sphinx/domains/cpp/_parser.py:667: in _parse_bin_op_expr
exprs.append(parser(inTemplate=inTemplate))
sphinx/domains/cpp/_parser.py:664: in parser
return _parse_bin_op_expr(self, opId + 1, inTemplate=inTemplate)
sphinx/domains/cpp/_parser.py:667: in _parse_bin_op_expr
exprs.append(parser(inTemplate=inTemplate))
sphinx/domains/cpp/_parser.py:664: in parser
return _parse_bin_op_expr(self, opId + 1, inTemplate=inTemplate)
sphinx/domains/cpp/_parser.py:667: in _parse_bin_op_expr
exprs.append(parser(inTemplate=inTemplate))
sphinx/domains/cpp/_parser.py:661: in parser
return self._parse_cast_expression()
sphinx/domains/cpp/_parser.py:643: in _parse_cast_expression
return self._parse_unary_expression()
sphinx/domains/cpp/_parser.py:619: in _parse_unary_expression
return self._parse_postfix_expression()