diff options
author | mdejong <mdejong> | 2005-06-29 03:28:56 (GMT) |
---|---|---|
committer | mdejong <mdejong> | 2005-06-29 03:28:56 (GMT) |
commit | 74e4d540d750139af207b77b2f32347ec287b2c9 (patch) | |
tree | cf0a37d4826a647109c653b9a68ab5d930e8e0b1 /generic/tclExecute.c | |
parent | 1e5b3a5233998d25d4ba019c04551d95f3100d7b (diff) | |
download | tcl-74e4d540d750139af207b77b2f32347ec287b2c9.zip tcl-74e4d540d750139af207b77b2f32347ec287b2c9.tar.gz tcl-74e4d540d750139af207b77b2f32347ec287b2c9.tar.bz2 |
* generic/tclExecute.c (TclExecuteByteCode):
When parsing an integer operand for a unary
minus expression operator, check for a wide
integer that is actually LONG_MIN. If found,
convert it back to a long int type.
* tests/expr.test: Add constraint for 32bit
long int type and 64bit wide int type. Add
tests that parse the smallest/largest long int
and wide int values.
Diffstat (limited to 'generic/tclExecute.c')
-rw-r--r-- | generic/tclExecute.c | 34 |
1 files changed, 29 insertions, 5 deletions
diff --git a/generic/tclExecute.c b/generic/tclExecute.c index ad06d99..06456d3 100644 --- a/generic/tclExecute.c +++ b/generic/tclExecute.c @@ -11,7 +11,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclExecute.c,v 1.192 2005/06/20 23:10:24 dkf Exp $ + * RCS: @(#) $Id: tclExecute.c,v 1.193 2005/06/29 03:29:00 mdejong Exp $ */ #include "tclInt.h" @@ -4224,10 +4224,11 @@ TclExecuteByteCode(interp, codePtr) double d; int boolvar; long i; + int negate_value = 1; Tcl_WideInt w; Tcl_ObjType *tPtr; Tcl_Obj *valuePtr; - + valuePtr = *tosPtr; tPtr = valuePtr->typePtr; if (IS_INTEGER_TYPE(tPtr) @@ -4247,6 +4248,23 @@ TclExecuteByteCode(interp, codePtr) char *s = Tcl_GetStringFromObj(valuePtr, &length); if (TclLooksLikeInt(s, length)) { GET_WIDE_OR_INT(result, valuePtr, i, w); + + /* + * An integer was parsed. If parsing a literal that + * is the smallest long value, then it would have + * been promoted to a wide since it would not fit in + * a long type without the leading '-'. Convert + * back to the smallest possible long. + */ + + if ((result == TCL_OK) && + (*pc == INST_UMINUS) && + (valuePtr->typePtr == &tclWideIntType) && + (w == -Tcl_LongAsWide(LONG_MIN))) { + valuePtr->typePtr = &tclIntType; + valuePtr->internalRep.longValue = LONG_MIN; + negate_value = 0; + } } else { result = Tcl_GetDoubleFromObj(NULL, valuePtr, &d); } @@ -4270,11 +4288,14 @@ TclExecuteByteCode(interp, codePtr) */ if (tPtr == &tclIntType) { i = valuePtr->internalRep.longValue; - TclNewLongObj(objResultPtr, -i); + if (negate_value) { + i = -i; + } + TclNewLongObj(objResultPtr, i); TRACE_WITH_OBJ(("%ld => ", i), objResultPtr); } else if (tPtr == &tclWideIntType) { TclGetWide(w,valuePtr); - TclNewWideIntObj(objResultPtr, -w); + TclNewWideIntObj(objResultPtr, -w); TRACE_WITH_OBJ((LLD" => ", w), objResultPtr); } else { d = valuePtr->internalRep.doubleValue; @@ -4288,7 +4309,10 @@ TclExecuteByteCode(interp, codePtr) */ if (tPtr == &tclIntType) { i = valuePtr->internalRep.longValue; - TclSetLongObj(valuePtr, -i); + if (negate_value) { + i = -i; + } + TclSetLongObj(valuePtr, i); TRACE_WITH_OBJ(("%ld => ", i), valuePtr); } else if (tPtr == &tclWideIntType) { TclGetWide(w,valuePtr); |