This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Draft pre-DR on unprototyped function types


Here's a draft pre-DR on issues with unprototyped function types, as
alluded to in
<http://gcc.gnu.org/ml/gcc-patches/2004-03/msg01322.html>.  The issues
involving inline functions are not of immediate relevance to GCC given
the lack of support for C99 inline semantics, but seem to represent a
defect that is new with C99.  Comments and corrections welcome.

Pre-DR: Unprototyped function types
===================================

Issue 1:

I believe the intent of C is that old-style function definitions with
empty parentheses do not give the function a type including a
prototype for the rest of the translation unit.  For example,

void f(){}
void g(){if(0)f(1);}

is valid.

6.9.1#7 specifies that if the declarator in the function definition
includes a parameter type list, it also serves as a prototype for the
rest of the translation unit.  It does not specify that nothing else
serves as a prototype.  Some readers of the standard interpret
6.7.5.3#14, "An empty list in a function declarator that is part of a
definition of that function specifies that the function has no
parameters.", as specifying that it provides a prototype.

Question 1: Does such a function definition give the function a type
including a prototype for the rest of the translation unit?

Question 2: Is the above translation unit valid?

Issue 2:

The rules for compatibility of function types in 6.7.5.3#15 do not
define when a function type is "specified by a function definition
that contains a (possibly empty) identifier list", and do not address
compatibility between two types with that property or what the
composite type is in such cases.

As a first example, consider:

void f(a)int a;{}
void g(a,b)int a,b;{}
void (*h)(int, int, int) = (0 ? f : g);

What is the type of (0 ? f : g)?  The types of f and g are
compatible.  Does (0 ? f : g) have a type specified by a function
definition?  Does (0 ? f : f)?

Question 3: Is the above translation unit valid?

Another example is:

void f(a)int a;{}
void (*h)(int, int, int) = f;

I believe the intent of the standard is that a type is specified by a
function definition _only_ for the purposes of checking compatibility
of multiple declarations of the same function; when as here the name
of the function appears in an expression, its type is determined by
its return type and contains no trace of the parameter types.

Question 4: Is the above translation unit valid?

It may still be necessary for compatibility of multiple unprototyped
function types determined by function definitions to be considered, if
those definitions are in different translation units and all but one
are inline.  (As an aside, while the text of 6.7.4#6 assumes that
there is only one definition of a function in a translation unit, I
can find nothing prohibiting more if inline is used, though the
presumption would probably mean compile-time undefined behavior if
there were more than one in a translation unit, with compatible
types.)  By way of example, consider the following three translation
units:

// TU 1:
inline void f(a)int a;{}

// TU 2:
inline void f(a,b)int a,b;{}

// TU 3:
void f(a,b,c)int a,b,c;{}

The function types seem to be compatible, so 6.2.7#2 does not apply.

Question 5: Must a program containing these three translation units,
which never calls the function f, be accepted?

The function f cannot be called above from TU 1 or TU 2 without
undefined behavior, but could be called from TU 3, where the inline
definitions in TU 1 and TU 2 cannot be used for a call.  (Though a
program containing calls in TU 1 and TU 2 which are conditioned by if
(0) would also seem to be valid.)  In the following case, the types
are similar enough that it would seem possible for calls to occur in
all three translation units without undefined behavior (by virtue of
the exceptions in 6.5.2.2#6):

// TU 1:
inline void f(a,b)int a;unsigned b;{}
void g(void){f(0,0);}

// TU 2:
inline void f(a,b)unsigned a;int b;{}
void h(void){f(0,0);}

// TU 3:
void f(a,b)int a,b;{}
void i(void){f(0,0);}

Question 6: Must a program containing these three translation units be
accepted?

It seems undesirable for such variation among the types of functions
with inline definitions to be permitted.  This could be fixed by
defining compatibility of multiple unprototyped function definitions
to require compatibility of the parameter types.

-- 
Joseph S. Myers
jsm@polyomino.org.uk


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]