I don't know whether I'm hitting a compiler bug or missing something. I'm attempting to run the following code:
program test
implicit none
integer, parameter :: dp=kind(1.d0)
integer, allocatable :: int_mat(:,:)
integer, allocatable :: int_mat_2(:,:)
real(dp), allocatable :: real_mat(:,:)
allocate(int_mat(2,2))
int_mat = 0
int_mat_2 = int_mat
real_mat = int_mat ! Falls over here.
end program
Compiling and running with nagfor (flags: -f2003 -C=all) works as expected. Compiling and running with gfortran (flags: -std=f2003 -fcheck=all) fails at runtime with the error message:
At line 13 of file test.f90
Fortran runtime error: Array bound mismatch for dimension 1 of array 'real_mat' (1/2)
I would expect the code to succeed, as int_mat_2 and real_mat should be allocated implicitly. This seems to be happening correctly for int_mat_2 but not for real_mat.
I have tried this with various gfortran versions (5.4, 6.3, 7.0), and all have the same problem.
As found by francescalus, this was this compiler bug, which has since been fixed for more recent gfortran versions.
Related
I am a little puzzled with the PGI Fortran compiler.
When I try to compiler the following simple module stored in the file named test.f90, with pgfortran 19.10 I get errors that I do not understand. While compiling with gfortran or ifort run well.
The file test.f90:
MODULE CT
IMPLICIT NONE
integer, parameter :: si = SELECTED_INT_KIND(4)
integer(kind=si), public, parameter :: strlen = 256
type, public :: CMT
integer (kind=si) :: nbTot
character(len=strlen), dimension(:), allocatable :: condi
CONTAINS
procedure :: find_line_condi
endtype CMT
CONTAINS
PURE function find_line_condi( table, cara ) result(k)
IMPLICIT NONE
class(CMT), intent(in) :: table
character(len=*), intent(in) :: cara
integer (kind=si) :: k
integer (kind=si) :: j
k=-1
do j=1,table%nbTot
if (trim(table%condi(j)) .eq. cara) then
k=j
RETURN
else if ( j == table%nbTot ) then
k=-1
RETURN
endif
enddo
end function find_line_condi
END MODULE CT
The compilation with pgfortran -c test.f90 returns me the following error message:
/opt/pgi/linux86-64-llvm/19.10/share/llvm/bin/llc: error: /opt/pgi/linux86-64-llvm/19.10/share/llvm/bin/llc: /tmp/pgfortranr2qeZBujkwvA.ll:23:77: error: invalid forward reference to function 'ct_find_line_condi_' with wrong type: expected 'i32 (i64*, i64*, i64*, i64)*' but was 'i16 (i64*, i64*, i64*, i64)*'
#ct$cmt$td$vft = global [1 x i8*] [i8* bitcast(i16 (i64*, i64*, i64*, i64)* #ct_find_line_condi_ to i8*)]
Does anyone has some ideas where this problem comes from?
This is a bug in the compiler. Consider the module
MODULE CT
IMPLICIT NONE
type CMT
CONTAINS
procedure, nopass :: find_line_condi
endtype CMT
CONTAINS
function find_line_condi()
integer(SELECTED_INT_KIND(4)) find_line_condi
find_line_condi=0
end function find_line_condi
END MODULE CT
which is quite a bit simpler than that of that question. Compiled with pgfortran 19.10 there is a similar gibberish output. It's left as an exercise to the reader/PGI support desk whether this simpler code is valid Fortran which should be accepted but I would consider the poor diagnostic to be something PGI would prefer to avoid.
However, this appears to be a weakness in the LLVM frontend of PGI: consider compiling with pgfortran -c -Mnollvm .... There are also ways to rewrite the code to attempt to work around this bug, such as changing the kind of the function result.
More widely, PGI introduced in the 2019 releases the LLVM code generator. This seems to be going through a number of teething difficulties. If you have code unexpectedly failing with PGI 2019 (which may have worked with 2018), then compiling with -Mnollvm to use the non-LLVM generator is worth a try.
I want to use the fortran coarray feature to have different size arrays on different images.
Following the 2008/2018 standard, this should be possible by using a derived type containing an allocatable. I am using gfortran 8.2.0 with opencoarrays 2.3.1.1 MPI library on macOS Mojave.
program Main
implicit none
type :: Array_Type
double precision, dimension(:), allocatable :: values
end type
type(Array_Type), codimension[*] :: array
if(this_image() == 1) then
allocate(array%values(2))
array%values = this_image()
else
allocate(array%values(1))
endif
sync all
print *, this_image(), array[1]%values(:)
sync all
end program
The program is compiled by
gfortran -Wall -fcoarray=lib Main.f90 -lcaf_mpi
An even simpler example leads to the same segmentation fault when the allocated array is accessed by other images.
program Main
implicit none
type :: Array_Type
double precision, dimension(:), allocatable :: values
end type
type(Array_Type), codimension[*] :: array
allocate(array%values(2))
sync all
print *, this_image(), array[1]%values(:)
sync all
end program
Solution
The code works correctly with the specified system as long as MPICH instead of the default OpenMpi is used with OpenCoarrays.
Additionally, the OpenCoarrays compiler wrapper should be used: caf Main.f90
I opened an issue at the OpenCoarrays GitHub site: https://github.com/sourceryinstitute/OpenCoarrays/issues/625
I'm using ieee_arithmetic with Fortran on a Linux machine that runs gfortran version 5.4.0.
I'm getting an error of division by zero when trying to initialize values for Inf and NaN.
There doesn't seem to be an issue with ieee_arithmetic because elsewhere in the file I can successfully call ieee_is_finite() with no issues.
I thought that ieee_arithmetic allowed division by zero to be used for these specific cases, but I must be missing something. Below is a sample of code:
module rcrlib_gnu
use, intrinsic :: ieee_arithmetic ! requires gfortran version 5.0 or higher
implicit none
integer, parameter :: SP=kind(1.0), DP=selected_real_kind(9,99)
integer, parameter :: stderr=0
public SP, DP, is_finite, stderr, initialize
contains
subroutine initialize(infty,nan)
real(kind=DP), intent(out) :: infty, nan
infty = 1.0_dp/0.0_dp ! huge(1.0_dp)
nan = 0.0_dp/0.0_dp
end subroutine initialize
elemental function is_finite(x)
real(kind=DP), intent(in) :: x
logical :: is_finite
is_finite = ieee_is_finite(x) ! This call requires "ieee_arithmetic"
end function is_finite
end module rcrlib_gnu
It seems I'm missing something basic, so I would appreciate any help.
To reproduce the error, save the above code snippet as rcrlib_gnu_example.f90 and then execute the following line:
gfortran -o rcr rcrlib_gnu_example.f90
The resulting error output is
rcrlib_gnu_example.f90:12:18:
infty = 1.0_dp/0.0_dp ! huge(1.0_dp)
1
Error: Division by zero at (1)
rcrlib_gnu_example.f90:13:16:
nan = 0.0_dp/0.0_dp
1
Error: Division by zero at (1)
Thanks to Pascal Cuoq, I solved the problem.
The version of the initialize subroutine that compiles is below:
subroutine initialize(infty,nan)
real(kind=DP), intent(out) :: infty, nan
infty = huge(1.0_dp)+100
nan = infty-infty
end subroutine initialize
So basically set infinity to be the largest floating point number plus 100, then set NaN to be the difference between infinity and itself.
Thanks, all, for your quick responses and patience with my lack of FORTRAN experience.
When I try to compile my code using gfortran 4.4.7 I get the following error message:
Error: Type mismatch in argument 'intkind8' at (1); passed INTEGER(4)
to INTEGER(8).
With ifort it does compile, unless I demand the F2003 standard, in which case a similar error is given.
My code:
program kindDummy
implicit none
call takeIntKind4And8(0,0)
contains
subroutine takeIntKind4And8(intKind4, intKind8)
implicit none
integer(kind=4), intent(in) :: intKind4
integer(kind=8), intent(in) :: intKind8
print *, 'Integer(kind4): ', intKind4
print *, 'Integer(kind8): ', intKind8
end subroutine takeIntKind4And8
end program kindDummy
I was wondering if there's an elegant way to make the compiler "turn" the first 0 into a kind=4 integer, and the second one into a kind=8?
In
call takeIntKind4And8(0,0)
both zeros have the default kind. The kind numbers are not portable, but your default one is probably 4.
To produce 0 of kind 8 use 0_8:
call takeIntKind4And8(0_4,0_8)
I recommend to stay away from using 4 and 8 directly and use integer constants like 0_ip where ip is an integer constant with the right value. See Fortran: integer*4 vs integer(4) vs integer(kind=4) for more.
This question is connected to my previous question: How to force compiler to interpret omitted intent as intent(inout) . It appears impossible to interpret omitted intent as intent(inout), so problem of violation of intent(in) is still exists.
The same example:
module test
implicit none
contains
subroutine fun1(x)
real(8), intent(in)::x
call fun2(x)
end subroutine
subroutine fun2(x)
real(8) :: x
x = 10
end subroutine
end module
This code can be compiled without any errors/warnings by gfortran and ifort. So my questions is:
How to force fortran compiler to generate an error when intent(in) variable is passed to subroutine with omitted intent ( but with declared interface)?
As IanH said you need a processor (i.e. compiler) that can pick this up for you. For instance the NAG compiler does (disclaimer - I work for NAG) if you give it the right flags. I modified your code a very little to make it portable and added a driver to show this:
$ cat t.f90
module test
implicit none
Integer, Parameter :: wp = Selected_real_kind( 12, 70 )
contains
subroutine fun1(x)
real(wp), intent(in)::x
call fun2(x)
end subroutine
subroutine fun2(x)
real(wp) :: x
x = 10
end subroutine
end module
Program test_test
Use test
Implicit None
Real( wp ) :: x
x = 5.0_wp
Call fun1( x )
End Program test_test
$ nagfor t.f90
NAG Fortran Compiler Release 5.3.1 pre-release(904)
[NAG Fortran Compiler normal termination]
$ ./a.out
$ nagfor -C=all -C=undefined t.f90
NAG Fortran Compiler Release 5.3.1 pre-release(904)
[NAG Fortran Compiler normal termination]
$ ./a.out
Runtime Error: t.f90, line 15: Dummy argument X is associated with an expression - cannot assign
Program terminated by fatal error
Aborted (core dumped)
$
So search the flags, there may be something to help - if not complain to whoever supplies the compiler!