# Creating temporary array when declared in a module

**URL:** <https://fortran-lang.discourse.group/t/creating-temporary-array-when-declared-in-a-module/7379>\
**Category:** GNU\
**Created:** [February 10, 2024, 11:17am UTC](https://fortran-lang.discourse.group/t/creating-temporary-array-when-declared-in-a-module/7379 "2024-02-10T11:17:36Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![yarchik](https://avatars.discourse-cdn.com/v4/letter/y/e8c25b/32.png) [@yarchik](https://fortran-lang.discourse.group/u/yarchik)\
**Post date:** [February 10, 2024, 11:17am UTC](https://fortran-lang.discourse.group/t/creating-temporary-array-when-declared-in-a-module/7379/1 "2024-02-10T11:17:36Z")

</div>

This is my first post here, I am still learning the etiquette here. Therefore, please, apologise me if I do not fully conform the style of posts here.

I decided to register here after my [post](https://stackoverflow.com/q/77970328/4954079) at Stackoverflow received only little attention. I copy it here almost verbatim.

I do not understand why `gfortran` creates a temporary array only in one case. Consider the following program

```auto
program temporary_arrays
  use Mvars, only : am
  use Mtemporaries, only: create_matrix
  implicit none
  integer, parameter :: dp = kind(1.d0), n = 3
  real(dp), allocatable :: bm(:, :)
  
  allocate(am(n, n), bm(n, n))

  ! -- temporary array is created --
  am = create_matrix(n)

  ! -- no temporary array --
  bm = create_matrix(n)
  
end program temporary_arrays

!------------------------
module Mtemporaries

contains
  function create_matrix(n) result(A)
    implicit none
    integer, parameter :: dp = kind(1.d0)
    integer :: n
    real(dp) :: a(n, n)
    A = 0.d0
  end function create_matrix

end module Mtemporaries  

!------------------------
module Mvars
  implicit none
  integer, parameter :: dp = kind(1.d0)
  real(dp), allocatable :: am(:, :)
  
end module Mvars

```

When compiled with `gfortran` (GNU Fortran (Homebrew GCC 13.2.0) 13.2.0 Copyright (C) 2023 Free Software Foundation, Inc.) with the `-Warray-temporaries` option, I get that temporary array is created only in one case, namely when the array is declared in a different module. No such warning when the array is declared in the main program.

I would like to know the logic behind and how to deal with this problem, i.e., avoid creation of temporary arrays.

---

<div class="post-metadata">

**Author:** ![ivanpribec](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/ivanpribec/32/3290_2.png) [@ivanpribec](https://fortran-lang.discourse.group/u/ivanpribec)\
**Post date:** [February 10, 2024, 1:50pm UTC](https://fortran-lang.discourse.group/t/creating-temporary-array-when-declared-in-a-module/7379/2 "2024-02-10T13:50:54Z")

</div>

I don’t see any temporary at runtime. I’m using gcc version 13.2.0 (Homebrew GCC 13.2.0).

```txt
$ gfortran -O2 -fcheck=array-temps temporary_arrays.f90 
$ ./a.out
$ gfortran -O1 -fcheck=array-temps temporary_arrays.f90 
$ ./a.out
$ gfortran -fcheck=array-temps temporary_arrays.f90 
$ ./a.out
$

```

---

<div class="post-metadata">

**Author:** ![yarchik](https://avatars.discourse-cdn.com/v4/letter/y/e8c25b/32.png) [@yarchik](https://fortran-lang.discourse.group/u/yarchik)\
**Post date:** [February 10, 2024, 2:35pm UTC](https://fortran-lang.discourse.group/t/creating-temporary-array-when-declared-in-a-module/7379/3 "2024-02-10T14:35:18Z")

</div>

I have the main program and modules in all different files, maybe that is the reason?

 ![Screenshot 2024-02-10 at 15.42.51](https://global.discourse-cdn.com/free1/uploads/fortran_lang/original/2X/4/42059116988906786a7b4603218f03a0b7779c8b.png)

Also, I noticed that changing optimisation level to `O1` or `O2` does not change anything. However, replacing `-Warray-temporaries` with `-fcheck=array-temps` does make a difference, which is not surprising because `fcheck` is the run-time check.

---

<div class="post-metadata">

**Author:** ![aradi](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/aradi/32/3659_2.png) [@aradi](https://fortran-lang.discourse.group/u/aradi)\
**Post date:** [February 10, 2024, 3:29pm UTC](https://fortran-lang.discourse.group/t/creating-temporary-array-when-declared-in-a-module/7379/4 "2024-02-10T15:29:26Z")

</div>

The difference might be that the `program` unit can not be accessed from elsewhere, so the compiler can be 100% sure, that `bm` is unallocated, when you call `bm = create_matrix(n)`. In the case of `am`, that’s not the warranted (e.g. the routine `create_matrix()` could in theory (as a nasty side effect) import the module `MVars` and allocate `am`).

But apparently, the warning does not necessary mean, that an actual temporary copy is made at run-time…

---

<div class="post-metadata">

**Author:** ![yarchik](https://avatars.discourse-cdn.com/v4/letter/y/e8c25b/32.png) [@yarchik](https://fortran-lang.discourse.group/u/yarchik)\
**Post date:** [February 10, 2024, 4:24pm UTC](https://fortran-lang.discourse.group/t/creating-temporary-array-when-declared-in-a-module/7379/5 "2024-02-10T16:24:05Z")

</div>

I think you are right, giving the dummy argument `n` attribute `intent(in)` makes the function effectively _pure_ and the warning goes away.

---

<div class="post-metadata">

**Author:** ![yarchik](https://avatars.discourse-cdn.com/v4/letter/y/e8c25b/32.png) [@yarchik](https://fortran-lang.discourse.group/u/yarchik)\
**Post date:** [February 10, 2024, 4:27pm UTC](https://fortran-lang.discourse.group/t/creating-temporary-array-when-declared-in-a-module/7379/6 "2024-02-10T16:27:09Z")

</div>

But what is the most strange, the following does not generate any warnings

```auto
  function create_matrix(n) result(A)
    use Mvars, only: am
    implicit none
    integer, parameter :: dp = kind(1.d0)
    integer, intent(in):: n
    real(dp) :: a(n, n)
    A = 0.0D0
  end function create_matrix

```

I think it is just a bug in `gfortran`.

---

<div class="post-metadata">

**Author:** ![PierU](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/pieru/32/1848_2.png) [@PierU](https://fortran-lang.discourse.group/u/PierU)\
**Post date:** [February 10, 2024, 10:00pm UTC](https://fortran-lang.discourse.group/t/creating-temporary-array-when-declared-in-a-module/7379/7 "2024-02-10T22:00:58Z")

</div>

> [@yarchik](#):
>
> But what is the most strange, the following does not generate any warnings

Which kind of warning would you expect here? `intent(in)` has been added to the declaration of `n`, which effectively suppresses the array temporary warning. Why the use of `Mvars` should change that ?

---

<div class="post-metadata">

**Author:** ![yarchik](https://avatars.discourse-cdn.com/v4/letter/y/e8c25b/32.png) [@yarchik](https://fortran-lang.discourse.group/u/yarchik)\
**Post date:** [February 10, 2024, 10:33pm UTC](https://fortran-lang.discourse.group/t/creating-temporary-array-when-declared-in-a-module/7379/8 "2024-02-10T22:33:20Z")

</div>

This was in response to @aradi comment, that create\_matrix might import variables from `Mvars` and that it necessitates the creation of the temporary copy.

I think that I learned two things from this thread:

1. `-Warray-temporaries` warnings should be verified with `-fcheck=array-temps`. Once I know that, I can live with it
2. `intent(in)` is more important than I thought.

---

<div class="post-metadata">

**Author:** ![PierU](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/pieru/32/1848_2.png) [@PierU](https://fortran-lang.discourse.group/u/PierU)\
**Post date:** [February 11, 2024, 9:53am UTC](https://fortran-lang.discourse.group/t/creating-temporary-array-when-declared-in-a-module/7379/9 "2024-02-11T09:53:53Z")

</div>

Still, there’s a problem with gfortran I think. Once the routine is declared as pure, gfortran does no longer create a temporary array… but it should. Here is a simplified version of your code:

```auto
module Mvars
  implicit none
  integer, allocatable :: am(:, :)
contains
  pure function create_matrix(n) result(a)
    integer, intent(in) :: n
    integer :: a(n, n)
    a = transpose(am)
  end function create_matrix
end module Mvars

program temporary_arrays
  use Mvars
  implicit none
  integer :: i, n=3

  allocate(am(n,n))
  am(1,:) = [11,12,13]
  am(2,:) = [21,22,23]
  am(3,:) = [31,32,33]

  am = create_matrix(n)

  do i = 1, n
    print*, am(i,:)
  end do

end program temporary_arrays

```

It’s a poor design, but valid (standard conforming) I think.

gfortran gets it wrong, because it doesn’t see this is actually an in-place transpose:

```txt
Program returned: 0
Program stdout

          11 12 13
          12 22 23
          13 23 33

```

> **[Compiler Explorer - Fortran](https://godbolt.org/z/v383Mfq38)**
>
> module Mvars
> implicit none
> integer, allocatable :: am(:, :)
> contains
> pure function create\_matrix(n) result(a)
> integer, intent(in) :: n
> integer :: a(n, n)
> a = transpose(am)
> end function create\_matrix
> end module Mvars
> 
> program...

---

<div class="post-metadata">

**Author:** ![yarchik](https://avatars.discourse-cdn.com/v4/letter/y/e8c25b/32.png) [@yarchik](https://fortran-lang.discourse.group/u/yarchik)\
**Post date:** [February 11, 2024, 12:41pm UTC](https://fortran-lang.discourse.group/t/creating-temporary-array-when-declared-in-a-module/7379/10 "2024-02-11T12:41:06Z")

</div>

Good catch! My test shows the same behaviour without the `pure` attribute. Do you know if `ifort` also does not issue any warnings?

By the way, your code can be rectified by removing the `intent(in)` attribute of `n`. `gfortran` issues a warning, returns the correct result, however, does not issue a run-time error according to `-fcheck=array-temps`.

However, despite this all, this still is a standard conforming code, and this is still not a bug but a usability issue. 🙂

---

<div class="post-metadata">

**Author:** ![PierU](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/pieru/32/1848_2.png) [@PierU](https://fortran-lang.discourse.group/u/PierU)\
**Post date:** [February 11, 2024, 12:54pm UTC](https://fortran-lang.discourse.group/t/creating-temporary-array-when-declared-in-a-module/7379/11 "2024-02-11T12:54:22Z")

</div>

> [@yarchik](#):
>
> this is still not a bug but a usability issue. 🙂

It’s very likely a bug. The standard requires the RHS (here `create_matrix(n)`) to be fully evaluated before being assigned to the LHS (`am`). So the end result should definitly be the transpose of the initial `am`. gfortran here has wrongly optimized out the temporary array that is normally required for the full evaluation before assignment. This illustrates how difficult can be the optimization for compilers.

---

<div class="post-metadata">

**Author:** ![yarchik](https://avatars.discourse-cdn.com/v4/letter/y/e8c25b/32.png) [@yarchik](https://fortran-lang.discourse.group/u/yarchik)\
**Post date:** [February 11, 2024, 1:05pm UTC](https://fortran-lang.discourse.group/t/creating-temporary-array-when-declared-in-a-module/7379/12 "2024-02-11T13:05:42Z")

</div>

I do not know, at least in the “Modern Fortran explained” book I read

> the expression is interpreted as being fully evaluated before the assignment commences

and not

> the expression must be fully evaluated before the assignment commences

Either way, it would be very good if the issue can be corrected in future releases.

---

<div class="post-metadata">

**Author:** ![PierU](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/pieru/32/1848_2.png) [@PierU](https://fortran-lang.discourse.group/u/PierU)\
**Post date:** [February 11, 2024, 1:15pm UTC](https://fortran-lang.discourse.group/t/creating-temporary-array-when-declared-in-a-module/7379/13 "2024-02-11T13:15:53Z")

</div>

Yes, the standard expresses this as an “as if”. Compilers are free to do whatever they want, as long as it doesn’t change the results.
