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

Passing array/skalar to a subroutine and switch /check:arg_temp_created

rwg
Beginner
893 Views
I have following subroutines:

SUBROUTINE SUB1(SCALAR)
INTEGER,INTENT(OUT)::SCALAR
SCALAR=...
ENDSUBROUTINE SUB1

SUBROUTINE SUB2(ARRAY,N)
INTEGER,INTENT(IN)::N
INTEGER,INTENT(IN)::ARRAY(*)
DO I=1,N
...ARRAY(I)...
DONE
ENDSUBROUTINE SUB2

and call them this way:

PROGRAM TEST
INTEGER IAR
CALL SUB1(IAR)
CALL SUB2((/IAR/),1)
END

Compiled with switches /gen-interfaces, /warn:interfaces and /check:arg_temp_created I get a run-time error which says an array temporary was created for argument #1

I've two questions concerning this:

1. Is it really true that an array is temporary created? In this special case (passing a scalar) only the address of iar has to be passed so a temporary array is unneeded.

2. Is there a way to avoid this runtime error and not to remove one of the switches /gen-interface, /warn:interface and /check:arg_temp_created? I know that I can declare IAR as an array and pass IAR(1) to SUB1 but is there a way to let IAR be a skalar an use SUB2 without any overhead?
Why I ask this? I've lots of old fortran77 subroutines to which sometimes a skalar is passed and sometimes an array. Adding (/ and /) around skalars in the calling subroutine is easy but changing the skalar to an array will result in compile errors for the other subroutines which needs a scalar.
0 Kudos
8 Replies
jimdempseyatthecove
Honored Contributor III
893 Views
On the second CALL statement you have

'(/IAR/)' with ()'s

This produces an expression with an array.
The /IAR/ creates and array.
The enclosing ()'s is an expression that creates another array.

Try removing the ()'s.

However, this will remove one of the twoarray creations.

Since this is an old program, it likely contains COMMON's and maybe EQUIVILANCE's. Why not declare in COMMON a one element array and a scalar that is EQUIVILANCED to the 1'st (only) cell.

Jim Dempsey
0 Kudos
Steven_L_Intel1
Employee
893 Views
Jim is close, but not quite right. (/ and /) are the Fortran 90/95 delimiters for an array constructor. Fortran 2003 allows [ ] as an alternative. In this case, the parentheses are part of the constructor syntax.

The issue here is that the compiler needs to create a temp to hold the array constructor value that is built from a variable. If you ask for the run-time warning when an array temp is created, you'll get one here too.

You might want to consider writing an ELEMENTAL subroutine which accepts a scalar but can also be called with an array. I am not sure what you are trying to accomplish here so that may not be what you need.
0 Kudos
rwg
Beginner
893 Views
I've a lot of very long fortran 77subroutines like this

SUBROUTINE TEST
INTEGER SCALAR
...
CALL SUB1(SCALAR) ! called 50 times
...
CALL SUB2(SCALAR) ! called 2 times
...
END

where in SUB2 SCALAR ist declared as INTEGER SCALAR(*) and in SUB1 SCALAR is declared as INTEGER SCALAR.

I can not compile these subroutines with switches /gen-interface and /warn:interface because SUB2 wants an array and not a scalar. I'm just looking for a simple solution to get subroutines like TEST compiled.

Changing CALL SUB2(SCALAR) to CALL SUB2((/SCALAR/)) solves the problem but I got the runtime error.

I hopedthe compiler does not create an array descriptor because he can see the interface and so he knows he has to pass only the address ofSCALAR to SUB2. An array descriptor is not needed in this special case. I think there is no way to tell the compiler to create only array descriptors when needed?

The other solution is to change the declaration of SCALAR in TEST from INTEGER SCALAR to INTEGER SCALAR(1). But then I've to change all calls of SUB1to CALL SUB1(SCALAR(1)) which is much more to do. Has someone a simpler solution to get subroutines like TEST compiled with /gen-interfaces /warn:interfaces and /check:arg_temp_created?
0 Kudos
Arjen_Markus
Honored Contributor I
893 Views

You may create a generic interface for two versions of SUB2 - one using an integerSCALAR and
one using an integer SCALAR(*). You will have to define a proper set of interfaces though (preferrably
via a module). But then the need for /gen-interfaces is becoming much smaller :)

Regards,

Arjen

0 Kudos
Steven_L_Intel1
Employee
893 Views
The simplest solution is to turn off the optional (and non-default) run-time warning (not an error) for temporary array arguments, and then just keep the code you have. In Visual Studio, this is Run-Time > Check for Actual Arguments Using Temporary Storage.
0 Kudos
rwg
Beginner
893 Views
Yes Arjen,
I did this already for some very often called subroutines. I renamed them to xxx_genmod.f and compiled them into the directory where the complier places the interfaces generated with /gen-interface. This works (with some restrictions) but it's a lot of work and to seperate the definition of a subroutine from the source code is not nice.
Creating modules is not an option because there are too many subroutines. But thanks for this suggestion.

Ralf
0 Kudos
Arjen_Markus
Honored Contributor I
893 Views
Hm, I think you misunderstand:

module something
contains
subroutine sub1
end subroutine
subroutine sub2
end subroutine
...
end module

is perfectly valid - and because of the use of a module you do NOT need to
separate the interface from the code. That is what the module will take care of.

Regards,

Arjen
0 Kudos
rwg
Beginner
893 Views
Thanks Steve,

I think I sadly have to abandon the option /check:arg_temp_created.

By the way, the dialog box with the warning is titled with "Intel Visual Fortran run-time-error". That's the reason why I called it an error. The text in the dialog box states more precisly " forrtl: warning ..."


Ralf
0 Kudos
Reply