nAG Fortran コンパイラ(Fortran Builder)のエラー検出の例

ここでは、他のコンパイラで見落とされることが多いプログラム上のエラーをいくつか紹介します。
nAG Fortran コンパイラ(Fortran Builder)は、これらのエラーをすべて検出することができます。

A. 比較的容易に検出されるべきエラー
 プログラム単位内のコンパイルエラー
   1. EQUIVALENCE 経由の DO ループ制御変数の変更 ◯ 
 配列範囲外参照
   2. 配列の範囲外参照 ◯ 
   3. 形状引継ぎ配列の範囲外参照 ◯ 
   4. パラメタ化構造型配列の範囲外参照 ◯ 
 配列の形状不適合
   5. 配列引数の寸法の不一致 ◯ 
   6. 寸法が異なる配列の代入 ◯ 
 遊離状態のポインタ、割付けされていない状態の配列への参照
   7. 未定義ポインタの参照 ◯ 
   8. 空状態のポインタの参照 ◯ 
 省略された引数の参照
   9. 省略された引数の参照 ◯ 
 DOループの増分値がゼロ
   10. DOループの増分値がゼロ ◯ 
 文字引数の長さの不一致
   11. 文字引数の長さの不一致 ◯ 
 パラメタ化構造型の長さ型パラメタの不一致
   12. 組込拡張型代入における変数と式の型パラメタの不一致 ◯ 
   13. 組込拡張型代入で変数と式の型パラメタが不一致の状態で代入 ◯ 
 引数の長さ型パラメタの不一致
   14. 仮引数と実引数で拡張型の型パラメタが異なる ◯ 
 スレッドセーフ関連
   15. 誤った純粋手続 ◯ 
   16. スレッドセーフではないコードの検出 ◯ 
B. 比較的検出が困難と思われるエラー
 大域的チェックを伴うファイル内のコンパイルエラー
   17. 実引数と仮引数の型の不一致 ◯ 
   18. 名前付き共通ブロックの大きさの不一致 ◯ 
 大きさ引継ぎ配列の範囲外参照
   19. 大きさ引き継ぎ配列の範囲外参照 ◯ 
 ビット組込関数の不適切な引数
   20. ビット組込み関数への誤った引数 ◯ 
 整数オーバーフロー
   21. 整数オーバーフロー ◯ 
 解放済みポインタの参照
   22. 解放済のポインタの利用 ◯ 
 非再帰手続の再帰的な利用
   23. 再帰的に呼び出された手続が非再帰 ◯ 
 誤った型の引数
   24. 誤った型の引数 ◯ 
 変更してはいけない仮引数の変更
   25. 定数(パラメタ)引数の変更 ◯ 
   26. サブルーチン内での DO ループ制御変数の変更 ◯ 
 未定義変数の参照
   27. 割付け配列の初期化忘れ ◯ 
   28. 配列の部分的な初期化忘れ ◯ 
   29. 大きさ引き継ぎ配列の初期化忘れ ◯ 
   30. 固定サイズ配列の初期化忘れ ◯ 
   31. 共通ブロックの初期化忘れ ◯ 
   32. モジュール変数の初期化忘れ ◯ 

※ 上記のエラー項目の検出を有効にするには、コンパイラオプション -C=... が必要です。
詳細は「nAG Fortran Compiler, Release 7.2 マニュアル - 2.4 コンパイラオプション」をご参照ください。

※ Fortran Builder では、プロジェクトの設定の「Fortran コンパイラ > 実行時診断」から、コンパイラオプション -C=... を有効/無効にすることができます。

1. EQUIVALENCE 経由の DO ループ制御変数の変更

[ ce_dovar.f90 ]

program main
  implicit none
  integer i, j
  equivalence(i, j)
  j = 0
  do i = 1, 10
    j = j + 1 ! ここで値を変更してはいけない!
    print *, i
  end do
end program

このエラーを有効にするためのコンパイラオプション

-C=all

2. 配列の範囲外参照

[ rtc_array.f90 ]

program main
  implicit none
  integer i, x(3)
  x = 999
  do i = 1, 5
    print *, x(i) ! 配列の範囲外 x(4), x(5) を参照している。
  end do
end program

このエラーを有効にするためのコンパイラオプション

-C=all

3. 形状引継ぎ配列の範囲外参照

[ rtc_ashape.f90 ]

Program test_assumed_shape
  Implicit None
  Call test([1,2,3])
Contains
  Subroutine test(x)
    Integer,Intent(In) :: x(:)
    Integer i
    Do i=1,10
      Print *,x(i)
    End Do
  End Subroutine
End Program

このエラーを有効にするためのコンパイラオプション

-C=all

4. パラメタ化構造型配列の範囲外参照

[ rtc_pdtbounds.f90 ]

Program rtc_pdtbounds
  Implicit None
  Type t(k)
    Integer,Len :: k
    Real c(k)
  End Type
  Type(t(7)) x
  x%c = [ 1,2,3,4,5,6,7 ]
  Call test(x)
Contains
  Subroutine test(y)
    Type(t(*)),Intent(In) :: y
    Integer i
    Do i=1,10
      Print *,y%c(i)
    End Do
  End Subroutine
End Program

このエラーを有効にするためのコンパイラオプション

-C=all

5. 配列引数の寸法の不一致

[ rtc_shape_mismatch_in_sub.f90 ]

program main
  implicit none
  integer x(3)
  x = 99
  call sub(x, 4)
  print *, x
end program

subroutine sub(a, n)
  implicit none
  integer n
  integer a(n) ! 配列の寸法が一致していない!
  a(1) = 100
end subroutine

このエラーを有効にするためのコンパイラオプション

-C=all

6. 寸法が異なる配列の代入

[ rtc_shape_mismatch_assignment.f90 ]

program main
  implicit none
  integer a(3)
  call sub(a)
  print *, a
contains
  subroutine sub(x)
    integer x(:), y(1)
    y = 99
    x = y ! x と y の寸法が異なる!
  end subroutine
end program

このエラーを有効にするためのコンパイラオプション

-C=all

7. 未定義ポインタの参照

[ rtc_pointer_undef.f90 ]

program main
  implicit none
  real, pointer :: x(:)
  print *, size(x) ! 未定義のポインタを参照している。
end program

このエラーを有効にするためのコンパイラオプション

-C=all

8. 空状態のポインタの参照

[ rtc_pointer_null.f90 ]

program main
  implicit none
  real, pointer :: y(:) => null()
  print *, size(y) ! 空状態のポインタを参照している。
end program

このエラーを有効にするためのコンパイラオプション

-C=all

9. 省略された引数の参照

[ rtc_optional_arg.f90 ]

program main
  implicit none
  integer :: a = 2, b = 3
  call add_print(a, b)
contains
  subroutine add_print(a, b, c)
    integer, intent(in) :: a, b
    integer, intent(in), optional :: c
    print *, a + b + c ! 省略された引数 c を参照している!
  end subroutine
end program

このエラーを有効にするためのコンパイラオプション

-C=all

10. DOループの増分値がゼロ

[ rtc_do.f90 ]

program main
  implicit none
  integer i, s
  s = 0
  do i = 1, 10, s ! ループの増分値が 0 である。
    print *, i
  end do
end program

このエラーを有効にするためのコンパイラオプション

-C=all

11. 文字引数の長さの不一致

[ rtc_charlen.f90 ]

program main
  implicit none
  character(3) c
  c = 'abc'
  call sub(c, 4)
  print *, c
end program

subroutine sub(a, n)
  implicit none
  integer n
  character a(n) ! 文字長が一致していない!
  a(1:1) = 'X'
end subroutine

このエラーを有効にするためのコンパイラオプション

-C=all

12. 組込拡張型代入における変数と式の型パラメタの不一致

[ rtc_pdt_len_params.f90 ]

Program rtc_pdt_len_params
  Implicit None
  Type t(k)
    Integer,Len :: k
    Real c(k)
  End Type
  Type(t(7)) x
  x%c = [ 1,2,3,4,5,6,7 ]
  Call test(x)
Contains
  Subroutine test(y)
    Type(t(*)),Intent(In) :: y
    Type(t(10)) :: z
    Integer i
    z = y
    Do i=1,10
      Print *,z%c(i)
    End Do
  End Subroutine
End Program

このエラーを有効にするためのコンパイラオプション

-C=all

13. 組込拡張型代入で変数と式の型パラメタが不一致の状態で代入

[ rtc_pdt_len_params2.f90 ]

Program rtc_pdt_len_params2
  Implicit None
  Type t(k)
    Integer,Len :: k
    Real c(k)
  End Type
  Type(t(7)) x
  x%c = [ 1,2,3,4,5,6,7 ]
  Call test(x,7) ! Okay
  Call test(x,3) ! Bad
  Call zap(123)
  Call test(x,123) ! Also bad
Contains
  Subroutine zap(n)
    Integer,Intent(In) :: n
    Real r(n)
    Real,Allocatable :: a(:)
    Call Random_Number(r)
    a = r*100
    If (Sum(a)==100*n) Stop 'Unbelievable'
  End Subroutine
  Subroutine test(y,n)
    Type(t(*)),Intent(InOut) :: y
    Integer,Intent(In) :: n
    Type(t(n)) :: z
    Integer i
    Real s
    Print *,'Assignment of K',y%k,'expression to K',z%k,'variable'
    z = y
    s = 0.0
    Do i=1,n
      s = s + z%c(i)
      z%c(i) = -z%c(i)
    End Do
    Print *,'Sum =',s
  End Subroutine
End Program

このエラーを有効にするためのコンパイラオプション

-C=all

14. 仮引数と実引数で拡張型の型パラメタが異なる

[ rtc_pdt_arg.f90 ]

Program rtc_pdt_arg
  Implicit None
  Type t(k)
    Integer,Len :: k
    Real c(k)
  End Type
  Type(t(7)) :: x
  x%c = 0
  Call sub1(x)
  Call sub2(x,7)
  Call sub2(x,999)
Contains
  Subroutine sub1(y)
    Type(t(*)) y
    Print *,'Y%K =',y%k
    If (Any(y%c/=0)) Stop 'FAIL value'
  End Subroutine
  Subroutine sub2(z,n)
    Integer,Intent(In) :: n
    Type(t(n)) :: z
    Print *,'Z%K =',z%k
    If (n/=z%k) Then
      Print *,'Z declared as TYPE(T(N)), but with N =',n,', Z%K =',z%k
      Stop 'FAIL z%k/=n'
    End If
    If (n/=7) Stop 'FAIL Actual arg has X%K = 7'
    If (Any(z%c/=0)) Stop 'FAIL value'
  End Subroutine
End Program

このエラーを有効にするためのコンパイラオプション

-C=all

15. 誤った純粋手続

[ purity.f90 ]

! This function is not pure, because it writes to global variables.
Pure Real Function f(x,y)
  Real,Intent(In) :: x,y
  Real :: z
  Common/c/z(2)
  Real,External :: sum_of_z
  z(1) = x
  z(2) = y
  f = sum_of_z()
End Function

! This function is pure, as although it reads from global variables,
! it does not change any.
Pure Real Function sum_of_z()
  Real z
  Common/c/z(2)
  sum_of_z = Sum(z)
End Function

! This function is thread-safe, but not pure: although it has no side-effects,
! the dummy arguments have not had their INTENT declared.
Real Function g(x,y)
  Real x,y
  g = x + y**2
End Function

このエラーを有効にするためのコンパイラオプション

オプションは必要ありません。

16. スレッドセーフではないコードの検出

[ threadsafety.f90 ]

! This function is not thread-safe, because it writes to global variables.
Real Function f(x,y)
  Real,Intent(In) :: x,y
  Real :: z
  Common/c/z(2)
  Real,External :: sum_of_z
  z(1) = x
  z(2) = y
  f = sum_of_z()
End Function

! This function is thread-safe, as although it reads from global variables,
! it does not change any.
Real Function sum_of_z()
  Real z
  Common/c/z(2)
  sum_of_z = Sum(z)
End Function

! This function is thread-safe, as it has no side-effects.
Real Function g(x,y)
  Real x,y
  g = x + y**2
End Function

このエラーを有効にするためのコンパイラオプション

-thread_safe

17. 実引数と仮引数の型の不一致

[ gcheck.f90 ]

Program gcheck
  Real x(10)
  External sub
  Call sub(x,10)
  Print *,'FAIL',x
End Program
Subroutine sub(y,n) ! Different data type.
  Integer n,y(n)
  y = 42
End Subroutine

このエラーを有効にするためのコンパイラオプション

-C=all

18. 名前付き共通ブロックの大きさの不一致

[ gcommon.f90 ]

Program gcommon
  Common/c/w,x,y,z
  w = 2.5
  Call sub
  Print *,w,x,y,z
End Program
Subroutine sub
  Common/c/w,xy,z ! Note the missing comma.
  x = w ** 2
  y = x * w
  z = y * x
End Subroutine

このエラーを有効にするためのコンパイラオプション

-C=all

19. 大きさ引き継ぎ配列の範囲外参照

[ assumed_size_array.f90 ]

program main
  implicit none
  integer x(3)
  x = 99
  call sub(x)
end program

subroutine sub(i)
  implicit none
  integer i(*)
  i(4) = 100 ! 配列の範囲外を参照している!
end subroutine

このエラーを有効にするためのコンパイラオプション

-C=all

20. ビット組込み関数への誤った引数

[ rtc_bit_intrinsic.f90 ]

program main
  implicit none
  integer i
  do i = 1, 100
    print 10, ibset(0, i) ! ここで i は 0~31 の範囲の値でなければならない!
    10 format (1x, z0)
  end do
end program

このエラーを有効にするためのコンパイラオプション

-C=all

21. 整数オーバーフロー

[ rtc_intovf.f90 ]

program main
  implicit none
  integer n
  n = huge(n)
  print *, n + 1 ! 整数の最大値に 1 を加算している!
end program

このエラーを有効にするためのコンパイラオプション

-C=all

22. 解放済のポインタの利用

[ rtc_dangling.f90 ]

program main
  implicit none
  integer, pointer :: p(:) => null()
  integer, target, allocatable :: a(:)
  allocate (a(4))
  a = (/ 1, 2, 3, 4 /)
  p => a
  deallocate (a)
  print *, p ! 解放されたメモリ領域を参照している!
end program

このエラーを有効にするためのコンパイラオプション

-C=all

23. 再帰的に呼び出された手続が非再帰

[ rtc_recursion.f90 ]

integer function func_recursively_called(func_to_call, n)
  implicit none
  external func_to_call
  integer n, m(1000, 1000), func_to_call
  m = n
  if (n < 2) then
	func_recursively_called = func_to_call(func_to_call, n + 1)
  end if
  if (any(m /= n)) then
    func_recursively_called = -999 ! おかしい!
  else
    func_recursively_called = 0    ! OK
  endif
end function

program main
  implicit none
  external func_recursively_called
  integer func_recursively_called
  if (func_recursively_called(func_recursively_called, 1) == 0) then
    print *, 'OK.  No error.'
  else
    print *, 'NG.  BAD'
  endif
end program

このエラーを有効にするためのコンパイラオプション

-C=all

24. 誤った型の引数

[ rtc_calls_main.f90 ]

program main
  implicit none
  integer :: a = 2, b = 3
  call add_print(a, b) ! 実数の仮引数に整数の実引数を渡している。
end program

[ rtc_calls_sub.f90 ]

subroutine add_print(a, b)
  implicit none
  real, intent(in) :: a, b
  print *, a + b
end subroutine

このエラーを有効にするためのコンパイラオプション

-C=all

25. 定数(パラメタ)引数の変更

[ rtc_parameter_changed.f90 ]

program main
  implicit none
  integer, parameter :: x = 99
  call sub(x)
  print *, x
end program

subroutine sub(i)
  implicit none
  integer i
  i = 10 ! i は定数なので変更してはいけない!
end subroutine

このエラーを有効にするためのコンパイラオプション

-C=all

26. サブルーチン内での DO ループ制御変数の変更

[ rtc_dovar_changed.f90 ]

program main
  implicit none
  integer i
  do i = 1, 10
    call sub(i)
    print *, i
  end do
end program

subroutine sub(i)
  implicit none
  integer i
  i = i + 1 ! ここで値を変更してはいけない!
end subroutine

このエラーを有効にするためのコンパイラオプション

-C=all

27. 割付け配列の初期化忘れ

[ rtc_undef_allocatable.f90 ]

program main
  implicit none
  integer, allocatable :: a(:)
  allocate (a(3))
  call sub(a)
end program

subroutine sub(x)
  implicit none
  integer x(3)
  print *, x ! 初期化されていない x を参照している!
end subroutine

このエラーを有効にするためのコンパイラオプション

-C=undefined

28. 配列の部分的な初期化忘れ

[ rtc_undef_partial_undef.f90 ]

program main
  implicit none
  integer i, x(4)
  do i = 1, 3
    x(i) = i
  end do
  print *, x ! 部分的に初期化されていない x を参照している!
end program

このエラーを有効にするためのコンパイラオプション

-C=undefined

29. 大きさ引き継ぎ配列の初期化忘れ

[ rtc_undef_assumed_size.f90 ]

program main
  implicit none
  integer i(4)
  call sub(i)
end program

subroutine sub(i)
  implicit none
  integer i(*)
  print *, i(1) ! 初期化されていない i(1) を参照している!
end subroutine

このエラーを有効にするためのコンパイラオプション

-C=undefined

30. 固定サイズ配列の初期化忘れ

[ rtc_undef_fixed_size.f90 ]

program main
  implicit none
  integer i(4)
  call sub(i)
end program

subroutine sub(i)
  implicit none
  integer i(4)
  print *, i(1) ! 初期化されていない i(1) を参照している!
end subroutine

このエラーを有効にするためのコンパイラオプション

-C=undefined

31. 共通ブロックの初期化忘れ

[ rtc_undef_common.f90 ]

program main
  implicit none
  integer x
  common /nAG/ x
  print *, x ! 初期化されていない x を参照している!
end program

このエラーを有効にするためのコンパイラオプション

-C=undefined

32. モジュール変数の初期化忘れ

[ rtc_undef_module_var.f90 ]

module mymod
  integer x
end module

program main
  use mymod
  print *, x ! 初期化されていない x を参照している!
end program

このエラーを有効にするためのコンパイラオプション

-C=undefined
関連情報
© 日本ニューメリカルアルゴリズムズグループ株式会社 2024
Privacy Policy  /  Trademarks