sphinx icon indicating copy to clipboard operation
sphinx copied to clipboard

cpp: structs with designated member initialization fail to parse

Open drewrisinger opened this issue 1 year ago • 0 comments

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()

drewrisinger avatar Jan 24 '24 00:01 drewrisinger