Is it standard C17 to wrap a parameter in a function declaration in parenthesis

120 Views Asked by At

Is the following a standard C function declaration according to ISO/IEC 9899:2017 (c17)?

int foo(int (bar), int (baz));

If so, please point me to the section in the standard that defines this.

In N2310 Appendix Phrase structure grammar, A.2.2 Declarations, Section 6.7.6, I see the following:

parameter-list:
    parameter-declaration
    parameter-list , parameter-declaration

I'm not familiar with this type of grammar expression, so I'm not sure how to interpret it.

The following program compiles without errors with gcc --std=c17 -Wall and clang --std=c17 -Wall

static int foo(int (bar), int (baz));
static int foo(int bar, int baz)
{
        return bar + baz;
}
int main() {
        return foo(1, 2);
}

However if I run cppcheck (a static analysis tool) on this program, it appears to parse incorrectly.

I'm most interested if this grammar is standard C, or a compiler-specific behavior so I can try to fix the parser or submit a bug report if I can't.

2

There are 2 best solutions below

1
dbush On BEST ANSWER

The declaration is allowed by the standard.

Sectin 6.7.6p1 of the C standard gives the full syntax for a declaration, including the portion you quoted. The relevant parts are as follows:

A parameter-declaration is defined as:

parameter-declaration:

  • declaration-specifiers declarator
  • declaration-specifiers abstract-declaratoropt

A declarator is defined as:

declarator:

  • pointeropt direct-declarator

And a direct-declarator is defined (in part) as:

direct-declarator:

  • ( declarator )

So we can see from the above that a parameter name can be enclosed in parenthesis.

7
Vlad from Moscow On

In this declaration of a function

int foo(int (bar), int (baz));

parameters consist from the type specifier int and declarators ( bar ) and ( baz ).

According to the grammar of the declarator (The C17 Standard, 6.7.6 Declarators)

declarator:
    pointeropt direct-declarator
direct-declarator:
    identifier
    ( declarator )
    //...

As you can see a declarator may be enclosed in parentheses.

And a function declarator looks like

direct-declarator ( parameter-type-list )

where parameter-type-list is defined like

parameter-type-list:
    parameter-list
    parameter-list , ...
parameter-list:
    parameter-declaration
    parameter-list , parameter-declaration

and parameter-declaration is defined like

parameter-declaration:
    declaration-specifiers declarator
    declaration-specifiers abstract-declaratoropt

So the declarators of the parameter-list of the shown above function are correct.

You could even write the function declaration like

int ( foo(int (bar), int (baz)) );

Another example. A function declaration with a parameter that declares a variable length array like for example

void f( size_t m, size_t n, int a[m][n] );

may be rewritten like

void f( size_t m, size_t n, int ( ( ( a )[m] )[n] ) );

though of course the parentheses used in the array declaration are redundant.

Without using parentheses enclosing a declarator it would be impossible for example to declare a pointer to an array or a function like for example

int a[m][n];
int ( *p )[n] = a;

because this declaration

int  *p[n] = a;

declares an array of pointers.