minow@decvax.UUCP (Martin Minow) (12/14/86)
This is one of a collection of comments on the Draft Standard, posted to comp.lang.c for discussion before I mail a final draft to the Ansi C committee. Each message discusses one problem I have found with the Draft Standard that I feel warrants a "no" vote. Note that this message is my personal opinion, and does not reflect on the opinions of my employer. ---- Problem: Page 19, line 42, page 49, line 43, page 70, line 22. "static" should be permitted only for definitions. "extern" should be the only declarator that specifies external linkage (whether file or program). Page 19, line 42ff. The formulation as given here does not allow the common use of "extern" to forward reference a variable or function that is actually declared "static." This breaks existing programs with sequences such as the following: char * func() { extern char *subr(); ... return (subr()); } ... static char * subr() { ... } A subsequent definition should be allowed to declare an object or function "static," overriding the previous linkage specification. The storage class specifier "static" (section 3.5.1, page 49) should be permitted only on definitions. Page 70, line 22. As noted above, "static" should not be used to declare external functions with file scope. The module referring to the function] does not need to ``know'' that the actual function definition is in the same file -- indeed, it should not. If only "extern" were used to specify linkage, the programmer would be free to move function definitions between files as required by the application. In the current standard, the *user* of a function must know whether the function is defined in the current file. The only time this use of "static" would be useful would be to permit one-pass compilers to produce smaller code segments for function calls. Given the current direction of the computer industry, there is no need for such limitations. ---- Martin Minow decvax!minow
gwyn@brl-smoke.ARPA (Doug Gwyn ) (12/15/86)
In article <108@decvax.UUCP> minow@decvax.UUCP (Martin Minow) writes
about the usage of "static" and "extern".
The interplay between "static" and "extern" was carefully worked out
to maximally support existing practice, while permitting one-pass
compilation implementations. Martin's code example falls into the
"undefined" category, which means that an implementation is free to
provide the semantics that Martin wants, but that a portable
application cannot count on them. I believe an editorial
clarification of this is in the works.
My feeling is that it would take a very strong argument to convince
X3J11 to change this aspect of the standard.
minow@decvax.UUCP (Martin Minow) (12/17/86)
Discussing my suggestion to change the interaction between "static" and "extern", Doug Gwyn (@ brl-smoke) notes that the Draft Standard's semantics were designed to permit one-pass compilation. Are there still true one-pass compilers being written today? My impression is that the minimum hardware being sold today is something on the order of a Macintosh or Atari ST, both of which support full-featured, multi-pass compilers. I would much prefer the Standard be written for the current (and future) "minimum" computer, rather than for some very limited 10-year old microcomputer. Martin Minow decvax!minow
braner@batcomputer.tn.cornell.edu (braner) (12/17/86)
[]
> [claims that one-pass compilers only belong on obsolete hardware...]
I use the Megamax C compiler on the Atari ST. It is a one-pass compiler,
vintage 1986. I love it, because it is VERY fast! Just because the machine
has 1 Meg RAM and a 68000 does NOT mean efficiency doesn't pay!
A note to compiler writers: One-pass, two-pass, I don't care what the
algorithm is, but please use RAM, not the disk, for "temporary files" stuff.
It's all that disk-grinding that is obsolete!
- Moshe Braner
bobr@zeus.UUCP (Robert Reed) (12/17/86)
Given that relying on the interplay between "static" and "extern" falls into the cracks between what should be in the standard and what is conventional practise, it is reasonable to ask: Does the standard provide a mechanism for forward referencing functions? (Not having a copy of the standard, I can't answer this myself). I know I can predeclare functions in most conventional implementations but having to insert two declarations which include type information, e.g.: static char *foo(); biz() { foo(); } static char *foo() { } seems to be a potential source of errors because of the duplicated type declaration. Though the static/extern technique may be a hack, Martin's need seems reasonable. -- Robert Reed, Tektronix CAE Systems Division, bobr@zeus.TEK
jdb@mordor.s1.gov (John Bruner) (12/18/86)
The last time I looked, PCC2 was a one-pass compiler. -- John Bruner (S-1 Project, Lawrence Livermore National Laboratory) MILNET: jdb@mordor.s1.gov (415) 422-0758 UUCP: ...!ucbvax!decwrl!mordor!jdb ...!seismo!mordor!jdb
greg@utcsri.UUCP (Gregory Smith) (12/19/86)
In article <114@decvax.UUCP> minow@decvax.UUCP (Martin Minow) writes: >Discussing my suggestion to change the interaction between "static" >and "extern", Doug Gwyn (@ brl-smoke) notes that the Draft Standard's >semantics were designed to permit one-pass compilation. > >Are there still true one-pass compilers being written today? My impression >is that the minimum hardware being sold today is something on the order >of a Macintosh or Atari ST, both of which support full-featured, multi-pass >compilers. I would much prefer the Standard be written for the current >(and future) "minimum" computer, rather than for some very limited >10-year old microcomputer. In article <264@mordor.s1.gov> jdb@mordor.UUCP (John Bruner) writes: >The last time I looked, PCC2 was a one-pass compiler. I think there is some confusion here. C compilers are normally 'One-pass' in the sense that they can generate code for X without requiring any information about the source which appears after X. Assemblers (normal assemblers anyway) cannot be one-pass in this sense, since they need to resolve forward references. A 'multi-pass' compiler is usually a bunch of programs which pipe their data from one to the other (The PCC2 can be considered 2-pass in this sense since it reads the output of the preprocessor). However, the entire system acts as a one-pass compiler, again, since code (assembler) is generated for X without knowing what comes after X. To compile stuff on this machine, e.g. 'cc -o foo foo.c', foo.c is run thru /bin/cpp, /bin/ccom, [ and /bin/c2 if you say -O ]. Then the assembler makes two passes on the output, and the linker probably makes two passes on the object module. Now do cpp and ccom count as two passes? Some pcc implementations split ccom into two stages, each of which is essentially a filter. Am I the only one who thinks there is a terminology problem here? I would like to see the word 'stage' used for a section of a pipe, while 'pass' refers to the number of times a module must read its input stream. So a compiler could be referred to as a '3-stage, 1-pass' compiler. Of course, the distinction applies whether pipes or intermediate files are used between stages. The use of temp files to delay such things as string constants is not really an issue here, since it has such a minor impact on the compiler design (Strictly speaking, when a pcc reopens this temp file in order to spool its contents onto the end of the .s file, it is making a second pass, since it is 'backing up' and re-examining information gleaned from the first 'pass'). -- ---------------------------------------------------------------------- Greg Smith University of Toronto UUCP: ..utzoo!utcsri!greg Have vAX, will hack...
tanner@ki4pv.UUCP (Tanner Andrews) (12/21/86)
While no doubt many people consider it good and fine to say something like the following example fragment, I find that the assorted compilers for our assorted machines all work just as well or better if you omit the storage class on the forward reference. That "extern" just isn't needed. Why not leave it off. Makes the code more accurate (seeing that "blunge" really ISN'T extern). Also, no harm results if "blunge" moves to another module! All in all, better to just leave off the "extern" entirely! /* start of example */ extern char *blunge(); /* declare blunge */ char *gork() { return(blunge(69)); } /* use blunge */ static char *blunge(arg) int arg; { /* body of blunge here */ } /* end of example */ -- <std dsclm, copies upon request> Tanner Andrews