From 15d93d2c763c920883da6f8fd9c0874a82cff50a Mon Sep 17 00:00:00 2001 From: Fabio Utzig Date: Thu, 23 Jul 2020 12:27:16 -0300 Subject: [PATCH 1/2] domains: c: add support for named variadic argument Add support for gcc extensions which allow variadic arguments to be named: https://gcc.gnu.org/onlinedocs/cpp/Variadic-Macros.html A named variadic argument takes the form "..." with spaces around allowed and must be the last argument. Currently it generates a warning "Invalid C declaration: Expected identifier, ')', or ',' in macro parameter list." Signed-off-by: Fabio Utzig --- sphinx/domains/c.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/sphinx/domains/c.py b/sphinx/domains/c.py index 642fee55e..240fe30e5 100644 --- a/sphinx/domains/c.py +++ b/sphinx/domains/c.py @@ -1200,13 +1200,17 @@ class ASTTypeWithInit(ASTBase): class ASTMacroParameter(ASTBase): - def __init__(self, arg: ASTNestedName, ellipsis: bool = False) -> None: + def __init__(self, arg: ASTNestedName, ellipsis: bool = False, + variadic: bool = False) -> None: self.arg = arg self.ellipsis = ellipsis + self.variadic = variadic def _stringify(self, transform: StringifyTransform) -> str: if self.ellipsis: return '...' + elif self.variadic: + return transform(self.arg) + '...' else: return transform(self.arg) @@ -1215,6 +1219,9 @@ class ASTMacroParameter(ASTBase): verify_description_mode(mode) if self.ellipsis: signode += nodes.Text('...') + elif self.variadic: + name = str(self) + signode += nodes.emphasis(name, name) else: self.arg.describe_signature(signode, mode, env, symbol=symbol) @@ -2915,9 +2922,14 @@ class DefinitionParser(BaseParser): if not self.match(identifier_re): self.fail("Expected identifier in macro parameters.") nn = ASTNestedName([ASTIdentifier(self.matched_text)], rooted=False) - arg = ASTMacroParameter(nn) - args.append(arg) self.skip_ws() + if self.skip_string_and_ws('...'): + args.append(ASTMacroParameter(nn, False, True)) + self.skip_ws() + if not self.skip_string(')'): + self.fail('Expected ")" after "..." in macro parameters.') + break + args.append(ASTMacroParameter(nn)) if self.skip_string_and_ws(','): continue elif self.skip_string_and_ws(')'): From 1b3bf4e3198bdbb59747c2b79ebbe23536059a93 Mon Sep 17 00:00:00 2001 From: Jakob Lykke Andersen Date: Mon, 27 Jul 2020 19:35:10 +0200 Subject: [PATCH 2/2] C, changelog and test for named variadic args --- CHANGES | 1 + sphinx/domains/c.py | 2 ++ tests/test_domain_c.py | 4 ++++ 3 files changed, 7 insertions(+) diff --git a/CHANGES b/CHANGES index f0dde1d25..52eb2c23c 100644 --- a/CHANGES +++ b/CHANGES @@ -37,6 +37,7 @@ Features added The warnings printed from this functionality can be suppressed by setting :confval:`c_warn_on_allowed_pre_v3`` to ``True``. The functionality is immediately deprecated. +* #7999: C, add support for named variadic macro arguments. Bugs fixed ---------- diff --git a/sphinx/domains/c.py b/sphinx/domains/c.py index 240fe30e5..65786b5de 100644 --- a/sphinx/domains/c.py +++ b/sphinx/domains/c.py @@ -2922,6 +2922,8 @@ class DefinitionParser(BaseParser): if not self.match(identifier_re): self.fail("Expected identifier in macro parameters.") nn = ASTNestedName([ASTIdentifier(self.matched_text)], rooted=False) + # Allow named variadic args: + # https://gcc.gnu.org/onlinedocs/cpp/Variadic-Macros.html self.skip_ws() if self.skip_string_and_ws('...'): args.append(ASTMacroParameter(nn, False, True)) diff --git a/tests/test_domain_c.py b/tests/test_domain_c.py index efef104f9..71bf251e9 100644 --- a/tests/test_domain_c.py +++ b/tests/test_domain_c.py @@ -296,6 +296,10 @@ def test_macro_definitions(): check('macro', 'M(arg, ...)', {1: 'M'}) check('macro', 'M(arg1, arg2, ...)', {1: 'M'}) check('macro', 'M(arg1, arg2, arg3, ...)', {1: 'M'}) + # GNU extension + check('macro', 'M(arg1, arg2, arg3...)', {1: 'M'}) + with pytest.raises(DefinitionError): + check('macro', 'M(arg1, arg2..., arg3)', {1: 'M'}) def test_member_definitions():