- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
TYPE foo INTEGER :: a INTEGER :: b CHARACTER(LEN=32) :: c END TYPE foo SUBROUTINE bar(fd) TYPE(foo), INTENT(OUT) :: fd fd%a = 1 END SUBROUTINE bar SUBROUTINE baz(fd) TYPE(foo), INTENT(INOUT) :: fd fd%b = 47 fd%c = 'dog' CALL bar(fd) END SUBROUTINE baz
The behaviour I have observed using the Intel compiler is that after the call to bar from within baz, the fd%c and fd%b members have been cleared (i.e. they do not contain the values 'dog' and 47). The only way to preserve the values is to have INTENT(INOUT) in bar.
I have not delved into the language spec, but the behaviour struck me as unusual until I thought about it some. I can see the logic behind it, however, I want to determine if this behaviour is in the standard or is it compiler dependent. Thanks
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The wording in the standard is as follows:
(13) When a procedure is invoked
5 (a) An optional dummy argument that is not associated with an actual argument becomes
6 undefined;
7 (b) A dummy argument with INTENT (OUT) becomes undefined except for any non
8 pointer default-initialized subcomponents of the argument;
9 (c) An actual argument associated with a dummy argument with INTENT (OUT) be-
10 comes undefined except for any nonpointer default-initialized subcomponents of the
11 argument;
12 (d) A subobject of a dummy argument that does not have INTENT (OUT) becomes
13 undefined if the corresponding subobject of the actual argument is undefined; and
14 (e) The result variable of a function becomes undefined except for any of its nonpointer
15 default-initialized subcomponents.
I assume that the real code has a CONTAINS in there somewhere...
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The fact that the INTENT(OUT) in the subroutine bar will change all the members of the derived type in the baz subroutine caught me by suprise. I guess one should only use INTENT(OUT) with a derived type with great care.
- 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
Steve,
Regarding the wording of the standard - could you rephrase it. As worded it does not make sense (to me). Example
(a) An optional dummy argument that is not associated with an actual argument becomes undefined;
Dummy arguments are (to the subroutine or function) symbolic references to one of
a) a reference (address)of a callers argument
b) a value of a callers argument
c) an indication of a missing argument for an optional argument not supplied
d) undefined for an argument not supplied by the caller but specified by the interface
e) trash for arguments supplied that do not conform to interface but somehow manage to reach the subroutine/function
The point is the the argument does not become it is.
Although this may seem like a picky little grammatical issue, the (mis)choice of the word is propagated to the remainder clauses (b, c, d, e) and thus compounds the confusion.
For (13)(b) A dummy argument with INTENT (OUT) becomes undefined except for any non-pointer default-initialized subcomponents of the argument;
The purpose of the INTENT attribute is as a programming aid to help the compiler detect programming errors at compile time. INTENT(OUT) declares that (should the dummy argument refer to a properly supplied argument on call) the initial state of the variable is undefined. As such, if used without first being set, report, at compile time, as an error in programming. INTENT(OUT) does not mean the state of the variable becomes undefined and as suchthe code is required (or free) to muck up the state of the variable without explicit statementsin the code. (i.e. as punishment for not writing good code).
It would be of benefit to some of the forum readers to have some clarification on this issue. My preference would be something along the lines of
Assuming caller supplies actual arguments conforming to calling interface:
INTENT(OUT) - Assert, at compile time, that should the code read from the referenced variable that the code had previouslywritten to the referenced variable. i.e. Assert, at compiletime, that the variable is initialized prior touse. And Warn, if the INTENT(OUT) argument is not written to.
INTENT(IN) - Assume the supplied referenced variable has been initialized and Assert, at compile time, that the code nevermodify the referenced variable.
INTENT(INOUT) -Assume the supplied referenced variable has been initialized. The code is free to modify the value of the referenced variable.
Regarding user defined types and INTENT
When a user defined typeis declared, values of sub-objects not initialized are undefined and remain undefined until initialized.
Compilcating circumstances:
For a single threaded application running on a single processor it is traditional for arguments passed by reference to have the subroutine or function to modify the variable(s) referenced by the argument in-situ (in place). Whenan application evolves to say an MPI type of application (Message Passing Interface) then the environment may necessitate that dummy arguments, specified as callby reference, be passed (to, to/from, from) by a messaging system transparent to the call stateme nt.
As a perfomance optimization, arguments specified with INTENT(OUT) need not be passed to the called subroutine via the messaging system. i.e. no requirement to send uninitialized variables through the messaging system. It should be noted by the programmer, that should the called subroutine not initialize the variables specified with INTENT(OUT), that the values returned willremain undefined, but of particular interest, the undefined values may be different than those contained prior to call. i.e. For INTENT(OUT) uninitialized variables returned from call (via messaging system) are undefined but need not remain thevalues fromprior to call.
What this means is the behavior is (may be) different depending on environment (unified system or message passing system).
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I don't agree with your rephrasing. The standard's wording can sometimes be obtuse, and you often need to go look at several different places in the standard to see what words mean for the purpose of the standard, but in general it "means what it says".
For optional arguments, the idea is that if you have an optional dummy argument not associated with an actual, that dummy argument is undefined on entry to the procedure. So, if you use its value, what happens is undefined. You know, of course, to always protect such references with PRESENT() but the standard needs to specify that the value is undefined.
When the standard says that an INTENT(OUT) dummy and any associated actual argument become undefined, it means exactly that. The dummy starts out undefined, and the actual becomes undefined. If the actual is an allocatable, for example, it gets deallocated automatically.
With an actual that is derived type, what happens depends on whether the type has default initialization specified for any of the components. If it does, those components become defined with the default values, all others become undefined. (and if those components are allocatable, they are deallocated.)
The act of "becoming undefined" does not necessarily mean that the value in memory changes, but it might. The key point here is that a standard-conforming program cannot tell if the value changes or not.
The moral of this story is that you should use INTENT(OUT) only if the called procedure completely defines the dummy argument before returning. If you want any values passed in to survive, you must use INTENT(INOUT) instead.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Steve,
>> The moral of this story is that you should use INTENT(OUT) only if the called procedure completely defines the dummy argument before returning. If you want any values passed in to survive, you must use INTENT(INOUT) instead.
Fair enough.
However, it is pure insanity to permit code to arbitrarily trash memory. (We all accept that trashing memory is the prerogative of the programmer)
>> If the actual is an allocatable, for example, it gets deallocated automatically.
SUBROUTINE FOO(A)
REAL, ALLOCATABLE :: A(:)
REAL, ALLOCATABLE :: B(:)
! implies an initialization code of
!IF(ALLOCATED(A)) DEALLOCATE(A)
!(initialize B descriptor to unallocated)
! explicit code follows
As for defined types. The question is: is how to identify a member of a defined type as INTENT(OUT) without unintentionally modifying the other (and possibly unknown) members of the drive type?
SUBROUTINE FOO(aFOO)
TYPE(TypeFOO), INTENT(INOUT):: aFOO
INTENT(OUT) :: aFOO%aMember
Is that valid?
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Note that for the ALLOCATABLE example, the dummy arguments have to have INTENT(OUT) in order for the automatic deallocation occur.
You want INTENT(INOUT). Don't try to stretch INTENT(OUT) into something it isn't. The only exception is that if you declare type TypeFOO to have components with default initialization. Then those components will be (re) initialized on entry to the routine.

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