--- /dev/null
+--- gcc/c-typeck.c (revision 110241)
++++ gcc/c-typeck.c (working copy)
+@@ -8101,12 +8101,35 @@ build_binary_op (enum tree_code code, tr
+ if (shorten && none_complex)
+ {
+ int unsigned0, unsigned1;
+- tree arg0 = get_narrower (op0, &unsigned0);
+- tree arg1 = get_narrower (op1, &unsigned1);
+- /* UNS is 1 if the operation to be done is an unsigned one. */
+- int uns = TYPE_UNSIGNED (result_type);
++ tree arg0, arg1;
++ int uns;
+ tree type;
+
++ /* Cast OP0 and OP1 to RESULT_TYPE. Doing so prevents
++ excessive narrowing when we call get_narrower below. For
++ example, suppose that OP0 is of unsigned int extended
++ from signed char and that RESULT_TYPE is long long int.
++ If we explicitly cast OP0 to RESULT_TYPE, OP0 would look
++ like
++
++ (long long int) (unsigned int) signed_char
++
++ which get_narrower would narrow down to
++
++ (unsigned int) signed char
++
++ If we do not cast OP0 first, get_narrower would return
++ signed_char, which is inconsistent with the case of the
++ explicit cast. */
++ op0 = convert (result_type, op0);
++ op1 = convert (result_type, op1);
++
++ arg0 = get_narrower (op0, &unsigned0);
++ arg1 = get_narrower (op1, &unsigned1);
++
++ /* UNS is 1 if the operation to be done is an unsigned one. */
++ uns = TYPE_UNSIGNED (result_type);
++
+ final_type = result_type;
+
+ /* Handle the case that OP0 (or OP1) does not *contain* a conversion
+Index: testsuite/gcc.c-torture/execute/pr19606.c
+===================================================================
+--- /dev/null 2005-09-01 09:08:28.063949816 -0700
++++ gcc/testsuite/gcc.c-torture/execute/pr19606.c 2006-01-15 14:41:56.490361111 -0800
+@@ -0,0 +1,33 @@
++/* PR c/19606
++ The C front end used to shorten the type of a division even when
++ the signedness changes. Make sure that won't happen. */
++
++signed char a = -4;
++
++int
++foo (void)
++{
++ return ((unsigned int) (signed int) a) / 2LL;
++}
++
++int
++bar (void)
++{
++ return ((unsigned int) (signed int) a) % 5LL;
++}
++
++int
++main (void)
++{
++ int r;
++
++ r = foo ();
++ if (r != ((unsigned int) (signed int) (signed char) -4) / 2LL)
++ abort ();
++
++ r = bar ();
++ if (r != ((unsigned int) (signed int) (signed char) -4) % 5LL)
++ abort ();
++
++ exit (0);
++}
+