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.
Related
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.
I am having trouble correctly accessing a variable in a Fortran DLL from a Fortran EXE when the variable is part of a COMMON block.
I have a trivial code simple.f90 which I compile into a DLL using MSYS64/MinGW-w64 gfortran 9.2 as
x86_64-w64-mingw32-gfortran simple.f90 -o simple.dll -shared
! simple.f90
module m
implicit none
integer :: a, b
!common /numbers/ a, b
end module
subroutine init_vals
use m
implicit none
a = 1
b = 2
end subroutine
This library is used from a even simpler program prog.f90, compiled as
x86_64-w64-mingw32-gfortran prog.f90 -o prog -L. -lsimple
! prog.90
program p
use m
implicit none
print *, 'Before', a, b
call init_vals
print *, 'After', a, b
end program
When the COMMON block /numbers/ is commented out, the code works and prints the expected result:
Before 0 0
After 1 2
However, when I uncomment the COMMON block, the output becomes
Before 0 0
After 0 0
as if the variables used by the program were suddenly distinct from those used in the library.
Both variants work equally well in a Linux-based OS with gfortran 9.1.
I am aware that "On some systems, procedures and global variables (module variables and COMMON blocks) need special handling to be accessible when they are in a shared library," as mentioned here: https://gcc.gnu.org/onlinedocs/gcc-4.9.0/gfortran/GNU-Fortran-Compiler-Directives.html . However, I was not able to insert a statement of the type
!GCC$ ATTRIBUTES DLLIMPORT :: numbers
or
!GCC$ ATTRIBUTES DLLEXPORT :: numbers
anywhere in the code without being snapped at by the compiler.
As pointed out by M. Chinoune in the comment, current gfortran lacks the ability to import common blocks from DLLs. Even though there has been a patch for some time, it is not yet merged. In the end, I needed two things to make the above code work:
First, apply the following patch to GCC 9.2 and compile the compiler manually in MSYS2:
--- gcc/fortran/trans-common.c.org 2019-03-11 14:58:44.000000000 +0100
+++ gcc/fortran/trans-common.c 2019-09-26 08:31:16.243405900 +0200
## -102,6 +102,7 ##
#include "trans.h"
#include "stringpool.h"
#include "fold-const.h"
+#include "attribs.h"
#include "stor-layout.h"
#include "varasm.h"
#include "trans-types.h"
## -423,6 +424,9 ##
/* If there is no backend_decl for the common block, build it. */
if (decl == NULL_TREE)
{
+ unsigned id;
+ tree attribute, attributes;
+
if (com->is_bind_c == 1 && com->binding_label)
decl = build_decl (input_location, VAR_DECL, identifier, union_type);
else
## -454,6 +458,23 ##
gfc_set_decl_location (decl, &com->where);
+ /* Add extension attributes to COMMON block declaration. */
+ if (com->head)
+ {
+ attributes = NULL_TREE;
+ for (id = 0; id < EXT_ATTR_NUM; id++)
+ {
+ if (com->head->attr.ext_attr & (1 << id))
+ {
+ attribute = build_tree_list (
+ get_identifier (ext_attr_list[id].middle_end_name),
+ NULL_TREE);
+ attributes = chainon (attributes, attribute);
+ }
+ }
+ decl_attributes (&decl, attributes, 0);
+ }
+
if (com->threadprivate)
set_decl_tls_model (decl, decl_default_tls_model (decl));
Second, only the line
!GCC$ ATTRIBUTES DLLIMPORT :: a, b
was needed in the main program (right after implicit none), but not any exports anywhere. This is apparently a different syntactical approach then in Intel Fortran, where one imports the COMMON block rather than its constituents. I also found out that I needed to import both a and b even if I only needed b. (When only a was needed, importing a only was enough.)
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.
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.