Hitachi

COBOL2002 Professional Tool Kit COBOLソース解析ガイド


10.6 デッドコード候補の検知方法

デッドコード候補の検知方法について説明します。

デッドコードとは,プログラム実行時に実行される可能性がない文,プログラムなど,プログラムの実行結果に影響を与えないソースコードのことです。デッドコード候補から,テストが不要なプログラムの選定や,プログラムの処理の誤りを発見できます。

デッドコードの例を次の図に示します。

図10‒1 デッドコードの例

[図データ]

デッドコード検出の対象

COBOLソース解析では,登録集原文を取り込んだあとのCOBOLプログラム中のプログラム定義で,コンパイル対象になる行を検出対象とします。

デッドコード検出の対象でない項目

次に示すコードは検出対象外です。

デッドコード候補の種類

検出されるデッドコード候補の種類を次の表に示します。

表10‒6 検出されるデッドコード候補の種類

項番

デッドコード候補の種類

内容

ソース表示(COPY展開後)時に背景をグレーにする行

1

未使用の外部プログラム

一度も呼び出されることがない外部プログラム

PROGRAM-IDの行

2

未使用の内部プログラム

一度も呼び出されることがない内部プログラム

PROGRAM-IDの行

3

未使用のデータ項目

一度も参照されていないデータ項目

データ項目の定義位置

4

未使用のファイル名,報告書名,画面名,通信記述名

一度も参照されていないファイル名,報告書名,画面名,通信記述名

報告書名,画面名,通信記述名の定義位置

5

制御が渡らない文

実行時に制御が渡ることがない文

制御が渡ることがない文の先頭行から終了行

6

制御が渡らない手続き

実行時に制御が渡ることがない手続き

制御が渡ることがない手続きの定義位置

デッドコード候補の詳細

デッドコード候補として検出される内容を次に示します。

未使用の外部プログラム

解析対象の翻訳単位間で,どのプログラムからも呼び出されていないCOBOL主プログラム以外の外部プログラムが検出されます。COBOLソース解析では,次に示すプログラムを未使用の外部プログラムとします。

(例)未使用の外部プログラムの例

次の例では,プログラムAにプログラムDを呼ぶCALL文が存在するが,CALL文がデッドコードであるためプログラムDもデッドコード候補として検出されます。また,プログラムDが呼ばれていないため,プログラムDからしか呼ばれていないプログラムEもデッドコード候補となります。プログラムFはプログラムCからの呼び出しがあるため,デッドコード候補にはなりません。

図10‒2 未使用の外部プログラムの例

[図データ]

注意
  • 重複するプログラム名/ENTRY文で定義した入口点の名称が存在する場合で,かつそのプログラムを呼び出すCALL文があるときは,それらのプログラムはすべて呼ばれるものと仮定して処理されます。

  • 未使用外部プログラムの場合,プログラム中のほかのデッドコードも検出します。

未使用の内部プログラム

最外プログラム中で,一度も呼び出されていない内部プログラムが検出されます。COBOLソース解析では,次に示すプログラムを未使用の内部プログラムとします。

プログラム中にCALL/CANCEL 一意名が存在する場合,COBOLソース解析では内部プログラムを次のように扱います。

未使用のデータ項目

データ部中の作業場所節,局所場所節,連絡節,画面節で定義している01,77,レベルのデータ項目定義で,プログラム中で1回も参照されていない項目が検出されます。COBOLソース解析では,定義したデータ項目が集団項目である場合,集団項目に属するすべてのデータ項目が未使用である場合だけ未使用のデータ項目として検出されます。また,デッドコード候補の処理からだけ参照されているデータ項目も,未使用のデータ項目として検出されます。

注意事項
  • COBOLソース解析では,ファイル節で定義しているレコード記述項および報告書節で定義している報告集団記述項が未使用かどうかは検出されません。これらが未使用かどうかは,未使用のファイル名,報告書名の検出結果で判断してください。

  • 埋め込みSQL宣言節内で定義しているデータ項目がSQL文中で使用されていても,COBOLの構文中で使用されていない場合は,未使用のデータ項目として検出します。このため,埋め込みSQL宣言節内のデータ項目が未使用のデータ項目として検出された場合は,SQL文中でも使用されていないかどうかを確認してください。

  • データ項目が参照された場合,そのデータ項目の定義に必要なデータ項目は未使用のデータ項目として検出されません。

(例)

未使用のデータ項目として検出されない例

01 A PIC X.
01 B REDEFINES A PIC 9.

上記の定義に対し,データ項目「B」が参照されている場合,データ項目「A」は未使用のデータ項目として検出されません。

未使用のファイル名,報告書名,画面名,通信記述名

ファイル名,報告書名,画面名,通信記述名の中で,手続き部から1回も参照されていないものが検出されます。

ファイル名,報告書名,画面名が参照された場合,各項目の定義に必要なデータ項目は未使用のデータ項目として検出されません。

(例)

未使用のデータ項目として検出されない例

FILE-CONTROL.
  SELECT FILE1
    ASSIGN TO 'FNAME'
    FILE STATUS FS1.
      :
WORKING-STORAGE SECTION. 
  01 FS1 PIC X(2).

上記の定義に対し,ファイル「FILE1」が参照されている場合,データ項目「FS1」は未使用のデータ項目として検出されません。

制御が渡らない文,手続き

実行時に制御が渡る可能性がない文,手続きが検出されます。COBOLソース解析では,次の文および手続きを制御が渡らない文と判断します。

ただし,次に示す文および手続きは,実行時に制御が渡る可能性がある文および手続きと判断します。

(例)

実行時に制御が渡る可能性がある文および手続きと判断する例

PROCEDURE DIVISION.
DECLARATIVES.
USE-PROC SECTION.                    *> 宣言部分のUSE手続きは制御が
  USE AFTER EXCEPTION CONDITION      *> 渡る可能性があると判断する
                      EC-SIZE-ZERO-DIVIDE.
    DISPLAY 'ゼロ除算発生'.
    RESUME 復帰手続き.
    DISPLAY 'DEAD CODE'.             *> デッドコード候補
END DECLARATIVES.
PROC-SEC SECTION.
    ACCEPT X.                        *> 非宣言部分の最初の文は制御が
                                     *> 渡る可能性があると判断する
>>TURN EC-SIZE CHECKING ON
    DIVIDE 10 BY X GIVING RESULT.
    DISPLAY RESULT.
    STOP RUN.
    DISPLAY 'DEAD CODE'.             *> デッドコード候補
 
    ENTRY 'ENTRY1'.                  *> ENTRY文は制御が渡る可能性が
    DISPLAY '入口点:ENTRY1'.        *> あると判断する
     :
次の文に実行の制御を移さない文

次の文に実行の制御を移さない文を次に示します。

  • 画面機能のACCEPT文/ REPLY文(USE FOR WINDOW節内)

  • EXIT PERFORM文

  • EXIT USE文

  • GO TO文

  • GOBACK文

  • IF文/SEARCH文のNEXT SENTENCE

  • RESUME文

  • STOP文

  • 手続き先から制御が戻って来ないそとPERFORM文,PROCEDURE指定のあるSORT/MERGE文(USE手続き中に「RESUME 手続き名」が存在する場合を除く)

(例)

PERFORM文の例

A.
  PERFORM B.
  DISPLAY  'A'.  *> デッドコード候補
B.
  STOP RUN.
USE手続き中に「RESUME 手続き名」が存在する場合

「RESUME 手続き名」が存在する場合,そとPERFORM文とPROCEDURE指定のがあるSORT/MERGE文は,指定された手続き先から必ず制御が戻ってくるものとして扱います。

次に示すプログラムでは,1.のPERFORM文を実行すると手続きA中で4. STOP RUN文を実行するため,PERFORM文に制御が戻ってきません。このため,2.のDISPLAY文は実行されません(デッドコード候補)。しかし,手続きA中の3.で例外が発生すると,USE手続きを通して手続きBへ制御が渡ることがあります。この場合,1.のPERFORM文に制御が戻り,2.のDISPLAY文も実行されます。

COBOLソース解析,PERFORM/SORT/MERGE文に指定した手続き先で,実行時に例外が発生するかどうかは判断しません。このため,手続き先での例外の発生を考慮し,「RESUME 手続き名」が存在するプログラムの場合,PERFORM/SORT/MERGE文に指定された手続き先からは,必ず制御が戻ると仮定します。

このプログラムの例では,1.のPERFORM文は必ず制御が戻ると仮定するため,2.のDISPLAY文はデッドコード候補として検出されません。

(例)

PERFORM文の例

USE-PROC SECTION.
  USE AFTER EXCEPTION CONDITION EC-ALL.
    RESUME B.               
END DECLARATIVES.
ST.
  ACCEPT      X.
  MOVE 123 TO Y.
  PERFORM A THRU B.         *> 1.
  DISPLAY 'AFTER PERFORM'.  *> 2. デッドコード候補ではないと仮定
  STOP RUN.
A.
  DISPLAY 'A'.
  COMPUTE X = Y / X.        *> 3.
  STOP RUN.                 *> 4.
B.
  DISPLAY 'B'.
  • 条件文(IF,EVALUATE)や条件指定([NOT] ON SIZE ERRORなど)のある文で,すべての分岐先の無条件文に制御を移す文が存在

(例)

すべての分岐先の無条件文に制御を移す文が存在する例

  A.
    IF X = 1 THEN
       GO TO B
    ELSE
       GO TO C
    END-IF.
    DISPLAY  'A'.  *> デッドコード候補
  B.
  C.
注意
  • 条件文,または条件指定付きの文がある場合,すべての分岐先が実行される可能性があると仮定されます。

    ALTER文で飛び先が変更されているGO TO文がある場合,そのGO TO文を参照しているすべてのALTER文に指定された飛び先の手続きは,実行されると仮定されます。

    (例) 次に示す例では,手続きA中のGO TO文は,ALTER文によって飛び先を手続きXまたはYに変更しています。このプログラムで手続きA中のGO TO文に制御が渡る場合,手続きX,手続きYの両方とも実行される手続きと仮定されます。

     ALTER A TO X.
       :
     ALTER A TO Y.
       :
 A.
     GO TO.
 B. 
     STOP RUN.
       :
 X.           *> 実行される可能性があると仮定する
       :
 Y.           *> 実行される可能性があると仮定する
       :
(例1)制御が渡らない文の例1

次のプログラムでは,GOBACK文の後ろにある文は実行されることがないため,デッドコード候補として検出されます。

   A.
       GOBACK.
       DISPLAY 'this is dead code'.   *>  デッドコード候補
(例2)制御が渡らない文の例2

次のプログラムでは,手続きBの最初の文であるDISPLAY文に制御が渡ることはないが,ENTRY文は実行される可能性があると判断されます。このため,手続きBの最初のDISPLAY文だけデッドコード候補として検出されます。

   PROCEDURE DIVISION.
   A.
       DISPLAY 'XXX'.
       STOP RUN.
   B.
       DISPLAY 'this is dead code'. *>   デッドコード候補
       ENTRY 'YYY'.
       DISPLAY 'YYY'.
(例3)制御が渡らない手続きの例

次のプログラムでは,IF文のTHEN節,ELSE節は両方実行される可能性があると判断されます。その結果,手続きBをデッドコード候補として検出されます。

       :
    PROCEDURE DIVISION.
    A.
       ACCEPT X.
       IF X = 1 THEN
          PERFORM C
       ELSE
          GO TO D
       END-IF.
       STOP RUN.
    B.              *> デッドコード候補の手続き
       GO TO D.
    C.
    D.

デッドコード候補の検知の注意