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

Passing a derived variable to a subroutine

dboggs
New Contributor I
2,950 Views
I am fairly new at this (F90), an old-school F77 programmer. I'm having trouble fully understanding the use of derived variables, especially regarding passage to subroutines. So please forgive me if this is a stupid question/comment.

I have condensed my rather large (10,000 line) legacy program to the following minimilist demo. I had presumed that a derived variable (say XMAIN) could be defined in a main routine (say TRYIT) and passed to a subroutine (say SUBROUTINE SUBPROC) where it is received as a dummy argument (say XSUB). That is, as long as the subroutine includes the very same TYPE definition as the main routine. And, in CVF if find that it works just fine. In IVF (2011)it fails to compile,giving error 6633 "The type of the actual argument differs from the type of the dummy argument."

Digging deeper, I found that it can be made to work in IVF by adding the statement SEQUENCE to the type definition, as indicated below. I infer from even the CVF documentation that this statement should be needed;could it be that this requirement was not envorced by CVF but it is in IVF? I'm not sufficiently comfortable with this concept yet to know if I am inferring correctly!

Finally, I know that this concept works much better if the subroutine can be CONTAINed in the main routine, or ifit can be relegated to a module. Please accept that for the time being I need to proceed as follows!


PROGRAM TRYIT
! Experimenting with passing derived variables to a subroutine.
TYPE X_DERIVED
SEQUENCE ! Needed for IVF, not for CVF
INTEGER(2) IX
REAL(4) RX
CHARACTER(6) TEXT
END TYPE
TYPE (X_DERIVED) XMAIN

XMAIN.IX = 2
XMAIN.RX = 12.34
XMAIN.TEXT = 'LabelX'
PRINT *, 'From main program: ', XMAIN
CALL SUBPROC (XMAIN)
END PROGRAM TRYIT

SUBROUTINE SUBPROC (XSUB)
TYPE X_DERIVED
SEQUENCE ! Needed for IVF, not for CVF
INTEGER(2) IX
REAL(4) RX
CHARACTER(6) TEXT
END TYPE
TYPE (X_DERIVED) XSUB

PRINT *, 'From subroutine: ', XSUB

END SUBROUTINE SUBPROC

Can someone clarify for me what is really supposed to work and why?

As an aside, I recognize that I'm using non-standard nomenclature for derived type reference (i.e. x.y instead of x%y). I would appreciate any comments on this usage--which I find much more convenient and readable than the standard % style--and fortunately is a supported option by Intel.

0 Kudos
9 Replies
John4
Valued Contributor I
2,950 Views

The SEQUENCE keyword is required so that both derived types definitions are considered the "equivalent" ---i.e., even though your derived types have the same name, they're taken as different by the compiler.

The F2008 standard (at 4.5.2.4) says:

Two data entities have the same type if they are declared with reference to the same derived-type definition.
Data entities also have the same type if they are declared with reference to different derived-type definitions
that specify the same type name, all have the SEQUENCE attribute or all have the BIND attribute, have no
components with PRIVATE accessibility, and have type parameters and components that agree in order, name, and attributes.

Sequence association for the particular case of derived types requires way too many rules and has a lot of restrictions, so it's better if you could avoid it. Even though you already mentioned that you would prefer not to use modules for this particular case, a good compromise between the two options would be:

[fortran]MODULE SOME_TYPES

TYPE X_DERIVED
     INTEGER(2) IX
     REAL(4) RX
     CHARACTER(6) TEXT
END TYPE

END MODULE SOME_TYPES

PROGRAM TRYIT
USE SOME_TYPES

TYPE (X_DERIVED) XMAIN

XMAIN.IX = 2
XMAIN.RX = 12.34
XMAIN.TEXT = 'LabelX'
PRINT *, 'From main program: ', XMAIN
CALL SUBPROC (XMAIN)
END PROGRAM TRYIT

SUBROUTINE SUBPROC (XSUB)
USE SOME_TYPES

TYPE (X_DERIVED) XSUB

PRINT *, 'From subroutine: ', XSUB

END SUBROUTINE SUBPROC
[/fortran]

Fortran 90+ also introduced the concept of explicit interfaces, which is required for pretty much every Fortran 90+ feature (e.g., if you plan to use allocatable arrays and some of those arrays are expected to be function/subroutine arguments). In your particular case, the interface to SUBPROC is implicit ---i.e., the main unit doesn't know the type of the XSUB argument, so it trusts you'll pass the right one.

A way to provide an explicit interface is through an interface block, thus:

[fortran]MODULE SOME_TYPES

TYPE X_DERIVED
     INTEGER(2) IX
     REAL(4) RX
     CHARACTER(6) TEXT
END TYPE

END MODULE SOME_TYPES

PROGRAM TRYIT
USE SOME_TYPES

TYPE (X_DERIVED) XMAIN

INTERFACE
SUBROUTINE SUBPROC (XSUB)
USE SOME_TYPES
TYPE (X_DERIVED) XSUB
END SUBROUTINE SUBPROC
END INTERFACE

XMAIN.IX = 2
XMAIN.RX = 12.34
XMAIN.TEXT = 'LabelX'
PRINT *, 'From main program: ', XMAIN
CALL SUBPROC (XMAIN)
END PROGRAM TRYIT

SUBROUTINE SUBPROC (XSUB)
USE SOME_TYPES

TYPE (X_DERIVED) XSUB

PRINT *, 'From subroutine: ', XSUB

END SUBROUTINE SUBPROC[/fortran]

The easiest way to provide explicit interfaces is through modules!

As for the % versus . thing, you're allowed to put spaces around %. so XMAIN % IX is perfectly valid. What I tend to do is changing the font color for VS operators to light gray or so.

0 Kudos
IanH
Honored Contributor III
2,950 Views
Quoting dboggs

As an aside, I recognize that I'm using non-standard nomenclature for derived type reference (i.e. x.y instead of x%y). I would appreciate any comments on this usage--which I find much more convenient and readable than the standard % style--and fortunately is a supported option by Intel.

Note the use of '.' results in syntax ambiguity. The fragment:

cat . dog . bird

could be the bird sub-component of the dog component of the derived type cat, or, consistent with the standard syntax, is the result of the user defined operator dog with operands cat and bird.

Obviously if you ever have to use a different compiler you are probably going to be out of luck...

Avoid it.

0 Kudos
Steven_L_Intel1
Employee
2,950 Views
I agree with Ian - use the standard syntax, even if you don't like it. Use of non-standard syntax when there is a standard alternative is just asking for trouble down the road.

Indeed, our compiler has to choose an order of preference when dot notation is ambiguous. As Ian says, other compilers that support this extension may choose to do it differently.
0 Kudos
dboggs
New Contributor I
2,950 Views
Thanks everyone for the helpful comments.

I will force myself to adopt the % notation in place of the . notation, even though it is harder to read and harder to type (I'm a semi-touch typist who can press "." without looking but stumble around to get "shift" and "&" simultaneously!). It's also somewhat awkward because so many other languages use x.y as an OOP feature to accomplish much the same thing.

As for the SEQUENCE statement, I understand perfectly. The confusing thing was that CVF apparently didn't enforce the standard, so I had fallen in to a bad habit of not using it (in fact not even knowing about it!)
0 Kudos
Steven_L_Intel1
Employee
2,950 Views
Well, some languages use x->y - % was chosen for Fortran as it did not create parsing ambiguities.
0 Kudos
Lorri_M_Intel
Employee
2,950 Views
RE:
As for the SEQUENCE statement, I understand perfectly. The confusing thing was that CVF apparently didn't enforce the standard, so I had fallen in to a bad habit of not using it (in fact not even knowing about it)

Well ... it's the -warn:interfaces switch that was giving you the failures. With CVF, that was not on by default, and in fact, to use it required a second command line switch.

I believe that if you compiled your program with CVF, and used /gen_interfaces /warn:interfaces you are likely to see the same errors.

-- Lorri
0 Kudos
Steven_L_Intel1
Employee
2,950 Views
Well, CVF will tell you that it has no idea what /gen_interfaces is. CVF had a limited form of interface checking that worked within the same source file only, but it had no switch to control it. It certainly did not take such subtleties as SEQUENCE into account.

The big difference here is that Intel Fortran has 8 years of improved and corrected error checking over CVF. There are many cases where CVF didn't know to check for a problem, or made wrong assumptions of what the standard required. We have probably made hundreds if not thousands of improvements since 2003 when development of CVF stopped.
0 Kudos
dboggs
New Contributor I
2,950 Views
Thanks Steve. I appreciate all the IVF development work and your responses in this forum.
0 Kudos
Harry_A_
Beginner
2,950 Views
Trivial though this point may be, I always put a space before and after the % symbol. I think the spaces greatly improve readability, putting a separator exactly where I would want a separator to be. Also, I would rather see % than a dot.
0 Kudos
Reply