Bug 41227 - COMMON block, BIND(C) and LTO interoperability issues
Summary: COMMON block, BIND(C) and LTO interoperability issues
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 4.5.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: lto, wrong-code
Depends on:
Blocks: 42361 fortran-lto
  Show dependency treegraph
 
Reported: 2009-09-02 14:26 UTC by Tobias Burnus
Modified: 2025-01-31 13:51 UTC (History)
7 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2010-06-03 13:48:44


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Tobias Burnus 2009-09-02 14:26:06 UTC
There are interoperability issues with
   integer :: single_variable
   COMMON /name/ single_variable
and C. Currently, gfortran generates the equivalent to
   struct { int single_variable }
however - at least with BIND(C) - it should be compatible to
   int single_variable

That's what bind_c_coms.f90/bind_c_coms_driver.c test and which is failing with -flto on the LTO branch.

See Fortran 2003, "15.3 Interoperation with C global variables":

"A C variable with external linkage interoperates with a common block that has 
 been specified in a BIND statement
(1) if the C variable is of a struct type and the variables that are members of
    the common block are interoperable with corresponding components of the
    struct type, or
(2) if the common block contains a single variable, and the variable is
    interoperable with the C variable."

 * * *

Next question: What should happen without BIND(C)?
Answer: In F2003, "5.5.2.4 Differences between named common and blank common" one finds:

"A blank common block has the same properties as a named common block, except 
 for the following:  [...]
(2) Named common blocks of the same name shall be of the same size in all 
    scoping units of a program in which they appear, but blank common blocks
    may be of different sizes."

By construction, blank common names are not accessible from C. Thus from the standard, one could do the "struct"-less version for named commons and the "struct" version for blank commons.

I do not know whether there are compatibility issues with old programs; however, the general advice was to use "struct".

 * * *

I think one should drop some kind of note in the Release Notes and add a few words about COMMON to http://gcc.gnu.org/onlinedocs/gfortran/Mixed_002dLanguage-Programming.html

Another huge issue is padding: In C one has - by default - padding, in Fortran (according to the language standard) not. gfortran uses padding (cf. -fno-align-commons), however. One probably should exclude the BIND(C) COMMONS from the -fno-align-commons option and should check that C does exactly the same padding.

See also PR 41209 for a means to set, e.g., the padding.
Comment 1 Tobias Burnus 2009-09-14 21:05:22 UTC
In any case gcc/dwarf2out.c needs to be modified. It currently has:

fortran_common (tree decl, HOST_WIDE_INT *value)
{ [...]
  if (TREE_CODE (val_expr) != COMPONENT_REF)
    return NULL_TREE;

However, one needs to create a DW_TAG_common_block which contains a DW_TAG_variable.
Comment 2 Tobias Schlüter 2009-09-28 19:58:55 UTC
The way usually recommended is to use a struct for interoperability with Fortran common blocks, say http://support.microsoft.com/kb/51614

Unfortunately, the idiom "use a single variable common block, say common/x/y, access it via the name of the common block, followed by an underscore, say x_" is also common.  At least in my workplace it's the way everybody uses.

In other words, we can't afford to break either way.
Comment 3 Tobias Burnus 2010-01-29 17:45:54 UTC
I have now asked at comp.lang.fortran:

http://groups.google.com/group/comp.lang.fortran/browse_thread/thread/c00efc5679b6a879

(In reply to comment #2)
> The way usually recommended is to use a struct for interoperability with
> Fortran common blocks, say http://support.microsoft.com/kb/51614

That matches - for multiple variables in the block - the Fortran 2003 standard.

> Unfortunately, the idiom "use a single variable common block, say common/x/y,
> access it via the name of the common block, followed by an underscore, say x_"
> is also common.  At least in my workplace it's the way everybody uses.

That matches what Fortran 2003 says about a single variable.

> In other words, we can't afford to break either way.

Well, as long as you do not use LTO it does not seem to matter. And if LTO you have to decide for "struct" or against "struct". (And as a user, use BIND(C) - either with COMMON or with TYPE - and you get a well-defined result.)

I am leaning towards using a "struct" only when there are multiple variables, which makes BIND(C) and non-BIND(C) behave identical. If the overwhelming opinion is differently, one can still add a "&& attr->is_bind_c".
Comment 4 Tobias Burnus 2010-02-02 10:28:52 UTC
Test case:
  gfortran -flto bind_c_coms_driver.c bind_c_coms.f90
Comment 5 Tobias Burnus 2010-02-11 16:29:23 UTC
Also asked at:
  http://gcc.gnu.org/ml/fortran/2010-02/msg00010.html

a) The derived-type issue (cf. PR 41664) is now fixed.

b) Regarding COMMON w/ single item in the named COMMON (F2003, 15.3); unclear whether it is supposed to interoperate with both the single C variable and the struct or only with the former. I have now asked at http://j3-fortran.org/pipermail/j3/2010-February/
Comment 6 Tobias Burnus 2010-02-23 09:08:35 UTC
Regarding my question, Toon ask this question to Bill Long @ Cray and Jim Xia @ IBM at the Las Vegas meeting of J3/WG5 - they came to different conclusions ;-)

Bill Long stated what he also wrote at
  http://j3-fortran.org/pipermail/j3/2010-February/003358.html

Namely: The "OR" is to be read as exclusive "OR":
> > Does a common block containing a single variable (e.g. of type
> > "integer(c_int)") need to be interoperable with the C variable ("int")
>  > only [i.e. only (2)] 
>
>  Yes, this is my interpretation.

Toon agreed more with Bill and commented: "I think this is due to the fact that - as every 'vendor' knows - the C compiler being the 'companion processor' (C interoperability terminology) to its Fortran processor, it can allow additional interoperability (for instance, allow COMMON /blah/ I interoperate with struct {int i;} blah;)."

Thus, from the standard in a three-to-two-reading*, one only needs to interoperate with the single variable and not with the struct. (* My reading, Toon's, Bill's vs. Nick's (fortran@gcc) and Jim's.) -- Note: I have not submitted an official interpretation request, for which all J3/WG5 members have to vote.

I really wonder whether supporting both in LTO would be the better option compared with changing it to a single variable in the frontend.
Comment 7 rguenther@suse.de 2010-02-23 09:33:03 UTC
Subject: Re:  COMMON block, BIND(C) and LTO interoperability
 issues

On Tue, 23 Feb 2010, burnus at gcc dot gnu dot org wrote:

> ------- Comment #6 from burnus at gcc dot gnu dot org  2010-02-23 09:08 -------
> Regarding my question, Toon ask this question to Bill Long @ Cray and Jim Xia @
> IBM at the Las Vegas meeting of J3/WG5 - they came to different conclusions ;-)
> 
> Bill Long stated what he also wrote at
>   http://j3-fortran.org/pipermail/j3/2010-February/003358.html
> 
> Namely: The "OR" is to be read as exclusive "OR":
> > > Does a common block containing a single variable (e.g. of type
> > > "integer(c_int)") need to be interoperable with the C variable ("int")
> >  > only [i.e. only (2)] 
> >
> >  Yes, this is my interpretation.
> 
> Toon agreed more with Bill and commented: "I think this is due to the fact that
> - as every 'vendor' knows - the C compiler being the 'companion processor' (C
> interoperability terminology) to its Fortran processor, it can allow additional
> interoperability (for instance, allow COMMON /blah/ I interoperate with struct
> {int i;} blah;)."
> 
> Thus, from the standard in a three-to-two-reading*, one only needs to
> interoperate with the single variable and not with the struct. (* My reading,
> Toon's, Bill's vs. Nick's (fortran@gcc) and Jim's.) -- Note: I have not
> submitted an official interpretation request, for which all J3/WG5 members have
> to vote.
> 
> I really wonder whether supporting both in LTO would be the better option
> compared with changing it to a single variable in the frontend.

That's certainly possible (though possibly not trivial - in fact part
of it is already implemented, as in LTO doesn't complain about this
inter-operation but later the optimizers might break things if you
do not build with -fno-strict-aliasing).

Richard.
Comment 8 Richard Biener 2010-06-03 13:48:44 UTC
Mine.  See http://gcc.gnu.org/ml/gcc-patches/2010-05/msg02424.html for an
outline for a possible fix.
Comment 9 Richard Biener 2012-01-05 13:37:09 UTC
This is still not fixed (at least by design - bind_c_coms.f90/bind_c_coms_driver.c
passes with -flto now).  Can somebody produce a reduced testcase pair that
just has a bind-C named common with a single int so I can experiment a bit?

Thx.
Comment 10 Francois-Xavier Coudert 2014-06-08 16:53:11 UTC
(In reply to Richard Biener from comment #9)
> Can somebody produce a reduced testcase pair that
> just has a bind-C named common with a single int so I can experiment a bit?

$ cat s.f90 
module foo
  use iso_c_binding
  integer(c_int) :: i
  common /com/ i
  bind(c,name="toto") :: /com/
end module foo

$ cat s.c 
int main(void)
{
  extern int toto;
  toto = 42;
}
Comment 11 Richard Biener 2014-06-10 13:06:38 UTC
I think there is no good way apart from treating single-element structs equal
to its single element in LTO with regarding to TYPE_CANONICAL.  At least not if
you want to inter-operate with both int i; and struct { int i; }.  Otherwise
I'd lean towards not using a struct in Fortran for single-element commons.
That should be an implementation detail anyways.

> Unfortunately, the idiom "use a single variable common block, say common/x/y,
> access it via the name of the common block, followed by an underscore, say x_"
> is also common.  At least in my workplace it's the way everybody uses.

But then simply name the symbol of the variable without a struct in that way, no?
Comment 12 Francois-Xavier Coudert 2014-07-14 10:21:00 UTC
I disagree with Tobias' reading: it seems to me that the single-variable common block should be interoperable with both the single-common C struct and C variable.

The Intel compiler makes both cases work:

[fx@kelvin tmp]$ cat a.f90 
program test
  use iso_c_binding
  integer(c_int) :: i
  common /a/ i
  bind(c) :: /a/

  interface
    subroutine foo() bind(c)
    end subroutine
  end interface

  i = 42
  print *, i
  call foo()
  print *, i
end program test
[fx@kelvin tmp]$ cat a1.c 
extern int a;
void foo (void) { a = -1; }
[fx@kelvin tmp]$ cat a2.c 
extern struct { int i; } a;
void foo (void) { a.i = -1; }
[fx@kelvin tmp]$ icc -c a1.c && ifort a.f90 a1.o && ./a.out
          42
          -1
[fx@kelvin tmp]$ icc -c a2.c && ifort a.f90 a2.o && ./a.out
          42
          -1


I believe we should do so too. And if I understand correctly what Richard said, this means relaxing the LTO type rules, is that right?
Comment 13 rguenther@suse.de 2014-07-14 10:35:57 UTC
On Mon, 14 Jul 2014, fxcoudert at gcc dot gnu.org wrote:

> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=41227
> 
> --- Comment #12 from Francois-Xavier Coudert <fxcoudert at gcc dot gnu.org> ---
> I disagree with Tobias' reading: it seems to me that the single-variable common
> block should be interoperable with both the single-common C struct and C
> variable.
> 
> The Intel compiler makes both cases work:
> 
> [fx@kelvin tmp]$ cat a.f90 
> program test
>   use iso_c_binding
>   integer(c_int) :: i
>   common /a/ i
>   bind(c) :: /a/
> 
>   interface
>     subroutine foo() bind(c)
>     end subroutine
>   end interface
> 
>   i = 42
>   print *, i
>   call foo()
>   print *, i
> end program test
> [fx@kelvin tmp]$ cat a1.c 
> extern int a;
> void foo (void) { a = -1; }
> [fx@kelvin tmp]$ cat a2.c 
> extern struct { int i; } a;
> void foo (void) { a.i = -1; }
> [fx@kelvin tmp]$ icc -c a1.c && ifort a.f90 a1.o && ./a.out
>           42
>           -1
> [fx@kelvin tmp]$ icc -c a2.c && ifort a.f90 a2.o && ./a.out
>           42
>           -1
> 
> 
> I believe we should do so too. And if I understand correctly what Richard said,
> this means relaxing the LTO type rules, is that right?

Yes (to get rid of the warning and to avoid eventual wrong-code bugs).

Does it need to inter-operate with

extern struct { struct { int i; } a; } a;

?  Or

extern union { int i; } a;

?
Comment 14 Francois-Xavier Coudert 2014-07-14 10:45:25 UTC
(In reply to rguenther@suse.de from comment #13)
> Does it need to inter-operate with
> extern struct { struct { int i; } a; } a;

No, I don't read anything in the standard that would allow this.

> extern union { int i; } a;

No, per F2008 15.3.4 ¶3: "There is no Fortran type that is interoperable with a C union type."
Comment 15 Richard Biener 2014-07-14 11:09:20 UTC
Ok, the warning is implemented with checking gimple type compatibility in
lto/lto-symtab.c:

      if (!types_compatible_p (TREE_TYPE (prevailing->decl),
                               TREE_TYPE (decl)))
        diagnosed_p |= warning_at (DECL_SOURCE_LOCATION (decl), 0,
                                   "type of %qD does not match original "
                                   "declaration", decl);

I'm not sure it is wise to drop the outermost single-element struct type
from all types during compute of canonical types.

We can adjust gimple_get_alias_set to at least assign the same alias
sets to such struct and its element, but that doesn't cure the warning
(obviously).  At least that avoids generating wrong code... like with

@@ -2307,6 +2308,27 @@ gimple_get_alias_set (tree t)
       || t == unsigned_char_type_node)
     return 0;
 
+  /* For C, Fortran interoperability assign the same alias-set to
+     a record with a single element as that element.  */
+  if (TREE_CODE (t) == RECORD_TYPE)
+    {
+      tree f = NULL_TREE;
+      for (tree fld = TYPE_FIELDS (t); fld != NULL_TREE; fld = TREE_CHAIN (fld))
+       {
+         if (TREE_CODE (fld) != FIELD_DECL)
+           continue;
+         if (f == NULL_TREE)
+           f = fld;
+         else
+           {
+             f = NULL_TREE;
+             break;
+           }
+       }
+      if (f)
+       return get_alias_set (TREE_TYPE (f));
+    }
+
   /* Allow aliasing between signed and unsigned variants of the same

but I'm sure we don't want to call get_alias_set on all globals during
WPA phase (Where the warning is emitted).

Humm.  We can special-case that case in lto-symtab.c of course.

Btw, what kind of single-elements can I expect?  I suppose they can
be arbitrary (so aggregate as well)?
Comment 16 Francois-Xavier Coudert 2014-07-14 11:20:27 UTC
(In reply to Richard Biener from comment #15)
> Btw, what kind of single-elements can I expect?  I suppose they can
> be arbitrary (so aggregate as well)?

From the Fortran/C interop side, we can get anything that is itself C/Fortran interoperable. So that is POD of various types (integers, floating-points and complexes, bool and char), pointer types, structs of those and arrays.
Comment 17 Tobias Burnus 2014-07-14 11:36:35 UTC
(In reply to Francois-Xavier Coudert from comment #12)
> I disagree with Tobias' reading: it seems to me that the single-variable
> common block should be interoperable with both the single-common C struct
> and C variable.

Well, Bill Long of Cray seems to agree with my interpretation, cf.
http://mailman.j3-fortran.org/pipermail/j3/2010-February/003358.html

> The Intel compiler makes both cases work:

Well, it also works with gfortran - the question is only whether it works by chance or by purpose. If it works by chance and is invalid LTO is not required to support it.
Comment 18 Tobias Burnus 2014-07-14 11:45:06 UTC
(In reply to Francois-Xavier Coudert from comment #14)
> (In reply to rguenther@suse.de from comment #13)
> > Does it need to inter-operate with
> > extern struct { struct { int i; } a; } a;
> No, I don't read anything in the standard that would allow this.

By your argument,
  int i;
and
  struct { int i; } a;
are interoperable. By this argument, one can also claim that it applies to
  struct { struct { int i; } a; } a;
At least I fail to see a difference between the single and the nested struct.

Otherwise, I stand to what I wrote before: I think the standard does not demand the interoperability.

There are surely programs out there which do assume for a scalar variable in a common block that it interoperates with "int" and others which assume that it interoperates with "struct { int i; }". Thus, one might decide that one wants to support both versions with LTO. But one shouldn't do so by arguing with the Fortran standard.
Comment 19 rguenther@suse.de 2014-07-14 11:46:19 UTC
On Mon, 14 Jul 2014, burnus at gcc dot gnu.org wrote:

> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=41227
> 
> --- Comment #17 from Tobias Burnus <burnus at gcc dot gnu.org> ---
> (In reply to Francois-Xavier Coudert from comment #12)
> > I disagree with Tobias' reading: it seems to me that the single-variable
> > common block should be interoperable with both the single-common C struct
> > and C variable.
> 
> Well, Bill Long of Cray seems to agree with my interpretation, cf.
> http://mailman.j3-fortran.org/pipermail/j3/2010-February/003358.html

But that answer suggests we get it wrong (currenty interoperating
with the C struct { int i; } works and with the plain decl it
doesn't).  The answer specifically doesn't say that only (1)
is valid.

> > The Intel compiler makes both cases work:
> 
> Well, it also works with gfortran - the question is only whether it works by
> chance or by purpose. If it works by chance and is invalid LTO is not required
> to support it.

Currently it works "by chance" because without LTO the compiler doesn't
see both sides.  With LTO it notices there is an inconsistency that
with a clever testcase will result in wrong code (make a fortran
subroutine that assigns sth to the variable, call it from the
C main after its assignment of 42, read the var again in main
and see it optimized to '42' in case the fortran function call is
inlined)
Comment 20 Tobias Schlüter 2014-07-14 12:05:16 UTC
Let's please not invent new semantics.  There are two things to distinguish:
1) legacy code, where no interoperability semantics were defined
2) new code, where the semantics are defined

I don't know much about 2), but I do know that the recommendation back in the days was that a common block is represented by a struct, and everybody knew that the layout of a struct with a single variable is the same as for the variable itself.  I don't think anybody was silly enough to nest structs around their variable.

Unfortunately, this is still not entirely simple.  Fortran allows accessing the same memory by different names which may have different types: what do you do with
 INTEGER A, B, C
 COMMON /D/ E(3)
 REAL E
 EQUIVALENCE (E(1),A), (E(2),B), (E(3),C)
?

Or, to make things even more annoying
 DOUBLE PRECISON X
 INTEGER I(2)
 EQUIVALENCE (X, I(1))
 COMMON /annoying/ X
?

There's one more problem: Fortran's TYPE, the equivalent of the struct {}, was defined in Fortran 90 -- before the interoperability stuff.  So the question is what to do with common block that contain a single TYPE variable.

Until I started writing this, I tought "well, just allow this struct vs. single variable only for single-valued, scalar contents of the common block", but my second example showed me that this wouldn't work -- after all is the common content scalar (one double) or array-valued (two ints)?

Now, since we're talking about legacy stuff and we don't want to invent new language rules, I think we can restrict ourselves to supporting the simplest case: a single INTEGER, REAL or DOUBLE PRECISION ignoring possible EQUIVALENCES, but I don't know if this is easily achieved on the LTO side.  Going further is not worth it, it's not like there are heaps of bug reports about this problem.
Comment 21 Francois-Xavier Coudert 2014-07-14 13:07:06 UTC
(In reply to Tobias Burnus from comment #18)
> By your argument,
>   int i;
> and
>   struct { int i; } a;
> are interoperable.

No. The standard only defines interoperability as a one-to-one mapping between one Fortran entity and one C entity.

An "extern int i" and "integer(int_c) :: i" are interoperable. By the standard, a common block with i as single variable is interoperable with "extern struct { int i; } a;" or "int i;" (where the question is whether "or" is exclusive or not).

But I don't see how you can expand that to mean that the common block is interoperable with "struct { struct { int i; } a; } a;" by a simple reading of the standard. There are, in my reading, 2 or 3 (with the same "or" as before) entities interoperable with this nested struct:

  - a derived type containing a derived type containing "integer(int_c) :: i"
  - a common containing the dt containing the dt
  - a common containing a derived type containing "integer(int_c) :: i"


> Otherwise, I stand to what I wrote before: I think the standard does not
> demand the interoperability.

Let's raise a formal interp, then.
Comment 22 Tobias Burnus 2014-07-14 13:33:50 UTC
(In reply to rguenther@suse.de from comment #19)
> > Well, Bill Long of Cray seems to agree with my interpretation, cf.
> > http://mailman.j3-fortran.org/pipermail/j3/2010-February/003358.html
> 
> But that answer suggests we get it wrong (currenty interoperating
> with the C struct { int i; } works and with the plain decl it
> doesn't).  The answer specifically doesn't say that only (1)
> is valid.

As I stumbled over it again (and missed what I wrote 5 years ago in comment 0):
One also needs to distinguish between common blocks with and without BIND(C). 


The Fortran standard only defines interoperability with C with Fortran 2003's C binding ("BIND(C)"). Thus, "external int i" interoperates with
  use iso_fortran_env, only: c_int
  integer(c_int) :: j
  common /i/ j
  bind(C) :: /i/
and for this construct, "struct {int i}" does not have to interoperate with it according to the standard. If the front-end produces the wrong code in this case, one can simply fix it. Seems as if we have to do this, including the output DWARF.

[By the way, I assume that there is essentially no code out there, which uses BIND(C) with COMMON: Either it is pre-Fortran-2003 code - or it uses modules where one avoids all those issues with COMMON and either has "integer, bind(C) :: i" or "type(t), bind(C) :: i" and no ambiguity.]


The other case is legacy code: There, programs can make the wildest assumptions what C code should interoperable with Fortran. See also T.S.'s comment 20. Seems as if a simple "struct" was the most common assumption - with a nonstruct being effectively interoperable with a one-variable struct; hence, also the latter seems to be used.
Comment 23 Jan Hubicka 2015-05-27 23:55:49 UTC
OK, I got here from discussion at https://gcc.gnu.org/ml/gcc-patches/2015-05/msg02577.html because I am trying to get the canonical type calculation to the more standard compliant shape.

My reading of the standard is that the variable in question should be interoperable with int, not struct {int}, because I do not see any derived type in Fortran source.

In that case it would be nice to make gfortran to just drop the struct for BIND(C) types if possible. Making this work on LTO level probably means to peel off single element struct/aggregate. Other variant is to simply punt those types to alias set 0.

So in this case I would agree with Tobias, Comment #22, but this is my first even attempt to make sense of Fortran standard.

As for legacy code, perhaps gfortran can propagate BIND(C) to middle-end (i.e. add type attribute "bind_c" to those types) and we could add a warning when fortran declaration of type !bind_c gets merged with non-fortran declaration in lto-symtab and hopefully help people to annotate their source codes.
Comment 24 Richard Biener 2025-01-31 13:51:00 UTC
I'm not working on this.  The comment#12 testcase shows the diagnostic happening but it works at runtime because we a) honor "must-alias" for QOI reasons
and the accesses are not enough obfuscated (and I don't know how to obfuscate
on the fortran side).

Adjusted testcase:

program test
  use iso_c_binding
  integer(c_int) :: i
  integer :: j
  common /a/ i
  bind(c) :: /a/

  interface
    subroutine foo() bind(c)
    end subroutine
  end interface

  i = 42
  call foo()
  j = i
  print *, j
end program test

---

extern int a;
void foo (void) { a = -1; }

where we end up with

  __MEM <int> (&a) = _Literal (int) -1;
  j = _Literal (int) -1;

with -O -fno-tree-fre -fno-tree-dominator-opts we see

  __MEM <int> (&a) = _Literal (int) -1;
  _1 = a.i;
  j = _1;

but clearly this way around is even valid when taking the struct as prevailing
and using the component as access type.

So I think we should be safe?