Nvfortran 25.5: "private ; public :: foo" is broken if "foo" is an entry point

This is identical to the problem reported here, which I shall copy and paste:

module entry_testing_m
  implicit none
  private
  public :: foo, bar

contains
  subroutine foo()
    integer :: x, y, z
    logical :: came_from_foo

    came_from_foo = .true.
    print *, 'came from foo'
    x = 1
    y = 2
  entry bar()
    if (.not. came_from_foo) then
      print *, 'came from bar'
      x = 1000
      y = 2000
    end if

    z = x + y
    print *, z
  end subroutine foo
end module entry_testing_m
program main_testing
  use entry_testing_m, only: foo, bar
  implicit none

  print *, 'testing foo'
  call foo()
  print *, 'testing bar'
  call bar()

end program main_testing

Compiling with nvfortran gives the error:

nvfortran -c -g -O0 -o entry_testing.o entry_testing.f90
NVFORTRAN-W-0155-MODULE PROCEDURE not defined: bar (entry_testing.f90: 25)
  0 inform,   1 warnings,   0 severes, 0 fatal for foo
nvfortran -c -g -O0 -o main_testing.o main_testing.f90
NVFORTRAN-S-0084-Illegal use of symbol bar - attempt to CALL a non-SUBROUTINE (main_testing.f90: 8)
  0 inform,   0 warnings,   1 severes, 0 fatal for main_testing
make: *** [Makefile:18: main_testing.o] Error 2

The program compiles succesfully if you change

PRIVATE
PUBLIC :: whatever_you_want_to_be_public, ...

to

PUBLIC
PRIVATE :: whater_you_want_to_be_private, ...

One of the replies says

…the behavior of using entry inside a module is undefined.

I’ve had a look at the Fortran standard and I believe this is not the case. Table 5.2 says that entry statements are allowed in module subprograms.

I think this should be regarded as a bug in nvfortran.

Ok, I went back to the standard and was able to find where ENTRY is explicitly allowed in a module subprogram (page 343 line 3).

Given ENTRY is obsolete, I’ll still assert that it’s use should be avoided, but did file a report this time, TPR #37520. Especially since if you comment out both the “private” and “public” statement, then it compiles and runs correctly.

-Mat

Thanks for that.

My use case is old Fortran 77 code that is wrapped in a Fortran 90 module to get explicit interfaces. The code works fine with other compilers (including pgfortran 20.4) and it’s probably not worth refactoring it.

Hi Andrew,

FYI, TPR #37520 has been fixed our 25.9 release.

Note the above example does have small error in that “came_from_foo” isn’t initialized when entering via “bar” which can lead to undefined behavior. It didn’t matter for the original issue, but just wanted to note that we did slightly modify your example:

% cat test2.F90
module entry_testing_m
  implicit none
  private
  public :: foo, bar

contains
  subroutine foo(in_bar)
    integer :: x, y, z
    logical :: in_bar

    print *, 'came from foo'
    x = 1
    y = 2
  entry bar(in_bar)
    if (in_bar) then
      print *, 'came from bar'
      x = 1000
      y = 2000
    end if

    z = x + y
    print *, z
  end subroutine foo
end module entry_testing_m
program main_testing
  use entry_testing_m, only: foo, bar
  implicit none

  print *, 'testing foo'
  call foo(.false.)
  print *, 'testing bar'
  call bar(.true.)

end program main_testing
% nvfortran test2.F90 -V25.9; a.out
 testing foo
 came from foo
            3
 testing bar
 came from bar
         3000

-Mat