Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Flang] Incorrect diagnostic due to private generic name still visible outside of the module. #126797

Open
DanielCChen opened this issue Feb 11, 2025 · 2 comments · May be fixed by #128777
Open
Assignees

Comments

@DanielCChen
Copy link
Contributor

DanielCChen commented Feb 11, 2025

Consider the following code:

module m
   type base
      character(3) :: c = 'xxx'
      contains
         procedure, pass :: write => writeb
         generic, private :: write(unformatted) => write  !! generic write(unformated) is private, so it should not 
                                                          !! be accessible outside of the module
   end type

   interface
      subroutine writeb (dtv, unit, iostat, iomsg)
         import base
         class(base), intent(in) :: dtv
         integer, intent(in) :: unit
         integer, intent(out) :: iostat
         character(*), intent(inout) :: iomsg
      end subroutine
   end interface

   contains
      subroutine mywrite( dtv, iostat, iomsg )
         class(base), intent(in) :: dtv
         integer, intent(out) :: iostat
         character(*), intent(inout) :: iomsg

         write ( 1, iostat = iostat, iomsg = iomsg ) dtv
         if (iostat .ne. 0) error stop 1
      end subroutine
end module

program resolve005a
   use m
   class(base), allocatable  :: b1
   integer :: stat
   character(200) :: msg

   allocate ( b1, source = base('abc') )
   open ( 1, file = 'resolve005a.1', form='unformatted', access='sequential' )

   call mywrite ( b1, stat, msg)

   deallocate(b1)
   close ( 1, status ='delete')

end program

subroutine writeb (dtv, unit, iostat, iomsg)
   use m, only: base
   class(base), intent(in) :: dtv
   integer, intent(in) :: unit
   integer, intent(out) :: iostat
   character(*), intent(inout) :: iomsg

   interface write(unformatted)                              !! This declaration should be allowed.
      subroutine writebaseext (dtv, unit, iostat, iomsg)
         import base
         class(base), intent(in) :: dtv
         integer, intent(in) :: unit
         integer, intent(out) :: iostat
         character(*), intent(inout) :: iomsg
      end subroutine
   end interface

   write (unit, iostat=iostat, iomsg=iomsg)    dtv
   if (iostat .ne. 0) error stop 2

end subroutine

subroutine writebaseext (dtv, unit, iostat, iomsg)
   use m, only: base
   class(base), intent(in) :: dtv
   integer, intent(in) :: unit
   integer, intent(out) :: iostat
   character(*), intent(inout) :: iomsg

   select type ( dtv )
      type is (base)
         write (unit, iostat=iostat, iomsg=iomsg)        dtv%c
         if (iostat .ne. 0) error stop 3
   end select
end subroutine

The test case in intentionally testing when a generic name is private, it should be allowed to declare another interface outside of the module.
Flang is currently issue an error as

error: Semantic errors in t1.f
./t1.f:54:18: error: Derived type 'base' has conflicting type-bound input/output procedure 'write(unformatted)'
        subroutine writebaseext (dtv, unit, iostat, iomsg)
                   ^^^^^^^^^^^^
./t1.f:10:18: Procedure 'write' of type 'base' is bound to 'writeb'
        subroutine writeb (dtv, unit, iostat, iomsg)
                   ^^^^^^

@llvmbot
Copy link
Member

llvmbot commented Feb 11, 2025

@llvm/issue-subscribers-flang-frontend

Author: Daniel Chen (DanielCChen)

Consider the following code: ``` module m type base character(3) :: c = 'xxx' contains procedure, pass :: write => writeb generic, private :: write(unformatted) => write !! generic write(unformated) is private, so it should not !! be accessible outside of the module end type

interface
subroutine writeb (dtv, unit, iostat, iomsg)
import base
class(base), intent(in) :: dtv
integer, intent(in) :: unit
integer, intent(out) :: iostat
character(*), intent(inout) :: iomsg
end subroutine
end interface

contains
subroutine mywrite( dtv, iostat, iomsg )
class(base), intent(in) :: dtv
integer, intent(out) :: iostat
character(*), intent(inout) :: iomsg

     write ( 1, iostat = iostat, iomsg = iomsg ) dtv
     if (iostat .ne. 0) error stop 1
  end subroutine

end module

program resolve005a
use m
class(base), allocatable :: b1
integer :: stat
character(200) :: msg

allocate ( b1, source = base('abc') )
open ( 1, file = 'resolve005a.1', form='unformatted', access='sequential' )

call mywrite ( b1, stat, msg)

deallocate(b1)
close ( 1, status ='delete')

end program

subroutine writeb (dtv, unit, iostat, iomsg)
use m, only: base
class(base), intent(in) :: dtv
integer, intent(in) :: unit
integer, intent(out) :: iostat
character(*), intent(inout) :: iomsg

interface write(unformatted). !! This declaration should be allowed.
subroutine writebaseext (dtv, unit, iostat, iomsg)
import base
class(base), intent(in) :: dtv
integer, intent(in) :: unit
integer, intent(out) :: iostat
character(*), intent(inout) :: iomsg
end subroutine
end interface

write (unit, iostat=iostat, iomsg=iomsg) dtv
if (iostat .ne. 0) error stop 2

end subroutine

subroutine writebaseext (dtv, unit, iostat, iomsg)
use m, only: base
class(base), intent(in) :: dtv
integer, intent(in) :: unit
integer, intent(out) :: iostat
character(*), intent(inout) :: iomsg

select type ( dtv )
type is (base)
write (unit, iostat=iostat, iomsg=iomsg) dtv%c
if (iostat .ne. 0) error stop 3
end select
end subroutine


The test case in intentionally testing when a generic name is private, it should be allowed to declare another interface outside of the module.
Flang is currently issue an error as

error: Semantic errors in t1.f
./t1.f:54:18: error: Derived type 'base' has conflicting type-bound input/output procedure 'write(unformatted)'
subroutine writebaseext (dtv, unit, iostat, iomsg)
^^^^^^^^^^^^
./t1.f:10:18: Procedure 'write' of type 'base' is bound to 'writeb'
subroutine writeb (dtv, unit, iostat, iomsg)
^^^^^^

</details>

@akuhlens akuhlens self-assigned this Feb 13, 2025
@klausler
Copy link
Contributor

Fixed test above to remove a spurious period on line 54.

klausler added a commit to klausler/llvm-project that referenced this issue Feb 25, 2025
When checking for conflicts between type-bound generic defined I/O
procedures and non-type-bound defined I/O generic interfaces,
don't worry about conflicts where the type-bound generic interface
is inaccessible in the scope around the non-type-bound interface.

Fixes llvm#126797.
@klausler klausler linked a pull request Feb 25, 2025 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants