khan@pslu1.psl.wisc.edu (Mumit Khan) (04/01/91)
---------------- MIPS C bug in post-increment of variables ---------- MACHINE = DS3100 OS = ULTRIX V4.1 (Rev. 52) System #1: Wed Dec 19 15:20:46 CST 1990 UWS V4.1 (Rev. 197) Note the output from the following program in various cases. MIPS C is the only one causing the problem (of not incrementing the global shared variable "pc" in the call (*(*pc++))(). ------------------------ START OF PROGRAM --------------------------- #include <stdio.h> typedef int (*Inst)(); #define StopInst (Inst) 0 static int dummy (); static Inst machine[] = {dummy, dummy, dummy, dummy, dummy, StopInst}; static Inst *pc = NULL; main () { extern int start; fprintf (stderr, "Starting pc: %x\n", pc = machine); for (; *pc != StopInst;) (*(*pc++)) (); /* BUG BUG BUG BUG BUG BUG BUG */ } static int dummy () { extern Inst *pc; fprintf (stderr, "PC (in dummy): %x\n", pc); return 0; } ------------------------- END OF PROGRAM ------------------------ OUTPUT FROM MIPS CC. (Version 2.1) > bug-mips-cc Starting pc: 10000430 PC (in dummy): 10000430 <--- NOTE *NO* INCREMENT PC (in dummy): 10000434 PC (in dummy): 10000438 PC (in dummy): 1000043c PC (in dummy): 10000440 OUTPUT FROM MIPS GCC. (Version 2.1) > gcc -v gcc version 1.37.1 OSF 1.9.2.14 Ultrix Dec Mips Dec 29 1990 > bug-mips-gcc Starting pc: 10000460 PC (in dummy): 10000464 <--- NOTE INCREMENT PC (in dummy): 10000468 PC (in dummy): 1000046c PC (in dummy): 10000470 PC (in dummy): 10000474 OUTPUT FROM SparcStation (IPC) CC. (SunOS rel. 4.1.1) > bug-sun4-cc Starting pc: 40a8 PC (in dummy): 40ac <--- NOTE INCREMENT PC (in dummy): 40b0 PC (in dummy): 40b4 PC (in dummy): 40b8 PC (in dummy): 40bc ---------------------------------------------------------------------
D. Allen [CGL]) (04/15/91)
In article <1991Mar31.214127.5224@pslu1.psl.wisc.edu>, khan@pslu1.psl.wisc.edu (Mumit Khan) writes: > > ---------------- MIPS C bug in post-increment of variables ---------- > MACHINE = DS3100 > OS = ULTRIX V4.1 (Rev. 52) System #1: Wed Dec 19 15:20:46 CST 1990 > UWS V4.1 (Rev. 197) > > Note the output from the following program in various cases. MIPS C is > the only one causing the problem (of not incrementing the global shared > variable "pc" in the call (*(*pc++))(). This is not a bug. The C Language does not require the increment to happen until the end of the expression, that is, until *after* the function call. Many compilers will do it *before* the function call, but it is not required. > ------------------------ START OF PROGRAM --------------------------- > #include <stdio.h> > > typedef int (*Inst)(); > #define StopInst (Inst) 0 > static int dummy (); > static Inst machine[] = {dummy, dummy, dummy, dummy, dummy, StopInst}; > static Inst *pc = NULL; > > main () { > extern int start; > fprintf (stderr, "Starting pc: %x\n", pc = machine); > for (; *pc != StopInst;) > (*(*pc++)) (); /* BUG BUG BUG BUG BUG BUG BUG */ > } > static int dummy () { > extern Inst *pc; > fprintf (stderr, "PC (in dummy): %x\n", pc); > return 0; > } > > > ------------------------- END OF PROGRAM ------------------------ > > OUTPUT FROM MIPS CC. (Version 2.1) > > bug-mips-cc > > Starting pc: 10000430 > PC (in dummy): 10000430 <--- NOTE *NO* INCREMENT > PC (in dummy): 10000434 > PC (in dummy): 10000438 > PC (in dummy): 1000043c > PC (in dummy): 10000440 > > > OUTPUT FROM MIPS GCC. (Version 2.1) > > gcc -v > gcc version 1.37.1 OSF 1.9.2.14 Ultrix Dec Mips Dec 29 1990 > > bug-mips-gcc > > Starting pc: 10000460 > PC (in dummy): 10000464 <--- NOTE INCREMENT > PC (in dummy): 10000468 > PC (in dummy): 1000046c > PC (in dummy): 10000470 > PC (in dummy): 10000474 > > > OUTPUT FROM SparcStation (IPC) CC. (SunOS rel. 4.1.1) > > bug-sun4-cc > > Starting pc: 40a8 > PC (in dummy): 40ac <--- NOTE INCREMENT > PC (in dummy): 40b0 > PC (in dummy): 40b4 > PC (in dummy): 40b8 > PC (in dummy): 40bc > > --------------------------------------------------------------------- I quote from someone who read the ANSI book: From: giguere@csg.uwaterloo.ca (Eric Giguere) Subject: Re: Autoincrement in function calls; when? Organization: University of Waterloo In article <1991Apr9.143020.3504@watcgl.waterloo.edu> "Ian! D. Allen [CGL]" <idallen@watcgl.waterloo.edu> writes: >Someone claims this is a bug, but I think it's just the way C works. > >>Newsgroups: comp.unix.ultrix >>Subject: auto-increment bug in Ultrix(4.1) C (DS3100) >> >>Note the output from the following program in various cases. MIPS C is >>the only one causing the problem (of not incrementing the global shared >>variable "pc" in the call (*(*pc++))(). Interesting problem. Best to go straight to the horse's mouth on this one, the ANSI Standard: Section 3.3.2.4: The side effect of updating the stored value of the operand shall occur between the previous and the next sequence point. Hmmm... so what's a sequence point? Section 2.1.2.3: At certain specified points in the execution sequence called sequence points, all side effects of previous evaluations shall be complete and no side effects of subsequent evaluations shall have taken place. Section 3.6: The end of a full expression is a sequence point. Section 3.3: Between the previous and next sequence point an object shall have its stored value modified at most once by the evaluation of an expression. So what can we conclude? Only that the increment has to have taken effect by the end of the expression. Hence within the function call (*(*pc++))() the value of pc is implementation-defined. Congratulations, Ian!, you can pick up your prize at.... -- Eric Giguere giguere@csg.UWaterloo.CA Unlike the cleaning lady, I have to do Windows. -- -IAN! (Ian! D. Allen) idallen@watcgl.uwaterloo.ca idallen@watcgl.waterloo.edu [129.97.128.64] Computer Graphics Lab/University of Waterloo/Ontario/Canada
merritt@milton.u.washington.edu (Ethan Merritt) (04/16/91)
In article <1991Apr15.161123.16353@watcgl.waterloo.edu> idallen@watcgl.waterloo.edu (Ian! D. Allen [CGL]) writes (quoting others): > [ discussion of why failing to increment pc in the expression below before > completing function call is "not a bug" ] > So what can we conclude? Only that the increment has to have taken effect > by the end of the expression. Hence within the function call > > (*(*pc++))() > > the value of pc is implementation-defined. Congratulations, Ian!, you > can pick up your prize at.... > All right, I'm willing to play the straight man here. What is the ANSI-provided definition of "expression"? As I see it the lexical element (*pc++) is already an expression, and the original complaint is perfectly valid. To make the point clearer, what would your ruling be on a statement of the form: extern (void *)xxx; ... (*(xxx = *pc++))(); What do you conclude about the value of xxx during the execution of the function invoked? Ethan A Merritt -------------------------------------------------------------------- Dept of Biological Structure H510 Health Sciences University of Washington SM-20 (206)543-8865 Seattle, WA 98195 merritt@u.washington.edu --------------------------------------------------------------------
diamond@jit345.swstokyo.dec.com (Norman Diamond) (04/16/91)
In article <1991Apr15.161123.16353@watcgl.waterloo.edu> idallen@watcgl.waterloo.edu (Ian! D. Allen [CGL]) writes: >In article <1991Mar31.214127.5224@pslu1.psl.wisc.edu>, khan@pslu1.psl.wisc.edu (Mumit Khan) writes: >> Note the output from the following program in various cases. MIPS C is >> the only one causing the problem (of not incrementing the global shared >> variable "pc" in the call (*(*pc++))(). [...] >> typedef int (*Inst)(); >> static Inst *pc = NULL; >> (*(*pc++)) (); /* BUG BUG BUG BUG BUG BUG BUG */ >This is not a bug. Well, Mumit Khan is using a compiler that does not claim ANSI conformance, and complaining that the result is not ANSI conformant. This makes the complaint partly meaningless. (However, quality of implementation might possibly be a consideration even for non-conformant compilers. Disclaimer: Although I do not know if this is possible or not, my employer is not the one suggesting it.) For an ANSI-conformant compiler, it would indeed be a bug. >The C Language does not require the increment to happen until the end of >the expression, that is, until *after* the function call. >I quote from someone who read the ANSI book: >From: giguere@csg.uwaterloo.ca (Eric Giguere) > Section 3.3.2.4: > The side effect of updating the stored value of the operand > shall occur between the previous and the next sequence point. > Section 2.1.2.3: > At certain specified points in the execution sequence called > sequence points, all side effects of previous evaluations shall > be complete and no side effects of subsequent evaluations shall > have taken place. > Section 3.6: > The end of a full expression is a sequence point. > Section 3.3: > Between the previous and next sequence point an object shall > have its stored value modified at most once by the evaluation > of an expression. >So what can we conclude? Only that the increment has to have taken effect >by the end of the expression. >Congratulations, Ian!, you can pick up your prize at.... Messrs. !Allen and Giguere win booby prizes on this one. There are also sequence points at some other places, too. For example: Section 3.3.2.2, page 42, line 21: ... but there is a sequence point before the actual call. If the compiler in this case had claimed ANSI conformance, then its implementors would also deserve booby prizes. (Disclaimer: this is not my employer's opinion.) -- Norman Diamond diamond@tkov50.enet.dec.com If this were the company's opinion, I wouldn't be allowed to post it.
lhoe@iddth.id.dk (Lasse H Oestergaard (EMP)) (04/23/91)
diamond@jit345.swstokyo.dec.com (Norman Diamond) writes: >In article <1991Apr15.161123.16353@watcgl.waterloo.edu> idallen@watcgl.waterloo.edu (Ian! D. Allen [CGL]) writes: >>In article <1991Mar31.214127.5224@pslu1.psl.wisc.edu>, khan@pslu1.psl.wisc.edu (Mumit Khan) writes: >>> Note the output from the following program in various cases. MIPS C is >>> the only one causing the problem (of not incrementing the global shared >>> variable "pc" in the call (*(*pc++))(). >[...] >>> typedef int (*Inst)(); >>> static Inst *pc = NULL; >>> (*(*pc++)) (); /* BUG BUG BUG BUG BUG BUG BUG */ >>This is not a bug. >Well, Mumit Khan is using a compiler that does not claim ANSI conformance, >and complaining that the result is not ANSI conformant. This makes the >complaint partly meaningless. >(However, quality of implementation might possibly be a consideration even >for non-conformant compilers. Disclaimer: Although I do not know if this >is possible or not, my employer is not the one suggesting it.) >For an ANSI-conformant compiler, it would indeed be a bug. >>The C Language does not require the increment to happen until the end of >>the expression, that is, until *after* the function call. >>I quote from someone who read the ANSI book: >>From: giguere@csg.uwaterloo.ca (Eric Giguere) >> Section 3.3.2.4: >> The side effect of updating the stored value of the operand >> shall occur between the previous and the next sequence point. >> Section 2.1.2.3: >> At certain specified points in the execution sequence called >> sequence points, all side effects of previous evaluations shall >> be complete and no side effects of subsequent evaluations shall >> have taken place. >> Section 3.6: >> The end of a full expression is a sequence point. >> Section 3.3: >> Between the previous and next sequence point an object shall >> have its stored value modified at most once by the evaluation >> of an expression. >>So what can we conclude? Only that the increment has to have taken effect >>by the end of the expression. >>Congratulations, Ian!, you can pick up your prize at.... >Messrs. !Allen and Giguere win booby prizes on this one. >There are also sequence points at some other places, too. For example: > Section 3.3.2.2, page 42, line 21: > ... but there is a sequence point before the actual call. >If the compiler in this case had claimed ANSI conformance, then its >implementors would also deserve booby prizes. (Disclaimer: this is >not my employer's opinion.) >-- >Norman Diamond diamond@tkov50.enet.dec.com >If this were the company's opinion, I wouldn't be allowed to post it. Try looking at the INDEX in the standard. That will, in addition to the abovementioned references, point you to APPENDIX A.2, which states (quoted in full, since people don't seem to know this, very important, definition): The following is the sequence points described in paragraph 2.1.2.3. . The call to a function, after the arguments have been evaluated (paragraph 3.3.2.2) . The end of the first operand of the following operators: logical AND && (paragraph 3.3.13); logical OR || (paragraph 3.3.14); conditional ? (paragraph 3.3.15); comma , (paragraph 3.3.17). . The end of a full expression: An initializer (paragraph 3.5.7); the expression in an expression statement (paragraph 3.6.3); the controlling expression of a selection statement (if or switch) (paragraph 3.6.4); the controlling expression of a while or do statement (paragraph 3.6.5); each of the 3 expressions of a for statement (paragraph 3.6.5.3); the expression in a return statement (paragraph 3.6.6.4). End of quote. Now, together with paragraph 2.1.2.3 (see included articles), the first of the above rules quite clearly requires a compliant compiler to do the increment BEFORE the call. That seems more important than handing out wisecracks and booby prizes. Unfortunately KERNIGHAN and RITCHIE (even in the 2.d, so called ANSI, compliant !? edition) mostly ignores this problem, which possibly is the cause of the misstatements seen in the previous articles. Lasse H. Oestergaard lhoe@id.dth.dk