diff --git a/CHANGES.current b/CHANGES.current
index 15769cbdf..89bceac9e 100644
--- a/CHANGES.current
+++ b/CHANGES.current
@@ -7,6 +7,12 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/
Version 4.1.0 (in progress)
===========================
+2022-07-26: olly
+ [Tcl] https://sourceforge.net/p/swig/bugs/977/
+ Fix handling of long long on 32-bit platforms. This fix raises
+ SWIG's minimum supported Tcl version to 8.4.0 (which was released
+ just under 20 years ago).
+
2022-07-26: olly
Fix incorrect operator precedence in preprocessor expressions.
diff --git a/Doc/Manual/Tcl.html b/Doc/Manual/Tcl.html
index bab5a8c1c..c271a2ee6 100644
--- a/Doc/Manual/Tcl.html
+++ b/Doc/Manual/Tcl.html
@@ -79,9 +79,9 @@
-This chapter discusses SWIG's support of Tcl. SWIG currently requires
-Tcl 8.0 or a later release. Earlier releases of SWIG supported Tcl 7.x, but
-this is no longer supported.
+This chapter discusses SWIG's support of Tcl. Since SWIG 4.1.0, Tcl 8.4 or a
+later release is required. Prior to that earlier Tcl 8.x releases were also
+supported.
diff --git a/Examples/test-suite/tcl/integers_runme.tcl b/Examples/test-suite/tcl/integers_runme.tcl
new file mode 100644
index 000000000..c04dd1e9e
--- /dev/null
+++ b/Examples/test-suite/tcl/integers_runme.tcl
@@ -0,0 +1,24 @@
+if [ catch { load ./integers[info sharedlibextension] integers} err_msg ] {
+ puts stderr "Could not load shared object:\n$err_msg"
+}
+
+set val 3902408827
+if {[signed_long_identity $val] != $val} {
+ puts stderr "Runtime test 1 failed"
+ exit 1
+}
+
+if {[unsigned_long_identity $val] != $val} {
+ puts stderr "Runtime test 2 failed"
+ exit 1
+}
+
+if {[signed_long_long_identity $val] != $val} {
+ puts stderr "Runtime test 3 failed"
+ exit 1
+}
+
+if {[unsigned_long_long_identity $val] != $val} {
+ puts stderr "Runtime test 4 failed"
+ exit 1
+}
diff --git a/Lib/tcl/tclprimtypes.swg b/Lib/tcl/tclprimtypes.swg
index 3b6d04f59..febbffb73 100644
--- a/Lib/tcl/tclprimtypes.swg
+++ b/Lib/tcl/tclprimtypes.swg
@@ -136,30 +136,13 @@ SWIG_From_dec(long long)(long long value)
SWIGINTERN int
SWIG_AsVal_dec(long long)(Tcl_Obj *obj, long long *val)
{
- long v;
- if (Tcl_GetLongFromObj(0,obj, &v) == TCL_OK) {
+ Tcl_WideInt v;
+ if (Tcl_GetWideIntFromObj(0, obj, &v) == TCL_OK) {
+ if (sizeof(v) > sizeof(*val) && (v < LLONG_MIN || v > LLONG_MAX)) {
+ return SWIG_OverflowError;
+ }
if (val) *val = v;
return SWIG_OK;
- } else {
- int len = 0;
- const char *nptr = Tcl_GetStringFromObj(obj, &len);
- if (nptr && len > 0) {
- char *endptr;
- long long v;
- errno = 0;
- v = strtoll(nptr, &endptr,0);
- if (nptr[0] == '\0' || *endptr != '\0')
- return SWIG_TypeError;
- if ((v == LLONG_MAX || v == LLONG_MIN) && errno == ERANGE) {
- errno = 0;
- return SWIG_OverflowError;
- } else {
- if (*endptr == '\0') {
- if (val) *val = v;
- return SWIG_OK;
- }
- }
- }
}
return SWIG_TypeError;
}