Как я могу указать в Fortran Compiler, что объявленные переменные не должны рассматриваться как неявное объявление функции? - PullRequest
1 голос
/ 14 января 2020

Я был довольно удивлен, что:

      subroutine test   (es, f)
!

      implicit none
!
      double precision es
      double precision f
      f=es(1,2)
!
      return
      end

скомпилировано без каких-либо ошибок или предупреждений: es не объявлено с dimension.
Я понимаю, что es тогда рассматривается как function.

Но при компоновке нет ошибки, учитывая отсутствующий символ es!

Глядя на ассемблер * es(1,2) соответствует call rdx, следовательно, нет ошибки компоновки.

Чтобы избежать этой проблемы, я могу объявить es как double precision, intent(inout), тогда получаю:

Ошибка: атрибут PROCEDURE конфликтует с атрибутом INTENT в 'es' в

То, чего я ожидал в первый раз.

Вопрос

Есть ли опция компилятора (ifort или gfortran), чтобы принудительно обрабатывать объявленные переменные как intent(inout) а не как procedure call?

Заранее спасибо.

Ps: У меня есть устаревший код, и я не хочу добавлять intent(inout) везде, чтобы обнаружить неправильную интерпретацию такого рода.

1 Ответ

3 голосов
/ 14 января 2020

«Но при связывании нет ошибки, учитывая отсутствующий символ es!»

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

"Есть ли опция компилятора (ifort или gfortran) заставить объявленные переменные рассматриваться как намерение (inout), а не как вызов процедуры? "

Нет, и даже если бы это было так, это нарушило бы семантику кода, и это ПЛОХАЯ вещь ). Любой, использующий код где-то еще или без опции, будет облажан. Особенно тот факт, что он создает возможную опасную уязвимость кода, является явной причиной, по которой нельзя этого допустить.


Лучше сказать это явно, хотя я полагаю, что вы знаете об этом и просто хотите, чтобы инструмент диагностики c предупреждал вас:

Правильное объявление массива включает в себя его размерность, например

double precision es(1,*)

Также имейте в виду, что компиляторы могут проверять для подобных ошибок при вызове процедуры. Gfortran узнает, когда вызывающий код находится в том же файле, иногда Intel, даже если нет (когда включен -warn interfaces). Включение оптимизации времени ссылки также может помочь найти его. И, конечно, современный Фортран должен использовать модули.

Рассмотрим:

      subroutine test   (es, f)
!

      implicit none
!
      double precision es
      double precision f
      f=es(1,2)
!
      return
      end

   double precision a(2,1), b   
   call test(a, b)
end

Поскольку вызов находится в одном и том же файле, gfortran автоматически, без каких-либо дополнительных опций, определит проблему:

declaration.f90:14:13:

    call test(a, b)
             1
Warning: Rank mismatch in argument ‘es’ at (1) (scalar and rank-2) [-Wargument-mismatch]

Intel потребует флаг предупреждения

ifort -warn interfaces declaration.f90 
declaration.f90(14): error #6637: When a dummy argument is a function, the corresponding actual argument must also be a function.   [A]
   call test(a, b)
-------------^
compilation aborted for declaration.f90 (code 1)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...