Re: Why is this not an error in Visual C?



Kenneth Brody wrote:
extern int foo(int,int,int,int);
...
within a function: i = foo(1,2,3,4);
...
int foo(a,b,c,d,e)
int a,b,c,d,e;
{
...
}

I suspect the reason answers are slow in coming is that you've touched on
some rather obscure aspects of C. I'll deal in full with the most
difficult case you've posted. Answers concerning the other two cases
appear at the end.

I'm assuming that the function call sits in between the "prototype" and
the function definition, i.e., I'm assuming that the code is in the
*exact* order you've given above. The importance of this will become
apparent soon.

What we're looking for to describe MSVC as broken is a constraint
violation (which requires a diagnostic), not undefined behavior alone
(which doesn't require one). Unfortunately, there are several red herrings
in the standard.

First let's look at constraint 6.5.2.2{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. Each argument shall have a type such that its
value may be assigned to an object with the unqualified version of the
type of its corresponding parameter.

The problem here is that the expression that denotes the called function
agrees with the first declaration (the "prototype"). The declaration that
appears in the function definition isn't visible at the point of the call.
Therefore, no constraint violation yet.

Now let's look at 6.5.2.2{9}:

If the function is defined with a type that is not compatible with the
type (of the expression) pointed to by the expression that denotes the
called function, the behavior is undefined.

So undefined behavior alone, right? That's one red herring. I'll spare you
the rest.

The constraint that is violated is 6.7{4}:

All declarations in the same scope that refer to the same object or
function shall specify compatible types.

To demonstrate a constraint violation, we must show that

extern int foo(int,int,int,int);

and

int foo(a,b,c,d,e)
int a,b,c,d,e;
{
...
}

involve declarations of incompatible types.

We turn to 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. *If one type has a parameter type list and the other type is
specified by a function definition that contains a (possibly empty)
identifer list, both shall agree in the number of parameters, and the
type of each prototype parameter shall be compatible with the type that
results from the application of the default argument promotions to the
type of the corresponding identifier.* (In the determination of type
compatibility and of a composite type, each parameter declared with
function or array type is taken as having the adjusted type and each
parameter declared with qualified type is taken as having the
unqualified version of its declared type.)

I've included that in full so you can get an answer for the three cases
you've posted. I've emphasized the sentences that apply for the first case
we're considering and the second case we're not considering. Other parts
of the above are for the third case we're not considering.

Since the two declarations are incompatible, we have a constraint
violation, and MSVC is required to issue a diagnostic. Pedantically
(ridiculously) speaking, however, as long as MSVC issues one diagnostic
for the constraint violation, no matter what that diagnostic says ("benign
[whatever]" qualifies), MSVC is conforming.

Yours,
Han from China

--
"Only entropy comes easy." -- Anton Chekhov

.



Relevant Pages

  • Re: Why is this not an error in Visual C?
    ... says that when an old-style function definition is processed, ... That is, I think, `int fint x; ... Concerning the compatibility of function ... All declarations in the same scope that refer to the same object or function ...
    (comp.lang.c)
  • Re: Why is this not an error in Visual C?
    ... says that when an old-style function definition is processed, ... That is, I think, `int fint x; ... Concerning the compatibility of function ... All declarations in the same scope that refer to the same object or function ...
    (comp.lang.c)
  • Re: Why is this not an error in Visual C?
    ... extern int foo; ... involve declarations of incompatible types. ... This is not a constraint so there is no requirement on an ... type compatibility, with no exception for functions that are not ...
    (comp.lang.c)
  • Re: typedef Used to Cast Function Pointers
    ... >> the result shall compare equal to the original pointer. ... integer type, usually int. ... The more complicated cases are compatibility between or with ... Both prototyped and unprototyped declarations of a ...
    (comp.lang.c)
  • Re: RAD vs. performance
    ... work with both int and float. ... name (e.g. "+" for both int and float addition). ... Again, it's a compatibility issue. ... contend that assuming interfaces are equivalent and inferring the most ...
    (comp.lang.misc)