In said:
Could you, please, give me the place in the Standard that supports this?
Since I have already located it for another thread, it's quite easy.
I'm not challenging your claim at all. I've checked on-line como
and it refuses to take
int f();
int f(int i, ...) { return 0; }
both in C90 and C99 mode.
It is right, as f is not declared with compatible types in the two
declarations:
6.7.5.3
15 For two function types to be compatible, both shall specify
compatible return types. Moreover, the parameter type lists,
if both are present, shall agree in the number of parameters and
in use of the ellipsis terminator; corresponding parameters shall
have compatible types. If one type has a parameter type list
and the other type is specified by a function declarator that
is not part of a function definition and that contains an empty
identifier list, the parameter list shall not have an ellipsis
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
terminator and the type of each parameter shall be compatible
^^^^^^^^^^
with the type that results from the application of the default
argument promotions...
Contrary to what other people said, this is not a case of undefined
behaviour: a diagnostic is required, because there are two conflicting
declarations for the same identifier, at file scope.
You'd have undefined behaviour if the declaration and definition were
in different translation units. Typical example:
int printf();
int main()
{
printf("hello world\n");
return 0;
}
What I meant is that gcc didn't protest. I thought that the compiler
might be wise enough to notice different number of arguments, if it
were an issue. Since it didn't (neither did como btw), I thought it
might consider f() variadic, which led me to next question.
Undefined behaviour doesn't require a diagnostic. The compiler didn't
have a prototype for f() in scope, so it had nothing to check the function
calls against. What it did see is that f(2, 3) is compatible with the
declaration of f() and that f(2, 3, 4) is compatible with the declaration
of f(), so there was nothing to complain about. No attempt to check
whether the two function calls were consistent.
More sophisticated code checkers would build a prototype from the
first call of f(): int f(int, int) and check all other calls of f()
against this prototype. Allowed, but not required by the standard.
This was quite popular in the pre-ANSI days, when prototypes didn't
exist at all. The down side of this technique was that it didn't
handle the unrecognised variadic functions calls well (they were
declared like ordinary functions, back then), so you had to somehow
inform the tool that it is dealing with a variadic function.
Dan