2012-07-13 88 views
2

我在我们的fortran代码的自定义预处理器的环境中工作。我使用预处理器将逻辑参数切换为一种穷人的函数指针。今天我意识到,我有一个类似的情况:gfortran编译器错误?

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),因为据推测,编译器优化了通话了。我目前没有其他编译器需要检查,这些代码是否可以在其他地方编译?可以/应该这被认为是一个编译器错误?

因为我切换逻辑开关(而不是包含/不包含代码),部分原因是编译器仍然可以检查该代码块中的接口/语法(如果有能力的话)(并针对事件发出适当的警告不是简单的函数调用)。这是否意味着这些测试没有被执行或者链接器不需要该功能,因此一切都会通过Ok?

回答

6

这不是一个编译器错误。缺少引用的外部子程序不是标准需要Fortran处理器进行诊断的问题。其他处理器可能会或可能不会抱怨。诸如优化设置等事情可能会影响结果 - 英特尔Fortran 12.1.5抱怨优化关闭,不会抱怨优化。

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

+0

谢谢。在这一点上,我不能依赖标准的新版本。代码是在15年前编写的,并且预处理器是这​​样的,许多f90构造甚至可能导致它断裂:-(我也知道需要一个接口的程序检查 - 但是,我们的pre -processor。我想,既然标准甚至没有解决死代码的问题,什么都行......谢谢(我会等一会儿,只是为了确保没有其他人有任何关于此的说法,如果他们不要,我会很乐意接受这一点+1对于一个很好的答案任何方式。) – mgilson 2012-07-13 03:43:52

1

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

logical,parameter :: untrue=.false. 

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

但是,如果你行说:

logical :: untrue=.false. 

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

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

+0

'ifort'的默认优化级别是'O2' :) – 2012-07-13 07:59:53

2

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

但是我仍然觉得很奇怪gfortran不会提示无法访问的代码,即使编译时使用-Wall -Wunreachable-code