Merge pull request #8928 from jakobandersen/c_fixes

C fixes
This commit is contained in:
Jakob Lykke Andersen
2021-02-24 16:22:36 +01:00
committed by GitHub
7 changed files with 47 additions and 52 deletions

View File

@@ -77,6 +77,8 @@ Bugs fixed
with size explicitly set in pixels) (fixed for ``'pdflatex'/'lualatex'`` only)
* #8911: C++: remove the longest matching prefix in
:confval:`cpp_index_common_prefix` instead of the first that matches.
* C, properly reject function declarations when a keyword is used
as parameter name.
Testing
--------

View File

@@ -387,19 +387,6 @@ class ASTPostfixDec(ASTPostfixOp):
signode.append(nodes.Text('--'))
class ASTPostfixMember(ASTPostfixOp):
def __init__(self, name):
self.name = name
def _stringify(self, transform: StringifyTransform) -> str:
return '.' + transform(self.name)
def describe_signature(self, signode: TextElement, mode: str,
env: "BuildEnvironment", symbol: "Symbol") -> None:
signode.append(nodes.Text('.'))
self.name.describe_signature(signode, 'noneIsName', env, symbol)
class ASTPostfixMemberOfPointer(ASTPostfixOp):
def __init__(self, name):
self.name = name
@@ -2256,7 +2243,7 @@ class DefinitionParser(BaseParser):
# | postfix "[" expression "]"
# | postfix "[" braced-init-list [opt] "]"
# | postfix "(" expression-list [opt] ")"
# | postfix "." id-expression
# | postfix "." id-expression // taken care of in primary by nested name
# | postfix "->" id-expression
# | postfix "++"
# | postfix "--"
@@ -2274,17 +2261,6 @@ class DefinitionParser(BaseParser):
self.fail("Expected ']' in end of postfix expression.")
postFixes.append(ASTPostfixArray(expr))
continue
if self.skip_string('.'):
if self.skip_string('*'):
# don't steal the dot
self.pos -= 2
elif self.skip_string('..'):
# don't steal the dot
self.pos -= 3
else:
name = self._parse_nested_name()
postFixes.append(ASTPostfixMember(name))
continue
if self.skip_string('->'):
if self.skip_string('*'):
# don't steal the arrow
@@ -2693,16 +2669,13 @@ class DefinitionParser(BaseParser):
def _parse_declarator_name_suffix(
self, named: Union[bool, str], paramMode: str, typed: bool
) -> ASTDeclarator:
assert named in (True, False, 'single')
# now we should parse the name, and then suffixes
if named == 'maybe':
pos = self.pos
try:
declId = self._parse_nested_name()
except DefinitionError:
self.pos = pos
declId = None
elif named == 'single':
if named == 'single':
if self.match(identifier_re):
if self.matched_text in _keywords:
self.fail("Expected identifier, "
"got keyword: %s" % self.matched_text)
identifier = ASTIdentifier(self.matched_text)
declId = ASTNestedName([identifier], rooted=False)
else:
@@ -2880,8 +2853,8 @@ class DefinitionParser(BaseParser):
def _parse_type(self, named: Union[bool, str], outer: str = None) -> ASTType:
"""
named=False|'maybe'|True: 'maybe' is e.g., for function objects which
doesn't need to name the arguments
named=False|'single'|True: 'single' is e.g., for function objects which
doesn't need to name the arguments, but otherwise is a single name
"""
if outer: # always named
if outer not in ('type', 'member', 'function'):

View File

@@ -1,3 +1,5 @@
.. c:namespace:: anon_dup_decl_ns
.. c:struct:: anon_dup_decl
.. c:struct:: @a.A

View File

@@ -1,3 +1,5 @@
.. c:namespace:: function_param_target
.. c:function:: void f(int i)
- :c:var:`i`

View File

@@ -1,3 +1,5 @@
.. c:namespace:: index
test-domain-c
=============

View File

@@ -1,10 +0,0 @@
.. c:member:: int member;
.. c:var:: int var;
.. c:function:: void f();
.. .. c:macro:: NO_SEMICOLON;
.. c:struct:: Struct;
.. c:union:: Union;
.. c:enum:: Enum;
.. c:enumerator:: Enumerator;
.. c:type:: Type;
.. c:type:: int TypeDef;

View File

@@ -417,6 +417,9 @@ def test_function_definitions():
check('function', 'void f(int arr[const static volatile 42])', {1: 'f'},
output='void f(int arr[static volatile const 42])')
with pytest.raises(DefinitionError):
parse('function', 'void f(int for)')
def test_nested_name():
check('struct', '{key}.A', {1: "A"})
@@ -523,8 +526,15 @@ def test_attributes():
# raise DefinitionError("")
def split_warnigns(warning):
ws = warning.getvalue().split("\n")
assert len(ws) >= 1
assert ws[-1] == ""
return ws[:-1]
def filter_warnings(warning, file):
lines = warning.getvalue().split("\n")
lines = split_warnigns(warning)
res = [l for l in lines if "domain-c" in l and "{}.rst".format(file) in l and
"WARNING: document isn't included in any toctree" not in l]
print("Filtered warnings for file '{}':".format(file))
@@ -578,10 +588,22 @@ def test_build_domain_c_anon_dup_decl(app, status, warning):
assert "WARNING: c:identifier reference target not found: @b" in ws[1]
@pytest.mark.sphinx(testroot='domain-c', confoverrides={'nitpicky': True})
def test_build_domain_c_semicolon(app, status, warning):
app.builder.build_all()
ws = filter_warnings(warning, "semicolon")
@pytest.mark.sphinx(confoverrides={'nitpicky': True})
def test_build_domain_c_semicolon(app, warning):
text = """
.. c:member:: int member;
.. c:var:: int var;
.. c:function:: void f();
.. .. c:macro:: NO_SEMICOLON;
.. c:struct:: Struct;
.. c:union:: Union;
.. c:enum:: Enum;
.. c:enumerator:: Enumerator;
.. c:type:: Type;
.. c:type:: int TypeDef;
"""
restructuredtext.parse(app, text)
ws = split_warnigns(warning)
assert len(ws) == 0
@@ -593,8 +615,8 @@ def test_build_function_param_target(app, warning):
assert len(ws) == 0
entries = extract_role_links(app, "function_param_target.html")
assert entries == [
('c.f', 'i', 'i'),
('c.f', 'f.i', 'f.i'),
('c.function_param_target.f', 'i', 'i'),
('c.function_param_target.f', 'f.i', 'f.i'),
]
@@ -656,6 +678,8 @@ def test_noindexentry(app):
@pytest.mark.sphinx(testroot='domain-c-intersphinx', confoverrides={'nitpicky': True})
def test_intersphinx(tempdir, app, status, warning):
# a splitting of test_ids_vs_tags0 into the primary directives in a remote project,
# and then the references in the test project
origSource = """\
.. c:member:: int _member
.. c:var:: int _var