TypeCobolTeam / TypeCobol

TypeCobol is an Incremental Cobol parser for IBM Enterprise Cobol 6 for zOS syntax. TypeCobol is also an extension of Cobol 85 language which can then be converted to Cobol85.
Other
78 stars 26 forks source link

Invalid "Warning: Unreachable code detected" on STOP RUN statement #2153

Open alvaro-vantis-pt opened 2 years ago

alvaro-vantis-pt commented 2 years ago

Describe the bug Message of Unreachable code when code is on normal program flow. Using TypeCobol V1.5.11.

To Reproduce run TypeCobol.CLI.exe with "-cfg=2" or "-cfg=3" option. The error does not occurs when -cfg=1 is in effect.

Expected behavior "Warning: Unreachable code detected" should be shown only for unreachable code lines

Example of Code to reproduce the problem:

       IDENTIFICATION DIVISION.
       PROGRAM-ID. TESTP02.
       PROCEDURE DIVISION.
       MAIN-SECTION SECTION.
           PERFORM SECTION1
                  STOP RUN.

       SECTION1 SECTION.
           DISPLAY "SECTION1".
           GO TO SECTION2.
           DISPLAY "UNREACHABLE CODE".
           PERFORM SECTION3.
       A01-EXIT.
           EXIT.

       SECTION2 SECTION.
           DISPLAY "SECTION2".
           GOBACK.

       SECTION3 SECTION.
           DISPLAY "SECTION3".

       SECTION4 SECTION.
           DISPLAY "SECTION4".
           GOBACK.
       END PROGRAM TESTP02.
Test runs:

TypeCobol.CLI.exe -cfg=2 -i=c:StopRunSection1 -o=c:out.cbl 2/28/2022 3:05:03 PM start parsing of StopRunSection1

ReturnCode=Warning_ 9 errors in "c:StopRunSection1": Line 6[19,22] <37, Warning, General> - Warning: GOBACK should be used instead of STOP RUN Line 6[19,26] <37, Warning, General> - Warning: Unreachable code detected Line 11[12,37] <37, Warning, General> - Warning: Unreachable code detected Line 12[12,27] <37, Warning, General> - Warning: Unreachable code detected Line 14[12,15] <37, Warning, General> - Warning: Unreachable code detected Line 21[12,29] <37, Warning, General> - Warning: Unreachable code detected Line 24[12,29] <37, Warning, General> - Warning: Unreachable code detected Line 25[12,17] <37, Warning, General> - Warning: Unreachable code detected Line 5[12,27] <37, Warning, General> - Warning: Statement ' GO TO SECTION2' located at line 10, column 12 prevents this PERFORM statement to reach its exit. parsed in 00:00:01.1221179 ms

Code: 1 TypeCobol.CLI.exe: Operation failed Try TypeCobol.CLI.exe --help for usage information.

TypeCobol.CLI.exe -cfg=3 -i=c:StopRunSection1 -o=c:out.cbl 2/28/2022 3:05:10 PM start parsing of StopRunSection1

ReturnCode=Warning_ 9 errors in "c:StopRunSection1": Line 6[19,22] <37, Warning, General> - Warning: GOBACK should be used instead of STOP RUN Line 6[19,26] <37, Warning, General> - Warning: Unreachable code detected Line 11[12,37] <37, Warning, General> - Warning: Unreachable code detected Line 12[12,27] <37, Warning, General> - Warning: Unreachable code detected Line 14[12,15] <37, Warning, General> - Warning: Unreachable code detected Line 21[12,29] <37, Warning, General> - Warning: Unreachable code detected Line 24[12,29] <37, Warning, General> - Warning: Unreachable code detected Line 25[12,17] <37, Warning, General> - Warning: Unreachable code detected Line 5[12,27] <37, Warning, General> - Warning: Statement ' GO TO SECTION2' located at line 10, column 12 prevents this PERFORM statement to reach its exit. parsed in 00:00:01.0822997 ms

Code: 1 TypeCobol.CLI.exe: Operation failed Try TypeCobol.CLI.exe --help for usage information.

TypeCobol.CLI.exe -cfg=1 -i=c:StopRunSection1 -o=c:out.cbl 2/28/2022 3:05:18 PM start parsing of StopRunSection1

ReturnCode=Warning_ 8 errors in "c:StopRunSection1": Line 6[19,22] <37, Warning, General> - Warning: GOBACK should be used instead of STOP RUN Line 11[12,37] <37, Warning, General> - Warning: Unreachable code detected Line 12[12,27] <37, Warning, General> - Warning: Unreachable code detected Line 14[12,15] <37, Warning, General> - Warning: Unreachable code detected Line 21[12,29] <37, Warning, General> - Warning: Unreachable code detected Line 24[12,29] <37, Warning, General> - Warning: Unreachable code detected Line 25[12,17] <37, Warning, General> - Warning: Unreachable code detected Line 5[12,27] <37, Warning, General> - Warning: Statement ' GO TO SECTION2' located at line 10, column 12 prevents this PERFORM statement to reach its exit. parsed in 00:00:01.0912782 ms

Code: 1 TypeCobol.CLI.exe: Operation failed Try TypeCobol.CLI.exe --help for usage information.

smedilol commented 2 years ago

Hello,

Thanks for the feedback. We are currently focusing on fixing blocking bug with our parser for our Cobol developers. Maybe we'll work on this kind of issues in a few weeks.

alvaro-vantis-pt commented 2 years ago

Thanks for the feedback. It seems that the problem is not related to "STOP RUN" statement, but the fact that it is after a PERFORM paragraph statement, because: 1) The same thing happened with another program with ALTER statement that is after a PERFORM paragraph statement; 2) Debugging it with visual studio, I found that the problem seems to be on the following function on ControlFlowGraphBuilder.cs:

    /// <summary>
    /// Extend BasicBlockForNodeGroup instance to point to the first block and make all terminal blocks
    /// have for successor the block successor.
    /// </summary>
    /// <param name="group">The group to be continued</param>
    private void ContinueBasicBlockGroup(BasicBlockForNodeGroup group)
    {
        if (group.Group.Count > 0)
        {
            System.Diagnostics.Debug.Assert(group.SuccessorEdges.Count == 1);
            int succIndex = group.SuccessorEdges[0];
            group.SuccessorEdges.Clear();

            //Make the First block the successor of the group
            LinkedListNode<BasicBlock<Node, D>> first = group.Group.First;
            int firstIndex = this.CurrentProgramCfgBuilder.Cfg.SuccessorEdges.Count;
            group.SuccessorEdges.Add(firstIndex);
            this.CurrentProgramCfgBuilder.Cfg.SuccessorEdges.Add(first.Value);

            //Make all terminal blocks of the group have the original successor of the block.
            foreach (var termBlock in group.TerminalBlocks)
            {
                if (!termBlock.SuccessorEdges.Contains(succIndex))
                {
                    if (!termBlock.HasFlag(BasicBlock<Node, D>.Flags.Ending))
                    {
                        termBlock.SuccessorEdges.Add(succIndex);
                    }
                }
            }
            group.SetFlag(BasicBlock<Node, D>.Flags.GroupGrafted, true);
        }
    }

When running with cfg 3, it enters 3 times on this function. The variable group.SuccessorEdges[0] has the correct value before the executation of "group.SuccessorEdges.Clear();" and gets a wrong value on "termBlock.SuccessorEdges.Add(succIndex);"