[Backport of r52452]
Patch #1549049: Rewrite type conversion in structmember.
Fixes #1545696 and #1566140.

The new warnings have been omitted in the backport.
diff --git a/Python/structmember.c b/Python/structmember.c
index 54eb055..03934c0 100644
--- a/Python/structmember.c
+++ b/Python/structmember.c
@@ -62,29 +62,28 @@
 	addr += l->offset;
 	switch (l->type) {
 	case T_BYTE:
-		v = PyInt_FromLong(
-			(long) (((*(char*)addr & 0xff) ^ 0x80) - 0x80));
+		v = PyInt_FromLong(*(char*)addr);
 		break;
 	case T_UBYTE:
-		v = PyInt_FromLong((long) *(char*)addr & 0xff);
+		v = PyLong_FromUnsignedLong(*(unsigned char*)addr);
 		break;
 	case T_SHORT:
-		v = PyInt_FromLong((long) *(short*)addr);
+		v = PyInt_FromLong(*(short*)addr);
 		break;
 	case T_USHORT:
-		v = PyInt_FromLong((long) *(unsigned short*)addr);
+		v = PyLong_FromUnsignedLong(*(unsigned short*)addr);
 		break;
 	case T_INT:
-		v = PyInt_FromLong((long) *(int*)addr);
+		v = PyInt_FromLong(*(int*)addr);
 		break;
 	case T_UINT:
-		v = PyInt_FromLong((long) *(unsigned int*)addr);
+		v = PyLong_FromUnsignedLong(*(unsigned int*)addr);
 		break;
 	case T_LONG:
 		v = PyInt_FromLong(*(long*)addr);
 		break;
 	case T_ULONG:
-		v = PyLong_FromDouble((double) *(unsigned long*)addr);
+		v = PyLong_FromUnsignedLong(*(unsigned long*)addr);
 		break;
 	case T_FLOAT:
 		v = PyFloat_FromDouble((double)*(float*)addr);
@@ -175,68 +174,91 @@
 	}
 	addr += l->offset;
 	switch (l->type) {
-	case T_BYTE:
-	case T_UBYTE:
-		if (!PyInt_Check(v)) {
-			PyErr_BadArgument();
+	case T_BYTE:{
+		long long_val;
+		long_val = PyInt_AsLong(v);
+		if ((long_val == -1) && PyErr_Occurred())
 			return -1;
-		}
-		*(char*)addr = (char) PyInt_AsLong(v);
+		*(char*)addr = (char)long_val;
 		break;
-	case T_SHORT:
-	case T_USHORT:
-		if (!PyInt_Check(v)) {
-			PyErr_BadArgument();
-			return -1;
 		}
-		*(short*)addr = (short) PyInt_AsLong(v);
-		break;
-	case T_UINT:
-	case T_INT:
-		if (!PyInt_Check(v)) {
-			PyErr_BadArgument();
+	case T_UBYTE:{
+		long long_val;
+		long_val = PyInt_AsLong(v);
+		if ((long_val == -1) && PyErr_Occurred())
 			return -1;
+		*(unsigned char*)addr = (unsigned char)long_val;
+		break;
 		}
-		*(int*)addr = (int) PyInt_AsLong(v);
-		break;
-	case T_LONG:
-		if (!PyInt_Check(v)) {
-			PyErr_BadArgument();
+	case T_SHORT:{
+		long long_val;
+		long_val = PyInt_AsLong(v);
+		if ((long_val == -1) && PyErr_Occurred())
 			return -1;
+		*(short*)addr = (short)long_val;
+		break;
 		}
-		*(long*)addr = PyInt_AsLong(v);
-		break;
-	case T_ULONG:
-		if (PyInt_Check(v))
-			*(long*)addr = PyInt_AsLong(v);
-		else if (PyLong_Check(v))
-			*(long*)addr = PyLong_AsLong(v);
-		else {
-			PyErr_BadArgument();
+	case T_USHORT:{
+		long long_val;
+		long_val = PyInt_AsLong(v);
+		if ((long_val == -1) && PyErr_Occurred())
 			return -1;
+		*(unsigned short*)addr = (unsigned short)long_val;
+		break;
+		}
+  	case T_INT:{
+		long long_val;
+		long_val = PyInt_AsLong(v);
+		if ((long_val == -1) && PyErr_Occurred())
+			return -1;
+		*(int *)addr = (int)long_val;
+		break;
+		}
+	case T_UINT:{
+		unsigned long ulong_val;
+		ulong_val = PyLong_AsUnsignedLong(v);
+		if ((ulong_val == (unsigned int)-1) && PyErr_Occurred()) {
+			/* XXX: For compatibility, accept negative int values
+			   as well. */
+			PyErr_Clear();
+			ulong_val = PyLong_AsLong(v);
+			if ((ulong_val == (unsigned int)-1) && PyErr_Occurred())
+				return -1;
+		}
+		*(unsigned int *)addr = (unsigned int)ulong_val;
+		break;
+		}
+	case T_LONG:{
+		*(long*)addr = PyLong_AsLong(v);
+		if ((*(long*)addr == -1) && PyErr_Occurred())
+			return -1;
+		break;
+		}
+	case T_ULONG:{
+		*(unsigned long*)addr = PyLong_AsUnsignedLong(v);
+		if ((*(unsigned long*)addr == (unsigned long)-1)
+		    && PyErr_Occurred()) {
+			/* XXX: For compatibility, accept negative int values
+			   as well. */
+			PyErr_Clear();
+			*(unsigned long*)addr = PyLong_AsLong(v);
+			if ((*(unsigned long*)addr == (unsigned int)-1) && PyErr_Occurred())
+				return -1;
 		}
 		break;
-	case T_FLOAT:
-		if (PyInt_Check(v))
-			*(float*)addr =
-				(float) PyInt_AsLong(v);
-		else if (PyFloat_Check(v))
-			*(float*)addr =
-				(float) PyFloat_AsDouble(v);
-		else {
-			PyErr_BadArgument();
-			return -1;
 		}
+	case T_FLOAT:{
+		double double_val;
+		double_val = PyFloat_AsDouble(v);
+		if ((double_val == -1) && PyErr_Occurred())
+			return -1;
+		*(float*)addr = (float)double_val;
 		break;
+		}
 	case T_DOUBLE:
-		if (PyInt_Check(v))
-			*(double*)addr = (double) PyInt_AsLong(v);
-		else if (PyFloat_Check(v))
-			*(double*)addr = PyFloat_AsDouble(v);
-		else {
-			PyErr_BadArgument();
+		*(double*)addr = PyFloat_AsDouble(v);
+		if ((*(double*)addr == -1) && PyErr_Occurred())
 			return -1;
-		}
 		break;
 	case T_OBJECT:
 	case T_OBJECT_EX: