Skip to content

Commit 4e901f8

Browse files
authoredJan 4, 2022
WI #2039 Remove PERFORM recursivity check from CFG (#2100)
1 parent 8426aa4 commit 4e901f8

20 files changed

+2
-132
lines changed
 
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
11
--- Diagnostics ---
2-
Line 28[15,29] <37, Warning, General> - Warning: A recursive loop has been encountered while analyzing 'PERFORM pararec', recursive instruction is ' perform pararec2'.
32
Line 29[15,57] <37, Warning, General> - Warning: Unreachable code detected
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,2 @@
11
--- Diagnostics ---
2-
Line 31[15,29] <37, Warning, General> - Warning: A recursive loop has been encountered while analyzing 'PERFORM pararec', recursive instruction is ' perform pararec2'.
32
Line 32[15,57] <37, Warning, General> - Warning: Unreachable code detected
4-
Line 57[15,64] <37, Warning, General> - Warning: A recursive loop has been encountered while analyzing 'PERFORM pararec4', recursive instruction is ' perform pararec4 varying n from 1 by 1 until n > 5'.
5-
Line 57[15,64] <37, Warning, General> - Warning: A recursive loop has been encountered while analyzing 'PERFORM pararec4', recursive instruction is ' perform pararec3 test after varying n from 1 by 1 until n'.

‎TypeCobol.Analysis.Test/BasicCfgInstrs/PerformIdentity.diag

-2
This file was deleted.

‎TypeCobol.Analysis.Test/BasicCfgInstrs/PerformProc1Recursive0.diag

-2
This file was deleted.

‎TypeCobol.Analysis.Test/BasicCfgInstrs/PerformProc2Recursive0.diag

-2
This file was deleted.

‎TypeCobol.Analysis.Test/BasicCfgInstrs/PerformProc3Recursive0.diag

-2
This file was deleted.

‎TypeCobol.Analysis.Test/BasicCfgInstrs/PerformProc4Recursive0.diag

-4
This file was deleted.

‎TypeCobol.Analysis.Test/BasicCfgInstrs/PerformProcIterativeAfterRecursive0.diag

-2
This file was deleted.

‎TypeCobol.Analysis.Test/BasicCfgInstrs/PerformProcIterativeAfterRecursive1.diag

-2
This file was deleted.

‎TypeCobol.Analysis.Test/BasicCfgInstrs/PerformProcIterativeAfterRecursive2.diag

-2
This file was deleted.

‎TypeCobol.Analysis.Test/BasicCfgInstrs/PerformProcIterativeRecursive0.diag

-2
This file was deleted.

‎TypeCobol.Analysis.Test/BasicCfgInstrs/SG102A.diag

-4
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,6 @@ Line 242[13,46] <37, Warning, General> - Warning: "end-if" is missing
1515
Line 250[12,37] <37, Warning, General> - Warning: "end-if" is missing
1616
Line 266[12,43] <37, Warning, General> - Warning: "end-if" is missing
1717
Line 267[12,42] <37, Warning, General> - Warning: "end-if" is missing
18-
Line 269[41,66] <37, Warning, General> - Warning: A recursive loop has been encountered while analyzing 'PERFORM WRITE-LINE', recursive instruction is ' PERFORM WRT-LN'.
19-
Line 269[41,66] <37, Warning, General> - Warning: A recursive loop has been encountered while analyzing 'PERFORM WRITE-LINE', recursive instruction is ' PERFORM WRT-LN 2 TIMES'.
20-
Line 269[41,66] <37, Warning, General> - Warning: A recursive loop has been encountered while analyzing 'PERFORM WRITE-LINE', recursive instruction is ' PERFORM WRT-LN'.
21-
Line 269[41,66] <37, Warning, General> - Warning: A recursive loop has been encountered while analyzing 'PERFORM WRITE-LINE', recursive instruction is ' PERFORM WRT-LN'.
2218
Line 276[12,43] <37, Warning, General> - Warning: "end-if" is missing
2319
Line 277[12,38] <37, Warning, General> - Warning: "end-if" is missing
2420
Line 293[12,16] <37, Warning, General> - Warning: ALTER should not be used

‎TypeCobol.Analysis/Cfg/ControlFlowGraphBuilder.BasicBlockForNodeGroup.cs

-11
Original file line numberDiff line numberDiff line change
@@ -63,17 +63,6 @@ internal bool IsAfterIterativeGroup
6363
set;
6464
}
6565

66-
/// <summary>
67-
/// To detect recursivity on PERFORM Procedure calls.
68-
/// This is a bit array of GroupIndex encountered during the workflow
69-
/// call of other PERFORM.
70-
/// </summary>
71-
internal BitArray RecursivityGroupSet
72-
{
73-
get;
74-
set;
75-
}
76-
7766
/// <summary>
7867
/// Constructor.
7968
/// </summary>

‎TypeCobol.Analysis/Cfg/ControlFlowGraphBuilder.cs

-40
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using System;
2-
using System.Collections;
32
using System.Collections.Generic;
43
using System.Linq;
54
using TypeCobol.Analysis.Graph;
@@ -1070,16 +1069,6 @@ void StoreSentences()
10701069
{
10711070
isPerform = true; //To avoid a second dynamic cast
10721071

1073-
//Is there a recursion in the graph ?
1074-
if (group.RecursivityGroupSet.Get(group0.GroupIndex) && !group0.HasFlag(BasicBlock<Node, D>.Flags.Recursive))
1075-
{
1076-
//Flag group and store recursive perform
1077-
group0.SetFlag(BasicBlock<Node, D>.Flags.Recursive, true);
1078-
Node offendingInstruction = group0.Instructions.Last.Value;
1079-
System.Diagnostics.Debug.Assert(offendingInstruction != null);
1080-
this.Cfg.AddRecursivePerform(p, offendingInstruction);
1081-
}
1082-
10831072
var clonedGroup0 = clonedPerforms
10841073
.Select(t => t.Item3)
10851074
.SingleOrDefault(g => g.GroupIndex == group0.GroupIndex);
@@ -1115,9 +1104,6 @@ void StoreSentences()
11151104
clonedGroup.Group = new LinkedList<BasicBlock<Node, D>>();
11161105
clonedGroup.TerminalBlocks = null;
11171106

1118-
group.RecursivityGroupSet.Set(clonedGroup.GroupIndex, true);
1119-
clonedGroup.RecursivityGroupSet = new BitArray(group.RecursivityGroupSet);
1120-
11211107
var originalPerform = this.CurrentProgramCfgBuilder.PendingPERFORMProcedures
11221108
.Single(t => t.Item3 == block);
11231109
clonedPerforms.Add(new Tuple<PerformProcedure, SectionNode, BasicBlockForNodeGroup>(originalPerform.Item1, originalPerform.Item2, clonedGroup));
@@ -1192,8 +1178,6 @@ private void ResolvePendingPERFORMProcedures()
11921178
//First pass: resolve targets of PERFORMs, some new groups may be created during this
11931179
foreach (var item in this.CurrentProgramCfgBuilder.PendingPERFORMProcedures)
11941180
{
1195-
item.Item3.RecursivityGroupSet = new BitArray(GroupCounter + 1);
1196-
item.Item3.RecursivityGroupSet.Set(item.Item3.GroupIndex, true);
11971181
ResolvePendingPERFORMProcedure(item, clonedPerforms);
11981182
}
11991183

@@ -1211,13 +1195,11 @@ private void ResolvePendingPERFORMProcedures()
12111195
{
12121196
BasicBlockForNodeGroup group = item.Item3;
12131197
groupOrder[group.GroupIndex] = group;
1214-
group.RecursivityGroupSet = null;
12151198
}
12161199
foreach (var item in clonedPerforms)
12171200
{
12181201
BasicBlockForNodeGroup group = item.Item3;
12191202
groupOrder[group.GroupIndex] = group;
1220-
group.RecursivityGroupSet = null;
12211203
}
12221204

12231205
//Extend groups according to the current building mode
@@ -1439,28 +1421,6 @@ private void CreateOptionalDiagnostics()
14391421
AddDiagnostic(d);
14401422
}
14411423
}
1442-
1443-
//RecursiveBlockOnPerformProcedure
1444-
if (_compilerOptions.CheckRecursivePerforms.IsActive && this.CurrentProgramCfgBuilder.Cfg.RecursivePerforms != null)
1445-
{
1446-
foreach (var recursivePerform in this.CurrentProgramCfgBuilder.Cfg.RecursivePerforms)
1447-
{
1448-
var perform = recursivePerform.Key;
1449-
SymbolReference procedureReference = perform.CodeElement.Procedure;
1450-
SymbolReference throughProcedureReference = perform.CodeElement.ThroughProcedure;
1451-
foreach (var offendingInstruction in recursivePerform.Value)
1452-
{
1453-
string performTarget = throughProcedureReference != null
1454-
? $"{procedureReference} THRU {throughProcedureReference}"
1455-
: procedureReference.ToString();
1456-
System.Diagnostics.Debug.Assert(offendingInstruction.CodeElement != null);
1457-
string offendingStatement = offendingInstruction.CodeElement.SourceText;
1458-
Diagnostic d = new Diagnostic(_compilerOptions.CheckRecursivePerforms.GetMessageCode(), perform.CodeElement.Position(),
1459-
string.Format(Resource.RecursiveBlockOnPerformProcedure, performTarget, offendingStatement));
1460-
AddDiagnostic(d);
1461-
}
1462-
}
1463-
}
14641424
}
14651425

14661426
/// <summary>

‎TypeCobol.Analysis/Graph/BasicBlock.cs

+1-2
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,7 @@ public enum Flags : uint
8181
Declaratives = 0x01 << 2, //Flag if this basic block is inside a declaratives section.
8282
Start = 0x01 << 3, //Flag for a start node.
8383
End = 0x01 << 4, //Flag for a end node.
84-
GroupGrafted = 0x01 << 5, //Flag a Grafted Group.
85-
Recursive = 0x01 << 6 //Flag a recursive block
84+
GroupGrafted = 0x01 << 5 //Flag a Grafted Group.
8685
}
8786

8887
/// <summary>

‎TypeCobol.Analysis/Graph/ControlFlowGraph.cs

-28
Original file line numberDiff line numberDiff line change
@@ -134,12 +134,6 @@ public BasicBlock<N, D> RootBlock
134134
/// </summary>
135135
public Dictionary<PerformProcedure, Tuple<N, N>> WrongOrderPerformThrus { get; private set; }
136136

137-
/// <summary>
138-
/// All recursive PERFORMs found in the program. Null if no such perform found.
139-
/// Key is the recursive PERFORM statement, value is the list of all detected instructions that lead to recursion.
140-
/// </summary>
141-
public Dictionary<PerformProcedure, List<N>> RecursivePerforms { get; private set; }
142-
143137
/// <summary>
144138
/// All unreachable blocks of this graph. The property may be null but not empty.
145139
/// </summary>
@@ -243,28 +237,6 @@ internal void AddWrongOrderPerformThru(PerformProcedure performThru, N procedure
243237
WrongOrderPerformThrus.Add(performThru, new Tuple<N, N>(procedure, throughProcedure));
244238
}
245239

246-
/// <summary>
247-
/// Register a recursive jump for a perform statement.
248-
/// </summary>
249-
/// <param name="perform">Perform node</param>
250-
/// <param name="recursiveJump">Recursive jump node</param>
251-
internal void AddRecursivePerform(PerformProcedure perform, N recursiveJump)
252-
{
253-
if (RecursivePerforms == null)
254-
{
255-
RecursivePerforms = new Dictionary<PerformProcedure, List<N>>();
256-
}
257-
258-
if (RecursivePerforms.TryGetValue(perform, out var nodes))
259-
{
260-
nodes.Add(recursiveJump);
261-
}
262-
else
263-
{
264-
RecursivePerforms.Add(perform, new List<N>() { recursiveJump });
265-
}
266-
}
267-
268240
/// <summary>
269241
/// Register one unreachable block of this graph
270242
/// </summary>

‎TypeCobol.Analysis/Resource.Designer.cs

+1-10
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎TypeCobol.Analysis/Resource.resx

-3
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,4 @@
126126
<data name="BasicBlockGroupGoesBeyondTheLimit" xml:space="preserve">
127127
<value>Statement '{0}' located at line {1}, column {2} prevents this PERFORM statement to reach its exit.</value>
128128
</data>
129-
<data name="RecursiveBlockOnPerformProcedure" xml:space="preserve">
130-
<value>A recursive loop has been encountered while analyzing 'PERFORM {0}', recursive instruction is '{1}'.</value>
131-
</data>
132129
</root>

‎TypeCobol/Compiler/Directives/TypeCobolOptions.cs

-6
Original file line numberDiff line numberDiff line change
@@ -81,11 +81,6 @@ public bool UseEuroInformationLegacyReplacingSyntax
8181
/// </summary>
8282
public TypeCobolCheckOption CheckPerformThruOrder { get; set; }
8383

84-
/// <summary>
85-
/// Check that perform statement are not recursive, requires CFG.
86-
/// </summary>
87-
public TypeCobolCheckOption CheckRecursivePerforms { get; set; }
88-
8984
public TypeCobolOptions(TypeCobolConfiguration config)
9085
{
9186
HaltOnMissingCopy = config.HaltOnMissingCopyFilePath != null;
@@ -104,7 +99,6 @@ public TypeCobolOptions(TypeCobolConfiguration config)
10499
CheckEndProgram = config.CheckEndProgram;
105100
CheckPerformPrematureExits = config.CheckPerformPrematureExits;
106101
CheckPerformThruOrder = config.CheckPerformThruOrder;
107-
CheckRecursivePerforms = config.CheckRecursivePerforms;
108102
}
109103

110104
public TypeCobolOptions()

‎TypeCobol/Tools/Options-Config/TypeCobolConfiguration.cs

-4
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@ public class TypeCobolConfiguration : ITypeCobolCheckOptions
4848
public TypeCobolCheckOption CheckEndProgram { get; set; }
4949
public TypeCobolCheckOption CheckPerformPrematureExits { get; set; }
5050
public TypeCobolCheckOption CheckPerformThruOrder { get; set; }
51-
public TypeCobolCheckOption CheckRecursivePerforms { get; set; }
5251

5352
public List<string> Copies = new List<string>();
5453
public List<string> Dependencies = new List<string>();
@@ -246,7 +245,6 @@ public interface ITypeCobolCheckOptions
246245
TypeCobolCheckOption CheckEndProgram { get; set; }
247246
TypeCobolCheckOption CheckPerformPrematureExits { get; set; }
248247
TypeCobolCheckOption CheckPerformThruOrder { get; set; }
249-
TypeCobolCheckOption CheckRecursivePerforms { get; set; }
250248
}
251249

252250
public static class TypeCobolCheckOptionsInitializer
@@ -257,7 +255,6 @@ public static void SetDefaultValues(ITypeCobolCheckOptions checkOptions)
257255
checkOptions.CheckEndProgram = new TypeCobolCheckOption(Severity.Error);
258256
checkOptions.CheckPerformPrematureExits = new TypeCobolCheckOption(Severity.Warning);
259257
checkOptions.CheckPerformThruOrder = new TypeCobolCheckOption(Severity.Warning);
260-
checkOptions.CheckRecursivePerforms = new TypeCobolCheckOption(Severity.Warning);
261258
}
262259
}
263260

@@ -293,7 +290,6 @@ public static OptionSet GetCommonTypeCobolOptions(TypeCobolConfiguration typeCob
293290
{ "diag.cep|diagnostic.checkEndProgram=", "Indicate level of check end program: warning, error, info, ignore.", v => typeCobolConfig.CheckEndProgram = TypeCobolCheckOption.Parse(v) },
294291
{ "diag.cppe|diagnostic.checkPerformPrematureExits=", "Indicate level of check perform premature exits: warning, error, info, ignore.", v => typeCobolConfig.CheckPerformPrematureExits = TypeCobolCheckOption.Parse(v) },
295292
{ "diag.cpto|diagnostic.checkPerformThruOrder=", "Indicate level of check perform thru procedure order: warning, error, info, ignore.", v => typeCobolConfig.CheckPerformThruOrder = TypeCobolCheckOption.Parse(v) },
296-
{ "diag.crp|diagnostic.checkRecursivePerforms=", "Indicate level of check recursive performs: warning, error, info, ignore.", v => typeCobolConfig.CheckRecursivePerforms = TypeCobolCheckOption.Parse(v) },
297293
{ "log|logfilepath=", "{PATH} to TypeCobol.CLI.log log file", v => typeCobolConfig.LogFile = Path.Combine(v, TypeCobolConfiguration.DefaultLogFileName)},
298294
{ "cfg|cfgbuild=", "CFG build option, recognized values are: None/0, Standard/1, Extended/2, WithDfa/3.", v => typeCobolConfig.RawCfgBuildingMode = v },
299295
{ "cob|cobol", "Indicate that it's a pure Cobol85 input file.", v => typeCobolConfig.IsCobolLanguage = true },

0 commit comments

Comments
 (0)
Please sign in to comment.