From: SourceForge.net <no...@so...> - 2003-01-09 21:15:49
|
Bugs item #633204, was opened at 2002-11-04 06:05 You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=110894&aid=633204&group_id=10894 Category: 44. Bytecode Compiler Group: 8.4.1 Status: Closed Resolution: Fixed Priority: 5 Submitted By: Nobody/Anonymous (nobody) Assigned to: Don Porter (dgp) Summary: catch { return foo } breaks inside proc Initial Comment: In TCL 8.4.1: % info patchlevel 8.4.1 % catch { return foo } 2 % proc foo {} { catch { return foo } } % foo 0 % ??? Putting the code inside a proc changes the return value? These should return the same thing. In Tcl 8.3.3 % info patchlevel 8.3.3 % catch { return foo } 2 % proc foo {} { catch { return foo } } % foo 2 % Since the behaviour changes when the code is put inside a proc, I *suspect* a bytecode compiler bug. Details: Tcl 8.4.1 $ uname -a SunOS xxxxxxxx 5.7 Generic_106541-10 sun4u sparc SUNW,UltraSPARC-IIi-cEngine $ gcc --version 2.95.2 ---------------------------------------------------------------------- >Comment By: Don Porter (dgp) Date: 2003-01-09 16:17 Message: Logged In: YES user_id=80530 correction patch committed to HEAD. ---------------------------------------------------------------------- Comment By: Don Porter (dgp) Date: 2003-01-09 16:11 Message: Logged In: YES user_id=80530 Ack! workaround.patch had an "off-by-one" error. Here's a correction.patch to fix things. ---------------------------------------------------------------------- Comment By: Don Porter (dgp) Date: 2003-01-07 19:37 Message: Logged In: YES user_id=80530 workaround patch committed. ---------------------------------------------------------------------- Comment By: Don Porter (dgp) Date: 2002-12-18 18:56 Message: Logged In: YES user_id=80530 Here's a patch that implements the workaround suitable for 8.4.x ---------------------------------------------------------------------- Comment By: Don Porter (dgp) Date: 2002-12-18 17:42 Message: Logged In: YES user_id=80530 The bugs I feared in calls to Tcl_EvalObjEx() are probably prevented by lines 2401-2403 of tclCompCmds.s where the bytecompiling of [return] is disabled if an enclosing proc is not detected. This is similar in spirit to the proposed workaround for this bug that involves disabling bytecompiling when an enclosing [catch] is present. ---------------------------------------------------------------------- Comment By: Don Porter (dgp) Date: 2002-12-18 12:42 Message: Logged In: YES user_id=80530 The patch defines a new opcode in the bytecode execution engine. In order to maintain compatibility with external bytecode brought in by tbcload, new opcodes can only be defined for a new minor release of Tcl, so this patch can't be applied until 8.5 development. So, 1. Can't add an opcode. 2. No existing opcode returns TCL_RETURN, Therefore, the only correct fix that can be applied in the 8.4.x timeframe is to disable bytecompiling of [return]. A workaround that would still be buggy, but would correct the reported example script, would be to add special detection of an enclosing [catch] in TclCompileReturnCmd() and return TCL_OUT_LINE_COMPILE in that case. The remaining bug after that workaround would be harder to demo. TEBC and TclCompEvalObj() should evaluate general Tcl scripts. The bug is that they are implicitly converting TCL_RETURN to TCL_OK, as if they were only good for evaluating proc bodies. This bug might still be exposed by C code that calls Tcl_EvalObjEx(). Better to get to 8.5 development and get the correct fix in the BC engine with the new opcode. ---------------------------------------------------------------------- Comment By: Don Porter (dgp) Date: 2002-12-17 18:15 Message: Logged In: YES user_id=80530 Improved patch; same basic approach. ---------------------------------------------------------------------- Comment By: Don Porter (dgp) Date: 2002-12-17 18:07 Message: Logged In: YES user_id=80530 Attached is a patch that appears to be an effective fix. I don't fully know what I'm doing in the BC engine, so it's very likely not the best fix, but it appears to fix the bug, and test suite results are unchanged. ---------------------------------------------------------------------- Comment By: miguel sofer (msofer) Date: 2002-12-16 14:47 Message: Logged In: YES user_id=148712 When compiling the body of 'a', the compiler encounters a bcc'ed command 'catch and proceeds to compile its arguments; as they are also bcc'ed ('return'), the whole thing gets compiled into the body of 'a'. When compiling 'b', the compiler encounters a non-bcc'ed command 'myreturn', and compiles an invocation for it. The effect at runtime is: the 'return' of 'a' executes in the same TEBC instance as the proc body, there is no C-return involved. OTOH, the return of 'b' comes from a child instance of TEBC, via a real C-return. The internal return in the first case cannot be handled in the same manner: as it essentially executes in the same process, the return value of an inlined 'retun -code $x' *has* to be $x for (almost) everything to work as it should - the exception being what we're talking about here :( I imagine things could conceivably be repaired, but at a high complexity cost in the compiler: the return-compiler could check if it is compiling within a catch-range or not, and compile-in the correct return code: TCL_OK if it is not caught, TCL_RETURN otherwise. New idea, I'll think about that ... ---------------------------------------------------------------------- Comment By: Don Porter (dgp) Date: 2002-12-16 13:52 Message: Logged In: YES user_id=80530 Yes, but both the body of [a] and the body of [b] are bytecompiled, right? So the problem is that bytecompiled [return] is not returning TCL_RETURN, when it should be, just like "bytecompiled" [myreturn] does. The example just shows that the TEBC and TclObjInterpProc framwork can handle a TCL_RETURN properly, so what's the obstacle to fixing BC'd [return] to return the correct return code? ---------------------------------------------------------------------- Comment By: Jeffrey Hobbs (hobbs) Date: 2002-12-16 13:36 Message: Logged In: YES user_id=72656 In 'myreturn', the return is not byte-compiled, but a regular "return" would be. ---------------------------------------------------------------------- Comment By: Don Porter (dgp) Date: 2002-12-16 12:47 Message: Logged In: YES user_id=80530 The BC execution engine appears to be capable of doing the right thing: % proc myreturn {} {return -code return} % proc a {} {catch return} % proc b {} {catch myreturn} % a 0 % b 2 So what path through TEBC does [a] take, and how can TEBC be corrected so that [b] takes a similar path? At least this seems to confirm that TEBC is capable of returning TCL_RETURN, and if TEBC does return TCL_RETURN, then TclObjInterpProc() will do the right thing. ---------------------------------------------------------------------- Comment By: Don Porter (dgp) Date: 2002-12-12 13:20 Message: Logged In: YES user_id=80530 Note an apparent workaround is to defeat the compiling of [return] like so: proc foo {} {catch {return -code ok foo}} ---------------------------------------------------------------------- Comment By: Don Porter (dgp) Date: 2002-12-12 13:13 Message: Logged In: YES user_id=80530 No, think I misread things. Real problem doesn't appear to be that simple after all. ---------------------------------------------------------------------- Comment By: Don Porter (dgp) Date: 2002-12-12 11:20 Message: Logged In: YES user_id=80530 seems this bug has been lurking in there for years, but only the recent bytecompilation of [return] has made it easy to expose? ---------------------------------------------------------------------- Comment By: Don Porter (dgp) Date: 2002-12-12 11:13 Message: Logged In: YES user_id=80530 Is this bug found in line 343 of tclCompCmds.c ? The comment on lines 329-333 says: /* * The "no errors" epilogue code: store the body's result into the * variable (if any), push "0" (TCL_OK) as the catch's "no error" * result, and jump around the "error case" code. */ but the result of [catch] should not always be TCL_OK. It should be whatever the return code of the $script argument was. ---------------------------------------------------------------------- Comment By: Don Porter (dgp) Date: 2002-12-11 17:38 Message: Logged In: YES user_id=80530 This must be a bug in the byte-compiling of [catch]. Compare with: % proc foo {} { set catch catch $catch {return foo} } % foo 2 and % proc bar {} { set script {return foo} catch $script } % bar 2 Only the literal "catch {return foo}" is causing trouble, indicating some mistaken "optimization" in the bytecode. ---------------------------------------------------------------------- Comment By: miguel sofer (msofer) Date: 2002-11-04 19:19 Message: Logged In: YES user_id=148712 Blast, bitten by bothersome bytecode bug! I do not immediately see how to fix this one :( ---------------------------------------------------------------------- You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=110894&aid=633204&group_id=10894 |