]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
backport: re PR fortran/57023 (Not packing arrays with changing variable used for...
authorThomas Koenig <tkoenig@netcologne.de>
Sat, 24 Jan 2015 12:50:51 +0000 (12:50 +0000)
committerThomas Koenig <tkoenig@gcc.gnu.org>
Sat, 24 Jan 2015 12:50:51 +0000 (12:50 +0000)
2015-01-24  Thomas Koenig  <tkoenig@netcologne.de>

Backport from trunk
PR fortran/57023
* dependency.c (callback_dummy_intent_not_int):  New function.
(dummy_intent_not_in):  New function.
(gfc_full_array_ref_p):  Use dummy_intent_not_in.

2015-01-24  Thomas Koenig  <tkoenig@netcologne.de>

Backport from trunk
PR fortran/57023
* gfortran.dg/internal_pack_15.f90:  New test.

From-SVN: r220080

gcc/fortran/ChangeLog
gcc/fortran/dependency.c
gcc/testsuite/ChangeLog
gcc/testsuite/gfortran.dg/internal_pack_15.f90 [new file with mode: 0644]

index cb7b7a6bae803f208e879d91b1267f1da0aa21bd..2afd58bbf045504ab969f23110638cbc1f636f37 100644 (file)
@@ -1,3 +1,11 @@
+2015-01-24  Thomas Koenig  <tkoenig@netcologne.de>
+
+       Backport from trunk
+       PR fortran/57023
+       * dependency.c (callback_dummy_intent_not_int):  New function.
+       (dummy_intent_not_in):  New function.
+       (gfc_full_array_ref_p):  Use dummy_intent_not_in.
+
 2015-01-24  Janus Weil  <janus@gcc.gnu.org>
 
        Backport from mainline
index f9b975ad9c5c97ae920bee3c1fd6ad726e18d47f..3c7d57913c39df9ed65cfc3d50699d2fe03dbac2 100644 (file)
@@ -1848,11 +1848,40 @@ gfc_check_element_vs_element (gfc_ref *lref, gfc_ref *rref, int n)
   return GFC_DEP_EQUAL;
 }
 
+/* Callback function for checking if an expression depends on a
+   dummy variable which is any other than INTENT(IN).  */
+
+static int
+callback_dummy_intent_not_in (gfc_expr **ep,
+                             int *walk_subtrees ATTRIBUTE_UNUSED,
+                             void *data ATTRIBUTE_UNUSED)
+{
+  gfc_expr *e = *ep;
+
+  if (e->expr_type == EXPR_VARIABLE && e->symtree
+      && e->symtree->n.sym->attr.dummy)
+    return e->symtree->n.sym->attr.intent != INTENT_IN;
+  else
+    return 0;
+}
+
+/* Auxiliary function to check if subexpressions have dummy variables which
+   are not intent(in).
+*/
+
+static bool
+dummy_intent_not_in (gfc_expr **ep)
+{
+  return gfc_expr_walker (ep, callback_dummy_intent_not_in, NULL);
+}
 
 /* Determine if an array ref, usually an array section specifies the
    entire array.  In addition, if the second, pointer argument is
    provided, the function will return true if the reference is
-   contiguous; eg. (:, 1) gives true but (1,:) gives false.  */
+   contiguous; eg. (:, 1) gives true but (1,:) gives false. 
+   If one of the bounds depends on a dummy variable which is
+   not INTENT(IN), also return false, because the user may
+   have changed the variable.  */
 
 bool
 gfc_full_array_ref_p (gfc_ref *ref, bool *contiguous)
@@ -1916,14 +1945,16 @@ gfc_full_array_ref_p (gfc_ref *ref, bool *contiguous)
          && (!ref->u.ar.as
              || !ref->u.ar.as->lower[i]
              || gfc_dep_compare_expr (ref->u.ar.start[i],
-                                      ref->u.ar.as->lower[i])))
+                                      ref->u.ar.as->lower[i])
+             || dummy_intent_not_in (&ref->u.ar.start[i])))
        lbound_OK = false;
       /* Check the upper bound.  */
       if (ref->u.ar.end[i]
          && (!ref->u.ar.as
              || !ref->u.ar.as->upper[i]
              || gfc_dep_compare_expr (ref->u.ar.end[i],
-                                      ref->u.ar.as->upper[i])))
+                                      ref->u.ar.as->upper[i])
+             || dummy_intent_not_in (&ref->u.ar.end[i])))
        ubound_OK = false;
       /* Check the stride.  */
       if (ref->u.ar.stride[i]
index c2f61d911e616d221e860e43eabfa7cbdcfc7339..4c592f85f1223c1ad6145dc1722528efaeba09e5 100644 (file)
@@ -1,3 +1,9 @@
+2015-01-24  Thomas Koenig  <tkoenig@netcologne.de>
+
+       Backport from trunk
+       PR fortran/57023
+       * gfortran.dg/internal_pack_15.f90:  New test.
+
 2015-01-24  Janus Weil  <janus@gcc.gnu.org>
 
        Backport from mainline
diff --git a/gcc/testsuite/gfortran.dg/internal_pack_15.f90 b/gcc/testsuite/gfortran.dg/internal_pack_15.f90
new file mode 100644 (file)
index 0000000..13e3304
--- /dev/null
@@ -0,0 +1,77 @@
+! { dg-do run }
+! { dg-options "-Warray-temporaries" }
+! PR 57023
+! This used to cause wrong packing because a(1:n,1:n) was
+! assumed to be a full array.
+module mymod
+  implicit none
+contains
+  subroutine foo1(a,n)
+    integer, dimension(n,n), intent(inout) :: a
+    integer :: n
+    n = n - 1
+    call baz(a(1:n,1:n),n)  ! { dg-warning "array temporary" }
+  end subroutine foo1
+
+  subroutine foo2(a,n)
+    integer, dimension(n,n), intent(inout) :: a
+    integer :: n
+    call decrement(n)
+    call baz(a(1:n,1:n),n)  ! { dg-warning "array temporary" }
+  end subroutine foo2
+
+  subroutine foo3(a,n)
+    integer, dimension(n,n), intent(inout) :: a
+    integer :: n, m
+    m = n - 1
+    call baz(a(1:m,1:m),m)  ! { dg-warning "array temporary" }
+  end subroutine foo3
+
+  subroutine foo4(a,n)
+    integer, dimension(n,n), intent(inout) :: a
+    integer, intent(in) :: n
+    a(1:n,1:n) = 1
+  end subroutine foo4
+
+  subroutine baz(a,n)
+    integer, dimension(n,n), intent(inout) :: a
+    integer, intent(in) :: n
+    a = 1
+  end subroutine baz
+
+  subroutine decrement(n)
+    integer, intent(inout) :: n
+    n = n - 1
+  end subroutine decrement
+
+end module mymod
+
+program main
+  use mymod
+  implicit none
+  integer, dimension(5,5) :: a, b
+  integer :: n
+
+  b = 0
+  b(1:4,1:4) = 1
+
+  n = 5
+  a = 0
+  call foo1(a,n)
+  if (any(a /= b)) call abort
+
+  n = 5
+  a = 0
+  call foo2(a,n)
+  if (any(a /= b)) call abort
+
+  n = 5
+  a = 0
+  call foo3(a,n)
+  if (any(a /= b)) call abort
+
+  n = 5
+  a = 0
+  call foo4(a,n)
+  if (any(a /= 1)) call abort
+end program main