Raise OverflowError when appropriate on long->float conversion.  Most of
the fiddling is simply due to that no caller of PyLong_AsDouble ever
checked for failure (so that's fixing old bugs).  PyLong_AsDouble is much
faster for big inputs now too, but that's more of a happy consequence
than a design goal.
diff --git a/Lib/test/test_long.py b/Lib/test/test_long.py
index b0eaff7..ac345a6 100644
--- a/Lib/test/test_long.py
+++ b/Lib/test/test_long.py
@@ -328,6 +328,42 @@
                                 raise TestFailed("pow%r should have raised "
                                 "TypeError" % ((longx, longy, long(z))))
 
+# ---------------------------------------- tests of long->float overflow
+
+def test_float_overflow():
+    import math
+
+    if verbose:
+        print "long->float overflow"
+
+    for x in -2.0, -1.0, 0.0, 1.0, 2.0:
+        verify(float(long(x)) == x)
+
+    huge = 1L << 30000
+    mhuge = -huge
+    namespace = {'huge': huge, 'mhuge': mhuge, 'math': math}
+    for test in ["float(huge)", "float(mhuge)",
+                 "complex(huge)", "complex(mhuge)",
+                 "complex(huge, 1)", "complex(mhuge, 1)",
+                 "complex(1, huge)", "complex(1, mhuge)",
+                 "1. + huge", "huge + 1.", "1. + mhuge", "mhuge + 1.",
+                 "1. - huge", "huge - 1.", "1. - mhuge", "mhuge - 1.",
+                 "1. * huge", "huge * 1.", "1. * mhuge", "mhuge * 1.",
+                 "1. // huge", "huge // 1.", "1. // mhuge", "mhuge // 1.",
+                 "1. / huge", "huge / 1.", "1. / mhuge", "mhuge / 1.",
+                 "1. ** huge", "huge ** 1.", "1. ** mhuge", "mhuge ** 1.",
+                 "math.sin(huge)", "math.sin(mhuge)",
+                 "math.log(huge)", "math.log(mhuge)", # should do better
+                 "math.sqrt(huge)", "math.sqrt(mhuge)", # should do better
+                 "math.log10(huge)", "math.log10(mhuge)", # should do better
+                 "math.floor(huge)", "math.floor(mhuge)"]:
+                 
+        try:
+            eval(test, namespace)
+        except OverflowError:
+            pass
+        else:
+            raise TestFailed("expected OverflowError from %s" % test)
 # ---------------------------------------------------------------- do it
 
 test_division()
@@ -335,3 +371,4 @@
 test_format()
 test_misc()
 test_auto_overflow()
+test_float_overflow()
diff --git a/Misc/NEWS b/Misc/NEWS
index 43eff32..a8f05c7 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -3,6 +3,9 @@
 
 Core
 
+- Conversion of long to float now raises OverflowError if the long is too
+  big to represent as a C double.
+
 - The 3-argument builtin pow() no longer allows a third non-None argument
   if either of the first two arguments is a float, or if both are of
   integer types and the second argument is negative (in which latter case
@@ -95,6 +98,15 @@
 
 API
 
+- Note that PyLong_AsDouble can fail!  This has always been true, but no
+  callers checked for it.  It's more likely to fail now, because overflow
+  errors are properly detected now.  The proper way to check:
+
+  double x = PyLong_AsDouble(some_long_object);
+  if (x == -1.0 && PyErr_Occurred()) {
+          /* The conversion failed. */
+  }
+
 - The GC API has been changed.  Extensions that use the old API will still
   compile but will not participate in GC.  To upgrade an extension
   module:
diff --git a/Objects/complexobject.c b/Objects/complexobject.c
index 236f4d5..7404993 100644
--- a/Objects/complexobject.c
+++ b/Objects/complexobject.c
@@ -522,6 +522,8 @@
 	}
 	else if (PyLong_Check(*pw)) {
 		cval.real = PyLong_AsDouble(*pw);
+		if (cval.real == -1.0 && PyErr_Occurred())
+			return -1;
 		*pw = PyComplex_FromCComplex(cval);
 		Py_INCREF(*pv);
 		return 0;
diff --git a/Objects/floatobject.c b/Objects/floatobject.c
index 478e131..8443aff 100644
--- a/Objects/floatobject.c
+++ b/Objects/floatobject.c
@@ -271,18 +271,19 @@
 		return obj;
 
 static int
-convert_to_double(PyObject **v,
-		  double *dbl)
+convert_to_double(PyObject **v, double *dbl)
 {
 	register PyObject *obj = *v;
-	
+
 	if (PyInt_Check(obj)) {
 		*dbl = (double)PyInt_AS_LONG(obj);
 	}
 	else if (PyLong_Check(obj)) {
-		PyFPE_START_PROTECT("convert_to_double", {*v=NULL;return -1;})
 		*dbl = PyLong_AsDouble(obj);
-		PyFPE_END_PROTECT(*dbl)
+		if (*dbl == -1.0 && PyErr_Occurred()) {
+			*v = NULL;
+			return -1;
+		}
 	}
 	else {
 		Py_INCREF(Py_NotImplemented);
diff --git a/Objects/longobject.c b/Objects/longobject.c
index b511928..e97ebd5 100644
--- a/Objects/longobject.c
+++ b/Objects/longobject.c
@@ -531,27 +531,28 @@
 double
 PyLong_AsDouble(PyObject *vv)
 {
-	register PyLongObject *v;
+	int e;
 	double x;
-	double multiplier = (double) (1L << SHIFT);
-	int i, sign;
-	
+
 	if (vv == NULL || !PyLong_Check(vv)) {
 		PyErr_BadInternalCall();
 		return -1;
 	}
-	v = (PyLongObject *)vv;
-	i = v->ob_size;
-	sign = 1;
-	x = 0.0;
-	if (i < 0) {
-		sign = -1;
-		i = -(i);
-	}
-	while (--i >= 0) {
-		x = x*multiplier + (double)v->ob_digit[i];
-	}
-	return x * sign;
+	x = _PyLong_AsScaledDouble(vv, &e);
+	if (x == -1.0 && PyErr_Occurred())
+		return -1.0;
+	if (e > INT_MAX / SHIFT)
+		goto overflow;
+	errno = 0;
+	x = ldexp(x, e * SHIFT);
+	if (errno == ERANGE)
+		goto overflow;
+	return x;
+
+overflow:
+	PyErr_SetString(PyExc_OverflowError,
+		"long int too large to convert to float");
+	return -1.0;
 }
 
 /* Create a new long (or int) object from a C pointer */
@@ -2098,9 +2099,9 @@
 long_float(PyObject *v)
 {
 	double result;
-	PyFPE_START_PROTECT("long_float", return 0)
 	result = PyLong_AsDouble(v);
-	PyFPE_END_PROTECT(result)
+	if (result == -1.0 && PyErr_Occurred())
+		return NULL;
 	return PyFloat_FromDouble(result);
 }