C++, support the template disambiguator for dependent names.

This commit is contained in:
Jakob Lykke Andersen 2017-12-24 16:31:10 +01:00
parent a9efb2517a
commit 9766c2f339
3 changed files with 41 additions and 18 deletions

View File

@ -96,6 +96,7 @@ Bugs fixed
* #4094: C++, allow empty template argument lists. * #4094: C++, allow empty template argument lists.
* C++, also hyperlink types in the name of declarations with qualified names. * C++, also hyperlink types in the name of declarations with qualified names.
* C++, do not add index entries for declarations inside concepts. * C++, do not add index entries for declarations inside concepts.
* C++, support the template disambiguator for dependent names.
* #4314: For PDF 'howto' documents, numbering of code-blocks differs from the * #4314: For PDF 'howto' documents, numbering of code-blocks differs from the
one of figures and tables one of figures and tables
* #4330: PDF 'howto' documents have an incoherent default LaTeX tocdepth counter * #4330: PDF 'howto' documents have an incoherent default LaTeX tocdepth counter

View File

@ -1285,7 +1285,7 @@ class ASTTemplateParamType(ASTBase):
def name(self): def name(self):
# type: () -> ASTNestedName # type: () -> ASTNestedName
id = self.get_identifier() id = self.get_identifier()
return ASTNestedName([ASTNestedNameElement(id, None)], rooted=False) return ASTNestedName([ASTNestedNameElement(id, None)], [False], rooted=False)
@property @property
def isPack(self): def isPack(self):
@ -1364,7 +1364,7 @@ class ASTTemplateParamTemplateType(ASTBase):
def name(self): def name(self):
# type: () -> ASTNestedName # type: () -> ASTNestedName
id = self.get_identifier() id = self.get_identifier()
return ASTNestedName([ASTNestedNameElement(id, None)], rooted=False) return ASTNestedName([ASTNestedNameElement(id, None)], [False], rooted=False)
def get_identifier(self): def get_identifier(self):
# type: () -> unicode # type: () -> unicode
@ -1401,7 +1401,7 @@ class ASTTemplateParamNonType(ASTBase):
def name(self): def name(self):
# type: () -> ASTNestedName # type: () -> ASTNestedName
id = self.get_identifier() id = self.get_identifier()
return ASTNestedName([ASTNestedNameElement(id, None)], rooted=False) return ASTNestedName([ASTNestedNameElement(id, None)], [False], rooted=False)
def get_identifier(self): def get_identifier(self):
# type: () -> unicode # type: () -> unicode
@ -1494,7 +1494,7 @@ class ASTTemplateIntroductionParameter(ASTBase):
def name(self): def name(self):
# type: () -> ASTNestedName # type: () -> ASTNestedName
id = self.get_identifier() id = self.get_identifier()
return ASTNestedName([ASTNestedNameElement(id, None)], rooted=False) return ASTNestedName([ASTNestedNameElement(id, None)], [False], rooted=False)
@property @property
def isPack(self): def isPack(self):
@ -1820,10 +1820,12 @@ class ASTNestedNameElement(ASTBase):
class ASTNestedName(ASTBase): class ASTNestedName(ASTBase):
def __init__(self, names, rooted): def __init__(self, names, templates, rooted):
# type: (List[Any], bool) -> None # type: (List[Any], List[bool], bool) -> None
assert len(names) > 0 assert len(names) > 0
self.names = names self.names = names
self.templates = templates
assert len(self.names) == len(self.templates)
self.rooted = rooted self.rooted = rooted
@property @property
@ -1864,8 +1866,13 @@ class ASTNestedName(ASTBase):
res = [] # type: List[unicode] res = [] # type: List[unicode]
if self.rooted: if self.rooted:
res.append('') res.append('')
for n in self.names: for i in range(len(self.names)):
res.append(text_type(n)) n = self.names[i]
t = self.templates[i]
if t:
res.append("template " + text_type(n))
else:
res.append(text_type(n))
return '::'.join(res) return '::'.join(res)
def describe_signature(self, signode, mode, env, symbol): def describe_signature(self, signode, mode, env, symbol):
@ -1892,10 +1899,14 @@ class ASTNestedName(ASTBase):
prefix = '' # type: unicode prefix = '' # type: unicode
first = True first = True
names = self.names[:-1] if mode == 'lastIsName' else self.names names = self.names[:-1] if mode == 'lastIsName' else self.names
for name in names: for i in range(len(names)):
name = names[i]
template = self.templates[i]
if not first: if not first:
signode += nodes.Text('::') signode += nodes.Text('::')
prefix += '::' prefix += '::'
if template:
signode += nodes.Text("template ")
first = False first = False
if name != '': if name != '':
if (name.templateArgs and # type: ignore if (name.templateArgs and # type: ignore
@ -1908,6 +1919,8 @@ class ASTNestedName(ASTBase):
if mode == 'lastIsName': if mode == 'lastIsName':
if len(self.names) > 1: if len(self.names) > 1:
signode += addnodes.desc_addname('::', '::') signode += addnodes.desc_addname('::', '::')
if self.templates[-1]:
signode += nodes.Text("template ")
self.names[-1].describe_signature(signode, mode, env, '', symbol) self.names[-1].describe_signature(signode, mode, env, '', symbol)
else: else:
raise Exception('Unknown description mode: %s' % mode) raise Exception('Unknown description mode: %s' % mode)
@ -3338,7 +3351,7 @@ class Symbol(object):
else: else:
decl = None decl = None
nne = ASTNestedNameElement(p.get_identifier(), None) nne = ASTNestedNameElement(p.get_identifier(), None)
nn = ASTNestedName([nne], rooted=False) nn = ASTNestedName([nne], [False], rooted=False)
self._add_symbols(nn, [], decl, docname) self._add_symbols(nn, [], decl, docname)
# add symbols for function parameters, if any # add symbols for function parameters, if any
if declaration is not None and declaration.function_params is not None: if declaration is not None and declaration.function_params is not None:
@ -3413,9 +3426,11 @@ class Symbol(object):
def get_full_nested_name(self): def get_full_nested_name(self):
# type: () -> ASTNestedName # type: () -> ASTNestedName
names = [] names = []
templates = []
for nne, templateParams in self.get_lookup_key(): for nne, templateParams in self.get_lookup_key():
names.append(nne) names.append(nne)
return ASTNestedName(names, rooted=False) templates.append(False)
return ASTNestedName(names, templates, rooted=False)
def _find_named_symbol(self, identifier, templateParams, def _find_named_symbol(self, identifier, templateParams,
templateArgs, operator, templateArgs, operator,
@ -4531,7 +4546,8 @@ class DefinitionParser(object):
def _parse_nested_name(self, memberPointer=False): def _parse_nested_name(self, memberPointer=False):
# type: (bool) -> ASTNestedName # type: (bool) -> ASTNestedName
names = [] names = [] # type: List[Any]
templates = [] # type: List[bool]
self.skip_ws() self.skip_ws()
rooted = False rooted = False
@ -4539,14 +4555,18 @@ class DefinitionParser(object):
rooted = True rooted = True
while 1: while 1:
self.skip_ws() self.skip_ws()
if self.skip_word_and_ws('template'): if len(names) > 0:
self.fail("'template' in nested name not implemented.") template = self.skip_word_and_ws('template')
elif self.skip_word_and_ws('operator'): else:
template = False
templates.append(template)
if self.skip_word_and_ws('operator'):
op = self._parse_operator() op = self._parse_operator()
names.append(op) names.append(op)
else: else:
if not self.match(_identifier_re): if not self.match(_identifier_re):
if memberPointer and len(names) > 0: if memberPointer and len(names) > 0:
templates.pop()
break break
self.fail("Expected identifier in nested name.") self.fail("Expected identifier in nested name.")
identifier = self.matched_text identifier = self.matched_text
@ -4571,7 +4591,7 @@ class DefinitionParser(object):
if memberPointer: if memberPointer:
self.fail("Expected '::' in pointer to member (function).") self.fail("Expected '::' in pointer to member (function).")
break break
return ASTNestedName(names, rooted) return ASTNestedName(names, templates, rooted)
def _parse_trailing_type_spec(self): def _parse_trailing_type_spec(self):
# type: () -> Any # type: () -> Any
@ -4836,7 +4856,7 @@ class DefinitionParser(object):
if self.match(_identifier_re): if self.match(_identifier_re):
identifier = ASTIdentifier(self.matched_text) identifier = ASTIdentifier(self.matched_text)
nne = ASTNestedNameElement(identifier, None) nne = ASTNestedNameElement(identifier, None)
declId = ASTNestedName([nne], rooted=False) declId = ASTNestedName([nne], [False], rooted=False)
# if it's a member pointer, we may have '::', which should be an error # if it's a member pointer, we may have '::', which should be an error
self.skip_ws() self.skip_ws()
if self.current_char == ':': if self.current_char == ':':
@ -5477,7 +5497,7 @@ class DefinitionParser(object):
def _make_phony_error_name(): def _make_phony_error_name():
# type: () -> ASTNestedName # type: () -> ASTNestedName
nne = ASTNestedNameElement(ASTIdentifier("PhonyNameDueToError"), None) nne = ASTNestedNameElement(ASTIdentifier("PhonyNameDueToError"), None)
return ASTNestedName([nne], rooted=False) return ASTNestedName([nne], [False], rooted=False)
class CPPObject(ObjectDescription): class CPPObject(ObjectDescription):

View File

@ -243,6 +243,8 @@ def test_type_definitions():
{1: 'gpio_callback_t', 2: '15gpio_callback_t'}) {1: 'gpio_callback_t', 2: '15gpio_callback_t'})
check('type', 'void (*f)(std::function<void(int i)> g)', {1: 'f', 2: '1f'}) check('type', 'void (*f)(std::function<void(int i)> g)', {1: 'f', 2: '1f'})
check('type', 'T = A::template B<int>::template C<double>', {2: '1T'})
def test_concept_definitions(): def test_concept_definitions():
check('concept', 'template<typename Param> A::B::Concept', check('concept', 'template<typename Param> A::B::Concept',