Выдача ошибки, если какой-либо интерфейс процедуры не определен явно, или в модуле в Fortran 90+

в статье ошибки в программах Fortran 90, которые могут вас удивить

есть следующий раздел,

опасность вызова процедур стиля Fortran 90

      program main
      real, dimension(5) :: x

      x = 0.
! THIS IS WRONG
      call incb(x)
      print *, x

      end program main

      subroutine incb(a)
! this is a fortran90 style subroutine
      real, dimension(:) :: a
      a = a + 1.
      end subroutine incb

объяснение подпрограмма incb использует предполагаемую форму стиля Fortran 90 массив (содержащий размер(:)). Такие процедуры должны быть в модуль, или иметь явный интерфейс везде, где они используются. В этом образец, ни одна правда.

одним из правильных способов вызова таких процедур является использование явного интерфейс следующим образом:

      program main
      real, dimension(5) :: x

! THIS IS THE RIGHT WAY
      interface
         subroutine incb(a)
           real, dimension(:) :: a
         end subroutine incb
      end interface

      x = 0.
      call incb(x)
      print *, x

      end program main

      subroutine incb(a)
! this is a fortran90 style subroutine
      real, dimension(:) :: a
      a = a + 1.
      end subroutine incb

если подпрограмма находится в модуле, интерфейсы генерируются автоматически и не нужно явно писать.

! THIS IS ANOTHER RIGHT WAY
      module inc
      contains
      subroutine incb(a)
! this is a fortran90 style subroutine
      real, dimension(:) :: a
      a = a + 1.
      end subroutine incb
      end module inc

      program main
      use inc
      real, dimension(5) :: x

      x = 0.
      call incb(x)
      print *, x

      end program main

если используются интерфейсы, интерфейс должен соответствовать фактической функции.

Итак, продолжая мой вопрос, есть ли вариант в gfortran или другие компиляторы для предотвращения компиляция если есть вызов процедуры, интерфейс которой не определен explicity (или определен в модуле)?

если нет, то разве это не должно быть функцией?

2 ответов


для gfortran есть опция компиляции -Wimplicit-interface:

- Wimplicit-процедура
Предупредите, если вызывается процедура, которая не имеет явного интерфейса и не объявлена как внешняя.

Это может быть связано с -Werror рассматривать это как ошибку.

при компиляции этого (с gfortran 4.8.2)

  call heffalump(1)
end

видит

вызовите heffalump (1)
1
Предупреждение: процедура 'heffalump' вызывается с неявным интерфейсом в (1)

обратите внимание, однако, что, хотя это может быть полезным тестом для "глупых ошибок" в недавно разработанном современном коде, все может быть совершенно правильно и все равно провалить этот тест. См. также комментарий Владимира Ф К этому ответу.

конечно, компилятор в большинстве случаев не может сказать, требует ли процедура явного интерфейса. См.ответ для опций, позволяющих компилятор сделать немного дополнительную работу в этом отношении.


Да, у компиляторов есть это. Ифорт имеет -warn interfaces, входящего в -warn, gfortran имеет эту регистрацию -Wall.

interf.f90:6.15:

      call incb(x)
               1
Error: Procedure 'incb' at (1) with assumed-shape dummy argument 'a' must have an explicit interface

у компилятора будет проблема с проверкой этого, если они находятся в разных файлах. Кто-то найдет, кто-то нет.

> gfortran incb.f90 interf.f90 -Wall
> ifort incb.f90 interf.f90 -warn
interf.f90(6): error #7978: Required interface for passing assumed shape array is missing from original source   [X]
      call incb(x)

----------------^
compilation aborted for interf.f90 (code 1)

как пишет @francesalus, вы можете заставить предупреждения для неявных интерфейсов -Wimplicit-interface. Это, однако, делает что-то другое. Он предупреждает для процедура с неявным интерфейсом, даже когда она стандарт соответствует его.

если вы соедините его с -Werror вам нужно будет написать интерфейс для каждой процедуры MPI, которая работает с буферами, для каждой используемой устаревшей библиотеки. Я использую его, но мой код строго в модулях, и мне действительно пришлось писать интерфейсы для каждой процедуры MPI, которую я использую, которая отправляет или получает некоторый буфер. Для каждого типа буфера вам нужен отдельный интерфейс (по крайней мере, в текущем Fortran 2008).

еще хуже, некоторые MPI реализации предоставляют явные интерфейсы для определенных процедур, а некоторые нет. Как только вы попытаетесь объявить требуемые интерфейсы для одной версии библиотеки MPI, другой начнет жаловаться, что интерфейс уже определен, и они отличаются. (Реальная история из окопов.)