2

我在一个为我们的 fortran 代码提供自定义预处理器的环境中工作。我使用预处理器将逻辑参数切换为一种穷人的函数指针。我今天意识到我遇到了类似这样的情况:

  program main
  logical,parameter :: untrue=.false.
  if(untrue)then
    call func1()
  else
    call func2()
  endif
  end

  subroutine func2()
  print*,"Hello, World!"
  end

换句话说,func1没有在任何地方定义,但是,它使用 gfortran(版本 4.4 和 4.6)编译,因为大概编译器优化了该调用。我目前没有其他编译器可以检查,这段代码是否在其他地方编译?可以/应该将其视为编译器错误吗?

我切换逻辑开关(而不是包括/不包括代码)的部分原因是编译器仍然可以检查该代码块内的接口/语法(如果有能力)(并对不简单的事情发出适当的警告函数调用)。这是否意味着没有执行这些测试,或者只是链接器不需要该功能,所以一切正常?

4

3 回答 3

6

这不是编译器错误。没有引用的外部子程序不是标准需要 Fortran 处理器来诊断的。其他处理器可能会或可能不会抱怨。优化设置之类的事情可能会影响结果 - 英特尔 Fortran 12.1.5 抱怨优化关闭,而不抱怨优化打开。

对于您的示例代码,其中 func2 是一个外部子程序,Fortran 的程序单元单独编译模型意味着不需要过程接口检查。对于许多处理器,这不太可能发生(实际上 func2 可能在一个单独的文件中,该文件在主程序之后很长时间编译,可能在另一台机器上,可能在主程序的源代码不再可用的情况下) . 如果要保证过程接口检查,则需要确保过程具有显式接口,例如将它们放入模块中。Fortran 2003 标准中引入并至少受 gfortran 4.6 支持的过程指针语言功能也可能有所帮助。

于 2012-07-13T03:35:54.443 回答
2

它似乎是 GNU Fortran 特定的行为,即使在优化级别也会删除无法访问的代码部分O0。这与 ISO/IEC 1539:1991 一致:§8.1.2 规定只有一个IF构造块必须执行,§8.1.1.2 明确禁止将控制从块外部转移到块内部。这允许编译器删除肯定不会执行的代码部分,这是有道理的,因为您无法IF在不重新编译程序源的情况下更改示例中构造的行为,并且编译器只是精通符号。

但我仍然觉得奇怪的是,gfortran即使使用-Wall -Wunreachable-code.

于 2012-07-13T09:19:36.600 回答
1

您在这里看到的只是编译器允许自己忽略任何永远不会被调用的引用。该行:

logical,parameter :: untrue=.false.

保证你的if块的第一部分不会被执行。正如 IanH 指出的 (+1),这不是编译器错误,而是优化过程的一部分。此代码还将使用pgf90 10.6-0和使用默认优化进行编译ifort 12.0.2.137。但是,如果指示在未启用优化的情况下进行编译,它们将失败。

但是,如果您的线路说:

logical :: untrue=.false.

编译器更有可能抱怨,因为untrue允许变量更改其值。例如,pgf90除非需要更高的优化级别,否则将失败,而“ifort”仍将在默认优化级别上编译。

在任何情况下,依赖编译器行为都不是最佳实践,而且正如 IanH 所指出的,最好通过使用模块来指定外部函数和子例程接口。

于 2012-07-13T04:27:37.227 回答