[comp.std.c] Prototypes and ID lists

jfh@rpp386.Dallas.TX.US (John F. Haugh II) (07/18/89)

Greetings.

I have a question about function declarations.

Suppose I prototype a function with

extern struct passwd *getpwuid (uid_t uid);

and later in the same compilation unit have a declaration

struct passwd *
getpwuid (uid)
uid_t uid;
{
	[ stuff ]
}

Is my [ supposedly ] ANSI-compliant compiler free to warn
me that getpwuid() has been redefined?  Is this just a
warning or should this be a fatal error?  And the final
trick question - was this ever illegal?

The relevant section is [ I think, dyslexia not withstanding ]
3.7.1.  It is unclear, except for stating that you may use
an identifier list or a type and identifier list.

Relevant draft information - this is the January 1989 draft.
-- 
John F. Haugh II                        +-Quote of the month club: ------------
VoiceNet: (512) 832-8832   Data: -8835  | "Computer security is to information
InterNet: jfh@rpp386.cactus.org         |  control as a chastity belt is to
UucpNet : <backbone>!bigtex!rpp386!jfh  +- birth control"    -- Doug Steves  --

walter@hpclwjm.HP.COM (Walter Murray) (07/19/89)

John F. Haugh II writes:

> extern struct passwd *getpwuid (uid_t uid);
> struct passwd * getpwuid (uid) uid_t uid; {}

> Is my [ supposedly ] ANSI-compliant compiler free to warn
> me that getpwuid() has been redefined?

A conforming compiler is always free to produce warnings about
anything.  It MUST produce at least one diagnostic (error or warning)
for a program which violates a syntax rule or a constraint.  It
MUST NOT produce a [fatal] error on a strictly conforming program.

> Is this just a warning or should this be a fatal error?

A fatal error is never required.  If the compiler thinks it can
make sense of what you gave it, it is always free to generate
whatever code it can, as long as it satisfies the requirement to
produce a diagnostic if a syntax rule or constraint has been broken.

The legality of your program, that is, whether it is strictly
conforming, depends on how uid_t is defined.  If uid_t is
defined as int, for example, your program is legal, but warnings (as
always) are allowed.  If uid_t is defined as short, your program is
illegal, and a diagnostic (error or warning) is required to be produced.
The constraint being violated is in 3.5:  "All declarations in the
same scope that refer to the same object or function shall specify
compatible types."

> The relevant section is [ I think, dyslexia not withstanding ]
> 3.7.1.  

More relevant, I think, is 3.5.4.3.  "For two function types
to be compatible, both shall specify compatible return types. ...
If one type has a parameter type list and the other type is
specified by a function definition that contains a (possibly empty)
identifier 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 your example, this requires that the default argument promotions,
when applied to the type uid_t, must result in a type that is
compatible with uid_t.  

The obvious solution is to change your program to use a function
prototype in the function definition as well as in the original
declaration:
   struct passwd * getpwuid (uid_t uid) {}

> Relevant draft information - this is the January 1989 draft.

That's new to me!  Where does one get a copy of the January 1989 draft?
(I am quoting from the December 7, 1988, draft.)

Walter Murray
Not speaking for X3J11
----------------------

gwyn@smoke.BRL.MIL (Doug Gwyn) (07/19/89)

In article <16803@rpp386.Dallas.TX.US> jfh@rpp386.Dallas.TX.US (John F. Haugh II) writes:
-Suppose I prototype a function with
-extern struct passwd *getpwuid (uid_t uid);
-and later in the same compilation unit have a declaration
-struct passwd *
-getpwuid (uid)
-uid_t uid;
-{
-	[ stuff ]
-Is my [ supposedly ] ANSI-compliant compiler free to warn
-me that getpwuid() has been redefined?

But it hasn't been redefined!  It's been defined just once, and
then compatibly with the prototype declaration of its interface
that's in scope at the point of definition.

rec@elf115.uu.net (Roger Critchlow) (08/15/89)

In article <10551@smoke.BRL.MIL>, gwyn@smoke.BRL.MIL (Doug Gwyn) writes:
} In article <16803@rpp386.Dallas.TX.US> jfh@rpp386.Dallas.TX.US (John F. Haugh II) writes:
} -Suppose I prototype a function with
} -extern struct passwd *getpwuid (uid_t uid);
} -and later in the same compilation unit have a declaration
} -struct passwd *
} -getpwuid (uid)
} -uid_t uid;
} -{
} -	[ stuff ]
} -Is my [ supposedly ] ANSI-compliant compiler free to warn
} -me that getpwuid() has been redefined?
} 
} But it hasn't been redefined!  It's been defined just once, and
} then compatibly with the prototype declaration of its interface
} that's in scope at the point of definition.

Compatibly defined if and only if uid_t is not hiding a type which
is promoted.  If

  typedef unsigned short int uid_t;

then the function definition is not compatible with the prototype.

-- rec@elf115.uu.net --