public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug fortran/101199] New: program changes the value of a dummy argument
@ 2021-06-24 19:37 ygalklein at gmail dot com
2021-06-25 5:55 ` [Bug fortran/101199] " ygalklein at gmail dot com
` (6 more replies)
0 siblings, 7 replies; 8+ messages in thread
From: ygalklein at gmail dot com @ 2021-06-24 19:37 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101199
Bug ID: 101199
Summary: program changes the value of a dummy argument
Product: gcc
Version: 11.1.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: fortran
Assignee: unassigned at gcc dot gnu.org
Reporter: ygalklein at gmail dot com
Target Milestone: ---
I have written the following example code:
```fortran
module mod_original_struct
implicit none
private
public :: original_struct, extended_struct
type original_struct
private
real, PUBLIC :: var1
real :: var2, var3, var4
real, dimension(3) :: vec1, vec2
contains
private
procedure, public :: init=>initoriginal_struct
end type original_struct
type, extends(original_struct) :: extended_struct
private
type(original_struct), dimension(2), public :: origs
contains
private
procedure, public :: init=>initextended_struct, advance
end type extended_struct
contains
subroutine advance(this)
class(extended_struct), intent(inout) :: this
print*, 'head of advance, this%var1 = ', this%var1
call this%init(vec1=this%vec1(:),&
vec2=this%vec2(:),&
var1=this%var1,&
var2=this%var2,&
var3=this%var3,&
var4=this%var4,&
origs=this%origs)
end subroutine advance
subroutine initoriginal_struct(this, vec1, vec2, var1, var2, var3, var4,
origs)
class(original_struct), intent(out) :: this
real, dimension(3), intent(in) :: vec1, vec2
real, intent(in) :: var1, var2, var3, var4
type(original_struct), intent(in), dimension(2), optional :: origs
this%vec1(:) = vec1(:)
this%vec2(:) = vec2(:)
this%var1 = var1
this%var2 = var2
this%var3 = var3
this%var4 = var4
if (present(origs)) error stop "initoriginal_struct was called with
origs, this is strange"
end subroutine initoriginal_struct
subroutine initextended_struct(this, vec1, vec2, var1, var2, var3, var4,
origs)
class(extended_struct), intent(out) :: this
real, dimension(3), intent(in) :: vec1, vec2
real, intent(in) :: var1, var2, var3, var4
type(original_struct), intent(in), dimension(2), optional :: origs
print*, 'head of initextended_struct, the input argument var1 = ', var1
this%vec1(:) = vec1(:)
this%vec2(:) = vec2(:)
this%var1 = var1
this%var2 = var2
this%var3 = var3
this%var4 = var4
if (.not. present(origs)) error stop "initextended_struct was called
without origs"
this%origs(:) = origs(:)
end subroutine initextended_struct
end module mod_original_struct
program example
use mod_original_struct, only: extended_struct, original_struct
implicit none
type(original_struct), DIMENSION(2) :: origs
type(extended_struct) :: extended1
call origs(1)%init(vec1=[0.5, 0., 0.],&
vec2=[0., 0.3, 0.],&
var1=3.,&
var2=1.2,&
var3=0.4,&
var4=4.5)
call origs(2)%init(vec1=[0., 0.8, 0.],&
vec2=[0.2, 0., 0.],&
var1=4.,&
var2=1.5,&
var3=0.5,&
var4=6.5)
call extended1%init(vec1=[0., 0., 0.7],&
vec2=[0.2, 0., 0.],&
var1=10.,&
var2=6.,&
var3=3.2,&
var4=10.,&
origs=origs)
print*, 'bf advance, extended1%var1 = ', extended1%var1
call extended1%advance()
end program example
```
when compiling with gfortran 11.1, the program compiles succesfully and the
output is:
head of initextended_struct, the input argument var1 = 10.000000000000000
bf advance, extended1%var1 = 10.000000000000000
head of advance, this%var1 = 10.000000000000000
head of initextended_struct, the input argument var1 = 0.0000000000000000
One can see that the value of var1 that was sent to init of the extented struct
in the routine advance has changed its value from the line bf the call to init
to the head of init.
This is a failure of the program.
The same happens with gfortran 10.3 and also gfortran 9.3 and also gfortran 8.2
and also 7.3 and also 6.4 and also 5.4 and also 4.8.2
One should note that compiling with intel compiler 2020u4 - compiles
succesfully and the output is:
head of initextended_struct, the input argument var1 = 10.00000
bf advance, extended1%var1 = 10.00000
head of advance, this%var1 = 10.00000
head of initextended_struct, the input argument var1 = 10.00000
as one can see - using intel compiler one has no problem and the value does not
change.
^ permalink raw reply [flat|nested] 8+ messages in thread
* [Bug fortran/101199] program changes the value of a dummy argument
2021-06-24 19:37 [Bug fortran/101199] New: program changes the value of a dummy argument ygalklein at gmail dot com
@ 2021-06-25 5:55 ` ygalklein at gmail dot com
2021-06-25 5:59 ` ygalklein at gmail dot com
` (5 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: ygalklein at gmail dot com @ 2021-06-25 5:55 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101199
--- Comment #1 from ygal klein <ygalklein at gmail dot com> ---
The problem stays for even a smaller example program:
``` fortran
module mod_original_struct
implicit none
private
public :: extended_struct
type original_struct
private
real, PUBLIC :: var1
contains
private
procedure, public :: init=>initoriginal_struct
end type original_struct
type, extends(original_struct) :: extended_struct
private
contains
private
procedure, public :: init=>initextended_struct, advance
end type extended_struct
contains
subroutine advance(this)
class(extended_struct), intent(inout) :: this
print*, 'head of advance, this%var1 = ', this%var1
call this%init(var1=this%var1)
end subroutine advance
subroutine initoriginal_struct(this, var1)
class(original_struct), intent(out) :: this
real, intent(in) :: var1
this%var1 = var1
end subroutine initoriginal_struct
subroutine initextended_struct(this, var1)
class(extended_struct), intent(out) :: this
real, intent(in) :: var1
print*, 'head of initextended_struct, the input argument var1 = ', var1
this%var1 = var1
end subroutine initextended_struct
end module mod_original_struct
program example
use mod_original_struct, only: extended_struct
implicit none
type(extended_struct) :: extended1
call extended1%init(var1=10.)
print*, 'bf advance, extended1%var1 = ', extended1%var1
call extended1%advance()
end program example
```
This is the wrong output coming from all gfortran versions (4.8.2, 5.4, 6.4,
7.3, 8.2, 9.3, 10.3 and 11.1):
head of initextended_struct, the input argument var1 = 10.000000000000000
bf advance, extended1%var1 = 10.000000000000000
head of advance, this%var1 = 10.000000000000000
head of initextended_struct, the input argument var1 = 0.0000000000000000
the dummy argument var1 changed its value at entrance to init from advance.
using intel 2020u4 provides the right output.
as presented in the first comment: The problem
^ permalink raw reply [flat|nested] 8+ messages in thread
* [Bug fortran/101199] program changes the value of a dummy argument
2021-06-24 19:37 [Bug fortran/101199] New: program changes the value of a dummy argument ygalklein at gmail dot com
2021-06-25 5:55 ` [Bug fortran/101199] " ygalklein at gmail dot com
@ 2021-06-25 5:59 ` ygalklein at gmail dot com
2021-06-25 13:17 ` juergen.reuter at desy dot de
` (4 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: ygalklein at gmail dot com @ 2021-06-25 5:59 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101199
--- Comment #2 from ygal klein <ygalklein at gmail dot com> ---
The problem also persists in an example code that is with no extended type:
```fortran
module mod_original_struct
implicit none
private
public :: original_struct
type original_struct
private
real, PUBLIC :: var1
contains
private
procedure, public :: init=>initoriginal_struct, advance
end type original_struct
contains
subroutine advance(this)
class(original_struct), intent(inout) :: this
print*, 'head of advance, this%var1 = ', this%var1
call this%init(var1=this%var1)
end subroutine advance
subroutine initoriginal_struct(this, var1)
class(original_struct), intent(out) :: this
real, intent(in) :: var1
print*, 'head of initoriginal_struct, the input argument var1 = ', var1
this%var1 = var1
end subroutine initoriginal_struct
end module mod_original_struct
program example
use mod_original_struct, only: original_struct
implicit none
type(original_struct) :: struct1
call struct1%init(var1=10.)
print*, 'bf advance, struct1%var1 = ', struct1%var1
call struct1%advance()
end program example
```
The gfortran wrong output is:
head of initoriginal_struct, the input argument var1 = 10.000000000000000
bf advance, struct1%var1 = 10.000000000000000
head of advance, this%var1 = 10.000000000000000
head of initoriginal_struct, the input argument var1 = 0.0000000000000000
using intel 2020u4 provides the right output.
^ permalink raw reply [flat|nested] 8+ messages in thread
* [Bug fortran/101199] program changes the value of a dummy argument
2021-06-24 19:37 [Bug fortran/101199] New: program changes the value of a dummy argument ygalklein at gmail dot com
2021-06-25 5:55 ` [Bug fortran/101199] " ygalklein at gmail dot com
2021-06-25 5:59 ` ygalklein at gmail dot com
@ 2021-06-25 13:17 ` juergen.reuter at desy dot de
2021-06-25 13:33 ` ygalklein at gmail dot com
` (3 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: juergen.reuter at desy dot de @ 2021-06-25 13:17 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101199
Jürgen Reuter <juergen.reuter at desy dot de> changed:
What |Removed |Added
----------------------------------------------------------------------------
CC| |juergen.reuter at desy dot de
--- Comment #3 from Jürgen Reuter <juergen.reuter at desy dot de> ---
I think that indeed this is not something the compiler needs to do as expected,
as it is an aliasing problem.
In the advance TBP you are calling again the init routine. The init
routines sets the value of this%var1 to the argument with which it is
called. In this%advance you are calling the init routine with the
argument this%var1. However, in the init routine, the struct1 type
is intent(out), so it is not guaranteed that the value of struct1%var1
is accessible when calling the init routine from an earlier initialization of
that type. That is the aliasing problem: advance calls
the init routine, the init routine creates a new instance of struct1
and you are not guaranteed that you can access the struct1%var1 component.
There are several ways out:
(1) define this in the init routine as intent(inout), very unusual for
an initializer, but then gfortran does what you expect
(2) define a global instance of struct1 in the module, e.g.
type(original_struct), save, public :: struct_global
and in advance then call the (before initialized)
this%init(struct_global%var1)
^ permalink raw reply [flat|nested] 8+ messages in thread
* [Bug fortran/101199] program changes the value of a dummy argument
2021-06-24 19:37 [Bug fortran/101199] New: program changes the value of a dummy argument ygalklein at gmail dot com
` (2 preceding siblings ...)
2021-06-25 13:17 ` juergen.reuter at desy dot de
@ 2021-06-25 13:33 ` ygalklein at gmail dot com
2021-06-25 13:45 ` juergen.reuter at desy dot de
` (2 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: ygalklein at gmail dot com @ 2021-06-25 13:33 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101199
--- Comment #4 from ygal klein <ygalklein at gmail dot com> ---
(In reply to Jürgen Reuter from comment #3)
> I think that indeed this is not something the compiler needs to do as
> expected, as it is an aliasing problem.
> In the advance TBP you are calling again the init routine. The init
> routines sets the value of this%var1 to the argument with which it is
> called. In this%advance you are calling the init routine with the
> argument this%var1. However, in the init routine, the struct1 type
> is intent(out), so it is not guaranteed that the value of struct1%var1
> is accessible when calling the init routine from an earlier initialization
> of that type. That is the aliasing problem: advance calls
> the init routine, the init routine creates a new instance of struct1
> and you are not guaranteed that you can access the struct1%var1 component.
> There are several ways out:
> (1) define this in the init routine as intent(inout), very unusual for
> an initializer, but then gfortran does what you expect
> (2) define a global instance of struct1 in the module, e.g.
> type(original_struct), save, public :: struct_global
> and in advance then call the (before initialized)
> this%init(struct_global%var1)
Thank you for the reply.
After posting the bug report - I saw that implementing (inout) as your number 1
suggestion - dodges the problem - though as you mentioned having inout for this
in an init routine is somewhat unnatural.
The 2nd suggestion is something that I was trying to avoid in the first place -
i.e copying a whole type (this minimal example is a small type - but originally
it is a type with a lot of instances and procedures)
In fact - I could have had advance as a function that returns a type - but then
I would be paying the price of copyin assignment of a big type.
Anyway - you conclude that gfortran is behaving as it should and that the fact
that ifort works - is somewhat a coincidence?
^ permalink raw reply [flat|nested] 8+ messages in thread
* [Bug fortran/101199] program changes the value of a dummy argument
2021-06-24 19:37 [Bug fortran/101199] New: program changes the value of a dummy argument ygalklein at gmail dot com
` (3 preceding siblings ...)
2021-06-25 13:33 ` ygalklein at gmail dot com
@ 2021-06-25 13:45 ` juergen.reuter at desy dot de
2021-07-12 14:58 ` tkoenig at gcc dot gnu.org
2021-07-12 16:26 ` tkoenig at gcc dot gnu.org
6 siblings, 0 replies; 8+ messages in thread
From: juergen.reuter at desy dot de @ 2021-06-25 13:45 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101199
--- Comment #5 from Jürgen Reuter <juergen.reuter at desy dot de> ---
(In reply to ygal klein from comment #4)
>)
>
> Thank you for the reply.
>
> After posting the bug report - I saw that implementing (inout) as your
> number 1 suggestion - dodges the problem - though as you mentioned having
> inout for this in an init routine is somewhat unnatural.
>
> The 2nd suggestion is something that I was trying to avoid in the first
> place - i.e copying a whole type (this minimal example is a small type - but
> originally it is a type with a lot of instances and procedures)
>
> In fact - I could have had advance as a function that returns a type - but
> then I would be paying the price of copyin assignment of a big type.
>
> Anyway - you conclude that gfortran is behaving as it should and that the
> fact that ifort works - is somewhat a coincidence?
Let's see what the gfortran developers have to say about this. In any case it
looks strange if you try to call an init routine from a different TBP of the
same object. An init routine is usually called only at the very instantiation
of the object. If you want a shallow copy then you need a pointer.
^ permalink raw reply [flat|nested] 8+ messages in thread
* [Bug fortran/101199] program changes the value of a dummy argument
2021-06-24 19:37 [Bug fortran/101199] New: program changes the value of a dummy argument ygalklein at gmail dot com
` (4 preceding siblings ...)
2021-06-25 13:45 ` juergen.reuter at desy dot de
@ 2021-07-12 14:58 ` tkoenig at gcc dot gnu.org
2021-07-12 16:26 ` tkoenig at gcc dot gnu.org
6 siblings, 0 replies; 8+ messages in thread
From: tkoenig at gcc dot gnu.org @ 2021-07-12 14:58 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101199
Thomas Koenig <tkoenig at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
CC| |tkoenig at gcc dot gnu.org
--- Comment #6 from Thomas Koenig <tkoenig at gcc dot gnu.org> ---
(In reply to Jürgen Reuter from comment #5)
> (In reply to ygal klein from comment #4)
> >)
> >
> > Thank you for the reply.
> >
> > After posting the bug report - I saw that implementing (inout) as your
> > number 1 suggestion - dodges the problem - though as you mentioned having
> > inout for this in an init routine is somewhat unnatural.
> >
> > The 2nd suggestion is something that I was trying to avoid in the first
> > place - i.e copying a whole type (this minimal example is a small type - but
> > originally it is a type with a lot of instances and procedures)
> >
> > In fact - I could have had advance as a function that returns a type - but
> > then I would be paying the price of copyin assignment of a big type.
> >
> > Anyway - you conclude that gfortran is behaving as it should and that the
> > fact that ifort works - is somewhat a coincidence?
>
> Let's see what the gfortran developers have to say about this. In any case
> it looks strange if you try to call an init routine from a different TBP of
> the same object. An init routine is usually called only at the very
> instantiation of the object. If you want a shallow copy then you need a
> pointer.
I can confirm Jürgen's analysis.
^ permalink raw reply [flat|nested] 8+ messages in thread
* [Bug fortran/101199] program changes the value of a dummy argument
2021-06-24 19:37 [Bug fortran/101199] New: program changes the value of a dummy argument ygalklein at gmail dot com
` (5 preceding siblings ...)
2021-07-12 14:58 ` tkoenig at gcc dot gnu.org
@ 2021-07-12 16:26 ` tkoenig at gcc dot gnu.org
6 siblings, 0 replies; 8+ messages in thread
From: tkoenig at gcc dot gnu.org @ 2021-07-12 16:26 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101199
Thomas Koenig <tkoenig at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
Status|UNCONFIRMED |RESOLVED
Resolution|--- |INVALID
See Also| |https://gcc.gnu.org/bugzill
| |a/show_bug.cgi?id=30373
--- Comment #7 from Thomas Koenig <tkoenig at gcc dot gnu.org> ---
This is indeed a problem with aliasing and INTENT(OUT).
When passing this to initoriginal_struct, specifying
intent(out) is telling the compiler that this%var1
contains random garbage, in other words, that you could also write
subroutine initoriginal_struct(this, var1)
class(original_struct), intent(out) :: this
real, intent(in) :: var1
call random_number(this%var1)
print*, 'head of initoriginal_struct, the input argument var1 = ', var1
this%var1 = var1
end subroutine initoriginal_struct
This will then show up the aliasing problem because var1 is aliased
to this%var1.
gfortran currently does not detect this. There is a longstanding
feature request about this, PR 30373.
Resolving as invalid.
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2021-07-12 16:26 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-06-24 19:37 [Bug fortran/101199] New: program changes the value of a dummy argument ygalklein at gmail dot com
2021-06-25 5:55 ` [Bug fortran/101199] " ygalklein at gmail dot com
2021-06-25 5:59 ` ygalklein at gmail dot com
2021-06-25 13:17 ` juergen.reuter at desy dot de
2021-06-25 13:33 ` ygalklein at gmail dot com
2021-06-25 13:45 ` juergen.reuter at desy dot de
2021-07-12 14:58 ` tkoenig at gcc dot gnu.org
2021-07-12 16:26 ` tkoenig at gcc dot gnu.org
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).