diff options
author | dkf <donal.k.fellows@manchester.ac.uk> | 2013-10-20 18:15:08 (GMT) |
---|---|---|
committer | dkf <donal.k.fellows@manchester.ac.uk> | 2013-10-20 18:15:08 (GMT) |
commit | ff83c9993b14e1a40c0003bbda71dbbf2fe79a98 (patch) | |
tree | 0733388d31d6723b8dbe3d4f2976ef2178516cae /generic/tclCompCmdsGR.c | |
parent | 6df7d9226ad0c3c3721e54bcb2d7a4b9fe914b93 (diff) | |
parent | 39e314ad912cdbd29ba3e01673b1097b40118f8b (diff) | |
download | tcl-ff83c9993b14e1a40c0003bbda71dbbf2fe79a98.zip tcl-ff83c9993b14e1a40c0003bbda71dbbf2fe79a98.tar.gz tcl-ff83c9993b14e1a40c0003bbda71dbbf2fe79a98.tar.bz2 |
[2835313] Ensure correct stack balance when break and continue exceptions are about: the hard cases with potential concealed exception generation.
Diffstat (limited to 'generic/tclCompCmdsGR.c')
-rw-r--r-- | generic/tclCompCmdsGR.c | 27 |
1 files changed, 24 insertions, 3 deletions
diff --git a/generic/tclCompCmdsGR.c b/generic/tclCompCmdsGR.c index 43ea3d3..d00327d 100644 --- a/generic/tclCompCmdsGR.c +++ b/generic/tclCompCmdsGR.c @@ -2367,7 +2367,7 @@ TclCompileReturnCmd( CompileWord(envPtr, optsTokenPtr, interp, 2); CompileWord(envPtr, msgTokenPtr, interp, 3); - TclEmitOpcode(INST_RETURN_STK, envPtr); + TclEmitInvoke(envPtr, INST_RETURN_STK); return TCL_OK; } @@ -2381,6 +2381,10 @@ TclCompileReturnCmd( * Scan through the return options. If any are unknown at compile time, * there is no value in bytecompiling. Save the option values known in an * objv array for merging into a return options dictionary. + * + * TODO: There is potential for improvement if all option keys are known + * at compile time and all option values relating to '-code' and '-level' + * are known at compile time. */ for (objc = 0; objc < numOptionWords; objc++) { @@ -2388,7 +2392,7 @@ TclCompileReturnCmd( Tcl_IncrRefCount(objv[objc]); if (!TclWordKnownAtCompileTime(wordTokenPtr, objv[objc])) { /* - * Non-literal, so punt to run-time. + * Non-literal, so punt to run-time assembly of the dictionary. */ for (; objc>=0 ; objc--) { @@ -2509,7 +2513,7 @@ TclCompileReturnCmd( * Issue the RETURN itself. */ - TclEmitOpcode(INST_RETURN_STK, envPtr); + TclEmitInvoke(envPtr, INST_RETURN_STK); return TCL_OK; } @@ -2521,6 +2525,23 @@ CompileReturnInternal( int level, Tcl_Obj *returnOpts) { + if (level == 0 && (code == TCL_BREAK || code == TCL_CONTINUE)) { + ExceptionRange *rangePtr; + ExceptionAux *exceptAux; + + rangePtr = TclGetInnermostExceptionRange(envPtr, code, &exceptAux); + if (rangePtr && rangePtr->type == LOOP_EXCEPTION_RANGE) { + TclCleanupStackForBreakContinue(envPtr, exceptAux); + if (code == TCL_BREAK) { + TclAddLoopBreakFixup(envPtr, exceptAux); + } else { + TclAddLoopContinueFixup(envPtr, exceptAux); + } + Tcl_DecrRefCount(returnOpts); + return; + } + } + TclEmitPush(TclAddLiteralObj(envPtr, returnOpts, NULL), envPtr); TclEmitInstInt4(op, code, envPtr); TclEmitInt4(level, envPtr); |