Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Is this program legal (use of array pointers)

3 views
Skip to first unread message

Patrick

unread,
Aug 23, 2002, 4:11:20 AM8/23/02
to
I'm trying to get used to pointers, and I would like to know if this
is conform to the f90 standard:

module def
type tt
integer,pointer :: IG(:)
end type
end module

Program test
use def
type(tt) :: ttvar(3)
integer :: in1,in2(2),in3(3,3)

in1=1
in2(:)=2
in3(:,:)=3

Call Add(ttvar(1),in1,1)
Call Add(ttvar(2),in2,2)
Call Add(ttvar(3),in3(1:2,1:2),4)
End

Subroutine Add(ttv,in,idim)
use def
integer :: idim
integer :: in(idim)
type(tt) :: ttv

ttv%IG => in

return
end

There is one main thing I am not sure about:
When I call subroutine Add for the first time, I use an array pointer
to point to a single variable, but because I put this association in a
subroutine, the program does not know this: in the subroutine, the
single variable in1 is treated as an array: in(1). Can this cause any
problems?

Are there any other parts of the program that are not legal? I tested
it on CVF6.6, and it seems ok.

Thanks a lot for your help
Pat

Bil Kleb

unread,
Aug 23, 2002, 5:33:00 AM8/23/02
to
Patrick wrote:
>
> Are there any other parts of the program that are not legal? I tested
> it on CVF6.6, and it seems ok.

In response to my Linux compilers thread a few weeks ago, several
folks recommended that instead of playing compiler roulette to find
bugs/standard violations, I should consider using a Fortran analyzer
like http://www.forcheck.nl/ or http://www.cleanscape.net/products/fortranlint/
I heeded their advice and am now trying out these two.

FWIW, I've included sample output for your program as generated by
these two products (first forchk, then flint).

-- LF95 compiler emulation

-- environmental options: -ff -f90 -allc -decl -ext -obs

-- program unit analysis

-- file: news.f90

- program unit: DEF

- program unit: TEST
17 Call Add(ttvar(2),in2,2)
ADD, dummy argument no 2
(file: news.f90, line: 17)
**[590 E] array versus scalar conflict
18 Call Add(ttvar(3),in3(1:2,1:2),4)
ADD, dummy argument no 2
(file: news.f90, line: 18)
**[590 E] array versus scalar conflict
ADD
(file: news.f90, line: 16)
**[518 I] referenced procedure not declared EXTERNAL

- program unit: ADD
27 ttv%IG => in
in
(file: news.f90, line: 27)
**[370 E] illegal target for a pointer
TTV
(file: news.f90, line: 21)
**[557 I] dummy argument not used

-- reference structure

-- global program analysis
ADD, referenced in TEST, argument no 2 (IN)
**[590 E] array versus scalar conflict

-- messages presented:

1x[370 E] illegal target for a pointer
1x[518 I] referenced procedure not declared EXTERNAL
1x[557 I] dummy argument not used
3x[590 E] array versus scalar conflict

number of error messages: 4
number of informative messages: 2

FORTRAN-lint Rev 5.00.03 23-Aug-2002 05:22:29

Default options: -a -m -w -f -g -u -s --t --x -Rfree -9 -Mdepend,noexit

>>> Source analysis:


news.f90

*******************************************************************************
Program TEST File news.f90 Line 7

>Call Add(ttvar(1),in1,1)
> ^
news.f90:TEST line 16:
INTERFACE ERROR #251- I*4 variable passed to dummy arg which is a I*4 array.

>Call Add(ttvar(3),in3(1:2,1:2),4)
> ^
news.f90:TEST line 18:
INTERFACE WARNING #752- ranks of the actual and dummy args differ (2 vs 1
dimensions).

news.f90:TEST line 18:
USAGE WARNING #127- local variable TTVAR is set but never referenced.

news.f90:TEST line 12:
USAGE WARNING #127- local variable IN1 is set but never referenced.

news.f90:TEST line 13:
USAGE WARNING #127- local variable IN2 is set but never referenced.

news.f90:TEST line 14:
USAGE WARNING #127- local variable IN3 is set but never referenced.

*******************************************************************************
Subroutine ADD File news.f90 Line 21

>ttv%IG => in
> ^
news.f90:ADD line 27:
SYNTAX ERROR #670- illegal target (missing the TARGET or POINTER attribute).

news.f90:ADD line 24:
USAGE FYI #124- dummy argument IN is unused.

*******************************************************************************


Global checking:

--- No additional global inconsistencies found ---

>>> Statistics:

Number of source files: 1

Source files: 30 lines, 340 bytes ( 0% comments,100% code )
Include files: 0 lines, 0 bytes
Total parsed: 30 lines, 340 bytes ( 0% comments,100% code )

Total subprograms: 3
Subroutines: 1
Functions: 0
Program: 1
Block Data: 0
Module: 1

Individual message summary
--------------------------
USAGE WARN #127- 4x: local variable * is set but never referenced.
USAGE FYI #124- 1x: dummy argument * is unused.
INTRFC ERR #251- 1x: * variable passed to dummy arg which is a * array.
SYNTAX ERR #670- 1x: illegal target (missing the TARGET or POINTER
attribute).
INTRFC WARN #752- 1x: ranks of the actual and dummy args differ (* vs *
dimensions).

Total messages: 8

Errors Warnings FYIs
-------- -------- --------
Syntax: 1 0 0
Interface: 1 1 0
Data usage: 0 4 1
ANSI-F90 port: 0 0 0

Implicit typing: 0

--
Bil

Michael Metcalf

unread,
Aug 23, 2002, 5:43:29 AM8/23/02
to

"Patrick" <pez3...@yahoo.com> wrote in message > Program test

> use def
> type(tt) :: ttvar(3)
> integer :: in1,in2(2),in3(3,3)
>
> in1=1
> in2(:)=2
> in3(:,:)=3
>
> Call Add(ttvar(1),in1,1)
> Call Add(ttvar(2),in2,2)
> Call Add(ttvar(3),in3(1:2,1:2),4)
> End
>
> Subroutine Add(ttv,in,idim)
> use def
> integer :: idim
> integer :: in(idim)
> type(tt) :: ttv
>
> ttv%IG => in
>
> return
> end

This program is illegal. Firstly, 'in' requires the target attribute in
order to be pointed at. This then requires that the corresponding actual
argument have the target attribute ("Fortran 90/95 Explained", Section
5.7.3). Lastly, you are playing games with mismatched ranks of the second
argument that will land you in serious trouble, even if, on a given
compiler, it appears to 'work' (have you tried printing the results
ttvar(3)%IG?).

Regards,

Mike Metcalf


Patrick

unread,
Aug 26, 2002, 3:41:24 AM8/26/02
to
Thanks for your answers, Bil and Micheal.

Bil: I took note of the fortran checkers, thanks for the tip.
But there is one warning I don't understand:


>Call Add(ttvar(3),in3(1:2,1:2),4)
> ^
>news.f90:TEST line 18:
>INTERFACE WARNING #752- ranks of the actual and dummy args differ (2
vs 1
dimensions)

I agree with the fact that in my subroutine, I declare an array of
rank 1, but isn't that one thing that is often done in Fortran? Over
here, we have a code that is pure F77, and tricks like this one are
very common in the program.
Lines like

Dimension a(10,10)
Call Srout(a)

..
Subroutine Srout(a)
Dimension a(100) !(or a(*)
....

are used all the times, and have never generated a compiler warning.
Does this depend on compiler settings, or is this not legal under f90
any more?

Michael: to my defense: I knew about he target attribute, but I must
have been absent-minded (yes I know: poor excuse). But what I didn't
know is that the argument needs the attribute ass well, thanks for the
tip.
On CVF6.6 ttvar(3)%IG has four elements, all of which have the value
of 3. In fact, I never had any doubts about this part of the program,
what could go wrong here? Maybe I misunderstood something about
passing array sections to subroutines?


Thanks for your help
Pat

Michael Metcalf

unread,
Aug 26, 2002, 5:26:17 AM8/26/02
to

"Patrick" <pez3...@yahoo.com> wrote in message
news:f7a75888.02082...@posting.google.com...

> On CVF6.6 ttvar(3)%IG has four elements, all of which have the value
> of 3.

If I print them using CVF6.6A, I get different values, with or without an
explicit interface.

Mike


Richard Maine

unread,
Aug 26, 2002, 11:25:57 AM8/26/02
to
pez3...@yahoo.com (Patrick) writes:

> >INTERFACE WARNING #752- ranks of the actual and dummy args differ...

> isn't that one thing that is often done in Fortran?

Yes. Note that this is a warning, not an error. Although it is
often done, it is somewhat esoteric (old-timers may be used to it,
but try explaining exactly what elemnts of the actual argument
correspond to what ones of the dummy, particularly for a non-trivial
case, to someone who hasn't been coding in Fortran for 20 years).
Although legal, this could also plausibly be unintended.

> is this not legal under f90 any more?

Everything that was legal in f77 is legal in f90. That includes
this. However, note that this does *NOT* mean that the same
practices necessarily work in contexts that are new to f90.
This is another reason why the practice is esoteric enough to
merit a warning - if you use this practice, you need to be aware
of its limitations. Namely

1. It doesn't work with assumed shape dummy arguments (which are new
to f90). I can't even imagine how one would define such a thing
for assumed shape in general.

2. It doesn't work in generics, which has resulted in several
questions here (and/or on the comp-fortran-90 mailing list).
Rank is a possible disambiguator for generics, making
rank mismatcing problematic.

There are other subtleties and complications, but the above are
the first two that occur to me. I'd say the issues are subtle
enough to well merit a warning.

--
Richard Maine | Good judgment comes from experience;
email: my last name at host.domain | experience comes from bad judgment.
host: altair, domain: dfrc.nasa.gov | -- Mark Twain

James Van Buskirk

unread,
Aug 26, 2002, 3:51:44 PM8/26/02
to

"Richard Maine" <nos...@see.signature> wrote in message
news:uey9atm...@altair.dfrc.nasa.gov...

> Yes. Note that this is a warning, not an error. Although it is
> often done, it is somewhat esoteric (old-timers may be used to it,
> but try explaining exactly what elemnts of the actual argument
> correspond to what ones of the dummy, particularly for a non-trivial
> case, to someone who hasn't been coding in Fortran for 20 years).
> Although legal, this could also plausibly be unintended.

I claim that the OP's usage is in fact illegal. If you wanted the
shapes of the actual and dummy arguments to differ in F77 you had
to pass the first element of the sequence of consecutive array
elements of the actual argument array. The OP is not doing this.
When in1 is passed the actual argument is scalar and the dummy is
not, so, without referring to the standard I would conclude that
the call is illegal. Also when in3(1:2,1:2) is passed, a rank-2
array section actual argument is associated with a rank-1 dummy.
Passing in3(1,1) would be legal and the dummy argument would be
defined via sequence association, but passing a rank-2 array section
is illegal here.

In section 12.4.1.1: "If the actual argument is scalar, the
corresponding dummy argument shall be scalar unless the actual
argument is an element of an array that is not an assumed-shape
or pointer array, or a substring of such an element."

Looking more carefully at the standard it seems that passing
in3(1:2,1:2) may in fact be legal, but it is what will cause
more problems in practice!

> There are other subtleties and complications, but the above are
> the first two that occur to me. I'd say the issues are subtle
> enough to well merit a warning.

The complication that bugs me most in the original example
is the fact that a discontiguous actual argument, in3(1:2,1:2),
is associated with an explicit-shape dummy argument, in(1:idim).
Since explicit shape dummies are pretty much required to be
contiguous by the standard because unlike assumed-shape arrays
they form a sequence of elements, a contiguous copy of in3(1:2,1:2)
must be made at invocation time. Inside subroutine add after
this invocation array in is actually a temporary copy of
in3(1:2,1:2) and ttvar(3)%IG is pointed at this temporary copy.
On return, the temporary copy is invalid memory (not a term
taken from the Fortran standard) so the pointer association
status of ttvar(3)%IG is all but required by the standard to
be undefined. Here, let's modify the example so that everything
pointed at is a target, and use the CVF (and many other vendors)
extension LOC to see what memory locations the original targets
occupy and what memory is pointed at by ttvar%IG:

module def
type tt
integer,pointer :: IG(:)
end type
end module

Program test
use def
type(tt) :: ttvar(3)
integer, target :: in1,in2(2),in3(3,3)

in1=1
in2(:)=2
in3(:,:)=3

write(*,'(a,z8.8)') 'LOC(in1) = ', LOC(in1)
Call Add(ttvar(1),in1,1)
write(*,'(a,z8.8)') 'LOC(ttvar(1)%IG(1)) = ', LOC(ttvar(1)%IG(1))
write(*,'(a,z8.8)') 'LOC(in2(1)) = ', LOC(in2(1))
write(*,'(a,z8.8)') 'LOC(in2(2)) = ', LOC(in2(2))
Call Add(ttvar(2),in2,2)
write(*,'(a,z8.8)') 'LOC(ttvar(2)%IG(1)) = ', LOC(ttvar(2)%IG(1))
write(*,'(a,z8.8)') 'LOC(ttvar(2)%IG(2)) = ', LOC(ttvar(2)%IG(2))
write(*,'(a,z8.8)') 'LOC(in3(1,1)) = ', LOC(in3(1,1))
write(*,'(a,z8.8)') 'LOC(in3(2,1)) = ', LOC(in3(2,1))
write(*,'(a,z8.8)') 'LOC(in3(1,2)) = ', LOC(in3(1,2))
write(*,'(a,z8.8)') 'LOC(in3(2,2)) = ', LOC(in3(2,2))
Call Add(ttvar(3),in3(1:2,1:2),4)
write(*,'(a,z8.8)') 'LOC(ttvar(3)%IG(1)) = ', LOC(ttvar(3)%IG(1))
write(*,'(a,z8.8)') 'LOC(ttvar(3)%IG(2)) = ', LOC(ttvar(3)%IG(2))
write(*,'(a,z8.8)') 'LOC(ttvar(3)%IG(3)) = ', LOC(ttvar(3)%IG(3))
write(*,'(a,z8.8)') 'LOC(ttvar(3)%IG(4)) = ', LOC(ttvar(3)%IG(4))
End

Subroutine Add(ttv,in,idim)
use def
integer :: idim

integer, target :: in(idim)
type(tt) :: ttv

ttv%IG => in

return
end

Output with CVF 6.6A:

LOC(in1) = 0043A2CC
LOC(ttvar(1)%IG(1)) = 0043A2CC
LOC(in2(1)) = 0043A2C4
LOC(in2(2)) = 0043A2C8
LOC(ttvar(2)%IG(1)) = 0043A2C4
LOC(ttvar(2)%IG(2)) = 0043A2C8
LOC(in3(1,1)) = 0043A2D0
LOC(in3(2,1)) = 0043A2D4
LOC(in3(1,2)) = 0043A2DC
LOC(in3(2,2)) = 0043A2E0
LOC(ttvar(3)%IG(1)) = 0012FF40
LOC(ttvar(3)%IG(2)) = 0012FF44
LOC(ttvar(3)%IG(3)) = 0012FF48
LOC(ttvar(3)%IG(4)) = 0012FF4C

We see the effect the the discontiguity of in3(1:2,1:2) here:
ttvar(3)%IG doesn't point at anything near to the in3 array
in memory.

Richard Maine

unread,
Aug 26, 2002, 4:54:06 PM8/26/02
to
"James Van Buskirk" <not_...@attbi.com> writes:

> "Richard Maine" <nos...@see.signature> wrote in message
> news:uey9atm...@altair.dfrc.nasa.gov...
>
> > Yes. Note that this is a warning, not an error. Although it is
> > often done, it is somewhat esoteric (old-timers may be used to it,
> > but try explaining exactly what elemnts of the actual argument
> > correspond to what ones of the dummy, particularly for a non-trivial
> > case, to someone who hasn't been coding in Fortran for 20 years).
> > Although legal, this could also plausibly be unintended.
>
> I claim that the OP's usage is in fact illegal. If you wanted the
> shapes of the actual and dummy arguments to differ in F77 you had
> to pass the first element of the sequence of consecutive array
> elements of the actual argument array. The OP is not doing this.
> When in1 is passed the actual argument is scalar and the dummy is
> not, so, without referring to the standard I would conclude that
> the call is illegal.

Agree for the in1 case of the original post. (Also agree with your
other points, where you have done your usual meticulous job). The
code of the original post was illegal for multiple reasons (this and
the target attribute bit), as Metcalf pointed out. I was focusing
more on the immediate question posed in the followup, where a rank 2
actual array was passed to a rank 1 dummy. Rank 0 (aka scalar) has
different and particularly quirky rules (and did so in f77).

All of this I think just reinforces my claim that this is a tricky
area, which merits warnings, even in some cases that are legal.

0 new messages