j3-fortran / fortran_proposals

Proposals for the Fortran Standard Committee
175 stars 14 forks source link

Add a PRIVATE clause to USE statements #294

Closed rweed closed 1 year ago

rweed commented 1 year ago

I don't know if this has been proposed in the past (or maybe you can already do this but I can't find anything that says you can) but I would like to propose the addition of a PRIVATE clause to USE statements to implicitly limit access to a modules content to just the client module or procedure USEing said module.

Example.

  1. Suppose you had modules A and B where module B USEs module A. Now suppose both module A and B contain lots of data or procedures. However, you don't want any other module or procedure downstream that USEs module B to have access to anything out of module A USEed in module B. As far as I know your current options are to

a) use ONLY to restrict what you want out of module A and then use explicit PRIVATE statement(s) for the values in the ONLY list. If there are a lot of things out of A you USE then you have a lot of PRIVATE statement(s) to type.

b) make everything in module B PRIVATE and then use PUBLIC to make the contents of module B visible. This can be a big pain if you really want all of the procedures/data in module B to be PUBLIC and there are a lot of them.

What I would like to be able to do is the following:

Module B

USE A, PRIVATE or USE A, PRIVATE, ONLY : one, two, three

or maybe

USE, PRIVATE :: A USE, PRIVATE :: A, ONLY: one,two,three

which would imply to the compiler that everything in A or in the ONLY list is PRIVATE to module B

This can save a lot of typing of explicit PUBLIC and/or PRIVATE statements.

FortranFan commented 1 year ago

@rweed,

Re: ".. maybe you can already do this ..", the answer is likely yes and that Fortran 2018 has introduced what you seek. So look into Fortran 2018 standard revision or a description of if (e.g., latest edition MFE) and a conforming processor (say Intel oneAPI 2023.0) and see if that covers your needs here.

FortranFan commented 1 year ago

@FortranFan wrote Mar 23, 2023 11:29 AM EDT:

@rweed,

Re: ".. maybe you can already do this ..", the answer is likely yes and that Fortran 2018 has introduced what you seek. So look into Fortran 2018 standard revision or a description of if (e.g., latest edition MFE) and a conforming processor (say Intel oneAPI 2023.0) and see if that covers your needs here.

So starting with Fortran 90, say you have code like so:

module a
   integer :: foo = 1
end module 
module b
   use a
   integer :: bar = 2
end module
   use b
   print *, foo, bar
end 

And it may be that you require that a consumer of module b not have access to object foo but as authored they do:

C:\temp>gfortran -ffree-form p.f -o p.exe

C:\temp>p.exe
           1           2

So then starting Fortran 2018, the language now allows this:

module a
   integer :: foo = 1
end module 
module b
   use a
   private :: a !<-- Fortran 2018 introduction, makes all USE'd entities from 'a' to be private
   integer :: bar = 2
end module
   use b
   implicit none
   print *, foo, bar
end 

And a conforming processor can then be expected to detect and report the issue with object foo

C:\temp>ifort /c /free /standard-semantics p.f
Intel(R) Fortran Intel(R) 64 Compiler Classic for applications running on Intel(R) 64, Version 2021.8.0 Build 20221119_000000
Copyright (C) 1985-2022 Intel Corporation.  All rights reserved.

p.f(11): error #6404: This name does not have a type, and must have an explicit type.   [FOO]
   print *, foo, bar
------------^
compilation aborted for p.f (code 1)

P.S.> The above is simply a simply illustration; you can construct other scenarios such as with ONLY clauses to check out the Fortran 2018 semantics.

rweed commented 1 year ago

@FortranFan

Big thanks. I looked initially in MFE but it didn't occur to me this would be a recent addition to the standard and their description is buried in the "F2018 minor changes" section. I'm guessing this is only implemented in ifort/ifx and maybe the Cray compiler. The question for me is this is something that should have been in the standard from the start and why did it take until 2018 to get fixed.