Tcl Source Code

Artifact [5e5502964c]
Login

Artifact 5e5502964caeffb32d1b612601edd5cdf7bfa1c1:

Attachment "patch219184.txt" to ticket [219184ffff] added by msofer 2001-08-22 21:00:53.
? patch419528.txt
? patch451200.txt
? patch219184.txt
Index: ChangeLog
===================================================================
RCS file: /cvsroot/tcl/tcl/ChangeLog,v
retrieving revision 1.528
diff -u -r1.528 ChangeLog
--- ChangeLog	2001/08/22 01:29:18	1.528
+++ ChangeLog	2001/08/22 13:55:13
@@ -1,3 +1,9 @@
+2001-08-21  Miguel Sofer  <[email protected]>
+
+	* generic/tclCompCmds.c:
+	* tests/compile.test: Fixed overagressive compilation of [catch]:
+	it was catching errors at substitution time. [Bug #219184]
+	
 2001-08-21  Jeff Hobbs  <[email protected]>
 
 	* tests/tcltest.test (tcltest-12.2): fixed test that would break
Index: generic/tclCompCmds.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclCompCmds.c,v
retrieving revision 1.9
diff -u -r1.9 tclCompCmds.c
--- generic/tclCompCmds.c	2001/06/28 00:42:39	1.9
+++ generic/tclCompCmds.c	2001/08/22 13:55:15
@@ -317,10 +317,27 @@
     range = TclCreateExceptRange(CATCH_EXCEPTION_RANGE, envPtr);
     TclEmitInstInt4(INST_BEGIN_CATCH4, range, envPtr);
 
-    startOffset = (envPtr->codeNext - envPtr->codeStart);
+    /*
+     * If the body is a simple word, compile the instructions to
+     * eval it. Otherwise, compile instructions to substitute its
+     * text without catching, a catch instruction that resets the 
+     * stack to what it was before substituting the body, and then 
+     * an instruction to eval the body. Care has to be taken to 
+     * register the correct startOffset for the catch range so that
+     * errors in the substitution are not catched [Bug 219184]
+     */
+
+    if (cmdTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) {
+	startOffset = (envPtr->codeNext - envPtr->codeStart);
+	code = TclCompileCmdWord(interp, cmdTokenPtr+1, 1, envPtr);
+    } else {
+	code = TclCompileTokens(interp, cmdTokenPtr+1,
+	        cmdTokenPtr->numComponents, envPtr);
+	startOffset = (envPtr->codeNext - envPtr->codeStart);
+	TclEmitOpcode(INST_EVAL_STK, envPtr);
+    }
     envPtr->exceptArrayPtr[range].codeOffset = startOffset;
-    code = TclCompileCmdWord(interp, cmdTokenPtr+1,
-	    cmdTokenPtr->numComponents, envPtr);
+
     if (code != TCL_OK) {
 	if (code == TCL_ERROR) {
 	    sprintf(buffer, "\n    (\"catch\" body line %d)",
Index: tests/compile.test
===================================================================
RCS file: /cvsroot/tcl/tcl/tests/compile.test,v
retrieving revision 1.9
diff -u -r1.9 compile.test
--- tests/compile.test	2000/05/03 00:14:36	1.9
+++ tests/compile.test	2001/08/22 13:55:15
@@ -1,4 +1,4 @@
-# This file contains tests for the file tclCompile.c.
+# This file contains tests for the files tclCompile.c and tclCompCmds.c
 #
 # This file contains a collection of tests for one or more of the Tcl
 # built-in commands.  Sourcing this file into Tcl runs the tests and
@@ -89,6 +89,14 @@
     catch-test
     set ::foo
 } 3
+test compile-3.3 {TclCompileCatchCmd: overagressive compiling [bug 219184]} {
+    proc catch-test {str} {
+	catch [eval $str GOOD]
+	error BAD
+    }
+    catch {catch-test error} ::foo
+    set ::foo
+} {GOOD}
 
 test compile-4.1 {TclCompileForCmd: command substituted test expression} {
     set i 0