Skip to content

Commit a4371ea

Browse files
committed
C++, update fundamental type handling a la in C
1 parent cf091f7 commit a4371ea

File tree

3 files changed

+65
-47
lines changed

3 files changed

+65
-47
lines changed

CHANGES

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ Features added
1919
template variable ``sphinx_version_tuple``
2020
* #9445: py domain: ``:py:property:`` directive supports ``:classmethod:``
2121
option to describe the class property
22-
* #9535: C, support more fundamental types, including GNU extensions.
22+
* #9535: C and C++, support more fundamental types, including GNU extensions.
2323

2424
Bugs fixed
2525
----------

sphinx/domains/cpp.py

Lines changed: 58 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,30 @@
334334
'while', 'xor', 'xor_eq'
335335
]
336336

337+
338+
_simple_type_sepcifiers_re = re.compile(r"""(?x)
339+
\b(
340+
auto|void|bool
341+
# Integer
342+
# -------
343+
|((signed|unsigned)\s+)?(char|__int128|(
344+
((long\s+long|long|short)\s+)?int
345+
))
346+
|wchar_t|char(8|16|32)_t
347+
# extensions
348+
|((signed|unsigned)\s+)?__int(64|128)
349+
# Floating-point
350+
# --------------
351+
|(float|double|long\s+double)(\s+(_Complex|_Imaginary))?
352+
# extensions
353+
|__float80|_Float64x|__float128|_Float128
354+
# Integer types that could be prefixes of the previous ones
355+
# ---------------------------------------------------------
356+
|((signed|unsigned)\s+)?(long\s+long|long|short)
357+
|signed|unsigned
358+
)\b
359+
""")
360+
337361
_max_id = 4
338362
_id_prefix = [None, '', '_CPPv2', '_CPPv3', '_CPPv4']
339363
# Ids are used in lookup keys which are used across pickled files,
@@ -449,11 +473,25 @@
449473
'long long int': 'x',
450474
'signed long long': 'x',
451475
'signed long long int': 'x',
476+
'__int64': 'x',
452477
'unsigned long long': 'y',
453478
'unsigned long long int': 'y',
479+
'__int128': 'n',
480+
'signed __int128': 'n',
481+
'unsigned __int128': 'o',
454482
'float': 'f',
455483
'double': 'd',
456484
'long double': 'e',
485+
'__float80': 'e',
486+
'_Float64x': 'e',
487+
'__float128': 'g',
488+
'_Float128': 'g',
489+
'float _Complex': 'Cf',
490+
'double _Complex': 'Cd',
491+
'long double _Complex': 'Ce',
492+
'float _Imaginary': 'f',
493+
'double _Imaginary': 'd',
494+
'long double _Imaginary': 'e',
457495
'auto': 'Da',
458496
'decltype(auto)': 'Dc',
459497
'std::nullptr_t': 'Dn'
@@ -1817,31 +1855,38 @@ def describe_signature(self, signode: TextElement, mode: str,
18171855

18181856
class ASTTrailingTypeSpecFundamental(ASTTrailingTypeSpec):
18191857
def __init__(self, name: str) -> None:
1820-
self.name = name
1858+
self.names = name.split()
18211859

18221860
def _stringify(self, transform: StringifyTransform) -> str:
1823-
return self.name
1861+
return ' '.join(self.names)
18241862

18251863
def get_id(self, version: int) -> str:
18261864
if version == 1:
18271865
res = []
1828-
for a in self.name.split(' '):
1866+
for a in self.names:
18291867
if a in _id_fundamental_v1:
18301868
res.append(_id_fundamental_v1[a])
18311869
else:
18321870
res.append(a)
18331871
return '-'.join(res)
18341872

1835-
if self.name not in _id_fundamental_v2:
1873+
txt = str(self)
1874+
if txt not in _id_fundamental_v2:
18361875
raise Exception(
18371876
'Semi-internal error: Fundamental type "%s" can not be mapped '
1838-
'to an id. Is it a true fundamental type? If not so, the '
1839-
'parser should have rejected it.' % self.name)
1840-
return _id_fundamental_v2[self.name]
1877+
'to an ID. Is it a true fundamental type? If not so, the '
1878+
'parser should have rejected it.' % txt)
1879+
return _id_fundamental_v2[txt]
18411880

18421881
def describe_signature(self, signode: TextElement, mode: str,
18431882
env: "BuildEnvironment", symbol: "Symbol") -> None:
1844-
signode += addnodes.desc_sig_keyword_type(self.name, self.name)
1883+
first = True
1884+
for n in self.names:
1885+
if not first:
1886+
signode += addnodes.desc_sig_space()
1887+
else:
1888+
first = False
1889+
signode += addnodes.desc_sig_keyword_type(n, n)
18451890

18461891

18471892
class ASTTrailingTypeSpecDecltypeAuto(ASTTrailingTypeSpec):
@@ -4996,15 +5041,6 @@ def dump(self, indent: int) -> str:
49965041

49975042

49985043
class DefinitionParser(BaseParser):
4999-
# those without signedness and size modifiers
5000-
# see https://en.cppreference.com/w/cpp/language/types
5001-
_simple_fundemental_types = (
5002-
'void', 'bool', 'char', 'wchar_t', 'char8_t', 'char16_t', 'char32_t',
5003-
'int', 'float', 'double', 'auto'
5004-
)
5005-
5006-
_prefix_keys = ('class', 'struct', 'enum', 'union', 'typename')
5007-
50085044
@property
50095045
def language(self) -> str:
50105046
return 'C++'
@@ -5821,33 +5857,11 @@ def _parse_nested_name(self, memberPointer: bool = False) -> ASTNestedName:
58215857
# ==========================================================================
58225858

58235859
def _parse_trailing_type_spec(self) -> ASTTrailingTypeSpec:
5824-
# fundemental types
5860+
# fundamental types, https://en.cppreference.com/w/cpp/language/type
5861+
# and extensions
58255862
self.skip_ws()
5826-
for t in self._simple_fundemental_types:
5827-
if self.skip_word(t):
5828-
return ASTTrailingTypeSpecFundamental(t)
5829-
5830-
# TODO: this could/should be more strict
5831-
elements = []
5832-
if self.skip_word_and_ws('signed'):
5833-
elements.append('signed')
5834-
elif self.skip_word_and_ws('unsigned'):
5835-
elements.append('unsigned')
5836-
while 1:
5837-
if self.skip_word_and_ws('short'):
5838-
elements.append('short')
5839-
elif self.skip_word_and_ws('long'):
5840-
elements.append('long')
5841-
else:
5842-
break
5843-
if self.skip_word_and_ws('char'):
5844-
elements.append('char')
5845-
elif self.skip_word_and_ws('int'):
5846-
elements.append('int')
5847-
elif self.skip_word_and_ws('double'):
5848-
elements.append('double')
5849-
if len(elements) > 0:
5850-
return ASTTrailingTypeSpecFundamental(' '.join(elements))
5863+
if self.match(_simple_type_sepcifiers_re):
5864+
return ASTTrailingTypeSpecFundamental(self.matched_text)
58515865

58525866
# decltype
58535867
self.skip_ws()
@@ -5867,7 +5881,7 @@ def _parse_trailing_type_spec(self) -> ASTTrailingTypeSpec:
58675881
# prefixed
58685882
prefix = None
58695883
self.skip_ws()
5870-
for k in self._prefix_keys:
5884+
for k in ('class', 'struct', 'enum', 'union', 'typename'):
58715885
if self.skip_word_and_ws(k):
58725886
prefix = k
58735887
break

tests/test_domain_cpp.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,9 @@ def test_domain_cpp_ast_fundamental_types():
123123
def makeIdV1():
124124
if t == 'decltype(auto)':
125125
return None
126-
id = t.replace(" ", "-").replace("long", "l").replace("int", "i")
126+
id = t.replace(" ", "-").replace("long", "l")
127+
if "__int" not in t:
128+
id = id.replace("int", "i")
127129
id = id.replace("bool", "b").replace("char", "c")
128130
id = id.replace("wc_t", "wchar_t").replace("c16_t", "char16_t")
129131
id = id.replace("c8_t", "char8_t")
@@ -135,7 +137,9 @@ def makeIdV2():
135137
if t == "std::nullptr_t":
136138
id = "NSt9nullptr_tE"
137139
return "1f%s" % id
138-
check("function", "void f(%s arg)" % t, {1: makeIdV1(), 2: makeIdV2()})
140+
input = "void f(%s arg)" % t.replace(' ', ' ')
141+
output = "void f(%s arg)" % t
142+
check("function", input, {1: makeIdV1(), 2: makeIdV2()}, output=output)
139143

140144

141145
def test_domain_cpp_ast_expressions():

0 commit comments

Comments
 (0)