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

Use of private/public Attributes in Derived Types Inside a Submodule Causes Compiler Error

FlyingHermes
New Contributor I
892 Views

I found what I believe is a compiler bug when a derived type declared in a submodule makes use of the private/public attributes, either globally in the component/procedure parts or locally in the component/procedure specification line inside the type. This confuses the compiler, which mistakenly interprets the private/public statements as belonging to the specification part of the submodule, rather than the type.

Here is a minimal working example (MWE):

Module module_A

  implicit none

  Type  ::  type_A
  contains
    procedure ,nopass ::  sub_A
  End Type

  Interface
    Module Subroutine sub_A()
    End Subroutine
  End Interface

End Module

SubModule(module_A) submodule_A

  implicit none

  ! The use of the private/public attributes, either globally 
  ! in the component/procedure parts, or locally in the
  ! component/procedure specification line inside the type
  ! confuses the complier and lead to the error:
  !   error #6848: This attribute specification is valid
  !                only in the specification part of a module.
  Type  ::  type_B
    private                                 ! BUG
    integer ,private :: i                   ! BUG
  contains
    private                                 ! BUG
    procedure ,nopass ,private ::  sub_B    ! BUG
  End Type

  contains

Module Procedure sub_A
End Procedure

Subroutine sub_B()
End Subroutine

End SubModule

I get the following errors with both ifx version 2025.0.4 and ifort version 2021.13.0:

test.f90(28): error #6848: This attribute specification is valid only in the specification part of a module.
    private                                 ! BUG
^
test.f90(29): error #6848: This attribute specification is valid only in the specification part of a module.   [PRIVATE]
    integer ,private :: i                   ! BUG
-------------^
test.f90(31): error #6848: This attribute specification is valid only in the specification part of a module.
    private                                 ! BUG
^
test.f90(32): error #6848: This attribute specification is valid only in the specification part of a module.   [PRIVATE]
    procedure ,nopass ,private ::  sub_B    ! BUG
-----------------------^

I think the code is valid, no?

Thanks.

 

0 Kudos
5 Replies
JohnNichols
Valued Contributor III
820 Views

I played with your code for a while and stripping out most of it, it still had problems, this works and one does not need private as nothing is visible inside each module until you are inside it in running it. 

 

    module module_B
Implicit none
Contains

double precision function function_B(i)
implicit none
integer,intent(in) :: i
function_B = 5.d0*i
write(*,*)function_B
end function function_B

end module module_B


    module module_A

use module_B
implicit none
contains

subroutine subroutine_A(i)
implicit none
integer, intent(in) :: i
double precision :: j
j = function_B(i)
end subroutine subroutine_A

end module module_A
        
    
    Program Test_program

Use module_A
Implicit none
Integer :: i
i = 1
call subroutine_A(i)

End program Test_program

 

or

 

module points
  type :: point
     real :: x, y
  end type point

  interface
     module function point_dist(a, b) result(distance)
       type(point), intent(in) :: a, b
       real :: distance
     end function point_dist
  end interface
end module points

submodule (points) points_a
contains
  module function point_dist(a, b) result(distance)
    type(point), intent(in) :: a, b
    real :: distance
    distance = sqrt((a%x - b%x)**2 + (a%y - b%y)**2)
  end function point_dist
end submodule points_a

 

 module points
 type :: point
     real :: x, y
 end type point

 interface
 module function point_dist(a, b) result(distance)
 type(point), intent(in) :: a, b
 real :: distance
 end function point_dist
 end interface
 end module points

 submodule (points) points_a
 contains
 module function point_dist(a, b) result(distance)
 type(point), intent(in) :: a, b
 real :: distance
 distance = sqrt((a%x - b%x)**2 + (a%y - b%y)**2)
 end function point_dist
 end submodule points_a

 Program Test_program

 Use points
 Implicit none
 Integer :: i
 type(point) :: a,b
 real dist
 i = 1
 A%X = 10.0
 A%Y = 20.0
 B%X = 20.0
 B%Y = 10.0
 
 dist = point_dist(a, b)
 
 write(*,*)dist
 
 End program Test_program

This runs and says 14.14 etc.. it does not require privates, 

FlyingHermes
New Contributor I
804 Views

Thanks for your response. The code I posted is a minimal working example intended to reproduce a specific issue I encountered in my real code. In the actual implementation, a derived type needs to be defined inside a submodule, and ideally, I would like to specify private/public attributes for its components and procedures within the type declaration.

The alternative examples you provided do not address this specific scenario, namely, a derived type defined inside a submodule that uses private/public attributes for its components and/or procedures. The key issue is whether the compiler is incorrectly rejecting private statements inside a derived type in a submodule. I believe this usage should be valid, but the compiler appears to mistakenly interpret the private/public keywords as applying to the submodule itself rather than the type.

0 Kudos
JohnNichols
Valued Contributor III
693 Views

You cannot compile with private inside the routines inside the modules, they are not visible outside the modules, they are only visible inside the module.  Private appears to be redundant.

IanH
Honored Contributor III
677 Views

The code is not valid.  The compiler is correct (and required) to issue a diagnostic.  See constraints C771 and C817 in Fortran 2023.

Access is all about visibility outside of the defining module.  As John says, if permitted the access specs would be superfluous because that type can't escape the module.

JohnNichols
Valued Contributor III
590 Views

In the old days, we used common statements, really handy. Then we are told to use classes etc.....

Now we can get a language that can pull something out of a class, change it, put it back  and we move on not realizing 6 months later we changed the value elsewhere. 

Programming requires discipline, fast coding skips discipline.  

 

0 Kudos
Reply