Bug 29489 - [4.1/4.2 only] LBOUND (array) and LBOUND (array, DIM) give different results.
Summary: [4.1/4.2 only] LBOUND (array) and LBOUND (array, DIM) give different results.
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 4.2.0
: P3 normal
Target Milestone: 4.1.3
Assignee: Francois-Xavier Coudert
URL:
Keywords: patch, wrong-code
Depends on:
Blocks:
 
Reported: 2006-10-17 10:17 UTC by Paul Thomas
Modified: 2006-11-24 22:46 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work: 4.3.0
Known to fail: 4.1.2 4.2.0
Last reconfirmed: 2006-10-18 21:50:55


Attachments
A patch to gfc_conv_intrinsic_bound to simplify diagnosis (475 bytes, patch)
2006-10-17 10:27 UTC, Paul Thomas
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Paul Thomas 2006-10-17 10:17:36 UTC
In the case of zero sized automatic arrays, LBOUND(array) and LBOUND(array, DIM) can give different results:

program fred

  call jackal (3, 2)

contains

  subroutine jackal (b, c)
    integer :: b, c
    integer :: soda(b:c, 1:2)

    print *, "SIZE = ", size(soda)
    print *, "LBOUND (soda, DIM) = ", ubound (soda, 1), ubound(soda, 2)
    print *, "LBOUND (soda)      = ", ubound (soda)

  end subroutine jackal
end

gives:

 SIZE =            0
 LBOUND (soda, DIM) =            2           2
 LBOUND (soda)      =            2           0

From my reading of the standard, it is the second LBOUND which is correct. ie. the array soda is zero size in that dimension.

I have stared at the code until I am blue in the face but cannot see why there is this difference in results.  I will attach a patch for trans-instrinsic.c that fixes the conditions in gfc_conv_intrinsic_bound and the code that it produces for print *, LBOUND(soda,2) and print *, LBOUND(soda).

Paul
Comment 1 Paul Thomas 2006-10-17 10:27:51 UTC
Created attachment 12450 [details]
A patch to gfc_conv_intrinsic_bound to simplify diagnosis

FX,

The patch, as promised, is attached.

I have seen what the problem is, in the meantime:  LBOUND (soda, 2) is being processed in simplify.c(simplify_bound), which does not kow about your middle end mods!

Paul
Comment 2 Francois-Xavier Coudert 2006-10-17 10:45:51 UTC
(In reply to comment #1)
> I have seen what the problem is, in the meantime:  LBOUND (soda, 2) is being
> processed in simplify.c(simplify_bound), which does not kow about your middle
> end mods!

Hum, I knew I would have to do that sometime. I've updated PR29391 to track this particular problem.
Comment 3 Francois-Xavier Coudert 2006-10-18 21:02:24 UTC
Paul, I need to be Enlightened as to why the gfc_evaluate_now statements in your patch are needed here. If and when you have a little time, that is.
Comment 4 Francois-Xavier Coudert 2006-10-18 21:50:55 UTC
Also, I should say, from my understanding the correct answer would be:

 SIZE =            0
 LBOUND (soda, DIM) =            1           1
 LBOUND (soda)      =            1           1
 UBOUND (soda, DIM) =            0           2
 UBOUND (soda)      =            0           2

And the difference (for the bounds with DIM arg specified) with what we currently yield is due to my conditions in trans-intrinsic being stupidly wrong:

Index: trans-intrinsic.c
===================================================================
--- trans-intrinsic.c   (revision 117862)
+++ trans-intrinsic.c   (working copy)
@@ -710,7 +710,7 @@
   tree type;
   tree bound;
   tree tmp;
-  tree cond, cond1, cond2, cond3, size;
+  tree cond, cond1, cond2, cond3, cond4, size;
   tree ubound;
   tree lbound;
   gfc_se argse;
@@ -840,15 +840,21 @@
   if (as)
     {
       tree stride = gfc_conv_descriptor_stride (desc, bound);
+
       cond1 = fold_build2 (GE_EXPR, boolean_type_node, ubound, lbound);
       cond2 = fold_build2 (LE_EXPR, boolean_type_node, ubound, lbound);
+
       cond3 = fold_build2 (GT_EXPR, boolean_type_node, stride,
                           gfc_index_zero_node);
+      cond3 = fold_build2 (TRUTH_AND_EXPR, boolean_type_node, cond3, cond1);
 
+      cond4 = fold_build2 (LT_EXPR, boolean_type_node, stride,
+                          gfc_index_zero_node);
+      cond4 = fold_build2 (TRUTH_AND_EXPR, boolean_type_node, cond4, cond2);
+
       if (upper)
        {
-         cond = fold_build2 (TRUTH_AND_EXPR, boolean_type_node, cond3, cond1);
-         cond = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, cond, cond2);
+         cond = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, cond3, cond4);
 
          se->expr = fold_build3 (COND_EXPR, gfc_array_index_type, cond,
                                  ubound, gfc_index_zero_node);
@@ -862,9 +868,7 @@
          else
            cond = boolean_false_node;
 
-         cond1 = fold_build2 (TRUTH_AND_EXPR, boolean_type_node, cond3, cond1);
-         cond1 = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, cond1, cond2);
-
+         cond1 = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, cond3, cond4);
          cond = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, cond, cond1);
 
          se->expr = fold_build3 (COND_EXPR, gfc_array_index_type, cond,
Comment 5 Francois-Xavier Coudert 2006-10-18 22:05:13 UTC
Yet another bug found, yet another patch. I think this one is the last:

Index: trans-intrinsic.c
===================================================================
--- trans-intrinsic.c   (revision 117862)
+++ trans-intrinsic.c   (working copy)
@@ -710,7 +710,7 @@
   tree type;
   tree bound;
   tree tmp;
-  tree cond, cond1, cond2, cond3, size;
+  tree cond, cond1, cond2, cond3, cond4, size;
   tree ubound;
   tree lbound;
   gfc_se argse;
@@ -840,15 +840,21 @@
   if (as)
     {
       tree stride = gfc_conv_descriptor_stride (desc, bound);
+
       cond1 = fold_build2 (GE_EXPR, boolean_type_node, ubound, lbound);
       cond2 = fold_build2 (LE_EXPR, boolean_type_node, ubound, lbound);
+
       cond3 = fold_build2 (GT_EXPR, boolean_type_node, stride,
                           gfc_index_zero_node);
+      cond3 = fold_build2 (TRUTH_AND_EXPR, boolean_type_node, cond3, cond1);
 
+      cond4 = fold_build2 (LT_EXPR, boolean_type_node, stride,
+                          gfc_index_zero_node);
+      cond4 = fold_build2 (TRUTH_AND_EXPR, boolean_type_node, cond4, cond2);
+
       if (upper)
        {
-         cond = fold_build2 (TRUTH_AND_EXPR, boolean_type_node, cond3, cond1);
-         cond = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, cond, cond2);
+         cond = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, cond3, cond4);
 
          se->expr = fold_build3 (COND_EXPR, gfc_array_index_type, cond,
                                  ubound, gfc_index_zero_node);
@@ -858,13 +864,11 @@
          if (as->type == AS_ASSUMED_SIZE)
            cond = fold_build2 (EQ_EXPR, boolean_type_node, bound,
                                build_int_cst (TREE_TYPE (bound),
-                                              arg->expr->rank));
+                                              arg->expr->rank - 1));
          else
            cond = boolean_false_node;
 
-         cond1 = fold_build2 (TRUTH_AND_EXPR, boolean_type_node, cond3, cond1);
-         cond1 = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, cond1, cond2);
-
+         cond1 = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, cond3, cond4);
          cond = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, cond, cond1);
 
          se->expr = fold_build3 (COND_EXPR, gfc_array_index_type, cond,
Comment 6 Francois-Xavier Coudert 2006-10-19 09:07:07 UTC
So that it doesn't get lost, here's another UBOUND problem:

$ cat a.f90 
subroutine foo (x,n)
  integer x(7,n,2,*)

  print *, ubound(x,1)
  print *, ubound(x,2)
  print *, ubound(x,3)
!  print *, ubound(x,4)
!  print *, ubound(x)
end

  integer i(7,4,2,9)

  call foo(i,4)
end
$ ifort a.f90 && ./a.out
           7
           4
           2
$ gfortran a.f90 && ./a.out
 In file a.f90:5

  print *, ubound(x,2)
                 1
Error: The upper bound in the last dimension must appear in the reference to the assumed size array 'x' at (1).
Comment 7 Francois-Xavier Coudert 2006-11-16 12:25:24 UTC
Subject: Bug 29489

Author: fxcoudert
Date: Thu Nov 16 12:25:11 2006
New Revision: 118888

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=118888
Log:
	PR fortran/29391
	PR fortran/29489

	* simplify.c (simplify_bound): Fix the simplification of
	LBOUND/UBOUND intrinsics.
	* trans-intrinsic.c (simplify_bound): Fix the logic, and
	remove an erroneous assert.

	* gcc/testsuite/gfortran.dg/bound_2.f90: Add more checks.
	* gcc/testsuite/gfortran.dg/bound_3.f90: New test.

Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/simplify.c
    trunk/gcc/fortran/trans-intrinsic.c
    trunk/gcc/testsuite/ChangeLog
    trunk/gcc/testsuite/gfortran.dg/bound_2.f90

Comment 8 Francois-Xavier Coudert 2006-11-24 22:25:48 UTC
Subject: Bug 29489

Author: fxcoudert
Date: Fri Nov 24 22:25:34 2006
New Revision: 119174

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=119174
Log:
	PR fortran/29391
	PR fortran/29489
	* simplify.c (simplify_bound): Fix the simplification of
	LBOUND/UBOUND intrinsics.
	* trans-intrinsic.c (simplify_bound): Fix the logic, and
	remove an erroneous assert.
	* gfortran.dg/bound_2.f90: New test.
	* gfortran.dg/bound_3.f90: New test.

	PR fortran/24285
	* io.c (check_format): Allow dollars everywhere in format, and
	issue a warning.
	* gfortran.dg/dollar_edit_descriptor-3.f: New test.

Added:
    branches/gcc-4_2-branch/gcc/testsuite/gfortran.dg/dollar_edit_descriptor-3.f
      - copied unchanged from r118971, trunk/gcc/testsuite/gfortran.dg/dollar_edit_descriptor-3.f
Modified:
    branches/gcc-4_2-branch/gcc/fortran/ChangeLog
    branches/gcc-4_2-branch/gcc/fortran/io.c
    branches/gcc-4_2-branch/gcc/fortran/simplify.c
    branches/gcc-4_2-branch/gcc/fortran/trans-intrinsic.c
    branches/gcc-4_2-branch/gcc/testsuite/ChangeLog
    branches/gcc-4_2-branch/gcc/testsuite/gfortran.dg/bound_2.f90

Comment 9 Francois-Xavier Coudert 2006-11-24 22:45:32 UTC
Subject: Bug 29489

Author: fxcoudert
Date: Fri Nov 24 22:45:21 2006
New Revision: 119175

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=119175
Log:
	PR fortran/29391
	PR fortran/29489
	* simplify.c (simplify_bound): Fix the simplification of
	LBOUND/UBOUND intrinsics.
	* trans-intrinsic.c (simplify_bound): Fix the logic, and
	remove an erroneous assert.

	PR fortran/29391
	* trans-intrinsic.c (gfc_conv_intrinsic_bound): Generate correct
	code for LBOUND and UBOUND intrinsics.

	PR fortran/29391
	PR fortran/29489
	* gfortran.dg/bound_2.f90: New test.
	* gfortran.dg/bound_3.f90: New test.

Added:
    branches/gcc-4_1-branch/gcc/testsuite/gfortran.dg/bound_2.f90
      - copied, changed from r117691, trunk/gcc/testsuite/gfortran.dg/bound_2.f90
Modified:
    branches/gcc-4_1-branch/gcc/fortran/ChangeLog
    branches/gcc-4_1-branch/gcc/fortran/simplify.c
    branches/gcc-4_1-branch/gcc/fortran/trans-intrinsic.c
    branches/gcc-4_1-branch/gcc/testsuite/ChangeLog

Comment 10 Francois-Xavier Coudert 2006-11-24 22:46:18 UTC
Fixed.