Index: generic/nsf.c =================================================================== diff -u -rb1775aaa4be30234fed712c5fb11949749db8273 -r56bee72be0878f8f9e7ccab05058ec15a89dbbbe --- generic/nsf.c (.../nsf.c) (revision b1775aaa4be30234fed712c5fb11949749db8273) +++ generic/nsf.c (.../nsf.c) (revision 56bee72be0878f8f9e7ccab05058ec15a89dbbbe) @@ -32424,11 +32424,24 @@ nonnull_assert(interp != NULL); nonnull_assert(object != NULL); + if (objc < 3) { + return NsfPrintError(interp, + "wrong # args: should be \"%s %s " + "?level? otherVar localVar ?otherVar localVar ...?\"", + ObjectName(object), + NsfMethodName(objv[0])); + } + if (objc % 2 == 0) { - frameInfoObj = NULL; + /* even number of arguments (incl. method) + * -> level specifier considered present + */ frameInfo = ObjStr(objv[1]); i = 2; } else { + /* odd number of arguments (incl. method) + * -> level specififer considered absent, compute jump level + */ frameInfoObj = ComputeLevelObj(interp, CALLING_LEVEL); INCR_REF_COUNT(frameInfoObj); frameInfo = ObjStr(frameInfoObj); @@ -32438,7 +32451,7 @@ if ((object->filterStack != NULL) || (object->mixinStack != NULL)) { CallStackUseActiveFrame(interp, &ctx); } - + for ( ; i < objc; i += 2) { result = Tcl_UpVar2(interp, frameInfo, ObjStr(objv[i]), NULL, ObjStr(objv[i+1]), 0 /*flags*/); @@ -32452,6 +32465,7 @@ } CallStackRestoreSavedFrames(interp, &ctx); return result; + } /* Index: tests/methods.test =================================================================== diff -u -rb97fe27792607e6e3d6b89d3e012760e641a90df -r56bee72be0878f8f9e7ccab05058ec15a89dbbbe --- tests/methods.test (.../methods.test) (revision b97fe27792607e6e3d6b89d3e012760e641a90df) +++ tests/methods.test (.../methods.test) (revision 56bee72be0878f8f9e7ccab05058ec15a89dbbbe) @@ -1905,7 +1905,54 @@ ? {uplevel #0 {objekt foo}} "#0" } +nx::test case upvar-method-signature { + Object create objekt + objekt public object method foo {} { + :upvar #1; + } + + ? {uplevel #0 {objekt foo}} \ + {wrong # args: should be "::objekt upvar ?level? otherVar localVar ?otherVar localVar ...?"} + + objekt public object method foo {} { + :upvar 1; + } + + ? {uplevel #0 {objekt foo}} \ + {wrong # args: should be "::objekt upvar ?level? otherVar localVar ?otherVar localVar ...?"} + + objekt public object method foo {} { + :upvar; + } + + ? {uplevel #0 {objekt foo}} \ + {wrong # args: should be "::objekt upvar ?level? otherVar localVar ?otherVar localVar ...?"} + + objekt public object method foo {} { + :upvar x z; + set z 5 + } + + ? {uplevel #0 {objekt foo; set x}} 5 + + objekt public object method foo {} { + :upvar #5 x z; + } + + ? {uplevel #0 {objekt foo}} \ + {bad level "#5"} + + objekt public object method foo {} { + :upvar #5 x z y; + set x 1 + } + + ? {uplevel #0 {apply {{} {objekt foo; info exists "#5"}}}} 1 +} + + + # Local variables: # mode: tcl # tcl-indent-level: 2