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) でコンパイルされます。これは、おそらくコンパイラがその呼び出しを最適化するためです。現時点では、チェックする他のコンパイラがありません。このコードは他の場所でコンパイルされますか? これはコンパイラのバグと見なすことができますか?

(コードを含める/含めないのではなく) 論理スイッチを切り替える理由の 1 つは、コンパイラがそのコード ブロック内のインターフェイス/構文 (可能な場合) を引き続きチェックできるようにするためです (単純でないものに対しては適切な警告を発行します)。関数呼び出し)。これは、これらのテストが実行されていないことを意味しますか、それとも関数がリンカによって必要とされていないため、すべて OK を通過することを意味しますか?

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構成要素の 1 つのブロックのみを実行する必要があると述べており、§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 に答える