Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Compiler difference between gfortran and ifort (allocatable arrays and global variables)

The Code

The following MWE describes what I want to use (note that I did not design this, I am merely trying to use someones code, I would not usually use global variables).

PROGRAM MAIN
IMPLICIT NONE

  integer :: N
  real(8), allocatable :: a(:,:)

  N=3
  allocate(a(N,3))

  a=initialize_array()

  CONTAINS
    function initialize_array() result(a)
    IMPLICIT NONE
        real(8) :: a(N,3)
        a=1
    end function initialize_array  

END PROGRAM MAIN

The Problem

gfortran gives an error which reads Error: Variable 'n' cannot appear in the expression at (1), pointing to to the real(8) :: a(N,3) inside the function. In a subroutine it would work, so what might be the problem here?

The question

Why does ifort (v. 15.0.3) compile this, while gfortran (v. 4.8.4) does not?

like image 884
GPMueller Avatar asked Oct 08 '15 15:10

GPMueller


2 Answers

As has been commented by others, it is hard to say whether something is clearly allowed: the language is mostly based on rules and constraints giving restrictions.

So, I won't prove that the code is not erroneous (and that gfortran is not allowed to reject it), but let's look at what's going on.

First, I'll object to one thing given by High Performance Mark as this is slightly relevant:

The declaration of an array with a dimension dependent on the value of a variable, such as a(N,3), requires that the value of the variable be known (or at least knowable) at compile time.

The bounds of an explicit shape array need not always be given by constant expressions (what we loosely define as "known/knowable at compile time"): in some circumstances an explicit shape array can have bounds given by variables. These are known as automatic objects (and the bounds given by specification expressions).

A function result is one such place where an automatic object is allowed. In the question's example for the declaration of the function result, N is host associated and forms a specification expression.

Rather than exhausting all other constraints to see that the declaration of a truly is allowed, let's look at how gfortran responds to small modifications of the program.

First, a trimmed down version of the question's code to which gfortran objects.

  integer n
contains
  function f() result(g)
     real g(n)
  end function f
end program

The function result for f has the name g. It doesn't matter what we call the function result, so what happens when we call it f?

  integer n
contains
  function f()
     real f(n)
  end function f
end program

This compiles happily for me.

What if we frame this first lump in a module instead of a main program?

module mod
  integer n
contains
  function f() result(g)
     real g(n)
  end function f
end module

That also compiles.

The natural conclusion: even if gfortran is correct (we've missed some well-hidden constraint) to reject the first code it's either horribly inconsistent in not rejecting the others, or the constraint is really quite strange.

like image 78
francescalus Avatar answered Sep 30 '22 09:09

francescalus


I think this might be an explanation, though like @VladimirF I can't actually either recall or find the relevant section (if there is one) of the standard.

This line

real(8) :: a(N,3)

declares that the result of the function is an array called a. This masks the possibility of the same name referring to the array a by host association. The a inside the function scope is not the a in the program scope.

The declaration of an array with a dimension dependent on the value of a variable, such as a(N,3), requires that the value of the variable be known (or at least knowable) at compile time. In this case giving n in the host scope the attribute parameter fixes the problem. Though it doesn't fix the poor design -- but OP's hands seem tied on that point.

It doesn't surprise me that the Intel compiler compiles this, it compiles all sorts of oddities that its ancestors have compiled over the years for the sake of backwards compatibility.

I only offer this half-baked explanation because experience has taught me that as soon as I do one of the real Fortran experts (IanH, francescalus, (usually) VladimirF) will get so outraged as to post a correction and we'll all learn something.

like image 26
High Performance Mark Avatar answered Sep 30 '22 08:09

High Performance Mark