C++, parse attributes on declerators as well.

Fixes sphinx-doc/sphinx#5187
This commit is contained in:
Jakob Lykke Andersen 2018-08-11 16:39:27 +02:00
parent 928cb3ef06
commit 349890266c
3 changed files with 46 additions and 8 deletions

View File

@ -210,6 +210,7 @@ Bugs fixed
* #344: autosummary does not understand docstring of module level attributes
* #5191: C++, prevent nested declarations in functions to avoid lookup problems.
* #5126: C++, add missing isPack method for certain template parameter types.
* #5187: C++, parse attributes on declerators as well.
* #5002: graphviz: SVGs do not adapt to the column width
Testing

View File

@ -2539,12 +2539,13 @@ class ASTArray(ASTBase):
class ASTDeclaratorPtr(ASTBase):
def __init__(self, next, volatile, const):
# type: (Any, bool, bool) -> None
def __init__(self, next, volatile, const, attrs):
# type: (Any, bool, bool, Any) -> None
assert next
self.next = next
self.volatile = volatile
self.const = const
self.attrs = attrs
@property
def name(self):
@ -2563,13 +2564,17 @@ class ASTDeclaratorPtr(ASTBase):
def _stringify(self, transform):
res = ['*'] # type: List[unicode]
for a in self.attrs:
res.append(transform(a))
if len(self.attrs) > 0 and (self.volatile or self.const):
res.append(' ')
if self.volatile:
res.append('volatile')
if self.const:
if self.volatile:
res.append(' ')
res.append('const')
if self.const or self.volatile:
if self.const or self.volatile or len(self.attrs) > 0:
if self.next.require_space_after_declSpecs:
res.append(' ')
res.append(transform(self.next))
@ -2621,6 +2626,10 @@ class ASTDeclaratorPtr(ASTBase):
# type: (addnodes.desc_signature, unicode, BuildEnvironment, Symbol) -> None
_verify_description_mode(mode)
signode += nodes.Text("*")
for a in self.attrs:
a.describe_signature(signode)
if len(self.attrs) > 0 and (self.volatile or self.const):
signode += nodes.Text(' ')
def _add_anno(signode, text):
signode += addnodes.desc_annotation(text, text)
@ -2630,17 +2639,18 @@ class ASTDeclaratorPtr(ASTBase):
if self.volatile:
signode += nodes.Text(' ')
_add_anno(signode, 'const')
if self.const or self.volatile:
if self.const or self.volatile or len(self.attrs) > 0:
if self.next.require_space_after_declSpecs:
signode += nodes.Text(' ')
self.next.describe_signature(signode, mode, env, symbol)
class ASTDeclaratorRef(ASTBase):
def __init__(self, next):
def __init__(self, next, attrs):
# type: (Any) -> None
assert next
self.next = next
self.attrs = attrs
@property
def name(self):
@ -2661,7 +2671,13 @@ class ASTDeclaratorRef(ASTBase):
return self.next.require_space_after_declSpecs()
def _stringify(self, transform):
return '&' + transform(self.next)
res = ['&']
for a in self.attrs:
res.append(transform(a))
if len(self.attrs) > 0 and self.next.require_space_after_declSpecs:
res.append(' ')
res.append(transform(self.next))
return u''.join(res)
def get_modifiers_id(self, version):
# type: (int) -> unicode
@ -2692,6 +2708,10 @@ class ASTDeclaratorRef(ASTBase):
# type: (addnodes.desc_signature, unicode, BuildEnvironment, Symbol) -> None
_verify_description_mode(mode)
signode += nodes.Text("&")
for a in self.attrs:
a.describe_signature(signode)
if len(self.attrs) > 0 and self.next.require_space_after_declSpecs:
signode += nodes.Text(' ')
self.next.describe_signature(signode, mode, env, symbol)
@ -5151,6 +5171,7 @@ class DefinitionParser(object):
self.skip_ws()
volatile = False
const = False
attrs = []
while 1:
if not volatile:
volatile = self.skip_word_and_ws('volatile')
@ -5160,13 +5181,23 @@ class DefinitionParser(object):
const = self.skip_word_and_ws('const')
if const:
continue
attr = self._parse_attribute()
if attr is not None:
attrs.append(attr)
continue
break
next = self._parse_declarator(named, paramMode, typed)
return ASTDeclaratorPtr(next=next, volatile=volatile, const=const)
return ASTDeclaratorPtr(next=next, volatile=volatile, const=const, attrs=attrs)
# TODO: shouldn't we parse an R-value ref here first?
if typed and self.skip_string("&"):
attrs = []
while 1:
attr = self._parse_attribute()
if attr is None:
break
attrs.append(attr)
next = self._parse_declarator(named, paramMode, typed)
return ASTDeclaratorRef(next=next)
return ASTDeclaratorRef(next=next, attrs=attrs)
if typed and self.skip_string("..."):
next = self._parse_declarator(named, paramMode, False)
return ASTDeclaratorParamPack(next=next)

View File

@ -665,6 +665,12 @@ def test_attributes():
check('function', 'static inline __attribute__(()) void f()',
{1: 'f', 2: '1fv'},
output='__attribute__(()) static inline void f()')
# position: declarator
check('member', 'int *[[attr]] i', {1: 'i__iP', 2:'1i'})
check('member', 'int *const [[attr]] volatile i', {1: 'i__iPVC', 2: '1i'},
output='int *[[attr]] volatile const i')
check('member', 'int &[[attr]] i', {1: 'i__iR', 2: '1i'})
check('member', 'int *[[attr]] *i', {1: 'i__iPP', 2: '1i'})
# def test_print():