- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Is there a way to determine if, in a subroutine, a local variable was passed in as a literal or as a variable from the calling scope.
The result of the (if it could work) program would be as follows then:
"Passed through a variable 2"
a = 3 after this call
"Passed literal value 3"
Is this at all possible? Thanks.
[fortran]program main_program implicit none integer :: a a = 2 call foo( a) call foo( 3) end program subroutine foo( x) integer :: x ! Is there a way to do the following if( x passed as a literal) then print*, "Passed literal value", x elseif( x passed as a variable) then print*, "Passed through a variable", x x = x + 1 endif return end subroutine foo[/fortran]
The result of the (if it could work) program would be as follows then:
"Passed through a variable 2"
a = 3 after this call
"Passed literal value 3"
Is this at all possible? Thanks.
Link Copied
8 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
No, unless you put in such checks yourself and follow your conventions meticulously.
If there were a difference at subroutine entry between literals and variables, practically every large Fortran code in existence would stop working. With most Fortran compilers, a literal argument is handled by creating a temporary variable, assigning the literal value to that variable, and passing the temporary variable as the actual argument.
There are ways of protecting literal actual arguments from being modified by the callee, but it is best to fix the code such that this never happens.
If there were a difference at subroutine entry between literals and variables, practically every large Fortran code in existence would stop working. With most Fortran compilers, a literal argument is handled by creating a temporary variable, assigning the literal value to that variable, and passing the temporary variable as the actual argument.
There are ways of protecting literal actual arguments from being modified by the callee, but it is best to fix the code such that this never happens.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Bummer. That's pretty much what I thought, but I didn't know if there was new wizardry added to F95 or F2003 that allowed for such things. I'll try adding in an optional argument to these routines and make sure I follow my convention for now.... This is a big legacy code base and updating it to modern standards will have to occur slowly over time.
Thanks for the quick reply!
Thanks for the quick reply!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
For the simple case you give as an example, you could define
subroutine FOO(var, lit)
OPTIONAL var, lit
and call it using
Call Foo(var=A) or
Call Foo(lit=3)
and use
IF(Present(var))
or
If (Present(lit))
It all quickly gets out of hand if you have lots of arguments that can be either or.
subroutine FOO(var, lit)
OPTIONAL var, lit
and call it using
Call Foo(var=A) or
Call Foo(lit=3)
and use
IF(Present(var))
or
If (Present(lit))
It all quickly gets out of hand if you have lots of arguments that can be either or.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
This suggestion is non-portable.
The object code (I should rather say output data)produced by most compilers are multi-stream with each stream going into an entity called a segment ("segment" useddue to legacy reasons). There is typically the following segment classifications under various name: code, variable data, literal data, stack, other...
The trick (hack) is to invent some way to figure out which segment the subroutine argument resides in.
Most linkers build up the the contents of the various differentsegments in link order.
Therefore, if you have a link order of
link objhack1,prog, obja, objb, liba, libc, objhack2
and objhack1 is compiled from
integer(C_PTR) function hack1
hack1 LOC("hack1")
end function hack1
and hack2 is similar
Then if the LOC of the variable in question resides between hack1() and hack2() it resides within the static data segment.
** however
CALL FOO(1,2,3,4,5)
Will likelypass the numeric variables on stack as opposed to using an address to a numeric literal in the static data segment. Floating point constants would likely be passed by reference to a numeric literal in the static data segment.
Determination of "constantness" of integer numeric dummy variables would be problematic.
Note,
If you define and use the function/subroutine interface and USE the interface the /warn:checkinterfaces should warn if you pass a literal into an argument that is declared with INTENT(OUT) or INTENT(INOUT).
Jim Dempsey
The object code (I should rather say output data)produced by most compilers are multi-stream with each stream going into an entity called a segment ("segment" useddue to legacy reasons). There is typically the following segment classifications under various name: code, variable data, literal data, stack, other...
The trick (hack) is to invent some way to figure out which segment the subroutine argument resides in.
Most linkers build up the the contents of the various differentsegments in link order.
Therefore, if you have a link order of
link objhack1,prog, obja, objb, liba, libc, objhack2
and objhack1 is compiled from
integer(C_PTR) function hack1
hack1 LOC("hack1")
end function hack1
and hack2 is similar
Then if the LOC of the variable in question resides between hack1() and hack2() it resides within the static data segment.
** however
CALL FOO(1,2,3,4,5)
Will likelypass the numeric variables on stack as opposed to using an address to a numeric literal in the static data segment. Floating point constants would likely be passed by reference to a numeric literal in the static data segment.
Determination of "constantness" of integer numeric dummy variables would be problematic.
Note,
If you define and use the function/subroutine interface and USE the interface the /warn:checkinterfaces should warn if you pass a literal into an argument that is declared with INTENT(OUT) or INTENT(INOUT).
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
This program works fine. Why is it non-portable?
Module varlit
contains
subroutine foo(var,lit)
optional var, lit
integer :: var , lit
if( Present(lit)) then
print*, "Passed literal value", lit
elseif( Present(var)) then
print*, "Passed through a variable", var
var=var + 1
endif
return
end subroutine foo
end module
program main_program
use varlit
implicit none
integer :: a
a = 2
call foo( var=a)
call foo( lit=3)
end program
Module varlit
contains
subroutine foo(var,lit)
optional var, lit
integer :: var , lit
if( Present(lit)) then
print*, "Passed literal value", lit
elseif( Present(var)) then
print*, "Passed through a variable", var
var=var + 1
endif
return
end subroutine foo
end module
program main_program
use varlit
implicit none
integer :: a
a = 2
call foo( var=a)
call foo( lit=3)
end program
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Supposing it could be done, what use would you have for the information? Can you cite situations where this knowledge would be very beneficial to have?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Anthony,
While your program is portable it does not solve the original poster's dilemma. I assume:
mford78 is the author of a subroutine that sits in a library and he is in no control of the source code of users (calls) of (to) his subroutine and therefore cannot enforce a literal flag upon the call statements. The intent of mford78 is to place defensive code into the subroutine to assert that the modifiable variables are indeed variables (not literals).
The likely best way to handle this is through an interface declaration (and required use of the interface).
In situations where an interface cannot be use then the hack presented earlier might be the only option available to at least catch calls with variables contained within the static data segment. Those literalspushed on the stack become variables and mutability of these variables would do no harm excepting where these are returning values to be used elsewhere (and are not use).
Jim Dempsey
While your program is portable it does not solve the original poster's dilemma. I assume:
mford78 is the author of a subroutine that sits in a library and he is in no control of the source code of users (calls) of (to) his subroutine and therefore cannot enforce a literal flag upon the call statements. The intent of mford78 is to place defensive code into the subroutine to assert that the modifiable variables are indeed variables (not literals).
The likely best way to handle this is through an interface declaration (and required use of the interface).
In situations where an interface cannot be use then the hack presented earlier might be the only option available to at least catch calls with variables contained within the static data segment. Those literalspushed on the stack become variables and mutability of these variables would do no harm excepting where these are returning values to be used elsewhere (and are not use).
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
OK I hadn't appreciated that.

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