diff --git a/CHANGES b/CHANGES index ee8bb59be54..f642906c556 100644 --- a/CHANGES +++ b/CHANGES @@ -16,7 +16,7 @@ Features added Bugs fixed ---------- -* #9917: C++, parse fundamental types no matter the order of simple type +* #9917: C and C++, parse fundamental types no matter the order of simple type specifiers. Testing diff --git a/sphinx/domains/c.py b/sphinx/domains/c.py index 84878cd05f4..6f8a21af5c8 100644 --- a/sphinx/domains/c.py +++ b/sphinx/domains/c.py @@ -95,28 +95,18 @@ _simple_type_specifiers_re = re.compile(r"""(?x) \b( void|_Bool|bool - # Integer - # ------- - |((signed|unsigned)\s+)?(char|( - ((long\s+long|long|short)\s+)?int - )) + |signed|unsigned + |short|long + |char + |int |__uint128|__int128 - # extensions - |((signed|unsigned)\s+)?__int(8|16|32|64|128) - # Floating-point - # -------------- - |(float|double|long\s+double)(\s+(_Complex|complex|_Imaginary|imaginary))? - |(_Complex|complex|_Imaginary|imaginary)\s+(float|double|long\s+double) + |__int(8|16|32|64|128) # extension + |float|double |_Decimal(32|64|128) - # extensions - |__float80|_Float64x|__float128|_Float128|__ibm128 - |__fp16 - # Fixed-point, extension - |(_Sat\s+)?((signed|unsigned)\s+)?((short|long|long\s+long)\s+)?(_Fract|fract|_Accum|accum) - # Integer types that could be prefixes of the previous ones - # --------------------------------------------------------- - |((signed|unsigned)\s+)?(long\s+long|long|short) - |signed|unsigned + |_Complex|complex|_Imaginary|imaginary + |__float80|_Float64x|__float128|_Float128|__ibm128 # extension + |__fp16 # extension + |_Sat|_Fract|fract|_Accum|accum # extension )\b """) @@ -636,8 +626,9 @@ class ASTTrailingTypeSpec(ASTBase): class ASTTrailingTypeSpecFundamental(ASTTrailingTypeSpec): - def __init__(self, name: str) -> None: - self.names = name.split() + def __init__(self, names: List[str]) -> None: + assert len(names) != 0 + self.names = names def _stringify(self, transform: StringifyTransform) -> str: return ' '.join(self.names) @@ -2580,12 +2571,24 @@ def _parse_nested_name(self) -> ASTNestedName: break return ASTNestedName(names, rooted) + def _parse_simple_type_specifiers(self) -> ASTTrailingTypeSpecFundamental: + names: List[str] = [] + + self.skip_ws() + while self.match(_simple_type_specifiers_re): + names.append(self.matched_text) + self.skip_ws() + if len(names) == 0: + return None + return ASTTrailingTypeSpecFundamental(names) + def _parse_trailing_type_spec(self) -> ASTTrailingTypeSpec: # fundamental types, https://en.cppreference.com/w/c/language/type # and extensions self.skip_ws() - if self.match(_simple_type_specifiers_re): - return ASTTrailingTypeSpecFundamental(self.matched_text) + res = self._parse_simple_type_specifiers() + if res is not None: + return res # prefixed prefix = None diff --git a/tests/test_domain_c.py b/tests/test_domain_c.py index 0800c505962..60d3fa488eb 100644 --- a/tests/test_domain_c.py +++ b/tests/test_domain_c.py @@ -8,6 +8,7 @@ :license: BSD, see LICENSE for details. """ +import itertools import zlib from xml.etree import ElementTree @@ -329,6 +330,13 @@ def signed(t): input = "{key}%s foo" % t output = ' '.join(input.split()) check('type', input, {1: 'foo'}, key='typedef', output=output) + if ' ' in t: + # try permutations of all components + tcs = t.split() + for p in itertools.permutations(tcs): + input = "{key}%s foo" % ' '.join(p) + output = ' '.join(input.split()) + check("type", input, {1: 'foo'}, key='typedef', output=output) def test_domain_c_ast_type_definitions(): diff --git a/tests/test_domain_cpp.py b/tests/test_domain_cpp.py index 881d911c3c9..5ff8f8e1296 100644 --- a/tests/test_domain_cpp.py +++ b/tests/test_domain_cpp.py @@ -144,7 +144,7 @@ def makeIdV2(): output = "void f(%s arg)" % t check("function", input, {1: id1, 2: id2}, output=output) if ' ' in t: - # try permutations of all commponents + # try permutations of all components tcs = t.split() for p in itertools.permutations(tcs): input = "void f(%s arg)" % ' '.join(p)