Print

Print


J. van Oosterwijk writes:
 >   My first idea was, and Salford seems to confirm this,
 >   that entities from M1 are available in PROGRAM TEST.
 >   
 >   However, Compaq and Absoft complain about X and T
 >   not being declared.

 >   What is in your opinion the "official" interpretation?

I'd not normally bother with a disclaimer on a question like this,
but since you mention the word "official", perhaps I'd better.
*NOTHING* you get in this mailing list is going to be official.
My reply certainly isn't.  That being said...

 >  module M1  !  DATA
 >    implicit NONE
 >    PUBLIC
 >    integer, parameter :: N = 10
 >    character(len=N)   :: T = "   Hallo !"
 >    real, dimension(N) :: X
 >  end module M1
 > 
 >  module M2   !  PROCEDURES
 >    use M1
 >    implicit NONE
 >    PRIVATE  !  QUESTION: Is M1 now PRIVATE too ?
 > 
 >    public :: p 
 >  contains
 >    subroutine p(z)  
 >       real, dimension(N) :: z
 >       z = 1  ;   z(N) = N
 >       print*, z(1), z(N)
 >    end subroutine 
 >  end module M2
 > 
 >  program test
 >    use M2    !  uses M1
 >    implicit NONE
 > 
 >    print *, t
 >    call p(x)
 > 
 >  end program test

I thought at first that this was going to be a case on interpretion
161.  That one takes subtle reading to get what "has" to be the right
answer.  And lots of compilers got it wrong before the interpretation
came out.  But that's not what you have here.  This one is simpler.
Simple eough that I'm afraid you won't find a published interpretation
on it because there's really not any debate here.  (Interp 161 was
debated quite a bit before finally coming to what I'm quite convinced
was the only reasonable answer.  It was very easy to misread the
standard on that point.)

First, the answer...  The names t and x M1 are not accessible in the
main program.  If Salford makes them so, then that's just a bug.

Then some explanation.  First, I must note the mis-statement in the
question "Is M1 now PRIVATE too?"  There is no such thing as a private
or public module.  If you try to use such concepts, you'll just get
confused.  The public and private attributes apply to the names in the
module, not to the module itself.  When you have (as you do) PUBLIC
and PRIVATE statements that don't list specific names, then those
statements specify ythe default accessibility for the names in the
module.  But its still accessibility of the names in the module, not
of the module itself.

Second, the terms PUBLIC and PRIVATE are probably a bit misleading;
alas that's what the standard uses.  Better might have been EXPORT and
NOEXPORT (or something - the EXPORT seems ok, but I don't know a good
name for the other.  Its not IMPORT.  Anyway, the names aren't likely
to change at this date).  Unlike most other attributes, PUBLIC and
PRIVATE apply only within a single scoping unit (which always has to
be a module).  The same entity may be PUBLIC in one module and PRIVATE
in another.  You can't have this with other attributes - an entity
can't be REAL type in one scope and CHARACTER type in another for
example (equivalence doesn't make 2 entities the same - it makes them
associated).  See 11.3.2, where it says that you can't respecify any
attribute of a name accessed via USE, but makes exceptions for PUBLIC
and PRIVATE.

If a name has the PUBLIC attribute in a module, it means that the
name is "exported" from that module and thus accessible to scoping
units that USE the module.  That's *ALL*.  It doesn't mean that
the name is necessarily public in any other module.

In your case, you declared the default accessibility in M2 to be
PRIVATE, so M2 doesn't export any names except those explicitly
declared to be PUBLIC *IN M2*.  It doesn't matter that the names
were PUBLIC in M1.  If you think of PUBLIC as being EXPORT, then
it makes more intuitive sense (at least to be).  Its not really
an attribute that attaches to the entity - rather it just controls
whether or not this module exports the name.  (The standard does
call it an attribute, but then has to explain how it is different
from other attributes.)

As you noted (I think - I already cut that part from your posting, but
I think I recall you noting it), you can do "USE M1" in the main
program to make x and t accessible there.

Or you could add the statement "public :: x, t" in M2.

-- 
Richard Maine
[log in to unmask]



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%