Выброс ошибки, если какой-либо интерфейс процедуры не определен явно или в модуле в 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 array (содержащий размерность (:)). Такие процедуры должны либо находиться в модулем или иметь явный интерфейс там, где они используются. В этом Например, никто не был прав.
Одним из правильных способов вызова таких процедур является использование явного интерфейс следующим образом:
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
или других компиляторах для предотвращения компиляции, если есть вызов процедуры, интерфейс которой не определен явно (или определен в модуле)?
Если нет, не должна ли это быть функцией?
Ответы
Ответ 1
Для gfortran существует опция компиляции -Wimplicit-interface
:
-Wimplicit-процедура
Предупреждать, если вызывается процедура, которая не имеет явного интерфейса и не объявлена как EXTERNAL.
Это можно связать с -Werror
, чтобы рассматривать это как ошибку.
При компиляции этого (с gfortran 4.8.2)
call heffalump(1)
end
видно, что
call heffalump (1)
1
Предупреждение: процедура "heffalump" вызывается с неявным интерфейсом в (1)
Обратите внимание, однако, что, хотя это может быть полезным тестом для "глупых ошибок" в недавно разработанном современном коде, все может быть совершенно правильным и все еще терпеть неудачу в этом тесте. См. Также комментарий Владимира Ф. к этому ответу.
Конечно, компилятор в большинстве случаев не может определить, требует ли процедура явного интерфейса. См. этот ответ для параметров, позволяющих компилятору сделать небольшую дополнительную работу в этом отношении.
Ответ 2
У компиляторов есть это. Ifort имеет -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, другой начнет жаловаться, что интерфейс уже определен и отличается. (Фактическая история из траншей.)