https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96158
--- Comment #9 from Steve Kargl <sgk at troutmask dot apl.washington.edu> --- On Mon, Jul 13, 2020 at 03:44:13PM +0000, amelvill at umich dot edu wrote: > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96158 > > --- Comment #8 from AJM <amelvill at umich dot edu> --- > > > >> I won't comment on the questionable programming idiom of placing > > > >> a common block in a module, which kind of defeats the niceties of > > > >> a module. > > > > If somebody wants to transition your code from using common blocks to > > > > modules, that is a good way to proceed. When all the direct usage > > > > of the common block have been removed, you can then remove the > > > > COMMON statement from the module. > > > > > > This is the case, more or less. I didn't write the code that did this. > > > > > > I would be quite happy to see the common blocks get moved to a module, > > > but to make things a bit more dangerous on that side, these variables > > > are bound to a C variable. > > Do you mean the variable is declared with BIND(C)? > > If so, you should be getting an error. > > The bind statement would look like this, directly under the "common" > statement, > inside somemodule.f90: > > module somemodule > > integer*8 moduleVar !then many more variables > > common /othermodule/ moduleVar !then many more variables > bind(C, name="othermodule") :: /othermodule/ > > end module > > The program, with the bind statement added, compiles without errors. Ah, I misunderstood what you wrote. I thought you meant you had instances of something like integer*8, bind(c) :: modulevar common /othermodule/ moduleVar in the module. That's invalid, and gfortran must issue an error as it is a numbered constraint. I'll need to go look at the Fortran standard about bind(c) and named common blocks. > If you really need to know, on the C side there is a struct with fields that > match the order and size of the variables in the common statement / module > declaration. I am almost certain that this is not the "right way" to do this, > and that there is some UB there in struct packing and compiler decisions on > the > size of the variables (neither the C side nor the fortran side has packing > pragmas, and worse, the C side uses compiler defined integer types like > "int"). > Without a doubt this is not an ideal setup, a rewrite is probably in order to > ensure portability. We don't have the time resources for that rewrite right > now, though (and that's not my call, either). Oh. That does look error prone. The correct way, if you're working on improvements to the code, would be to use a derived type on the Fortran side that matches a struct on the C side. I would need check on whether you need to use a SEQUENCEd derived type, and what other restrictions apply (e.g., no allocatable components etc). > While I was making a minimal example I originally thought bind was the root > cause, but I eliminated it as the source of the problem (I found that I could > reproduce the issue with only common). I removed it to try and make the most > minimal example possible. Does the -fno-align-common option help you. The manual says '-falign-commons' By default, 'gfortran' enforces proper alignment of all variables in a 'COMMON' block by padding them as needed. On certain platforms this is mandatory, on others it increases performance. If a 'COMMON' block is not declared with consistent data types everywhere, this padding can cause trouble, and '-fno-align-commons' can be used to disable automatic alignment. The same form of this option should be used for all files that share a 'COMMON' block. To avoid potential alignment issues in 'COMMON' blocks, it is recommended to order objects from largest to smallest. Trying to match a named common block with memory alignment requirements with a C struct (which may have different alignment requirements) seems to the path to very hard to find bugs. > > A quick scan of the DWARF5 standard does not show > > a DW_TAG that applies to a variable declared in > > a module. > > Referring to the github repo quickly > https://github.com/amelvill-umich/Fortran_GDB_Common#with-that-line-commented-out > , with the common statement commented out, > > $ nm somemodule.o > 0000000000000000 B __somemodule_MOD_modulevar > Interesting. My guess would be that a common block is simply considered to be a chunk of memory under DWARF5. It provides a base address and one needs to know how to compute offsets into that chunk (including dealing with any padding).