- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
See https://godbolt.org/z/dssaono3d line 11
Both ifx and ifort accept it, every other compiler that I try rejects this code. Is this a compiler bug?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Please add the code so one does not have to go and find it, I know it is simple but it would be simpler to do this.
module mod_a
implicit none
private
end module mod_a
module mod_b
implicit none
private
contains
subroutine f(x)
use mod_a, only: x ! <== This should not be possible!
integer, intent(out) :: x
x = 10
end subroutine f
end module mod_b
program main
use mod_b, only:
implicit none
end program main
original above and then modified
module mod_a
implicit none
private
end module mod_a
module mod_b
implicit none
public
contains
subroutine f(x)
use mod_a, only: x ! <== This should not be possible!
integer, intent(out) :: x
x = 10
end subroutine f
end module mod_b
program main
use mod_b, only: f
implicit none
integer X
x = 1
call f(x)
write(*,*)X
end program main
It compiles and runs with minor mods, mod_a is never called so I assume the compiler is smart enough to ignore it. but it should flag an error.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I will open a feature request for a warning for this case.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
module mod_a
implicit none
public
contains
subroutine x1(f)
integer, intent(INOUT) :: f
f = 2
return
end subroutine x1
end module mod_a
module mod_b
implicit none
public
contains
subroutine f(x)
use mod_a, only: x1 ! <== This should not be possible!
integer, intent(out) :: x
integer a
a = 200
write(*,*)a,x
call x1(a)
write(*,*)a
end subroutine f
end module mod_b
program main
use mod_b, only: f
implicit none
integer X
x = 1
write(*,*)x
call f(x)
write(*,*)X
end program main
Why does line 22 not throw an error as the value coming in should be indeterminate, even though I set it in main. It prints as 1. intent(out) should not pass anything in, that is intent(in) or intent(inout)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Well line 22 is a bug in the code, but the compiler is not obliged to tell you that, like with many code bugs. In standard speak on entry X becomes undefined, that does not mean the value in memory necessarily changes, it may or may not. It is undefined. Warn Uninit, might give an error but that feature in Intel is pretty hit and miss with scalers.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Fortran is pass by reference. So I understand what you are saying, but the INTENT(OUT) should override the pass by reference otherwise it is no different to INTENT(INOUT), there has to be an order of precedence.
X11 should not be the same as X coming in, but X is the same as X11 going out.
Otherwise intent(in) has no meaning in reality.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Intent(out) does do more for vars with ptr or allocatable attributes or derived types with components that have an initialiser/default. Other than that you are asking for more than the standard defines and what it does define is clear (but maybe not obvious). It is one of those things you just have to get right as a programmer. The compiler in most instances does stop you redefining intent(in) where it can see that you are violating that, e.g. simple assignment.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I understand what you are saying, but I disagree with the philosophy, if I write intent(out) then the compiler should by default discard any value I read into the call, otherwise there is no point to the intent statement, it definitely blocks the out if I leave it out.
I have not read the standard, so could you show me where to find it?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
INTENT
Statement and Attribute: Specifies the intended use of one or more dummy arguments.
The INTENT attribute can be specified in a type declaration statement or an INTENT statement, and takes one of the following forms:
Type Declaration Statement:
type,[att-ls,] INTENT (intent-spec) [, att-ls] :: d-arg[, d-arg]...
Statement:
INTENT (intent-spec) [::] d-arg[, d-arg] ...
type
Is a data type specifier.
att-ls
Is an optional list of attribute specifiers.
intent-spec
Is one of the following specifiers:
IN
Specifies that the dummy argument will be used only to provide data to the procedure. The dummy argument must not be redefined (or become undefined) during execution of the procedure.
OUT
Specifies that the dummy argument will be used to pass data from the procedure back to the calling program. The dummy argument is undefined on entry, although it may have subcomponents that are initialized by default. An undefined argument must be defined before it is referenced in the procedure.
Any associated actual argument must be definable.
INOUT
Specifies that the dummy argument can both provide data to the procedure and return data to the calling program.
Any associated actual argument must be definable.
d-arg
Is the name of a dummy argument or dummy pointer. It cannot be a dummy procedure.
Clearly the Intel Intent is that without "in" then the dummy variable in the procedure is undefined. An undefined argument must be defined before it is referenced in the procedure.
module mod_a
implicit none
public
contains
subroutine x1(f)
integer, intent(INOUT) :: f
f = 2
return
end subroutine x1
end module mod_a
module mod_b
implicit none
public
contains
subroutine f(x11)
use mod_a, only: x1 ! <== This should not be possible!
integer, intent(out) :: x11
integer a
a = 200
write(*,*)a,x11
call x1(a)
call x1(x11)
write(*,*)a,x11
end subroutine f
end module mod_b
program main
use mod_b, only: f
implicit none
integer X
x = 1
write(*,*)x
call f(x)
write(*,*)X
end program main
This is a compiler bug, at line 22, X11 should be undefined, nothing should have been passed in, but it has been set to X no matter what value I give X, and X and X11 are not the same memory slot.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
undefined has a defined meaning within the standard, if you want undefined to mean 'initialised with something' that that isn't what you get. There would be an overhead in doing a default initialisation e.g. NaN, it is down to the programmer to ensure variables are initalised before use and intent(out) get defined, that compiler can help but it is under no obligation to do so and in some cases couldn't anyway,
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Two things. First, if INTENT is unspecified, then that says nothing about the definition status of the effective argument nor whether it is allowed to be defined in the procedure. Second, Fortran is not "pass by reference", even if it seems that way most of the time.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
module mod_a
implicit none
public
contains
subroutine x1(f)
integer, intent(INOUT) :: f
f = 2
return
end subroutine x1
end module mod_a
module mod_b
implicit none
public
contains
subroutine f(x11)
use mod_a, only: x1 ! <== This should not be possible!
integer, intent(out) :: x11
integer x , a, b, c, d
a = 200
b = 400
c = 600
d = 80000
write(*,30)x11,loc(x11)
write(*,40)a,loc(a)
x = loc(x11) - loc(a)
write(*,20)(x)
x = loc(b) - loc(a)
write(*,50)(x)
x = loc(c) - loc(b)
write(*,60)(x)
x = loc(d) - loc(c)
write(*,70)(x)
call x1(a)
call x1(x11)
write(*,40)a,loc(a)
write(*,30)x,loc(x11)
20 Format(" Numerical difference in X to a location :: ",I20, " in module B")
30 Format(" Value of X11 :: ", I20, " Location of X11 :: ",I16, " in module B")
40 Format(" Value of a :: ", I20, " Location of a :: ",I16, " in module B")
50 Format(" Numerical difference in b to a location :: ",I20, " in module B")
60 Format(" Numerical difference in c to b location :: ",I20, " in module B")
70 Format(" Numerical difference in d to c location :: ",I20, " in module B")
return
end subroutine f
end module mod_b
program main
use mod_b, only: f
implicit none
integer p
integer k
integer X
POINTER(p, k)
INTEGER j(2)
integer, target :: a
integer, pointer :: b
b => a
write(*,10) loc(a), loc(b)
10 Format(" Location of a :: ", I20, " Location of b :: ",I20, " in main programme")
x = loc(a) - loc(b)
write(*,20)(x)
20 Format(" Numerical difference in a to b location :: ",I20, " in main programme")
x = 100
write(*,30)x,loc(x)
30 Format(" Value of X :: ", I22, " Location of X :: ",I18, " in main programme")
call f(x)
write(*,40)x,loc(x)
40 Format(" Value of X :: ", I22, " Location of X :: ",I18, " in main programme")
! This has the same effect as j(1) = 0, j(2) = 5
write(*,*)j(1),j(2)
p = LOC(j)
write(*,*)j(1),j(2),p,k
k = 0
write(*,*)j(1),j(2),p,k
p = p + SIZEOF(k) ! 4 for 4-byte integer
write(*,*)j(1),j(2),p,k
k = 5
write(*,*)j(1),j(2),p,k
end program main
The Fortran manual said that It is almost always pass by reference, I missed the almost on first reading.
At line 19 I am thinking I am saying to the program discard any value that comes with X11, but it does not, it has been passed the address and the value. I was not intending to leave INTENT(IN) out I am assuming that INTENT(OUT) means you discard the in, that is how it appears to be referenced in the INTENT pages I read in the Fortran manuals.
I borrowed Line 78 to the end from the Intel manual, if you run the code, you never see in the watch window, k and P turns up as an integer 8 and not 4. Perhaps someone could explain the finer points. The order on Line 20 is important, if I interchange the X and A then the numerical difference from B to A rises to 8.
For all purposes X and X11 are identical at all times.
If I change line 19 to intent(in) then the compiler honours the not OUT, see picture
I was expecting a symmetric function on inout, but it is not.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
When I read a subroutine and I see intent(out) that tells me:
1) The programmer intended that the variables value will always be defined within the subroutine. If that does not happen that is a programming bug.
2) The variable prior to that definition is undefined and therefore its contents are immaterial. The variable must not be used before it is initialised. If it is then that is a programming bug.
John you are expecting more. You are expecting that because a variable has a value before the call then on entry to the subroutine the corresponding dummy arg should be set to something different otherwise you deem it has been passed in. Why would a compiler waste (potentially a lot of time) time doing that given points 1 and 2?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
To add to Andrew's point, a dummy argument with INTENT(OUT) becomes undefined at entry to the procedure. If the argument is allocatable and is allocated, it gets automatically deallocated.

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page