0

The following code produces a compilation error on both clang (3.6.0) and gcc(4.9.2) (coliru link)

#include <stdio.h>                      

void foo(void){
    printf("lalala\n");
}

int main(void)
{
    foo(1, 2, 3, 4, 5, 6, 67);
    return 0;
}

While VS2013 (while being compiled with /TC /W4) only produces a warning

warning C4087: 'foo' : declared with 'void' parameter list ... 9 1

Is this a bug in VC or are clang and gcc being too harsh?

Scis
  • 2,934
  • 3
  • 23
  • 37
  • In VC, are you doing a C compile of C++ compile? Warning looks like a C++ one as a function with no parameters is typically `foo()`. – chux - Reinstate Monica May 01 '15 at 12:06
  • @chux in [C++ it is an error for VC](http://rextester.com/RYTJH69552) – Shafik Yaghmour May 01 '15 at 12:09
  • @chux Yes as I wrote in the question I use the /TC flag aka "Compile as C Code (/TC)" in the project properties -> Configuration Properties -> C/C++ -> Advanced -> Compile As option – Scis May 01 '15 at 12:10
  • @Shafik Yaghmour We are discussing different `it`. Your `it` refers to an error due to `foo(1, 2, 3, 4, 5, 6, 67);` (which is certainty a problem). I am suggestion the warning is due to `foo(void)`. – chux - Reinstate Monica May 01 '15 at 12:13
  • 1
    Maybe it's just a case of VS being dumb, or trying to preserve some weird backwards compatibility. That definitely ought to be an error. In C, `void foo()` means the function takes an unspecified number of parameters (which is a leftover from pre-ANSI C). `void foo(void)` explicitly says it takes no parameters. – Ulfalizer May 01 '15 at 12:14
  • See also http://stackoverflow.com/questions/26570012/visual-c-accepting-wrong-number-of-arguments – ecatmur May 01 '15 at 12:22

5 Answers5

4

From 6.5.2.2 Function calls:

2 - If the expression that denotes the called function has a type that includes a prototype, the number of arguments shall agree with the number of parameters. [...]

VC is being deliberately permissive in order to permit compilation of (for compatibility with) incorrect code. This is allowed by the Standard as the implementation on encountering certain types of incorrect code such as this is allowed to emit a program as long as a diagnostic is also emitted.

ecatmur
  • 152,476
  • 27
  • 293
  • 366
4

The function takes no parameters but you are passing arguments. So it's a constraint violation. A compiler is required to issue a diagnostic in such cases. All three compilers are issuing a diagnostic and hence conforming to the standard. But whether it's classified as warning or error is compiler's choice.

So there's no "bug" in Visual Studio, just that GCC and clang are just more stringent in this case. Perhaps, VS implementers thought it's not serious enough as the passed arguments will be ignored anway and decided to issue warning only, I can only speculate.

P.P
  • 117,907
  • 20
  • 175
  • 238
2

According to C99 gcc and clang are both correct, void in the parameter list means it takes no parameters. From the draft c99 standard section 6.7.5.3 Function declarators (including prototypes):

The special case of an unnamed parameter of type void as the only item in the list specifies that the function has no parameters.

But since Visual Studio is issuing a diagnostic, it is a valid extension. Which is consistent with the documentation for C4087:

The function declaration has no formal parameters, but the function call has actual parameters. Extra parameters are passed according to the calling convention of the function.

This warning is for the C compiler.

Although the documentation does not go up to Visual Stuido 2013.

Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
0

Whether your code is bound to fail depends on the calling convention, which the compiler builder is allowed to implement as they wish. It can therefore be reasonable for one compiler to flag it as an an error while another only warns. But I would almost always set the compiler as strict as possible, in MSVS ‘warnings as errors’ – the most likely reason for passing unexpected arguments is some mistake on your part.

PJTraill
  • 1,353
  • 12
  • 30
-1

When you call a function with arguments each argument is pushed onto your call stack before you program jumps to the function called. Then, when you get to the function only the data specified by the arguements are removed, or really the stack pointer only moves as far as it should have to to for the arguements specified by the function declaration. After your function returns you stack pointer won't be in the propper place since it will have moved too far down during the function call. I'm not sure how the compiler handles this, but it seems like doing this can cause problems if you are returning from multiple functions.