I was wondering whether it is possible to show a variable's value declared in a submodule during a debugging session in MSVS (2019), say in a watch window? My attempts have failed so far.
I know that module variables are accessible as "module1::variable_name". However, "submodule1::variable_name" does not work, nor does "module1::submodule1::variable_name" (when module1 is the module containing submodule1). Any ideas?
Hi Andreas, in VS2017 (15.9.25) with PSXE 2020 update 1 integration the watch window as well as hover over works fine for submodule variables without having to define the variable with its module/submodule name in front. Maybe its an regression?
How is the submodule defined? I use the verbose definition with repeating the interface in the submodule (module function/subroutine instead of module procedure). I don't know if it makes a difference for debugging.
However, it sounds like an issue of VS 2019 integration. You should file it.
This is the code with which I tested the debugging functionality in VS 2017. Maybe your code does something more complex (OO, derived types...). However it should work in VS 2019.
submodule (mod_test) smod_test contains ! this version is without repeating the interface module procedure foo implicit none d = real(i*j*k,rk) return end procedure foo ! this version repeats the interface module subroutine bar1(i, j, k, d) use ISO_FORTRAN_ENV, only : ik => int32 use ISO_FORTRAN_ENV, only : rk => real64 implicit none integer(ik), intent(in ) :: i, j, k real(rk) , intent(out) :: d d = real(i*j*k,rk) return end subroutine bar1 module procedure bar2 d = real(i*j,rk) return end procedure bar2 end submodule module mod_test use ISO_FORTRAN_ENV, only : ik => int32 use ISO_FORTRAN_ENV, only : rk => real64 implicit none private public :: foo, bar interface bar module procedure :: bar1 module procedure :: bar2 end interface bar interface module subroutine foo(i, j, k, d) implicit none integer(ik), intent(in ) :: i, j, k real(rk) , intent(out) :: d end subroutine foo module subroutine bar1(i, j, k, d) use mod_parameter implicit none integer(ik), intent(in ) :: i, j, k real(rk) , intent(out) :: d end subroutine bar1 module subroutine bar2(i, j, d) use mod_parameter implicit none integer(ik), intent(in ) :: i, j real(rk) , intent(out) :: d end subroutine bar2 end interface end module mod_test program submodule_test2 use ISO_FORTRAN_ENV, only : ik => int32 use ISO_FORTRAN_ENV, only : rk => real64 use mod_test implicit none integer(ik) :: i, j, k real (rk) :: d ! ---------------------------------------------- i = 2 j = 5 k = 3 call foo(i,j,k,d) write(*,'(1ES18.4)') d call bar(i,j,k,d) write(*,'(1ES18.4)') d call bar(i,j,d) write(*,'(1ES18.4)') d end program submodule_test2
Thanks for your reply and for providing a test program. I was able to run your program (using VS2019, Intel Fortran Compiler 188.8.131.52) and the variables show in the debug watch windows as intended.
Summary: in my case, the issue is related to the use of !$OMP threadprivate(....) variables within the submodule.
One difference in my code where the issue appears is that I declared variables within the submodule declaration part, such as integer(ik),dimension(:),allocatable :: iarray, in the attached code. Debugging of this variables still works as intended within the submodule's scope.
However, after comparing to my application, I realized that the issue arises due to the use of OpenMP threadprivate directives within the submodule declaration part. If the code is not using that or not compiled with the /Qopenmp switch, the debugging / watch variables are shown as expected in VS.
Below is a short example program (adapted from Johannes' example) that demostrates the issue I experience in VS2019 (see also attached screenshot). In the screenshot, Watch1 window, the iarray values are inaccessible and a strange value range is displayed, while the actual array values are as intended. So this is likely only a debugger issue but not a Fortran problem.
OpenMP threadprivate variables from the parent module are shown correctly. Therefore, my question is whether this is a bug in the VS debugger when !$OMP directives are used in submodules or whether submodule variables should not be declared threadprivate?
- the command line used in the VS solution was:
/nologo /debug:full /Od /Qopenmp /debug-parameters:all /warn:interfaces /module:"x64\Debug\\" /object:"x64\Debug\\" /Fd"x64\Debug\vc160.pdb" /traceback /check:bounds /libs:dll /threads /dbglibs /c
Hi Andi, I think it is a bug in Intel's debugger integration in case of compiling with /Qopenmp.
I also can only see variables in normal modules (break point in a parallel region), if I prefix the module name as you described in the opener. This is true for the main thread only, in the worker threads I do not see any variables. In serial regions it works without module name prefix. This, too, can be improved by Intel.
Further OpenMP does not allow to use all Fortran (2018?) features. Steve Lionel wrote something about that in an older thread. I can't remember whether submodules are officially supported in PSXE 2020 with OpenMP. The OpenMP documentation, let's say, could be improved regarding the allowed combinations (https://www.openmp.org/wp-content/uploads/OpenMP-API-Specification-5.0.pdf page 33, line 21):
While future versions of the OpenMP specification are expected to address the following features, currently their use may result in unspecified behavior.
>>the issue is related to the use of !$OMP threadprivate(....) variables within the submodule.
For debugging, you could conditionally compile in a local pointer to the watch variable.
(This may require a (conditional) TARGET on the pointee)