Why does PGI not pick up on public attribute in this module? - fortran

Working with someone else's code here. It compiles just fine with gfortran. Under Portland Group, though, I get an error:
pgf90 -DsysLinux -DcompPGF90 -I/home/cables/GITM/share/Library/src -c -r8 -fast ModUtilities.F90
PGF90-S-0084-Illegal use of symbol mpi_wtime - not public entity of module (ModUtilities.F90: 419)
0 inform, 0 warnings, 1 severes, 0 fatal for sleep
The offending line looks like:
use ModMpi, ONLY : MPI_wtime
(There's obviously a lot of MPI stuff going on here, but I don't think that's the point.) So I go to the source code for ModMpi, which is ModMpi.f90, where I see no reference to MPI_WTIME, but I see:
use ModMpiInterfaces
So finally, I go to the source for ModMpiInterface and I find the line:
public:: mpi_wtime
OK, I was able to get a compile from PGI by editing ModMpi.f90 and declaring mpi_wtime to be public. But still, I wonder: Why did gfortran assume (apparently) that mpi_wtime was public, but PGI had to be told this explicitly? Why does PGI not assume that the original public declaration holds throughout the "use chain"?
I presume that one behavior or the other is closer to the Fortran standard. Which would that be?

For exactly the same Fortran source code (as opposed to some sort of MPI library) compiler behaviour should be the same here.
Whether or not an entity is a public entity of a module is specific to each module that defines or accesses (via USE) that entity. Module A might declare "something" and specify that it is public, module B might USE module A and then specify that same "something" is then private. Any code using module A will be able to access "something", any code only using module B will not.
The default accessibility of things declared in a module is PUBLIC, but that default can be changed by a PRIVATE statement (one without any following identifiers). If such a private statement appeared, you would see the behaviour you describe with the PGI compiler.
Implicit typing (i.e. from source code without IMPLICIT NONE) can also confuse things here.

Related

Fortran derived-type parameter with allocatables

I have a derived-type with pointer (or allocatable) component
type Tmy
real, dimension(:), pointer :: vals
integer :: nVals
end type Tmy
And I want to create a parameter, e.g. to pass it to a subroutine as intent(in):
type (Tmy), parameter, public :: my_missing = Tmy(null(), 0)
Currently a similar code compiles fine to me by GNU Fortran (Spack GCC) 9.4.0, but introduction of the parameter triggers numerous strange errors in another module that uses the current one. The using module has variables of the type, but no reference to the parameter. The first error is triggered in a derived-type declaration with default initialization:
550 | logical, dimension(:,:), pointer :: ifValid => null()
| 1
Error: Cannot change attributes of USE-associated symbol null at (1)
and follows by numerous similar errors and complains about missing members in various structures. If I comment out the parameter declaration the code compiles and runs just fine.
So the questions are:
How introducing a parameter in one module can trigger compilation errors in another module, given that the name my_missing is unique within the project? Or is it just a bug in the compiler?
Is introducing such a parameter a valid practice in Fortran?
If it is valid, what is the effect of assigning this parameter to a structure that has vals already allocated (in case if vals is declared as allocatable)?
PS Yes, I know that allocating pointers is a bad idea. I try to turn them to allocatables bit by bit..
UPD: The issue is reproducible with two different versions of gfortran, but only at one specific computer. Also I did not manage to compile any observable MWE so far..
UPD2: Thank you all, who commented so far. It seems clear that there is no breaking of Fortran standards in my examples here. MWE is of little use since the issue is reproducible only at one computer. I'll then ask for help from our HPC staff and come back once something interesting found.
TL;DR
Bug in gfortran-9 (9.4.0 from Spack, 9.5.0-1ubuntu1~22.04). Other gfortran compilers available for Ubuntu 22.04 (10.4.0-4ubuntu1~22.04,11.3.0-1ubuntu1~22.04, and 12.1.0-2ubuntu1~22.04) work just fine.
Details
I have managed to reproduce the issue in Ubuntu 20.04, by changing to gcc-9. Here is the way to reproduce it:
Make sure that gcc-9 is called for gfortran
Checkout and compile https://github.com/fmidev/silam-model/ See README there for more details
Edit source/namelist.silam.mod.f90 with adding after the definition of Tsilam_namelist (around l. 257):
! Enabling these lines causes a mysterious error at GNU Fortran 9.4.0 and 9.5.0
type(Tsilam_namelist), parameter, private :: silam_namelist_missing = Tsilam_namelist( &
& null(), int_missing, int_missing, int_missing, &
& silja_false, "Missing_namelist" &
& )
make clean
make full
The problematic lines were added in our development branch quite some time ago. The only way to pinpoint the line that triggers the bug was a bisect on many revisions. Luckily, the revision that introduced the trigger was small.
The specific bug in gcc-9 responsible for the problem is yet unknown, but it is more of an academic interest...
Thank everyone once again for valuable comments!

sstream redeclared with public access compiler error

I came across this error when running make on a large project using gcc5.4.0.
/usr/include/c++/5/sstream:300:14: error: '__xfer_bufptrs' redeclared with 'public' access
struct __xfer_bufptrs
^
/usr/include/c++/5/sstream:67:14: note: previously declared 'private' here
struct __xfer_bufptrs;
To me it seems like an issue with the compiler? Since the issue arises in a standard c++ library sstream? It does not make sense to me, am I using a wrong compiler?
Here are the code snippets the error messages refer to:
1.) sstream starting at line 67
class basic_stringbuf : public basic_streambuf<_CharT, _Traits>
{
struct __xfer_bufptrs;
public:
2.) sstream at line 300
#if _GLIBCXX_USE_CXX11_ABI
// This type captures the state of the gptr / pptr pointers as offsets
// so they can be restored in another object after moving the string.
struct __xfer_bufptrs
{
__xfer_bufptrs(const basic_stringbuf& __from, basic_stringbuf* __to)
: _M_to{__to}, _M_goff{-1, -1, -1}, _M_poff{-1, -1, -1}
{
I know there cannot be anything wrong with the standard library so why is it throwing an error?
This is the closest I got to some answer:
https://github.com/PacificBiosciences/pbbam/issues/14
And it seems the answer revolves around these "Dprivate" and "Dpublic" flags. Which I assume are compiler flags, but I'm not sure what they do.
Although the thread at github hits the spot, it seems to miss the reason. You most likely are building some unit or other tests in your project that redefine the 'private' keyword like so:
#define private public
Or do the respective thing via command like (-Dprivate=public). This is a commonly used practice to expose private members for testing without making the tested code dependent on the testing code.
However look at your snippets. The first one declares __xfer_bufptrs as private regardless of your definition of private. Next second snippet is surely (haven't checked though) in an explicit private block. Now if your definition of private is in place you will ned up with public in the second snippet which is a fault.
You have at least two options, other are surely also possible:
You #undef the private definition before including system headers and define again after inclusion of those, or
You use another macro to define your own private/public sections e.g.: #define my_public public which can be redefined at will. This solution seems icky though ;)
Oh and for the future in your own code always use explicit access qualification to avoid this sort of mess at least with your own code :)

Gfortran attribute that requires an explicit interface for this procedure

I am new to Fortran, trying to compile a Atmospheric Wind model which is available here:
http://nssdcftp.gsfc.nasa.gov/models/atmospheric/hwm07/
I am using Ubuntu 12.04 and gfortan (gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5)).
The model contains 4 datafiles with .f90 extension and 3 of them compile just fine. The last one gives me the error:
$ gfortran -c hwm07e.f90
hwm07e.f90:168.22:
call HWMupdate(input,last,gfs,gfl,gfm,gvbar,gwbar,gbz,gbm,gzwght,glev,u
1
Error: Dummy argument 'ebz' of procedure 'hwmupdate' at (1) has an attribute that requires an explicit interface for this procedure
hwm07e.f90:168.22:
call HWMupdate(input,last,gfs,gfl,gfm,gvbar,gwbar,gbz,gbm,gzwght,glev,u
1
Error: Dummy argument 'ebz' of procedure 'hwmupdate' at (1) has an attribute that requires an explicit interface for this procedure
ebz and ebm are defined as targets which seems to be a source of the problem:
subroutine HWMupdate(input,last,fs,fl,fm,vbar,wbar,ebz,ebm,zwght,lev,u,v)
use NewModel
implicit none
...
real(8),intent(inout),target :: ebz(nbf,0:p)
real(8),intent(inout),target :: ebm(nbf,0:p)
...
ebz = 0.0
ebm = 0.0
bz => ebz(:,b)
bm => ebm(:,b)
In the included makefile.g95 it suggests to use g95 as the compiler, is it possible that it is not possible to compile this using gfortran?
Any suggestions are highly appreciated!
Thank you
The compiler is (and you are) correct here that the call to HWMupdate requires an explicit interface because of the target attribute on the dummy arguments. This doesn't mean that a compiler must reject the code: ifort for example can be persuaded to continue, and perhaps g95 also.
To get your compilation to continue, you could find a compiler flag to allow this: -fno-whole-file being possibly one option as this restricts gfortran's ability to do this checking. The documentation recommends against doing this, however.
If you aren't against changing the code then a better solution would be to provide an explicit interface.

Output of program depends on arbitrary print statements?

I have a Fortran 95 code whose output seems to be a function of things that it shouldn't be a function of. Specifically, the following scenerio is happening:
Run code with version A; it doesn't work (I mean, it works as in it compiles and runs, but it doesn't give the result I expect)
Run code with Version B; it works. Version B contains only trivial modifications to version A such as print statements or small changes in numerical values of variables.
Run code with version A; all of a sudden, it works.
I think there's some issue with memory or using variables before they're initialized, so I was wondering whether or not there was a way to check this sort of thing with gfortran, or if any one knows what the problem might be. I've tried gfortran my_program.f95 -Wall - Wextra, but it just gives me a bunch of complaints about nonconforming tab characters.
This was a while ago, but I fixed the problem so I figured I might as well post it. To be honest, I'm not sure whether or not these steps in particular are what fixed it, but it works, so here they are:
Put all procedures in modules (this also helps to organize the code) as opposed to just "out in the open."
Declare the intent (in, out or inout) of all variables via real, intent(in) :: foo. This is obviously useful for optimization and organization but apparently it has something to do with interfaces as well ... no idea what that's about.
And that's it!

Why Are Vtables Not Being Implemented Correctly On Embedded Platform?

I am developing code for an embedded system (specifically, the PSoC 5, using PSoC Creator), and writing in C++.
While I've overcome most hurdles with using C++ , first off compiling in C++ using the compiler flag -x c++, defining the new and delete operators, making sure exceptions aren't thrown with the compiler flag -fno-exception, I've come to a brick wall when it comes to using virtual functions.
If I try and declare a virtual function, the compiler gives me the error undefined reference to "vtable for __cxxabiv1::__class_type_info". The only way to get around this is to use the compiler flag -fno-rtti, which prevents the error and makes it compile successfully. However, if I do that, the embedded program crashes when trying to run the overloaded virtual function, and I'm thinking this is because the vtable does not exist.
I don't see why you shouldn't be able to implement vtables on an embedded platform, since all it is a extra space in memory before or after member objects (depending on the exact compiler).
The reason I am trying to use virtual functions is because I am wanting to use FreeRTOS with C++, and other people have implemented this by using virtual functions (see http://www.freertos.org/FreeRTOS_Support_Forum_Archive/July_2010/freertos_Is_it_possible_create_freertos_task_in_c_3778071.html for the discussion, and https://github.com/yuriykulikov/Event-driven_Framework_for_Embedded_Systems for a well written embedded C++ FreeRTOS framework)
The fact that the error message refers to a class named __cxxabiv1 suggests that you are not linking against the correct C++ runtime for your platform. I don't know anything about PSoC, but on more "normal" platforms, this sort of error could happen if you used the gcc (resp. clang) command at link-time instead of g++ (resp. clang++); or under handwavey circumstances if you used -lc++ without -stdlib=libc++ or -lstdc++ without -stdlib=libstdc++.
Use the -v option to examine your linker command line, and try to find out exactly which C++ runtime library it's pulling in. It'll probably be named something like libcxxabi or libcxxrt.
This guy here gives step-by-step instructions for compiling C++ in PSoC Creator; but he never figured out how to link with a C++ runtime library, so all his tips are focused on how to remove C++isms from your code (-fno-rtti, -fno-exceptions,...). I agree that there doesn't seem to be any information online about how to actually use C++ with PSoC.
For this specific error, you could always try defining the missing symbol yourself:
// file "fix-link-errors.cpp"
namespace __cxxabiv1 {
class __class_type_info {
virtual void dummy();
};
void __class_type_info::dummy() { } // causes the vtable to get created here
};
Or many linkers have the ability to define undefined symbols as 0x0 through command-line options such as -C or --defsym. However, that's not only a Bad Idea but also inconvenient, because you'd have to figure out what the actual (mangled) name of the vtable object is, and the linker didn't tell you that. (This being GCC, it's probably something like __ZTVN10__cxxabiv117__class_type_infoE.)
Either of those "solutions" would result in horrible crashes if the program ever tried to do anything with the vtable; but they'd shut the linker up, if that's all you cared about and you knew the program would never actually use RTTI. But in that case, it should be sufficient to use -fno-rtti consistently on your entire project.
What, specifically, goes wrong when you use -fno-rtti?