[comp.std.c] multiple definitions of identifiers with external linkage

eggert@twinsun.com (Paul Eggert) (11/28/89)

Norman Diamond writes:

	... the standard does not limit an identifier with external linkage to
	having only one initialization (when the identifier is never used in an
	expression).

Doug Gwyn replies:

	... I have not been convinced that the Standard has a problem in this
	area.  Section 2.1.2 makes the initialization model pretty clear, and
	combined with the obvious notion that a variable holds a single value
	at a time it precludes multiple simultaneous initializers.

2.1.2 (Execution environments) does not really resolve this issue because 2.1.2
doesn't have to be combined with the ``obvious notion''.  2.1.2 says:

	All objects in static storage shall be _initialized_ (set to their
	initial values) before program startup.  The manner and timing of such
	initialization are otherwise unspecified.

It's reasonable to interpret this to mean that multiple initial values are
allowed, and that the multiple initializations are performed, but that because
the manner and timing of initialization is unspecified, the ``winning'' initial
value is unspecified.

Besides, 2.1.2 is a red herring here.  The real problem is a bug in the wording
in 3.7 (External definitions).  This bug applies to both objects and functions,
so it also permits multiple definitions of unused functions with external
linkage.  HP's Walter Murray pointed this out in a news posting, as did Twin
Sun's Mike Coleman when he originally brought this problem to my attention.
Thus, the following program is strictly conforming even though it's
``obviously'' wrong:

	int F(){return 0;}
	int F(){return 1;}
	int V = 0;
	int V = 1;
	int main(){return 0;}

Even assuming that the above quote from 2.1.2 prohibited the two Vs,
it wouldn't address the problem of the two Fs.

steve@groucho.ucar.edu (Steve Emmerson) (11/28/89)

eggert@twinsun.com (Paul Eggert) writes:

>Thus, the following program is strictly conforming even though it's
>``obviously'' wrong:

>	int F(){return 0;}
>	int F(){return 1;}
>	int V = 0;
>	int V = 1;
>	int main(){return 0;}

That's right.  pANS C -- just like the old C -- still allows you to 
write nonsense programs.

But, ah..., why would you want to?

-----
Steve Emmerson		steve@unidata.ucar.edu

gwyn@smoke.BRL.MIL (Doug Gwyn) (11/29/89)

In article <57@looney.twinsun.com> eggert@twinsun.com (Paul Eggert) writes:
>The real problem is a bug in the wording in 3.7 (External definitions).
>This bug applies to both objects and functions, so it also permits multiple
>definitions of unused functions with external linkage.  HP's Walter Murray
>pointed this out in a news posting, as did Twin Sun's Mike Coleman when he
>originally brought this problem to my attention.  Thus, the following
>program is strictly conforming even though it's ``obviously'' wrong:
>	int F(){return 0;}
>	int F(){return 1;}
>	int V = 0;
>	int V = 1;
>	int main(){return 0;}
>Even assuming that the above quote from 2.1.2 prohibited the two Vs,
>it wouldn't address the problem of the two Fs.

As indicated by the footnote, this wording ("if ... is used in an
expression") was designed to permit ZERO definitions for unused objects
and functions, to support existing practice.  (Some compilers cannot
reasonably generate references to unused, albeit declared, external names.)
While agreeing that the wording in 3.7 would have been better if it had
explicitly prohibited MULTIPLE definitions for unused objects or functions,
I still don't think that there is a large practical problem in correctly
implementing this, because throughout the Standard the notion that a
particular named external function has A definition, not a class of
definitions, is quite obvious.  And when a definition has no use it
really doesn't matter whether or not it is multiple, apart from the
question of how to implement this so that "strictly conforming" code that
abuses this loophole will be accepted.  My suggestion is to generate a
warning (not an official diagnostic) for the second definition within a
translation unit, and generate code for only the first definition.
Inter-translation unit multiple definitions are handled the usual way
(typically by the linker).  That technique should be standard conforming.

eggert@twinsun.com (Paul Eggert) (11/30/89)

Doug Gwyn writes:

	My suggestion is to generate a warning (not an official diagnostic) for
	the second definition within a translation unit, and generate code for
	only the first definition.  Inter-translation unit multiple definitions
	are handled the usual way (typically by the linker).  That technique
	should be standard conforming.

Does this suggestion mean that the following strictly conforming program with
two translation units should link correctly, albeit perhaps with warnings?

	x.c:
		int F(){return 0;}
		int G(int i){return i;}
	y.c:
		int F(){return 1;}
		int G(int);
		int main() {return G(0);}

Won't most linkers flatly refuse to link this program
because F is defined twice?

gwyn@smoke.BRL.MIL (Doug Gwyn) (12/01/89)

In article <58@looney.twinsun.com> eggert@twinsun.com (Paul Eggert) writes:
>Doug Gwyn writes:
>>My suggestion is to generate a warning (not an official diagnostic) for
>>the second definition within a translation unit, and generate code for
>>only the first definition.
>Does this suggestion mean that the following strictly conforming program with
>two translation units should link correctly, albeit perhaps with warnings?
[omitted to save space]
>Won't most linkers flatly refuse to link this program
>because F is defined twice?

Oops.  Your argument is evidence that multiple external definitions
for the same identifier could not have been the Committee's intent
(since that linker model is the most commonly encountered one).
Therefore the lack of a clear prohibition against multiple definitions
(amongst the entire set of modules constituting a program, not just
confined to a single translation unit) must really have been an
oversight.  In fact, I recall something like that constraint in
earlier drafts, so it probably got lost in the editing that occurred
in this area in response to public review comments on external linkage.

One can still fall back on the ANDIPS and the obvious model of an
object/function as having only one definition implied by phraseology
scattered throughout the Standard to back the "no more than one
definition" interpretation.  However, this one really does need to
receive an official X3J11 interpretation ruling, since it potentially
impacts implementations in a major way.  (Having to support multiple
external definitions would require linker changes in many environments,
and that was definitely not the committee's intention.)