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).

Reply via email to