- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
I'm wondering is the following code is valid.
I'm defining a type bound procedure which has 2 argument:
- the passed-object dummy argument with the attribute 'intent(inout)'
- a integer variable with the attribute 'intent(in)'
If the actual argument associated to the dummy argument n°2 is a component of the passed-object dummy argument and if this component is modified in the TBP, then there is an inconsistency since the argument n°2 is declared as 'intent(in)' but its value is actually changing.
Below, an example which run without any warnings or errors
! ifort main.f90; ./a.out Module MyModule implicit none private public :: MyType Type :: MyType integer :: Var contains procedure ,public :: Do_Something_Inconsistent End Type contains Subroutine Do_Something_Inconsistent( This, Var ) class(MyType) ,intent(inout) :: This integer ,intent(in) :: Var This%Var = Var + 1 End Subroutine End Module Program Main use MyModule ,only: MyType implicit none type(MyType) :: Obj Obj%Var = 1 write(*,"('BEFORE: Obj%Var = ',g0)") Obj%Var call Obj%Do_Something_Inconsistent( Obj%Var ) ! Is this valid write(*,"('AFTER: Obj%Var = ',g0)") Obj%Var End Program
sd
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
It's not legal Fortran, as it violates the aliasing rules, but a compiler is not required to diagnose it. Intent has nothing to do with it other than it is the programmer's promise as to what will happen.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Enclosing the argument in parentheses should make the call valid:
call Obj%Do_Something_Inconsistent( ( Obj%Var ) )
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Steve,
I do not think this "violates" the aliasing rules. Rather, this is an exemplar of "using arguments that alias one another may produce unpredictable results".
Perhaps there could be a compiler option or better, !DEC$, that generates warnings for arguments that alias.
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
It's not that simple. The standard doesn't prohibit aliasing, per se, but it restricts what you can do if arguments are aliased, depending on argument attributes. In this case, the program violates the rules of the following section, in particular (3) and (4):
1 12.5.2.13 Restrictions on entities associated with dummy arguments
2 1 While an entity is associated with a dummy argument, the following restrictions hold.
3 (1) Action that affects the allocation status of the entity or a subobject thereof shall be taken through
4 the dummy argument.
5 (2) If the allocation status of the entity or a subobject thereof is affected through the dummy argument,
6 then at any time during the invocation and execution of the procedure, either before or after the
7 allocation or deallocation, it shall be referenced only through the dummy argument.
8 (3) Action that affects the value of the entity or any subobject of it shall be taken only through the
9 dummy argument unless
10 (a) the dummy argument has the POINTER attribute or
11 (b) the dummy argument has the TARGET attribute, the dummy argument does not have INTENT
12 (IN), the dummy argument is a scalar object or an assumed-shape array without the CONTI-
13 GUOUS attribute, and the actual argument is a target other than an array section with a
14 vector subscript.
15 (4) If the value of the entity or any subobject of it is affected through the dummy argument, then at
16 any time during the invocation and execution of the procedure, either before or after the definition,
17 it may be referenced only through that dummy argument unless
18 (a) the dummy argument has the POINTER attribute or
19 (b) the dummy argument has the TARGET attribute, the dummy argument does not have INTENT
20 (IN), the dummy argument is a scalar object or an assumed-shape array without the CONTI-
21 GUOUS attribute, and the actual argument is a target other than an array section with a
22 vector subscript.
This is not something detectable without generating run-time checking code and it's complex. We do have an option, /assume:dummy_alias, which will effectively remove this restriction by disabling certain optimizations.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
What is the effect of enclosing the argument in parentheses ?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Trying this program will show you the effect (in essence, the variable becomes an expression):
program xparen implicit none integer :: i=3 call sub(i) write(*,*)i call sub((i)) write(*,*)i end program xparen subroutine sub(i) implicit none integer :: i i=i+1 return end subroutine sub
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
And the effect of that is that a temporary copy of the value is passed - that copy can be modified but the modifications are discarded when the procedure returns.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Steve Lionel (Intel) wrote:
And the effect of that is that a temporary copy of the value is passed - that copy can be modified but the modifications are discarded when the procedure returns.
To avoid any misunderstandings, let me point out that what Steve said is practically true of the Intel implementation and most other implementations, but it is almost backwards with respect to the standard. The standard expects the expression to be evaluated as part of the procedure invocation and that it should remain unchanged throughout the execution of the procedure. (Indeed, some implementations put the value of some expressions in read-only memory to give them hardware protection against being changed.) By copying the value of the expression into a temporary location, the implementation makes it possible to change the value of the original variable without modifying the previously computed value of the expression.
Steve's description is much closer to the standard's idea of the effect of the VALUE attribute on a dummy argument.
-Kurt
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
mecej4 wrote:
Trying this program will show you the effect (in essence, the variable becomes an expression):
program xparen implicit none integer :: i=3 call sub(i) write(*,*)i call sub((i)) write(*,*)i end program xparen subroutine sub(i) implicit none integer :: i i=i+1 return end subroutine sub
For the record, this program will work in Intel's implementation and many others, but it does not conform to the Fortran standard, because one is not allowed to redefined a dummy argument associated with an actual argument that is an expression.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
sd could use VALUE in place of intent(in) to provide some measure of protection in event that the input argument would unexpectedly change through the modification of an intent(inout) variable. This way, sd won't have to hunt down all calls and add () where appropriate.
That said, the code could conceivably have been written to obfuscate the fact that the intention was to expressly modify the intent(in) variable.
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
hrichert728 is correct.
![](/skins/images/2E08A100FB92911314A240D1EAFB2828/responsive_peak/images/icon_anonymous_message.png)
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page