diff mbox

[Fortran] PR fortran/46794: Fix ICE with powers of integers

Message ID 4D00FDE6.1050702@domob.eu
State New
Headers show

Commit Message

Daniel Kraft Dec. 9, 2010, 4:03 p.m. UTC
Tobias Burnus wrote:
> Dear Daniel,
> 
> Daniel Kraft wrote:
>> I do not entirely like the way this is done in the patch (with the two 
>> variables and "special casing"), but don't see a better implementation 
>> -- what do you think?
> 
> I think it is OK - at least I have trouble finding a better solution.
> 
>> Regression-tested on x86_64-unknown-linux-gnu without failures -- 
>> though the run somehow looked strange to me (on the compile-farm); 
>> I'll try again to be sure.  Ok for trunk?
> 
> OK for the trunk. Can you check whether one needs to likewise for the 
> 4.5 and 4.4 branch? (I think one should check on source level - the 
> verify_tree might not always catch it. For some reasons, it ICEs here 
> with 4.4 and 4.6 but not with 4.5; however, I think that's rather by 
> chance and not because of a proper casting.)

Committed the attached (patch adapted to 4.4 including fix of test-case) 
as rev. 167644 to 4.4 branch.  When 4.5 is open again, I will fix the 
test-case there, too, and then close the PR.

Yours,
Daniel
diff mbox

Patch

Index: gcc/testsuite/gfortran.dg/power2.f90
===================================================================
--- gcc/testsuite/gfortran.dg/power2.f90	(revision 0)
+++ gcc/testsuite/gfortran.dg/power2.f90	(revision 0)
@@ -0,0 +1,25 @@ 
+! { dg-do compile }
+! PR fortran/46794
+
+! Check that results of powers of integers with kinds 1 and 2 are
+! correctly converted back; this used to ICE because a conversion
+! from kind 4 to the correct one was missing.
+
+! Contributed by Daniel Kraft, d@domob.eu.
+
+PROGRAM main
+  IMPLICIT NONE
+
+  INTEGER(KIND=1) :: k1
+  INTEGER(KIND=2) :: k2
+
+  k1 = 1_1
+  k2 = 1_2
+
+  k1 = 1_1 + 1_1**k1
+  k2 = 1_2 + 1_2**k2
+
+  k2 = 1_1 + 1_1**k2
+  k2 = 1_1 + 1_2**k1
+  k2 = 1_1 + 1_2**k2
+END PROGRAM main
Index: gcc/fortran/trans-expr.c
===================================================================
--- gcc/fortran/trans-expr.c	(revision 167632)
+++ gcc/fortran/trans-expr.c	(working copy)
@@ -917,6 +917,7 @@ 
   tree gfc_int4_type_node;
   int kind;
   int ikind;
+  int res_ikind_1, res_ikind_2;
   gfc_se lse;
   gfc_se rse;
   tree fndecl;
@@ -937,6 +938,13 @@ 
 
   gfc_int4_type_node = gfc_get_int_type (4);
 
+  /* In case of integer operands with kinds 1 or 2, we call the integer kind 4
+     library routine.  But in the end, we have to convert the result back
+     if this case applies -- with res_ikind_K, we keep track whether operand K
+     falls into this case.  */
+  res_ikind_1 = -1;
+  res_ikind_2 = -1;
+
   kind = expr->value.op.op1->ts.kind;
   switch (expr->value.op.op2->ts.type)
     {
@@ -947,6 +955,7 @@ 
 	case 1:
 	case 2:
 	  rse.expr = convert (gfc_int4_type_node, rse.expr);
+	  res_ikind_2 = ikind;
 	  /* Fall through.  */
 
 	case 4:
@@ -969,7 +978,10 @@ 
 	case 1:
 	case 2:
 	  if (expr->value.op.op1->ts.type == BT_INTEGER)
-	    lse.expr = convert (gfc_int4_type_node, lse.expr);
+	    {
+	      lse.expr = convert (gfc_int4_type_node, lse.expr);
+	      res_ikind_1 = kind;
+	    }
 	  else
 	    gcc_unreachable ();
 	  /* Fall through.  */
@@ -1080,6 +1092,15 @@ 
     }
 
   se->expr = build_call_expr (fndecl, 2, lse.expr, rse.expr);
+
+  /* Convert the result back if it is of wrong integer kind.  */
+  if (res_ikind_1 != -1 && res_ikind_2 != -1)
+    {
+      /* We want the maximum of both operand kinds as result.  */
+      if (res_ikind_1 < res_ikind_2)
+	res_ikind_1 = res_ikind_2;
+      se->expr = convert (gfc_get_int_type (res_ikind_1), se->expr);
+    }
 }