Bug 37486 - alignment of data in COMMON blocks
Summary: alignment of data in COMMON blocks
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 4.4.0
: P3 normal
Target Milestone: ---
Assignee: janus
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2008-09-11 20:54 UTC by janus
Modified: 2008-09-22 11:50 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2008-09-22 10:00:34


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description janus 2008-09-11 20:54:37 UTC
Currently, gfortran automatically aligns data in COMMON blocks, as in the following example:

implicit none
integer(kind=4) :: n
real(kind=8) :: p
common /foo/ n,p
end

This gives the warning:

COMMON 'foo' at (1) requires 4 bytes of padding at start

This automatic padding can result in unexpected results, as demonstrated by the following code:

subroutine one()
 implicit none
 integer :: n1,n2,n3,n4
 common /foo/ n1,n2(2),n3,n4
 print *, n3, n4
end subroutine one

program prog
 implicit none
 integer :: n1,n2,n3
 real(8) :: r1
 common /foo/ n1,r1,n2,n3
 n2 = 2
 n3 = 3
 call one()
end program prog

The output of this program is "0 2" instead of "2 3".

Therefore gfortran should have an option to suppress automatic alignment. Preferrably this option should be enabled by default.

See also http://gcc.gnu.org/ml/fortran/2008-09/msg00221.html
Comment 1 Joost VandeVondele 2008-09-12 17:56:03 UTC
the program is non-standard Fortran, but it is legacy, so an option would be useful.
Comment 2 kargl 2008-09-12 18:30:04 UTC
(In reply to comment #1)
> the program is non-standard Fortran, but it is legacy, so an option would be
> useful.
> 

Why is it nonstandard?

Maybe I'm misreading 5.5.2.1 and 5.5.2.3 from the F95 standard, which
suggest to me that the program is conforming.
Comment 3 kargl 2008-09-12 18:44:33 UTC
(In reply to comment #2)
> (In reply to comment #1)
> > the program is non-standard Fortran, but it is legacy, so an option would be
> > useful.
> > 
> 
> Why is it nonstandard?
> 
> Maybe I'm misreading 5.5.2.1 and 5.5.2.3 from the F95 standard, which
> suggest to me that the program is conforming.
> 

Yeah, I'm responding to myself.  5.5.2.1 actually suggests that gfortran's
behavior of adding padding is violation of standard.
Comment 4 Joost VandeVondele 2008-09-12 18:48:45 UTC
(In reply to comment #2)
> (In reply to comment #1)
> > the program is non-standard Fortran, but it is legacy, so an option would be
> > useful.
> > 
> 
> Why is it nonstandard?
> 

Maybe not, I was guessing based on 16.5.6 that n3 and n4 are actually undefined at the point of printing.
Comment 5 kargl 2008-09-12 19:03:18 UTC
(In reply to comment #4)
> (In reply to comment #2)
> > (In reply to comment #1)
> > > the program is non-standard Fortran, but it is legacy, so an option would be
> > > useful.
> > > 
> > 
> > Why is it nonstandard?
> > 
> 
> Maybe not, I was guessing based on 16.5.6 that n3 and n4 are actually
> undefined at the point of printing.

AFAICT, n3 and n4 are defined in one() because they are associated
with n3 and n4 of the main program which have the same type and kind.
n2(2) is undefined in one() and it would be undefined even if r1 had
been set in prog because their types are different.

This is equivalent to the ever popular use of EQUIVALENCE to set a
real type to Inf or NaN via integers.

   equivalence(x,i)
   ! The following makes x undefined.
   i = SOME_INT_BIT_PATTERN_FOR_INF 
   ! Do stuff with i.
   ! The following makes i undefined.
   x  = 1.
   end
Comment 6 Tobias Burnus 2008-09-12 20:42:06 UTC
> This is equivalent to the ever popular use of EQUIVALENCE to set a
> real type to Inf or NaN via integers.

Actually, it is a bit different: Here, already the COMMON is invalid for EQUIVALENCE only accessing the value is invalid as the value is undefined. Default integer and default real are in the same storage sequence (and here probably the analog to EQUIVALENCE holds). I think the following program is valid according to the standard and it has the same problem:

subroutine one()
  integer :: i
  common /com/ i
  print *, i
end subroutine one

program test
integer :: j
real(8) :: r8
common /com/ i, r8 
i = 5
call one()
end program test

(If I recall correctly, the commons do not need to have the same size, but the shorter ones need to be identical to the longer one minus the extra elements.)
Comment 7 kargl 2008-09-12 21:18:53 UTC
(In reply to comment #6)
> > This is equivalent to the ever popular use of EQUIVALENCE to set a
> > real type to Inf or NaN via integers.
> 
> Actually, it is a bit different: Here, already the COMMON is invalid for
> EQUIVALENCE only accessing the value is invalid as the value is undefined.

I can't parse the above sentence. :(

> Default integer and default real are in the same storage sequence (and here
> probably the analog to EQUIVALENCE holds). I think the following program is
> valid according to the standard and it has the same problem:
> 
> subroutine one()
>   integer :: i
>   common /com/ i
>   print *, i
> end subroutine one
> 
> program test
> integer :: j
> real(8) :: r8
> common /com/ i, r8 
> i = 5
> call one()
> end program test
> 
> (If I recall correctly, the commons do not need to have the same size, but the
> shorter ones need to be identical to the longer one minus the extra elements.)

Yes, the above is a valid program via 5.5.2.1(2) of the F95 standard.

A problem does not exist if by default gfortran does not pad the
common block to align double precision types on 8 byte boundaries.

Returning to your code in comment #1.  The two common statements
occupy 5 storage units.  As soon as gfortran puts padding into
the "common /foo/ n1,r1,n2,n3", gfortran has violated 5.5.2.1(1) of
the standard because it is changing the storage sequence of 
"common /foo/n1,n2(2),n3,n4".

To summarize, gfortran should not pad common blocks.  gfortran can
issue a warning alerting the user of an align issue if one exists.
gfortran should implement a -falign-common option to user a gun to
blow their feet off.

Comment 8 Dominique d'Humieres 2008-09-12 21:31:49 UTC
> If I recall correctly, the commons do not need to have the same size 

5.7.2.5 Differences between named common and blank common (F2008, 5.5.2.4 for f95)

...

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

For the test in comment #6, the common should be blank one to make the test valid (detected with 
-Wall).
Comment 9 janus 2008-09-22 11:46:25 UTC
Subject: Bug 37486

Author: janus
Date: Mon Sep 22 11:45:02 2008
New Revision: 140546

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=140546
Log:
2008-09-22  Janus Weil  <janus@gcc.gnu.org>

	PR fortran/37486
	* gfortran.h (gfc_option_t): New members flag_align_commons and
	warn_align_commons. 
	* lang.opt: New options falign-commons and Walign-commons.
	* invoke.texi: Documentation for new options.
	* options.c (gfc_init_options): Initialize new options.
	(gfc_handle_options): Handle new options.
	* trans-common.c (translate_common): Implement new options.
	(gfc_trans_common): Set correct locus.


2008-09-22  Janus Weil  <janus@gcc.gnu.org>

	PR fortran/37486
	* gfortran.dg/common_align_1.f90: New.
	* gfortran.dg/warn_align_commons.f90: New.

Added:
    trunk/gcc/testsuite/gfortran.dg/common_align_1.f90
    trunk/gcc/testsuite/gfortran.dg/warn_align_commons.f90
Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/gfortran.h
    trunk/gcc/fortran/invoke.texi
    trunk/gcc/fortran/lang.opt
    trunk/gcc/fortran/options.c
    trunk/gcc/fortran/trans-common.c
    trunk/gcc/testsuite/ChangeLog

Comment 10 janus 2008-09-22 11:50:52 UTC
Fixed with r140546. Closing.