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

Using Optional assumed-shape array

abhimodak
New Contributor I
1,300 Views

Is there a special restriction on the "presence" of (an element from) assumed-shape optional array?

The program below throws access-violation at the call to "SomeMethod" when run in the debug mode if array M is assumed-shape. It works fine if array M has dimension specified (i.e. the commented-out line).

Abhi

p.s. Intuitively, may I say that it somewhat makes sense that when an element from an absent array is referred to, there can be a problem. But then it would be valid for any such variable and passing on the presence would not work at all. Humn, I am confused....

----

Module OptionalArray
Implicit None
Private
Integer :: nL
Public :: nL
Public :: ExposedMethod
Contains
Subroutine ExposedMethod(Strng, M)
Character(*), Intent(IN) :: Strng
Integer, Intent(IN), Optional :: M(:)
!Integer, Intent(IN), Optional :: M(nL)
Print *, Trim(Strng)
Call SomeSub(Strng, M(1))
End Subroutine ExposedMethod

Subroutine SomeSub(strng, i)
Implicit None
Character(*), Intent(IN) :: strng
Integer, Intent(IN), Optional :: i
if (Present(i)) then
Print *, " integer argument is present."
else
Print *, " integer argument is absent."
endif
End Subroutine SomeSub

End Module OptionalArray

Program Test_Optional

Use OptionalArray

Implicit None

Integer :: Q(10)

Q = 1
nL = Size(Q)

Print *, "First Call"
Call ExposedMethod("With Argument", Q)

Print *, "Second Call"
Call ExposedMethod("Without Argument")

End Program Test_Optional


0 Kudos
9 Replies
qolin
Novice
1,300 Views

You need to add a "USE OPTIONALARRAY" statement to program test_optional. Without this, test_optional doesn't know that exposedmethod has optional arguments, so it doesn't pass any of the additional info to allow the subroutine to know that one of them is not provided.

I must say I would expect the compiler to throw a warning when it finds 2 calls to the same routine with different numbers of arguments. Did you see any such warnings when you compiled?

Qolin

0 Kudos
qolin
Novice
1,300 Views
Sorry I am blind this morning, its allready there. Need some more coffee...
0 Kudos
qolin
Novice
1,300 Views

OK let's try again.

Probably need a judgement from the language police, but I think the use of M(1) counts as an "expression", or some other term, that means it doesn't conform to an "optional argument" for the purposees of being passed (or not) to SomeSub, depending on the presence (or not) of M in the call to ExposedMethod.

0 Kudos
IanH
Honored Contributor III
1,300 Views

F2003 12.4.1.6:

An optional dummy argument that is not present is subject to the following restrictions: ... (5) A designator with it as the base object and with at least one component selector, array section selector, array element selector, or substring selector shall not be supplied as an actual argument on pain of process death by access violation.

So you can't do it.

I think the access violation you see is actually caused by array bounds checking code (/check:bounds) trying to get the necessary bounds information out of the (not...) passed array descriptor for the assumed shape case. That's not required with the explicit shape case, because the bounds are, well... explicit.

0 Kudos
abhimodak
New Contributor I
1,300 Views

Many thanks IanH; that's precisely what I was looking for.

I was referring to page 477 of the Fortran 2003 Handbook by Adams et al.. I didn't find it among the 11 restrictions specified there but after reading your post and reading the definition of "subobject" on page 27 I find that the handbook entry -- "(6) A subobject of it must not be supplied as an actual argument." means the same thing.

You are also correct that it is the /check:bounds flag that gives access violation. Removing it would make the program go over it. {I, however, I find it to be untrue for DVF 6.6c where the access violation would come up in the release mode as well which does not have array-string-bounds check option ON.}

Since this (passing an element from a non-present array) is non-standard, the compiler should catch this error, shouldn't it? and that too regardless of what type of array it is...

One more question on the subobject being not allowed. Does this mean that the following should not work?

Subroutine ExposedMethod(n, Obj)
Implicit None
Integer, Intent(IN) :: n
Type(newDerived), Intent(IN), Optional :: Obj
Call Proc(n, Obj%Base)
End Subroutine ExposedMethod

Where the newDerived type is of the form

Type newDerived

Type(newBase) :: Base

End Type newDerived

Abhi

0 Kudos
Steven_L_Intel1
Employee
1,300 Views

The compiler is not required to detect all non-standard usages. In this case, the reference is only non-standard if the argument is omitted. You might have done a PRESENT test before passing it.

You are correct that the second example with Obj%Base is also not allowed.

0 Kudos
abhimodak
New Contributor I
1,300 Views

Thanks Steve. I think I understand what you mean. In fact, I have always been using the if (present) then and was just going through the language elements to brush-up things and hence this test.

Abhi

0 Kudos
Steven_L_Intel1
Employee
1,300 Views

Just to be clear - in some cases you are allowed to "pass through" the "omitted" aspect to another routine which has the argument also declared as optional. But you have to pass the whole variable, not a "subobject".

For further reading, see Doctor Fortran and the Virtues of Omission

0 Kudos
abhimodak
New Contributor I
1,300 Views

Yes Steve, I understand that the "absence" can be passed along; always using if(Present()) then may be considered conservative. With not understanding the "subobject" part, I was wondering if I was violating the standard or not and hence this thread.

By the way, I had read the Virtues of Omission article a long time back and have liked the 4 lines at the begining of it.

Abhi

0 Kudos
Reply