Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
29274 Discussions

Component of derived type as optional argument

trobitaille
Beginner
371 Views
Hi,

I'm running into what I thought was a bug with ifort XE, but it seems that all compilers behave in the same way, so I'm just posting for general advice. In the following example, the value of opt inside the subroutine is 0 when I was expecting 1. What must be happening is that the first argument of the subroutine is reset to default values as soon as it is passed because of the intent(out). Is that correct? I guess that this is because the values are being passed by reference, not by value, so a%opt changes straight away before it is used? However, there is no way to use the 'value' keyword with the 'optional' keyword, so is the only way around this to create a new variable to contain a%opt before the subroutine call and then to call it with that?
[fortran]program test

  type test_type
     integer :: opt = 0
  end type test_type

  type(test_type) :: a

  a%opt = 1

  call sub(a, opt=a%opt)

contains

  subroutine sub(b, opt)
    implicit none
    type(test_type),intent(out) :: b
    integer,optional,intent(in) :: opt
    print *, present(opt)
    if(present(opt)) then
       print *,opt
    end if
  end subroutine sub

end program test
[/fortran]
Thanks for any advice,
Thomas
0 Kudos
1 Reply
Hirchert__Kurt_W
New Contributor II
371 Views
1. This program is not standard conforming. (If you pass the same or overlapping actual arguments to two different dummy arguments, you are prohibited from changing either.) However, compilers are not required to diagnose this error.

2. Your analysis of how ifort is handling your erroneous program appears to be essentially correct.

3. You can make your program correct and get the behavior you want by making the actual argument for opt an expression rather directly using the component. E.g.,

callsub(a,opt=(a%opt))

or

callsub(a,opt=a%opt+0)

In either case, the compiler will evaluate the expression into a temporary location and pass that location rather than the component, so its resetting of the b (and thus a) will not affect the value of opt.

-Kurt
0 Kudos
Reply