can foo() be called with arguments?

Hi,

clang is rejecting the code below, but any other compiler I tried
accepts it (some give a warning though).

From my reading of the C99 standard (N1256.pdf) calling foo with

parameters when it is declared as foo() is allowed only if the
declaration doesn't involve a definition too.
If it involves a definition, then you can't call it with parameters,
and foo() is equivalent to foo(void). Is this correct?

I couldn't find the ANSI C standard online, I don't know what it
says about this.

6.7.5.3.14 Function declarators (including prototypes)
"An identifier list declares only the identifiers of the parameters of
the function. An empty list in a function declarator that is part of
a definition of that function specifies that the function has no
parameters. The empty list in a function declarator that is not part
of a definition of that function specifies that no information about
the number or types of the parameters is supplied.126)"

This is the code in question:
#ifdef DEBUG
#define dbgmsg printf
#else
static void dbgmsg() {}
#endif
int main(void)
{
        dbgmsg("some message:%d",5);
        return 0;
}

Of course the code can be easily changed to
static void dbgmsg(const char *fmt,...){}

Clang rejects it with an error:
$ clang x.c
x.c:8:9: error: too many arguments to function
        dbgmsg("some message:%d",5);
        ~~~~~~ ^~~~~~~~~~~~~~~~~~~
1 diagnostic generated.

GCC accepts it without even giving a warning!
$ gcc -Wall -W x.c
$ gcc --version
gcc (GCC) 4.2.3 (Debian 4.2.3-1)

Other compilers:

$ icc -w2 x.c
x.c(8): warning #140: too many arguments in function call
        dbgmsg("some message:%d",5);
$ icc -V
Intel(R) C Compiler for applications running on Intel(R) 64, Version
10.1 Build 20080112 Package ID: l_cc_p_10.1.012 ^

$ cc x.c
c"x.c", line 8: warning #2140-D: too many arguments in function call
          dbgmsg("some message:%d",5);
$ cc -V
                 ^

$ tcc -Wall x.c
$ tcc -v
tcc version 0.9.24

Best regards,
--Edwin

See Defect report #317.
Essentially, executing the call is technically undefined behavior, but
it's a perfectly legal construct. I've filed
2042 – clang incorrectly considers f(){} to have a prototype on the issue.

It looks like your module does actually execute such an undefined
call, so the program technically has undefined behavior. That said,
I've never heard of a C compiler producing code that actually did
anything weird... generally, C calling conventions allow for an
arbitrary number of arguments even if the callee doesn't expect them
for compatibility reasons.

-Eli

I just checked in a fix for this,

-Chris

Chris Lattner wrote:

From my reading of the C99 standard (N1256.pdf) calling foo with
parameters when it is declared as foo() is allowed only if the
declaration doesn't involve a definition too.
If it involves a definition, then you can't call it with parameters,
and foo() is equivalent to foo(void). Is this correct?
      

See Defect report #317.
Essentially, executing the call is technically undefined behavior, but
it's a perfectly legal construct. I've filed
2042 – clang incorrectly considers f(){} to have a prototype on the issue.

It looks like your module does actually execute such an undefined
call, so the program technically has undefined behavior.

Thanks for the pointer.

  That said,
I've never heard of a C compiler producing code that actually did
anything weird... generally, C calling conventions allow for an
arbitrary number of arguments even if the callee doesn't expect them
for compatibility reasons.
    
I've filed a bug for the original program to avoid the undefined behaviour.

I just checked in a fix for this,

Thanks a lot!

Best regards,
--Edwin