I am trying to implement a simple finalizer, but I can't get even this example to compile:
MODULE m
TYPE :: t1
REAL a,b
END TYPE
TYPE, EXTENDS(t1) :: t2
REAL,POINTER :: c(:),d(:)
CONTAINS
FINAL :: t2f
END TYPE
TYPE, EXTENDS(t2) :: t3
REAL,POINTER :: e
CONTAINS
FINAL :: t3f
END TYPE
CONTAINS
SUBROUTINE t2f(x) ! Finalizer for TYPE(t2)'s extra components
TYPE(t2) :: x
print *, 'entering t2f'
IF (ASSOCIATED(x%c)) then
print *, ' c allocated, cleaning up'
DEALLOCATE(x%c)
end if
IF (ASSOCIATED(x%d)) then
print *, ' d allocated, cleaning up'
DEALLOCATE(x%d)
end if
END SUBROUTINE
SUBROUTINE t3f(y) ! Finalizer for TYPE(t3)'s extra components
TYPE(t3) :: y
print *, 'entering t3f'
IF (ASSOCIATED(y%e)) then
print *, ' e allocated, cleanup up'
DEALLOCATE(y%e)
end if
END SUBROUTINE
END MODULE
using GNU Fortran (GCC) 4.8.2 20131212 (Red Hat 4.8.2-7) gives me this error output:
$ gfortran -c
m_example.f03 m_example.f03:5.26:
TYPE, EXTENDS(t1) :: t2
1 Error: Finalization at (1) is not yet implemented m_example.f03:10.26:
TYPE, EXTENDS(t2) :: t3
1 Error: Finalization at (1) is not yet implemented
Is this a bug, does it mean that finalizers are not yet implemented in gfortran, or am I doing something wrong?
Since gcc 4.9, finalizers are recognized. Furthermore, if you do not implement them yourself, the compiler appears to generate finalization code itself.
Which unfortunately leads to bug 59765. Still available in gcc gfortran 4.10, as I was unfortunate to discover.
Related
I have a derived type in Fortran and I need to read values from a text file into that type. My problem is that my code is working fine with the Intel Fortran compiler as well as the NAG Fortran compiler, but GFortran exits with an error. The minimal working example is below.
Module my_mod
Type T
Real :: a
End Type T
Interface Read (Formatted)
Module Procedure read_T
End Interface
Contains
Subroutine read_T(var, unit, iotype, v_list, iostat, iomsg)
Class (T), Intent (Inout) :: var
Integer, Intent (In) :: unit
Character (*), Intent (In) :: iotype
Integer, Intent (In) :: v_list(:)
Integer, Intent (Out) :: iostat
Character (*), Intent (Inout) :: iomsg
Read (unit, *, iostat=iostat, iomsg=iomsg) var%a
End Subroutine
End Module my_mod
Program main
Use my_mod
Implicit None
Type(T) :: x
Type(T) :: y
Open(unit=20, file='data.txt', action='read')
Read(20, *) x ! Here GFortran fails because it somehow reaches EOF
Write(*, *) x
Read(20, *) y
Write(*, *) y
End Program main
with the data.txt file:
1.0
2.0
With GFortran I get the error
At line 30 of file test.f90 (unit = 20, file = 'data.txt')
Fortran runtime error: End of file
Error termination. Backtrace:
#0 0x7f27a76fef2f in finalize_transfer
at ../.././libgfortran/io/transfer.c:4175
#1 0x400aca in ???
#2 0x400b86 in ???
#3 0x7f27a69a8504 in ???
#4 0x4007e8 in ???
#5 0xffffffffffffffff in ???
One thing that works is to replace the Read statements as follows
Read(20, fmt='(DT)', advance='no') x ! Works with all compilers :)
Write(*, *) x
Read(20, fmt='(DT)', advance='no') y ! Works with all compilers :)
Write(*, *) y
So my question .. is it possible to get the same behaviour in GFortran without fmt='(DT)', advance='no'?
And who has the correct behavior? GFortran or Intel Fortran and NAG Fortran?
Thanks for any help,
Simon
I am trying to compile some really old code (1986 and before). This code references an external function. Today's compilers ask for far more code to make this work. And I keep failing.
I now created a small hello world program, which demonstrates the problem.
hello.for
PROGRAM hello
USE func
PRINT *, "Hello World!"
PRINT *, f ()
END PROGRAM hello
func.for
MODULE func
PUBLIC f
CONTAINS
FUNCTION f ()
f='Hello Func'
END FUNCTION
END MODULE
This has not only one, but two problems:
How do I define the return type? Docs tell <type> FUNCTION <function> or FUNCTION <function> () <type>::<something> , but neither works.
How do I make the linker find the function?
gfortran -c func.for works (if I use the default return type real) and creates a mod file but linking does not work
$ gfortran hello.for
/tmp/ccHNzcXA.o: In function `MAIN__':
hello.for:(.text+0xa4): undefined reference to `__func_MOD_f'
collect2: error: ld returned 1 exit status
__func_MOD_f is not contained in the mod file, but in the o file there is func.for__func_MOD_f.
Any idea?
thanks
You have two issues, the delcaration of f and properly linking the module.
First, compiling the module yields the error:
% gfortran -c func.f
func.f:5:8:
f='Hello Func'
1
Error: Can't convert CHARACTER(1) to REAL(4) at (1)
This error is due to implicit typing of f and an incompatible assignment. Fixing this is simple, declare f explicitly as a character instead of an implicit type. Add:
character(len=30) :: f
to the function and now your module compiles. Here is the modified module:
MODULE func
PUBLIC f
CONTAINS
FUNCTION f ()
character(len=30) :: f
f='Hello Func'
END FUNCTION
END MODULE
Your second problem is linking. Your command:
gfortran hello.for
fails because you did not specify the module object. If you already compiled the module you would specify:
gfortran hello.for func.o
if you were compiling them both at the same time you would do:
gfortran -o hworld func.for hello.for
if you are compiling everything individually:
gfortran -c func.for
gfortran -c hello.for
gfortran -o hworld hello.o func.o
Any of these will compile and run:
% ./hworld
Hello World!
Hello Func
If you are modernizing your code, it would also be worth adding implicit none to avoid any implicit typing and declaring explicit variables for everything. e.g.:
module func
implicit none
contains
function f
implicit none
character(len=30) :: f
f='Hello Func'
end function f
end module func
and
program hello
use func
implicit none
print *, "Hello World!"
print *, f ()
end program hello
This question already has answers here:
Fortran functions returning unexpected types and values
(3 answers)
Closed 2 years ago.
I have the following short piece of code in Fortran, which I named myDLL.f90:
Real(Kind=8) Function mySinCos(x,y)
Real(Kind=8), Intent(In) :: x, y
mySinCos = Sin(x)*Cos(y)
End Function mySinCos
Real(Kind=8) Function myPiSinCos(x,y)
Real(Kind=8), Intent(In) :: x, y
Real(Kind=8), Parameter :: Pi = 4.0d0*Datan(1.0d0)
myPiSinCos = Sin(Pi*x)*Cos(Pi*y)
End Function myPiSinCos
And the following main program TestDLL.f90:
Program TestDLL
Real(Kind=8) :: x, y
Real(Kind=8) :: a, b
x = 2.0d-01
y = 9.0d-01
a = mySinCos(x,y) !Should be 0.12349483641187213
b = myPiSinCos(x,y) !Should be -0.5590169943749475
Write(*,*) a
Write(*,*) b
End Program TestDLL
I compiled and linked the above sources with:
gfortran -shared -fPIC -o myDLL.dll myDLL.f90
gfortran -o a.exe TestDLL.f90 -L. myDLL.dll
No compilation/linkedition errors and a.exe runs without error messages. What it produces is:
6.0000000000000000
6.0000000000000000
Which obviously aren't the expected results as sin(...)*cos(...) must never be > 0.5 (or < -0.5), let alone 6.0000[...].
In a nutshell: compiled well, linked well, executed well and produced garbage.
Changing either x or y doesn't change the results. They're always 6.0000[...].
What went wrong? The example above doesn't differ a lot from other simple examples I've found in the internet.
I'm using GNU Fortran (MinGW.org GCC Build-20200227-1) 9.2.0, Windows 10 64-bit.
It works fine if I turn the two functions into a module:
Module myDLL
Implicit None
Contains
... The two original functions are inserted here ...
End Module myDLL
and import/use the module in the main program:
Program TestDLL
Use myDLL
Implicit None
... Other commands are inserted here ...
End Program TestDLL
Then, and only then, the correct results are spit.
What is the remedy for this gcc Fortran compilation warning?
USE statement at (1) has no ONLY qualifier
The warning occurs when using submodules in gcc 6.0, 6.1, 6.2, and, 7.0.
The full compilation sequence and warning:
$ gfortran -c -Wuse-without-only -o mod_module.o mod_module.f08
$ gfortran -c -Wuse-without-only -o mod_module_sub.o mod_module_sub.f08
mod_module_sub.f08:1:19:
submodule ( mModule ) mSubModule
1
Warning: USE statement at (1) has no ONLY qualifier [-Wuse-without-only]
$ gfortran -c -Wuse-without-only -o demonstration.o demonstration.f08
$ gfortran -o demonstration demonstration.o mod_module.o mod_module_sub.o
$ ./demonstration
this + that = 3.00000000
expected value is 3
Main program (demonstration.f08):
program demonstration
use mModule, only : myType
implicit none
type ( myType ) :: example
example % this = 1.0
example % that = 2.0
call example % adder ( )
write ( *, * ) 'this + that = ', example % other
write ( *, * ) 'expected value is 3'
stop
end program demonstration
Module (mod_module.f08):
module mModule
implicit none
type :: myType
real :: this, that, other
contains
private
procedure, public :: adder => adder_sub
end type myType
private :: adder_sub
interface
module subroutine adder_sub ( me )
class ( myType ), target :: me
end subroutine adder_sub
end interface
end module mModule
Submodule (mod_module_sub.f08):
submodule ( mModule ) mSubModule ! <=== problematic statement
implicit none
contains
module subroutine adder_sub ( me )
class ( myType ), target :: me
me % other = me % this + me % that
end subroutine adder_sub
end submodule mSubModule
That is, what is the proper way to specify submodules? The flag -Wuse-without-only is essential in compilation of longer codes.
Depending on your perspective, it is just a compiler bug. File a bug report and wait for it to get fixed (or fix it yourself).
(An alternative perspective is that because that code gives submodules access to all the entities of their host, whether required or not, the warning is appropriate. But limiting host association requires F2015 support.)
-Wuse-without-only is just a warning to help enforce a particular programming style (one that I don't think is particularly useful). It cannot be "essential" to compile any code, short or long. If the warning bothers you in the meantime, remove that option.
Is there any means to accessing (reading, writing to) files that are opened in some other source code by just passing the unit number?
Yes, that is possible (for both reading and writing). Here is a short example:
module test_mod
contains
subroutine myWrite( uFile )
implicit none
integer, intent(in) :: uFile
write(uFile, *) 'Hello world'
end subroutine
end module
program test
use test_mod
implicit none
integer :: uFile, stat
open(newunit=uFile, file='test.txt', status='replace', &
action='write', iostat=stat)
if(stat.ne.0) return
call myWrite( uFile )
close (uFile)
end program
$ cat test.txt
Hello world
External file units are globally accessible. You need not even pass the unit number, though that is a better practice than using hardcoded units. This behavior defined in Fortran 2008 Cl. 9.5.1,
3 The external unit identified by a particular value of a scalar-int-expr is the same external unit in all program
units of the program.
where they provide this sample code in note 9.14:
In the example:
SUBROUTINE A
READ (6) X
...
SUBROUTINE B
N = 6
REWIND N
the value 6 used in both program units identifies the same external unit.