mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
C++, fix parsing of certain non-type template parameters
Specifically 'template<int (X::*)(bool)...>'
This commit is contained in:
parent
a95949aa13
commit
aa43a37865
1
CHANGES
1
CHANGES
@ -21,6 +21,7 @@ Bugs fixed
|
|||||||
|
|
||||||
- #10257: C++, ensure consistent non-specialization template argument
|
- #10257: C++, ensure consistent non-specialization template argument
|
||||||
representation.
|
representation.
|
||||||
|
- #10729: C++, fix parsing of certain non-type template parameter packs.
|
||||||
|
|
||||||
Testing
|
Testing
|
||||||
--------
|
--------
|
||||||
|
@ -3668,9 +3668,11 @@ class ASTTemplateParamTemplateType(ASTTemplateParam):
|
|||||||
class ASTTemplateParamNonType(ASTTemplateParam):
|
class ASTTemplateParamNonType(ASTTemplateParam):
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
param: Union[ASTTypeWithInit,
|
param: Union[ASTTypeWithInit,
|
||||||
ASTTemplateParamConstrainedTypeWithInit]) -> None:
|
ASTTemplateParamConstrainedTypeWithInit],
|
||||||
|
parameterPack: bool = False) -> None:
|
||||||
assert param
|
assert param
|
||||||
self.param = param
|
self.param = param
|
||||||
|
self.parameterPack = parameterPack
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self) -> ASTNestedName:
|
def name(self) -> ASTNestedName:
|
||||||
@ -3679,7 +3681,7 @@ class ASTTemplateParamNonType(ASTTemplateParam):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def isPack(self) -> bool:
|
def isPack(self) -> bool:
|
||||||
return self.param.isPack
|
return self.param.isPack or self.parameterPack
|
||||||
|
|
||||||
def get_identifier(self) -> ASTIdentifier:
|
def get_identifier(self) -> ASTIdentifier:
|
||||||
name = self.param.name
|
name = self.param.name
|
||||||
@ -3700,14 +3702,22 @@ class ASTTemplateParamNonType(ASTTemplateParam):
|
|||||||
# the anchor will be our parent
|
# the anchor will be our parent
|
||||||
return symbol.parent.declaration.get_id(version, prefixed=None)
|
return symbol.parent.declaration.get_id(version, prefixed=None)
|
||||||
else:
|
else:
|
||||||
return '_' + self.param.get_id(version)
|
res = '_'
|
||||||
|
if self.parameterPack:
|
||||||
|
res += 'Dp'
|
||||||
|
return res + self.param.get_id(version)
|
||||||
|
|
||||||
def _stringify(self, transform: StringifyTransform) -> str:
|
def _stringify(self, transform: StringifyTransform) -> str:
|
||||||
return transform(self.param)
|
res = transform(self.param)
|
||||||
|
if self.parameterPack:
|
||||||
|
res += '...'
|
||||||
|
return res
|
||||||
|
|
||||||
def describe_signature(self, signode: TextElement, mode: str,
|
def describe_signature(self, signode: TextElement, mode: str,
|
||||||
env: "BuildEnvironment", symbol: "Symbol") -> None:
|
env: "BuildEnvironment", symbol: "Symbol") -> None:
|
||||||
self.param.describe_signature(signode, mode, env, symbol)
|
self.param.describe_signature(signode, mode, env, symbol)
|
||||||
|
if self.parameterPack:
|
||||||
|
signode += addnodes.desc_sig_punctuation('...', '...')
|
||||||
|
|
||||||
|
|
||||||
class ASTTemplateParams(ASTBase):
|
class ASTTemplateParams(ASTBase):
|
||||||
@ -4155,7 +4165,7 @@ class LookupKey:
|
|||||||
|
|
||||||
def _is_specialization(templateParams: Union[ASTTemplateParams, ASTTemplateIntroduction],
|
def _is_specialization(templateParams: Union[ASTTemplateParams, ASTTemplateIntroduction],
|
||||||
templateArgs: ASTTemplateArgs) -> bool:
|
templateArgs: ASTTemplateArgs) -> bool:
|
||||||
"""Checks if `templateArgs` does not exactly match `templateParams`."""
|
# Checks if `templateArgs` does not exactly match `templateParams`.
|
||||||
# the names of the template parameters must be given exactly as args
|
# the names of the template parameters must be given exactly as args
|
||||||
# and params that are packs must in the args be the name expanded
|
# and params that are packs must in the args be the name expanded
|
||||||
if len(templateParams.params) != len(templateArgs.args):
|
if len(templateParams.params) != len(templateArgs.args):
|
||||||
@ -6775,7 +6785,7 @@ class DefinitionParser(BaseParser):
|
|||||||
def _parse_template_parameter(self) -> ASTTemplateParam:
|
def _parse_template_parameter(self) -> ASTTemplateParam:
|
||||||
self.skip_ws()
|
self.skip_ws()
|
||||||
if self.skip_word('template'):
|
if self.skip_word('template'):
|
||||||
# declare a tenplate template parameter
|
# declare a template template parameter
|
||||||
nestedParams = self._parse_template_parameter_list()
|
nestedParams = self._parse_template_parameter_list()
|
||||||
else:
|
else:
|
||||||
nestedParams = None
|
nestedParams = None
|
||||||
@ -6822,7 +6832,9 @@ class DefinitionParser(BaseParser):
|
|||||||
# non-type parameter or constrained type parameter
|
# non-type parameter or constrained type parameter
|
||||||
self.pos = pos
|
self.pos = pos
|
||||||
param = self._parse_type_with_init('maybe', 'templateParam')
|
param = self._parse_type_with_init('maybe', 'templateParam')
|
||||||
return ASTTemplateParamNonType(param)
|
self.skip_ws()
|
||||||
|
parameterPack = self.skip_string('...')
|
||||||
|
return ASTTemplateParamNonType(param, parameterPack)
|
||||||
except DefinitionError as eNonType:
|
except DefinitionError as eNonType:
|
||||||
self.pos = pos
|
self.pos = pos
|
||||||
header = "Error when parsing template parameter."
|
header = "Error when parsing template parameter."
|
||||||
|
@ -876,6 +876,9 @@ def test_domain_cpp_ast_templates():
|
|||||||
# defaulted constrained type parameters
|
# defaulted constrained type parameters
|
||||||
check('type', 'template<C T = int&> {key}A', {2: 'I_1CE1A'}, key='using')
|
check('type', 'template<C T = int&> {key}A', {2: 'I_1CE1A'}, key='using')
|
||||||
|
|
||||||
|
# pack expansion after non-type template parameter
|
||||||
|
check('type', 'template<int (X::*)(bool)...> {key}A', {2: 'I_DpM1XFibEE1A'}, key='using')
|
||||||
|
|
||||||
|
|
||||||
def test_domain_cpp_ast_placeholder_types():
|
def test_domain_cpp_ast_placeholder_types():
|
||||||
check('function', 'void f(Sortable auto &v)', {1: 'f__SortableR', 2: '1fR8Sortable'})
|
check('function', 'void f(Sortable auto &v)', {1: 'f__SortableR', 2: '1fR8Sortable'})
|
||||||
@ -1472,9 +1475,7 @@ def parse_template_parameter(param: str):
|
|||||||
('int X::*...', True),
|
('int X::*...', True),
|
||||||
('int (X::*)(bool)', False),
|
('int (X::*)(bool)', False),
|
||||||
('int (X::*x)(bool)', False),
|
('int (X::*x)(bool)', False),
|
||||||
# TODO: the following two declarations cannot currently be parsed
|
('int (X::*)(bool)...', True),
|
||||||
# ('int (X::*)(bool)...', True),
|
|
||||||
# ('int (X::*x...)(bool)', True),
|
|
||||||
('template<typename> class', False),
|
('template<typename> class', False),
|
||||||
('template<typename> class...', True),
|
('template<typename> class...', True),
|
||||||
])
|
])
|
||||||
|
Loading…
Reference in New Issue
Block a user